leasehold-chain
Version:
Leasehold sidechain
217 lines (189 loc) • 5.83 kB
JavaScript
/*
* Copyright © 2019 Lisk Foundation
*
* See the LICENSE file at the top-level directory of this distribution
* for licensing information.
*
* Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation,
* no part of this software, including this file, may be copied, modified,
* propagated, or distributed except according to the terms contained in the
* LICENSE file.
*
* Removal or modification of this copyright notice is prohibited.
*/
;
const _ = require('lodash');
const path = require('path');
const {
entities: { Transaction: TransactionEntity },
} = require('leasehold-lisk-framework/src/components/storage');
/**
* Basic Transaction
* @typedef {Object} BasicTransaction
* @property {string} id
* @property {string} blockId
* @property {Integer} [height]
* @property {Integer} [confirmations]
* @property {Integer} type
* @property {Number} timestamp
* @property {string} senderPublicKey
* @property {string} [recipientPublicKey]
* @property {string} requesterPublicKey
* @property {string} senderId
* @property {string} recipientId
* @property {string} amount
* @property {string} fee
* @property {string} signature
* @property {string} signSignature
* @property {Array.<string>} signatures
*/
/**
* Transfer Transaction
* @typedef {BasicTransaction} TransferTransaction
* @property {Object} asset
* @property {string} asset.data
*/
/**
* Second Passphrase Transaction
* @typedef {BasicTransaction} SecondPassphraseTransaction
* @property {Object} asset
* @property {Object} asset.signature
* @property {string} asset.signature.publicKey
*/
/**
* Delegate Transaction
* @typedef {BasicTransaction} DelegateTransaction
* @property {Object} asset
* @property {Object} asset.delegate
* @property {string} asset.delegate.username
*/
/**
* Vote Transaction
* @typedef {BasicTransaction} VoteTransaction
* @property {Object} asset
* @property {Array.<string>} asset.votes
*/
/**
* Multisig Registration Transaction
* @typedef {BasicTransaction} MultisigRegistrationTransaction
* @property {Object} asset
* @property {Object} asset.multisignature
* @property {Integer} asset.multisignature.min
* @property {Integer} asset.multisignature.lifetime
* @property {Array.<string>} asset.multisignature.keysgroup
*/
/**
* Dapp Registration Transaction
* @typedef {BasicTransaction} DappRegistrationTransaction
* @property {Object} asset
* @property {Object} asset.dapp
* @property {Integer} asset.dapp.type
* @property {string} asset.dapp.name
* @property {string} asset.dapp.description
* @property {string} asset.dapp.tags
* @property {string} asset.dapp.link
* @property {string} asset.dapp.icon
* @property {Integer} asset.dapp.category
*/
/**
* InTransfer Transaction
* @typedef {BasicTransaction} InTransferTransaction
* @property {Object} asset
* @property {Object} asset.inTransfer
* @property {string} asset.inTransfer.dappId
*/
/**
* OutTransfer Transaction
* @typedef {BasicTransaction} OutTransferTransaction
* @property {Object} asset
* @property {Object} asset.outTransfer
* @property {string} asset.outTransfer.dappId
* @property {string} asset.outTransfer.transactionId
*/
/**
* Transaction
* @typedef {(TransferTransaction|SecondPassphraseTransaction|DelegateTransaction|VoteTransaction|MultisigRegistrationTransaction|DappRegistrationTransaction|InTransferTransaction|OutTransferTransaction)} Transaction
*/
/**
* Transaction Filters
* @typedef {Object} filters.Transaction
*/
const sqlFiles = {
create: 'transactions/create.sql',
};
const trsCreateFields = [
'id',
'blockId',
'type',
'timestamp',
'senderPublicKey',
'requesterPublicKey',
'senderId',
'recipientId',
'amount',
'fee',
'signature',
'signSignature',
'signatures',
'asset',
'transferData',
];
class ChainTransaction extends TransactionEntity {
/**
* Constructor
* @param {BaseAdapter} adapter - Adapter to retrive the data from
* @param {filters.Transaction} defaultFilters - Set of default filters applied on every query
*/
constructor(adapter, defaultFilters = {}) {
super(adapter, defaultFilters);
this.sqlDirectory = path.join(path.dirname(__filename), '../sql');
this.SQLs = this.loadSQLFiles('transaction', sqlFiles, this.sqlDirectory);
}
/**
* Create transactions object
*
* @param {Transaction|Array.<Transaction>} data
* @param {Object} [_options]
* @param {Object} [tx] - Transaction object
* @return {*}
*/
create(data, _options, tx) {
const transactions = ChainTransaction._sanitizeCreateData(data);
const createSet = this.getValuesSet(transactions, trsCreateFields);
return this.adapter.executeFile(
this.SQLs.create,
{ values: createSet, attributes: trsCreateFields },
{ expectedResultCount: 0 },
tx,
);
}
static _sanitizeCreateData(data) {
const transactions = Array.isArray(data)
? _.cloneDeep(data)
: [_.cloneDeep(data)];
transactions.forEach(transaction => {
transaction.signatures = transaction.signatures
? transaction.signatures.join()
: null;
transaction.amount = transaction.amount.toString();
transaction.fee = transaction.fee.toString();
transaction.recipientId = transaction.recipientId || null;
transaction.transferData = null;
// Transfer data is bytea and can not be included as json when null byte is present
if (
transaction.type === 0 &&
transaction.asset &&
transaction.asset.data
) {
transaction.transferData = Buffer.from(transaction.asset.data, 'utf8');
delete transaction.asset;
}
// stringify should be done after converting asset.data into transferData
transaction.asset = transaction.asset
? JSON.stringify(transaction.asset)
: null;
});
return transactions;
}
}
module.exports = ChainTransaction;