From 401c53da5d16163f914b211ff24c569ebc5be014 Mon Sep 17 00:00:00 2001 From: Denis Davidyuk Date: Wed, 17 Feb 2021 05:16:04 +0300 Subject: [PATCH] txDryRun: Simplify arguments, support `txEvents` option --- es/ae/contract.js | 17 ++++------------- es/chain/index.js | 9 +++++---- es/chain/node.js | 21 ++++++++++++++++++--- es/utils/swagger.js | 4 ++++ 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/es/ae/contract.js b/es/ae/contract.js index 17c9252f6a..855ae8b5f8 100644 --- a/es/ae/contract.js +++ b/es/ae/contract.js @@ -176,27 +176,18 @@ async function contractCallStatic (source, address, name, args = [], { top, opti } } -async function dryRunContractTx (tx, callerId, source, name, opt = {}) { - const { top } = opt - // Resolve Account for Dry-run - const dryRunAmount = BigNumber(opt.dryRunAccount.amount).gt(BigNumber(opt.amount || 0)) ? opt.dryRunAccount.amount : opt.amount - const dryRunAccount = { - amount: dryRunAmount, - pubKey: callerId - } - // Dry-run - const [{ result: status, callObj, reason }] = (await this.txDryRun([tx], [dryRunAccount], top)).results +async function dryRunContractTx (tx, callerId, source, name, options) { + const { callObj, ...dryRunOther } = await this.txDryRun(tx, callerId, options) - // Process response - if (status !== 'ok') throw Object.assign(new Error('Dry run error, ' + reason), { tx: TxObject({ tx }), dryRunParams: { accounts: [dryRunAccount], top } }) const { returnType, returnValue } = callObj if (returnType !== 'ok') { await this._handleCallError(callObj, tx) } return { + ...dryRunOther, tx: TxObject({ tx }), result: callObj, - decode: () => this.contractDecodeData(source, name, returnValue, returnType, opt) + decode: () => this.contractDecodeData(source, name, returnValue, returnType, options) } } diff --git a/es/chain/index.js b/es/chain/index.js index 2944cb345d..3cb3a93311 100644 --- a/es/chain/index.js +++ b/es/chain/index.js @@ -245,10 +245,11 @@ const Chain = Oracle.compose({ * @instance * @abstract * @category async - * @rtype (txs, accounts, hashOrHeight) => result: Object - * @param {Array} txs - Array of transaction's - * @param {Array} accounts - Array of account's - * @param {String|Number} hashOrHeight - hash or height of block on which to make dry-run + * @rtype (tx, accountAddress, options) => result: Object + * @param {String} tx - transaction to execute + * @param {String} accountAddress - address that will be used to execute transaction + * @param {String|Number} [options.top] - hash of block on which to make dry-run + * @param {Boolean} [options.txEvents] - collect and return on-chain tx events that would result from the call * @return {Object} Result */ diff --git a/es/chain/node.js b/es/chain/node.js index 8753efb985..7778aac547 100644 --- a/es/chain/node.js +++ b/es/chain/node.js @@ -24,7 +24,7 @@ import NodePool from '../node-pool' import { assertedType } from '../utils/crypto' import { pause } from '../utils/other' import { isNameValid, produceNameId } from '../tx/builder/helpers' -import { NAME_ID_KEY } from '../tx/builder/schema' +import { DRY_RUN_ACCOUNT, NAME_ID_KEY } from '../tx/builder/schema' /** * ChainNode module @@ -174,8 +174,23 @@ async function getMicroBlockHeader (hash) { return this.api.getMicroBlockHeaderByHash(hash) } -async function txDryRun (txs, accounts, top) { - return this.api.dryRunTxs({ txs: txs.map(tx => ({ tx })), accounts, top }) +async function txDryRun (tx, accountAddress, options) { + const { results: [{ result, reason, ...resultPayload }], ...other } = + await this.api.dryRunTxs({ + ...options, + txs: [{ tx }], + accounts: [{ + pubKey: accountAddress, + amount: DRY_RUN_ACCOUNT.amount + }] + }) + + if (result === 'ok') return { ...resultPayload, ...other } + + throw Object.assign( + new Error('Dry run error, ' + reason), + { tx, accountAddress, options } + ) } async function getContractByteCode (contractId) { diff --git a/es/utils/swagger.js b/es/utils/swagger.js index ef7c4d7526..6461c7fb71 100644 --- a/es/utils/swagger.js +++ b/es/utils/swagger.js @@ -120,6 +120,10 @@ const conformTypes = { throw TypeError('Not a string', spec, value) } }, + boolean (value, spec) { + if (typeof value === 'boolean') return value + throw TypeError('Not a boolean', spec, value) + }, object (value, spec, types) { if (R.type(value) === 'Object') { const required = (spec.required || []).map(snakeToPascal)