From 80ab628643dfeb482a04b11ef0a7b2a7ce302ef1 Mon Sep 17 00:00:00 2001 From: Jaco Date: Sun, 9 May 2021 10:46:21 +0300 Subject: [PATCH] Adjust contract call result decoding (#3510) * Adjust types for node/node-template * Adjust contract call result * Adjust * Raw directly * CHANGELOG --- CHANGELOG.md | 3 + packages/api-contract/src/base/Contract.ts | 70 ++++++------------- packages/api-contract/src/util.ts | 8 +-- .../src/interfaces/contracts/definitions.ts | 3 +- .../types/src/interfaces/contracts/types.ts | 2 +- 5 files changed, 29 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28505cc1b1..8c5d00acf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ Changes: - Allow for `Bounded*` type usage (as per latest Substrate) - Adjust internal TS definitions for providers - Fix `ContractRx` query result definitions (no extra Observable) +- Handle contract call RPC result directly as `Raw` (returned as hex) +- Use `BN_*` constants as non-specified defaults in contract interfaces +- Remove all type overrides for node/node-template (API tracks latest) ## 4.9.1 May 6, 2021 diff --git a/packages/api-contract/src/base/Contract.ts b/packages/api-contract/src/base/Contract.ts index 80770fb2cd..af3cc66bf5 100644 --- a/packages/api-contract/src/base/Contract.ts +++ b/packages/api-contract/src/base/Contract.ts @@ -4,8 +4,8 @@ import type { SubmittableExtrinsic } from '@polkadot/api/submittable/types'; import type { ApiTypes, DecorateMethod } from '@polkadot/api/types'; import type { Bytes } from '@polkadot/types'; -import type { AccountId, ContractExecResult, EventRecord, Weight } from '@polkadot/types/interfaces'; -import type { AnyJson, CodecArg, ISubmittableResult, Registry } from '@polkadot/types/types'; +import type { AccountId, EventRecord, Weight } from '@polkadot/types/interfaces'; +import type { AnyJson, CodecArg, ISubmittableResult } from '@polkadot/types/types'; import type { AbiMessage, ContractCallOutcome, ContractOptions, DecodedEvent } from '../types'; import type { ContractCallResult, ContractCallSend, ContractQuery, ContractTx, MapMessageQuery, MapMessageTx } from './types'; @@ -13,11 +13,12 @@ import BN from 'bn.js'; import { SubmittableResult } from '@polkadot/api'; import { ApiBase } from '@polkadot/api/base'; +import { createTypeUnsafe } from '@polkadot/types'; import { assert, BN_HUNDRED, BN_ONE, BN_ZERO, bnToBn, isFunction, isUndefined, logger } from '@polkadot/util'; import { map } from '@polkadot/x-rxjs/operators'; import { Abi } from '../Abi'; -import { applyOnEvent, extractOptions, formatData, isOptions } from '../util'; +import { applyOnEvent, extractOptions, isOptions } from '../util'; import { Base } from './Base'; // As per Rust, 5 * GAS_PER_SEC @@ -50,33 +51,6 @@ export class ContractSubmittableResult extends SubmittableResult { } } -// map from a JSON result to current-style ContractExecResult -function mapExecResult (registry: Registry, json: Record): ContractExecResult { - if (!Object.keys(json).some((key) => ['error', 'success'].includes(key))) { - return registry.createType('ContractExecResult', json); - } - - const from = registry.createType('ContractExecResultTo260', json); - - if (from.isSuccess) { - const s = from.asSuccess; - - return registry.createType('ContractExecResult', { - gasConsumed: s.gasConsumed, - result: { - ok: { - data: s.data, - flags: s.flags - } - } - }); - } - - // in the old format error has no additional information, - // map it as-is with an "unknown" error - return registry.createType('ContractExecResult', { result: { err: { other: 'unknown' } } }); -} - export class Contract extends Base { /** * @description The on-chain address for this contract @@ -159,24 +133,24 @@ export class Contract extends Base { return { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment send: this._decorateMethod((origin: string | AccountId | Uint8Array) => - this.api.rx.rpc.contracts.call.json({ - dest: this.address, - gasLimit: this.#getGas(gasLimit, true), - inputData: message.toU8a(params), - origin, - value - }).pipe(map((json): ContractCallOutcome => { - const { debugMessage, gasConsumed, result } = mapExecResult(this.registry, json.toJSON()); - - return { - debugMessage, - gasConsumed, - output: result.isOk && message.returnType - ? formatData(this.registry, result.asOk.data, message.returnType) - : null, - result - }; - })) + this.api.rx.rpc.contracts + .call({ + dest: this.address, + gasLimit: this.#getGas(gasLimit, true), + inputData: message.toU8a(params), + origin, + value + }) + .pipe( + map(({ debugMessage, gasConsumed, result }): ContractCallOutcome => ({ + debugMessage, + gasConsumed, + output: result.isOk && message.returnType + ? createTypeUnsafe(this.registry, message.returnType.type, [result.asOk.data], { isPedantic: true }) + : null, + result + })) + ) ) }; } diff --git a/packages/api-contract/src/util.ts b/packages/api-contract/src/util.ts index d96c91e1c8..3b6d61070a 100644 --- a/packages/api-contract/src/util.ts +++ b/packages/api-contract/src/util.ts @@ -2,24 +2,18 @@ // SPDX-License-Identifier: Apache-2.0 import type { SubmittableResult } from '@polkadot/api'; -import type { Raw } from '@polkadot/types'; import type { EventRecord } from '@polkadot/types/interfaces'; -import type { Codec, CodecArg, Registry, TypeDef } from '@polkadot/types/types'; +import type { CodecArg } from '@polkadot/types/types'; import type { BlueprintOptions, ContractOptions } from './types'; import BN from 'bn.js'; -import { createTypeUnsafe } from '@polkadot/types/create'; import { isBigInt, isBn, isNumber, isString } from '@polkadot/util'; type ContractEvents = 'CodeStored' | 'ContractEmitted' | 'ContractExecution' | 'Instantiated'; type TOptions = BlueprintOptions | ContractOptions; -export function formatData (registry: Registry, data: Raw, { type }: TypeDef): Codec { - return createTypeUnsafe(registry, type, [data], { isPedantic: true }); -} - export function applyOnEvent (result: SubmittableResult, types: ContractEvents[], fn: (records: EventRecord[]) => T): T | undefined { if (result.isInBlock || result.isFinalized) { const records = result.filterRecords('contracts', types); diff --git a/packages/types/src/interfaces/contracts/definitions.ts b/packages/types/src/interfaces/contracts/definitions.ts index 23513969e5..571f6b36b5 100644 --- a/packages/types/src/interfaces/contracts/definitions.ts +++ b/packages/types/src/interfaces/contracts/definitions.ts @@ -133,7 +133,8 @@ export default { }, ContractExecResultOk: { flags: 'u32', - data: 'Bytes' + // only via RPC, decode hex exactly as received + data: 'Raw' }, ContractExecResultResult: { _enum: { diff --git a/packages/types/src/interfaces/contracts/types.ts b/packages/types/src/interfaces/contracts/types.ts index 6f8b080887..52fabb8659 100644 --- a/packages/types/src/interfaces/contracts/types.ts +++ b/packages/types/src/interfaces/contracts/types.ts @@ -56,7 +56,7 @@ export interface ContractExecResultErrModule extends Struct { /** @name ContractExecResultOk */ export interface ContractExecResultOk extends Struct { readonly flags: u32; - readonly data: Bytes; + readonly data: Raw; } /** @name ContractExecResultResult */