mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-12-06 17:27:59 +00:00
Move ripple-rest/api into src/api, exposing RippleAPI
This commit is contained in:
60
src/api/transaction/order.js
Normal file
60
src/api/transaction/order.js
Normal file
@@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const utils = require('./utils');
|
||||
const ripple = utils.common.core;
|
||||
const validate = utils.common.validate;
|
||||
|
||||
function renameCounterpartyToIssuer(amount) {
|
||||
if (amount === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const issuer = amount.counterparty === undefined ?
|
||||
amount.issuer : amount.counterparty;
|
||||
const withIssuer = _.assign({}, amount, {issuer: issuer});
|
||||
return _.omit(withIssuer, 'counterparty');
|
||||
}
|
||||
|
||||
function renameCounterpartyToIssuerInOrder(order) {
|
||||
const taker_gets = renameCounterpartyToIssuer(order.taker_gets);
|
||||
const taker_pays = renameCounterpartyToIssuer(order.taker_pays);
|
||||
const changes = {taker_gets: taker_gets, taker_pays: taker_pays};
|
||||
return _.assign({}, order, _.omit(changes, _.isUndefined));
|
||||
}
|
||||
|
||||
const OfferCreateFlags = {
|
||||
Passive: {name: 'passive', set: 'Passive'},
|
||||
ImmediateOrCancel: {name: 'immediate_or_cancel', set: 'ImmediateOrCancel'},
|
||||
FillOrKill: {name: 'fill_or_kill', set: 'FillOrKill'}
|
||||
};
|
||||
|
||||
function createOrderTransaction(account, order) {
|
||||
validate.address(account);
|
||||
validate.order(order);
|
||||
|
||||
const _order = renameCounterpartyToIssuerInOrder(order);
|
||||
const transaction = new ripple.Transaction();
|
||||
const takerPays = _order.taker_pays.currency !== 'XRP'
|
||||
? _order.taker_pays : utils.xrpToDrops(_order.taker_pays.value);
|
||||
const takerGets = _order.taker_gets.currency !== 'XRP'
|
||||
? _order.taker_gets : utils.xrpToDrops(_order.taker_gets.value);
|
||||
|
||||
transaction.offerCreate(account, ripple.Amount.from_json(takerPays),
|
||||
ripple.Amount.from_json(takerGets));
|
||||
|
||||
utils.setTransactionBitFlags(transaction, {
|
||||
input: _order,
|
||||
flags: OfferCreateFlags
|
||||
});
|
||||
|
||||
if (_order.type === 'sell') {
|
||||
transaction.setFlags('Sell');
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
function prepareOrder(account, order, instructions, callback) {
|
||||
const transaction = createOrderTransaction(account, order);
|
||||
utils.createTxJSON(transaction, this.remote, instructions, callback);
|
||||
}
|
||||
|
||||
module.exports = utils.wrapCatch(prepareOrder);
|
||||
20
src/api/transaction/ordercancellation.js
Normal file
20
src/api/transaction/ordercancellation.js
Normal file
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
const validate = utils.common.validate;
|
||||
const ripple = utils.common.core;
|
||||
|
||||
function createOrderCancellationTransaction(account, sequence) {
|
||||
validate.address(account);
|
||||
validate.sequence(sequence);
|
||||
|
||||
const transaction = new ripple.Transaction();
|
||||
transaction.offerCancel(account, sequence);
|
||||
return transaction;
|
||||
}
|
||||
|
||||
function prepareOrderCancellation(account, sequence, instructions, callback) {
|
||||
const transaction = createOrderCancellationTransaction(account, sequence);
|
||||
utils.createTxJSON(transaction, this.remote, instructions, callback);
|
||||
}
|
||||
|
||||
module.exports = utils.wrapCatch(prepareOrderCancellation);
|
||||
125
src/api/transaction/payment.js
Normal file
125
src/api/transaction/payment.js
Normal file
@@ -0,0 +1,125 @@
|
||||
/* eslint-disable valid-jsdoc */
|
||||
'use strict';
|
||||
const BigNumber = require('bignumber.js');
|
||||
const utils = require('./utils');
|
||||
const ripple = utils.common.core;
|
||||
const validate = utils.common.validate;
|
||||
const convertAmount = utils.common.convertAmount;
|
||||
|
||||
function isSendMaxAllowed(payment) {
|
||||
const srcAmt = payment.source_amount;
|
||||
const dstAmt = payment.destination_amount;
|
||||
|
||||
// Don't set SendMax for XRP->XRP payment
|
||||
// temREDUNDANT_SEND_MAX removed in:
|
||||
// https://github.com/ripple/rippled/commit/
|
||||
// c522ffa6db2648f1d8a987843e7feabf1a0b7de8/
|
||||
return srcAmt && !(srcAmt.currency === 'XRP' && dstAmt.currency === 'XRP');
|
||||
}
|
||||
|
||||
function createPaymentTransaction(account, payment) {
|
||||
validate.address(account);
|
||||
validate.payment(payment);
|
||||
|
||||
// Convert blank issuer to sender's address
|
||||
// (Ripple convention for 'any issuer')
|
||||
// https://ripple.com/build/transactions/
|
||||
// #special-issuer-values-for-sendmax-and-amount
|
||||
// https://ripple.com/build/ripple-rest/#counterparties-in-payments
|
||||
if (payment.source_amount && payment.source_amount.currency !== 'XRP'
|
||||
&& payment.source_amount.issuer === '') {
|
||||
payment.source_amount.issuer = payment.source_account;
|
||||
}
|
||||
|
||||
// Convert blank issuer to destinations's address
|
||||
// (Ripple convention for 'any issuer')
|
||||
// https://ripple.com/build/transactions/
|
||||
// #special-issuer-values-for-sendmax-and-amount
|
||||
// https://ripple.com/build/ripple-rest/#counterparties-in-payments
|
||||
if (payment.destination_amount
|
||||
&& payment.destination_amount.currency !== 'XRP'
|
||||
&& payment.destination_amount.issuer === '') {
|
||||
payment.destination_amount.issuer = payment.destination_account;
|
||||
}
|
||||
// Uppercase currency codes
|
||||
if (payment.source_amount) {
|
||||
payment.source_amount.currency =
|
||||
payment.source_amount.currency.toUpperCase();
|
||||
}
|
||||
if (payment.destination_amount) {
|
||||
payment.destination_amount.currency =
|
||||
payment.destination_amount.currency.toUpperCase();
|
||||
}
|
||||
/* Construct payment */
|
||||
const transaction = new ripple.Transaction();
|
||||
const transactionData = {
|
||||
from: payment.source_account,
|
||||
to: payment.destination_account,
|
||||
amount: convertAmount(payment.destination_amount)
|
||||
};
|
||||
|
||||
// invoice_id Because transactionData is a object, transaction.payment
|
||||
// function is ignored invoiceID
|
||||
if (payment.invoice_id) {
|
||||
transaction.invoiceID(payment.invoice_id);
|
||||
}
|
||||
transaction.payment(transactionData);
|
||||
// Tags
|
||||
if (payment.source_tag) {
|
||||
transaction.sourceTag(parseInt(payment.source_tag, 10));
|
||||
}
|
||||
if (payment.destination_tag) {
|
||||
transaction.destinationTag(parseInt(payment.destination_tag, 10));
|
||||
}
|
||||
|
||||
// SendMax
|
||||
if (isSendMaxAllowed(payment)) {
|
||||
const max_value = new BigNumber(payment.source_amount.value)
|
||||
.plus(payment.source_slippage || 0).toString();
|
||||
|
||||
if (payment.source_amount.currency === 'XRP') {
|
||||
transaction.sendMax(utils.xrpToDrops(max_value));
|
||||
} else {
|
||||
transaction.sendMax({
|
||||
value: max_value,
|
||||
currency: payment.source_amount.currency,
|
||||
issuer: payment.source_amount.issuer
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Paths
|
||||
if (typeof payment.paths === 'string') {
|
||||
transaction.paths(JSON.parse(payment.paths));
|
||||
} else if (typeof payment.paths === 'object') {
|
||||
transaction.paths(payment.paths);
|
||||
}
|
||||
|
||||
// Memos
|
||||
if (payment.memos && Array.isArray(payment.memos)) {
|
||||
for (let m = 0; m < payment.memos.length; m++) {
|
||||
const memo = payment.memos[m];
|
||||
transaction.addMemo(memo.MemoType, memo.MemoFormat, memo.MemoData);
|
||||
}
|
||||
}
|
||||
|
||||
// Flags
|
||||
let flags = [];
|
||||
if (payment.partial_payment) {
|
||||
flags.push('PartialPayment');
|
||||
}
|
||||
if (payment.no_direct_ripple) {
|
||||
flags.push('NoRippleDirect');
|
||||
}
|
||||
if (flags.length > 0) {
|
||||
transaction.setFlags(flags);
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
function preparePayment(account, payment, instructions, callback) {
|
||||
const transaction = createPaymentTransaction(account, payment);
|
||||
utils.createTxJSON(transaction, this.remote, instructions, callback);
|
||||
}
|
||||
|
||||
module.exports = utils.wrapCatch(preparePayment);
|
||||
159
src/api/transaction/settings.js
Normal file
159
src/api/transaction/settings.js
Normal file
@@ -0,0 +1,159 @@
|
||||
/* eslint-disable valid-jsdoc */
|
||||
'use strict';
|
||||
const _ = require('lodash');
|
||||
const assert = require('assert');
|
||||
const utils = require('./utils');
|
||||
const ripple = utils.common.core;
|
||||
const validate = utils.common.validate;
|
||||
const constants = utils.common.constants;
|
||||
const InvalidRequestError = utils.common.errors.InvalidRequestError;
|
||||
|
||||
// Emptry string passed to setting will clear it
|
||||
const CLEAR_SETTING = '';
|
||||
|
||||
/**
|
||||
* Pad the value of a fixed-length field
|
||||
*
|
||||
* @param {String} value
|
||||
* @param {Number} length
|
||||
* @return {String}
|
||||
*/
|
||||
function padValue(value, length) {
|
||||
assert.strictEqual(typeof value, 'string');
|
||||
assert.strictEqual(typeof length, 'number');
|
||||
|
||||
let result = value;
|
||||
|
||||
while (result.length < length) {
|
||||
result = '0' + result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set integer flags on a transaction based on input and a flag map
|
||||
*
|
||||
* @param {Transaction} transaction
|
||||
* @param {Object} input - Object whose properties determine whether
|
||||
* to update the transaction's SetFlag or ClearFlag property
|
||||
* @param {Object} flags - Object that maps property names to transaction
|
||||
* integer flag values
|
||||
*
|
||||
* @returns undefined
|
||||
*/
|
||||
function setTransactionIntFlags(transaction, input, flags) {
|
||||
for (let flagName in flags) {
|
||||
const flag = flags[flagName];
|
||||
|
||||
if (!input.hasOwnProperty(flag.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const value = input[flag.name];
|
||||
|
||||
if (value) {
|
||||
transaction.tx_json.SetFlag = flag.value;
|
||||
} else {
|
||||
transaction.tx_json.ClearFlag = flag.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set fields on a transaction based on input and fields schema object
|
||||
*
|
||||
* @param {Transaction} transaction
|
||||
* @param {Object} input - Object whose properties are used to set fields on
|
||||
* the transaction
|
||||
* @param {Object} fieldSchema - Object that holds the schema of each field
|
||||
*
|
||||
* @returns undefined
|
||||
*/
|
||||
function setTransactionFields(transaction, input, fieldSchema) {
|
||||
for (let fieldName in fieldSchema) {
|
||||
const field = fieldSchema[fieldName];
|
||||
let value = input[field.name];
|
||||
|
||||
if (typeof value === 'undefined') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The value required to clear an account root field varies
|
||||
if (value === CLEAR_SETTING && field.hasOwnProperty('defaults')) {
|
||||
value = field.defaults;
|
||||
}
|
||||
|
||||
if (field.encoding === 'hex') {
|
||||
// If the field is supposed to be hex, why don't we do a
|
||||
// toString('hex') on it?
|
||||
if (field.length) {
|
||||
// Field is fixed length, why are we checking here though?
|
||||
// We could move this to validateInputs
|
||||
if (value.length > field.length) {
|
||||
throw new InvalidRequestError(
|
||||
'Parameter length exceeded: ' + fieldName);
|
||||
} else if (value.length < field.length) {
|
||||
value = padValue(value, field.length);
|
||||
}
|
||||
} else {
|
||||
// Field is variable length. Expecting an ascii string as input.
|
||||
// This is currently only used for Domain field
|
||||
value = new Buffer(value, 'ascii').toString('hex');
|
||||
}
|
||||
|
||||
value = value.toUpperCase();
|
||||
}
|
||||
|
||||
transaction.tx_json[fieldName] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a numerical transfer rate in ripple-rest format to ripple-lib
|
||||
*
|
||||
* Note: A fee of 1% requires 101% of the destination to be sent for the
|
||||
* destination to receive 100%.
|
||||
* The transfer rate is specified as the input amount as fraction of 1.
|
||||
* To specify the default rate of 0%, a 100% input amount, specify 1.
|
||||
* To specify a rate of 1%, a 101% input amount, specify 1.01
|
||||
*
|
||||
* @param {Number|String} transferRate
|
||||
*
|
||||
* @returns {Number|String} numbers will be converted while strings
|
||||
* are returned
|
||||
*/
|
||||
function convertTransferRate(transferRate) {
|
||||
if (_.isNumber(transferRate)) {
|
||||
return transferRate * Math.pow(10, 9);
|
||||
}
|
||||
|
||||
return transferRate;
|
||||
}
|
||||
|
||||
function createSettingsTransaction(account, settings) {
|
||||
validate.address(account);
|
||||
validate.settings(settings);
|
||||
|
||||
const transaction = new ripple.Transaction();
|
||||
transaction.accountSet(account);
|
||||
|
||||
utils.setTransactionBitFlags(transaction, {
|
||||
input: settings,
|
||||
flags: constants.AccountSetFlags,
|
||||
clear_setting: CLEAR_SETTING
|
||||
});
|
||||
setTransactionIntFlags(transaction, settings, constants.AccountSetIntFlags);
|
||||
setTransactionFields(transaction, settings, constants.AccountRootFields);
|
||||
|
||||
transaction.tx_json.TransferRate = convertTransferRate(
|
||||
transaction.tx_json.TransferRate);
|
||||
return transaction;
|
||||
}
|
||||
|
||||
function prepareSettings(account, settings, instructions, callback) {
|
||||
const transaction = createSettingsTransaction(account, settings);
|
||||
utils.createTxJSON(transaction, this.remote, instructions, callback);
|
||||
}
|
||||
|
||||
module.exports = utils.wrapCatch(prepareSettings);
|
||||
65
src/api/transaction/sign.js
Normal file
65
src/api/transaction/sign.js
Normal file
@@ -0,0 +1,65 @@
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
const ripple = utils.common.core;
|
||||
const validate = utils.common.validate;
|
||||
|
||||
/**
|
||||
* These prefixes are inserted before the source material used to
|
||||
* generate various hashes. This is done to put each hash in its own
|
||||
* "space." This way, two different types of objects with the
|
||||
* same binary data will produce different hashes.
|
||||
*
|
||||
* Each prefix is a 4-byte value with the last byte set to zero
|
||||
* and the first three bytes formed from the ASCII equivalent of
|
||||
* some arbitrary string. For example "TXN".
|
||||
*/
|
||||
const HASH_TX_ID = 0x54584E00; // 'TXN'
|
||||
const HASH_TX_SIGN = 0x53545800; // 'STX'
|
||||
const HASH_TX_SIGN_TESTNET = 0x73747800; // 'stx'
|
||||
|
||||
function getKeyPair(address, secret) {
|
||||
return ripple.Seed.from_json(secret).get_key(address);
|
||||
}
|
||||
|
||||
function getPublicKeyHex(keypair) {
|
||||
return keypair.to_hex_pub();
|
||||
}
|
||||
|
||||
function serialize(txJSON) {
|
||||
return ripple.SerializedObject.from_json(txJSON);
|
||||
}
|
||||
|
||||
function hashSerialization(serialized, prefix) {
|
||||
return serialized.hash(prefix || HASH_TX_ID).to_hex();
|
||||
}
|
||||
|
||||
function hashJSON(txJSON, prefix) {
|
||||
return hashSerialization(serialize(txJSON), prefix);
|
||||
}
|
||||
|
||||
function signingHash(txJSON, isTestNet) {
|
||||
return hashJSON(txJSON, isTestNet ? HASH_TX_SIGN_TESTNET : HASH_TX_SIGN);
|
||||
}
|
||||
|
||||
function computeSignature(txJSON, keypair) {
|
||||
const signature = keypair.sign(signingHash(txJSON));
|
||||
return ripple.sjcl.codec.hex.fromBits(signature).toUpperCase();
|
||||
}
|
||||
|
||||
function sign(txJSON, secret) {
|
||||
validate.txJSON(txJSON);
|
||||
validate.addressAndSecret({address: txJSON.Account, secret: secret});
|
||||
|
||||
const keypair = getKeyPair(txJSON.Acccount, secret);
|
||||
if (txJSON.SigningPubKey === undefined) {
|
||||
txJSON.SigningPubKey = getPublicKeyHex(keypair);
|
||||
}
|
||||
txJSON.TxnSignature = computeSignature(txJSON, keypair);
|
||||
const serialized = serialize(txJSON);
|
||||
return {
|
||||
tx_blob: serialized.to_hex(),
|
||||
hash: hashSerialization(serialized, HASH_TX_ID)
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = sign;
|
||||
13
src/api/transaction/submit.js
Normal file
13
src/api/transaction/submit.js
Normal file
@@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
const ripple = utils.common.core;
|
||||
const validate = utils.common.validate;
|
||||
|
||||
function submit(tx_blob, callback) {
|
||||
validate.blob(tx_blob);
|
||||
const request = new ripple.Request(this.remote, 'submit');
|
||||
request.message.tx_blob = tx_blob;
|
||||
request.request(callback);
|
||||
}
|
||||
|
||||
module.exports = submit;
|
||||
51
src/api/transaction/trustline.js
Normal file
51
src/api/transaction/trustline.js
Normal file
@@ -0,0 +1,51 @@
|
||||
'use strict';
|
||||
const utils = require('./utils');
|
||||
const ripple = utils.common.core;
|
||||
const validate = utils.common.validate;
|
||||
|
||||
const TrustSetFlags = {
|
||||
SetAuth: {name: 'authorized', set: 'SetAuth'},
|
||||
ClearNoRipple: {name: 'account_allows_rippling', set: 'ClearNoRipple',
|
||||
unset: 'NoRipple'},
|
||||
SetFreeze: {name: 'account_trustline_frozen', set: 'SetFreeze',
|
||||
unset: 'ClearFreeze'}
|
||||
};
|
||||
|
||||
function createTrustLineTransaction(account, trustline) {
|
||||
validate.address(account);
|
||||
validate.trustline(trustline);
|
||||
|
||||
if (trustline && trustline.limit) {
|
||||
trustline.limit = String(trustline.limit);
|
||||
}
|
||||
|
||||
const transaction = new ripple.Transaction();
|
||||
const limit = [
|
||||
trustline.limit,
|
||||
trustline.currency,
|
||||
trustline.counterparty
|
||||
].join('/');
|
||||
|
||||
transaction.trustSet(account, limit);
|
||||
|
||||
if (typeof trustline.quality_in === 'number') {
|
||||
transaction.tx_json.QualityIn = trustline.quality_in;
|
||||
}
|
||||
if (typeof trustline.quality_out === 'number') {
|
||||
transaction.tx_json.QualityOut = trustline.quality_out;
|
||||
}
|
||||
|
||||
utils.setTransactionBitFlags(transaction, {
|
||||
input: trustline,
|
||||
flags: TrustSetFlags,
|
||||
clear_setting: ''
|
||||
});
|
||||
return transaction;
|
||||
}
|
||||
|
||||
function prepareTrustLine(account, trustline, instructions, callback) {
|
||||
const transaction = createTrustLineTransaction(account, trustline);
|
||||
utils.createTxJSON(transaction, this.remote, instructions, callback);
|
||||
}
|
||||
|
||||
module.exports = utils.wrapCatch(prepareTrustLine);
|
||||
104
src/api/transaction/utils.js
Normal file
104
src/api/transaction/utils.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/* eslint-disable valid-jsdoc */
|
||||
'use strict';
|
||||
const BigNumber = require('bignumber.js');
|
||||
const common = require('../common');
|
||||
|
||||
/**
|
||||
* Helper that sets bit flags on transactions
|
||||
*
|
||||
* @param {Transaction} transaction - Transaction object that is used to submit
|
||||
* requests to ripple
|
||||
* @param {Object} options
|
||||
* @param {Object} options.flags - Holds flag names to set on transaction when
|
||||
* parameter values are true or false on input
|
||||
* @param {Object} options.input - Holds parameter values
|
||||
* @param {String} options.clear_setting - Used to check if parameter values
|
||||
* besides false mean false
|
||||
*
|
||||
*
|
||||
* @returns undefined
|
||||
*/
|
||||
function setTransactionBitFlags(transaction, options) {
|
||||
for (let flagName in options.flags) {
|
||||
const flag = options.flags[flagName];
|
||||
|
||||
// Set transaction flags
|
||||
if (!(flag.name in options.input)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let value = options.input[flag.name];
|
||||
|
||||
if (value === options.clear_setting) {
|
||||
value = false;
|
||||
}
|
||||
|
||||
if (flag.unset) {
|
||||
transaction.setFlags(value ? flag.set : flag.unset);
|
||||
} else if (flag.set && value) {
|
||||
transaction.setFlags(flag.set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getFeeDrops(remote) {
|
||||
const feeUnits = 10; // all transactions currently have a fee of 10 fee units
|
||||
return remote.feeTx(feeUnits).to_text();
|
||||
}
|
||||
|
||||
function createTxJSON(transaction, remote, instructions, callback) {
|
||||
common.validate.options(instructions);
|
||||
|
||||
transaction.complete();
|
||||
const account = transaction.getAccount();
|
||||
const tx_json = transaction.tx_json;
|
||||
|
||||
if (instructions.last_ledger_sequence !== undefined) {
|
||||
tx_json.LastLedgerSequence =
|
||||
parseInt(instructions.last_ledger_sequence, 10);
|
||||
} else {
|
||||
const offset = instructions.last_ledger_offset !== undefined ?
|
||||
parseInt(instructions.last_ledger_offset, 10) : 3;
|
||||
tx_json.LastLedgerSequence = remote.getLedgerSequence() + offset;
|
||||
}
|
||||
|
||||
if (instructions.fixed_fee !== undefined) {
|
||||
tx_json.Fee = common.xrpToDrops(instructions.fixed_fee);
|
||||
} else {
|
||||
const serverFeeDrops = getFeeDrops(remote);
|
||||
if (instructions.max_fee !== undefined) {
|
||||
const maxFeeDrops = common.xrpToDrops(instructions.max_fee);
|
||||
tx_json.Fee = BigNumber.min(serverFeeDrops, maxFeeDrops).toString();
|
||||
} else {
|
||||
tx_json.Fee = serverFeeDrops;
|
||||
}
|
||||
}
|
||||
|
||||
if (instructions.sequence !== undefined) {
|
||||
tx_json.Sequence = parseInt(instructions.sequence, 10);
|
||||
callback(null, {tx_json: tx_json});
|
||||
} else {
|
||||
remote.findAccount(account).getNextSequence(function(error, sequence) {
|
||||
tx_json.Sequence = sequence;
|
||||
callback(null, {tx_json: tx_json});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function wrapCatch(asyncFunction) {
|
||||
return function() {
|
||||
const callback = arguments[arguments.length - 1];
|
||||
try {
|
||||
asyncFunction.apply(this, arguments);
|
||||
} catch (error) {
|
||||
callback(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setTransactionBitFlags: setTransactionBitFlags,
|
||||
createTxJSON: createTxJSON,
|
||||
wrapCatch: wrapCatch,
|
||||
common: common
|
||||
};
|
||||
Reference in New Issue
Block a user