@liskhq/lisk-api-client
Version:
An API client for the Lisk network
147 lines • 7.23 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TransactionMethods = void 0;
const lisk_transactions_1 = require("@liskhq/lisk-transactions");
const lisk_cryptography_1 = require("@liskhq/lisk-cryptography");
const lisk_validator_1 = require("@liskhq/lisk-validator");
const lisk_codec_1 = require("@liskhq/lisk-codec");
const codec_1 = require("./codec");
class TransactionMethods {
constructor(channel, registeredSchema, moduleMetadata, nodeInfo) {
this._channel = channel;
this._metadata = moduleMetadata;
this._schema = registeredSchema;
this._nodeInfo = nodeInfo;
}
async create(input, privateKeyHex) {
var _a, _b, _c;
const txInput = input;
const chainID = Buffer.from(this._nodeInfo.chainID, 'hex');
const privateKey = Buffer.from(privateKeyHex, 'hex');
const publicKey = lisk_cryptography_1.ed.getPublicKeyFromPrivateKey(privateKey);
const address = lisk_cryptography_1.address.getLisk32AddressFromPublicKey(publicKey);
let authAccount;
try {
authAccount = await this._channel.invoke('auth_getAuthAccount', {
address,
});
}
catch (error) {
throw new Error('Auth module is not registered or does not have "getAuthAccount" endpoint.');
}
const registeredModule = this._metadata.find(m => m.name === txInput.module);
if (!registeredModule) {
throw new Error(`Module corresponding to name ${txInput.module} not registered.`);
}
const registeredCommand = registeredModule.commands.find(command => command.name === txInput.command);
if (!registeredCommand) {
throw new Error(`Command corresponding to name ${txInput.command} not registered.`);
}
(_a = txInput.nonce) !== null && _a !== void 0 ? _a : (txInput.nonce = BigInt(authAccount.nonce));
const nonce = BigInt(txInput.nonce);
if (nonce < BigInt(0)) {
throw new Error('Nonce must be greater or equal to zero');
}
(_b = txInput.senderPublicKey) !== null && _b !== void 0 ? _b : (txInput.senderPublicKey = publicKey.toString('hex'));
(_c = txInput.signatures) !== null && _c !== void 0 ? _c : (txInput.signatures = []);
const commandSchema = (0, codec_1.getTransactionParamsSchema)(txInput, this._metadata);
const rawTx = {
...txInput,
module: txInput.module,
command: txInput.command,
nonce,
fee: BigInt(txInput.fee),
signatures: txInput.signatures.map(s => Buffer.from(s, 'hex')),
senderPublicKey: Buffer.from(txInput.senderPublicKey, 'hex'),
params: commandSchema
? lisk_codec_1.codec.fromJSON(commandSchema, txInput.params)
: {},
};
if (authAccount.numberOfSignatures > 0) {
const signedTx = (0, lisk_transactions_1.signMultiSignatureTransaction)(rawTx, chainID, privateKey, {
mandatoryKeys: authAccount.mandatoryKeys.map(k => Buffer.from(k, 'hex')),
optionalKeys: authAccount.optionalKeys.map(k => Buffer.from(k, 'hex')),
}, commandSchema);
return this.toJSON(signedTx);
}
const signedTx = (0, lisk_transactions_1.signTransaction)(rawTx, chainID, privateKey, commandSchema);
return this.toJSON(signedTx);
}
async get(id) {
const idString = Buffer.isBuffer(id) ? id.toString('hex') : id;
const transactionJSON = await this._channel.invoke('chain_getTransactionByID', {
id: idString,
});
return this.fromJSON(transactionJSON);
}
async getFromPool() {
const transactions = await this._channel.invoke('txpool_getTransactionsFromPool');
return transactions.map(tx => this.fromJSON(tx));
}
async sign(transaction, privateKeyHexes) {
const commandSchema = (0, codec_1.getTransactionParamsSchema)(transaction, this._metadata);
const decodedTx = this.fromJSON(transaction);
this._validateTransaction(decodedTx);
const chainID = Buffer.from(this._nodeInfo.chainID, 'hex');
const address = lisk_cryptography_1.address.getLisk32AddressFromPublicKey(decodedTx.senderPublicKey);
const authAccount = await this._channel.invoke('auth_getAuthAccount', {
address,
});
if (authAccount.numberOfSignatures > 0) {
for (const privateKeyHex of privateKeyHexes) {
const privateKey = Buffer.from(privateKeyHex, 'hex');
(0, lisk_transactions_1.signMultiSignatureTransaction)(decodedTx, chainID, privateKey, {
mandatoryKeys: authAccount.mandatoryKeys.map(k => Buffer.from(k, 'hex')),
optionalKeys: authAccount.optionalKeys.map(k => Buffer.from(k, 'hex')),
}, commandSchema);
}
return this.toJSON(decodedTx);
}
const signedTx = (0, lisk_transactions_1.signTransaction)(decodedTx, chainID, Buffer.from(privateKeyHexes[0], 'hex'), commandSchema);
return this.toJSON(signedTx);
}
async send(transaction) {
const decodedTx = this.fromJSON(transaction);
this._validateTransaction(decodedTx);
const encodedTx = (0, codec_1.encodeTransaction)(decodedTx, this._schema, this._metadata);
return this._channel.invoke('txpool_postTransaction', { transaction: encodedTx.toString('hex') });
}
decode(transaction) {
const transactionBuffer = Buffer.isBuffer(transaction)
? transaction
: Buffer.from(transaction, 'hex');
return (0, codec_1.decodeTransaction)(transactionBuffer, this._schema, this._metadata);
}
encode(transaction) {
this._validateTransaction(transaction);
return (0, codec_1.encodeTransaction)(transaction, this._schema, this._metadata);
}
computeMinFee(transaction, options) {
const decodedTx = this.fromJSON(transaction);
this._validateTransaction(decodedTx);
const commandSchema = (0, codec_1.getTransactionParamsSchema)(transaction, this._metadata);
return (0, lisk_transactions_1.computeMinFee)(decodedTx, commandSchema, options);
}
toJSON(transaction) {
this._validateTransaction(transaction);
return (0, codec_1.toTransactionJSON)(transaction, this._schema, this._metadata);
}
fromJSON(transaction) {
return (0, codec_1.fromTransactionJSON)(transaction, this._schema, this._metadata);
}
_validateTransaction(transaction) {
if (typeof transaction !== 'object' || transaction === null) {
throw new Error('Transaction must be an object.');
}
const { params, ...rest } = transaction;
lisk_validator_1.validator.validate(this._schema.transaction, {
...rest,
params: Buffer.alloc(0),
});
if (Buffer.isBuffer(params)) {
throw new Error('Transaction parameter is not decoded.');
}
}
}
exports.TransactionMethods = TransactionMethods;
//# sourceMappingURL=transaction_methods.js.map