Cater for new/old contracts_call results (#2810)

* Cater for new/old contracts_call results

* Update packages/types/src/interfaces/contracts/definitions.ts

* Allow RPC layer to output JSON

* Typing for json outputs

* Convert results

* RPC compat mapping

* Ensure RPC .json is exposed

* Remove compat layer

* Old error detection

* Map to unknown

* Update packages/rpc-core/src/index.ts

* linting
This commit is contained in:
Jaco Greeff
2020-10-31 11:18:58 +01:00
committed by GitHub
parent 2a0e481710
commit e855d5a9d4
11 changed files with 189 additions and 60 deletions
+42 -9
View File
@@ -4,14 +4,14 @@
import { ApiTypes, DecorateMethod } from '@polkadot/api/types';
import { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import { AccountId, ContractExecResult } from '@polkadot/types/interfaces';
import { AnyJson, CodecArg } from '@polkadot/types/types';
import { AnyJson, CodecArg, Registry } from '@polkadot/types/types';
import { AbiMessage, ContractCallOutcome } from '../types';
import { ContractRead, MapMessageExec, MapMessageRead } from './types';
import BN from 'bn.js';
import { map } from 'rxjs/operators';
import ApiBase from '@polkadot/api/base';
import { assert, bnToBn, isFunction, isUndefined, stringCamelCase } from '@polkadot/util';
import { assert, bnToBn, isFunction, isObject, isUndefined, stringCamelCase } from '@polkadot/util';
import Abi from '../Abi';
import { formatData } from '../util';
@@ -19,6 +19,35 @@ import Base from './Base';
const ERROR_NO_CALL = 'Your node does not expose the contracts.call RPC. This is most probably due to a runtime configuration.';
// map from a JSON result to current-style ContractExecResult
function mapExecResult (registry: Registry, json: AnyJson): ContractExecResult {
assert(isObject(json) && !Array.isArray(json), 'Invalid JSON result retrieved');
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 default class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
public readonly address: AccountId;
@@ -80,20 +109,24 @@ export default class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
return {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
send: this._decorateMethod((origin: string | AccountId | Uint8Array) =>
this.api.rx.rpc.contracts.call({
this.api.rx.rpc.contracts.call.json({
dest: this.address,
gasLimit: this.#getGas(gasLimit),
inputData: message.toU8a(params),
origin,
value
}).pipe(
map((result: ContractExecResult): ContractCallOutcome => ({
output: result.isSuccess && message.returnType
? formatData(this.registry, result.asSuccess.data, message.returnType)
}).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
}))
)
};
}))
)
};
}
+6 -2
View File
@@ -2,10 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
import { ApiTypes } from '@polkadot/api/types';
import { ContractExecResult, ContractSelector } from '@polkadot/types/interfaces';
import { ContractExecResultResult, ContractSelector } from '@polkadot/types/interfaces';
import { Codec, CodecArg, TypeDef } from '@polkadot/types/types';
import ApiBase from '@polkadot/api/base';
import { Text, u64 } from '@polkadot/types';
import Abi from './Abi';
export interface ContractBase<ApiType extends ApiTypes> {
@@ -51,8 +53,10 @@ export interface InterfaceContractCalls {
}
export interface ContractCallOutcome {
debugMessage: Text;
gasConsumed: u64;
output: Codec | null;
result: ContractExecResult;
result: ContractExecResultResult;
}
export interface DecodedEvent {