Expose instantiate on contract Blueprint (#2706)

* Expose instantiate on contract Blueprint

* Allow BigInt & string types

* CodecArg

* Selector

* Cleanup selectors

* Remove Bytes override
This commit is contained in:
Jaco Greeff
2020-10-11 18:51:21 +02:00
committed by GitHub
parent 4cb563ba89
commit af0b4362c9
7 changed files with 97 additions and 111 deletions
+10 -8
View File
@@ -2,20 +2,20 @@
// SPDX-License-Identifier: Apache-2.0
import { ApiTypes, DecorateMethod, SignerOptions } from '@polkadot/api/types';
import { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import { AccountId, EventRecord, Hash } from '@polkadot/types/interfaces';
import { AnyJson, IKeyringPair, ISubmittableResult } from '@polkadot/types/types';
import { ApiObject } from '../types';
import { AnyJson, CodecArg, IKeyringPair, ISubmittableResult } from '@polkadot/types/types';
import { AbiConstructor, ApiObject } from '../types';
import BN from 'bn.js';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { SubmittableResult } from '@polkadot/api';
import { assert } from '@polkadot/util';
import Abi from '../Abi';
import { applyOnEvent, encodeMessage } from '../util';
import Base from './Base';
import Contract from './Contract';
import { applyOnEvent } from './util';
// eslint-disable-next-line no-use-before-define
type BlueprintCreateResultSubscription<ApiType extends ApiTypes> = Observable<BlueprintCreateResult<ApiType>>;
@@ -38,21 +38,23 @@ class BlueprintCreateResult<ApiType extends ApiTypes> extends SubmittableResult
export default class Blueprint<ApiType extends ApiTypes> extends Base<ApiType> {
public readonly codeHash: Hash;
constructor (api: ApiObject<ApiType>, abi: AnyJson | Abi, decorateMethod: DecorateMethod<ApiType>, codeHash: string | Hash) {
constructor (api: ApiObject<ApiType>, abi: AnyJson | Abi, decorateMethod: DecorateMethod<ApiType>, codeHash: string | Hash | Uint8Array) {
super(api, abi, decorateMethod);
this.codeHash = this.registry.createType('Hash', codeHash);
}
public deployContract (constructorIndex = 0, endowment: number | BN, maxGas: number | BN, ...params: any[]): BlueprintCreate<ApiType> {
assert(!!this.abi.constructors[constructorIndex], `Specified constructor index ${constructorIndex} does not exist`);
public instantiate (constructorOrIndex: AbiConstructor | number, endowment: BigInt | string | number | BN, gasLimit: BigInt | string | number | BN, ...params: CodecArg[]): SubmittableExtrinsic<ApiType> {
return this.api.tx.contracts.instantiate(endowment, gasLimit, this.codeHash, encodeMessage(this.registry, this.abi.findConstructor(constructorOrIndex), params)) as SubmittableExtrinsic<ApiType>;
}
public createContract (constructorOrIndex: AbiConstructor | number, endowment: BigInt | string | number | BN, gasLimit: BigInt | string | number | BN, ...params: CodecArg[]): BlueprintCreate<ApiType> {
return {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
signAndSend: this._decorateMethod(
(account: IKeyringPair | string | AccountId, options?: SignerOptions): BlueprintCreateResultSubscription<ApiType> =>
this.api.rx.tx.contracts
.create(endowment, maxGas, this.codeHash, this.abi.constructors[constructorIndex](...params))
.instantiate(endowment, gasLimit, this.codeHash, encodeMessage(this.registry, this.abi.findConstructor(constructorOrIndex), params))
.signAndSend(account, options)
.pipe(
map((result) =>
+1 -1
View File
@@ -12,9 +12,9 @@ import { SubmittableResult } from '@polkadot/api';
import { compactAddLength, u8aToU8a } from '@polkadot/util';
import Abi from '../Abi';
import { applyOnEvent } from '../util';
import Base from './Base';
import Blueprint from './Blueprint';
import { applyOnEvent } from './util';
// eslint-disable-next-line no-use-before-define
type CodePutCodeResultSubscription<ApiType extends ApiTypes> = Observable<CodePutCodeResult<ApiType>>;
+15 -32
View File
@@ -3,7 +3,6 @@
import { ApiTypes, DecorateMethod, ObsInnerType } from '@polkadot/api/types';
import { SubmittableExtrinsic } from '@polkadot/api/submittable/types';
import { AccountId, ContractExecResult } from '@polkadot/types/interfaces';
import { AnyJson, CodecArg, IKeyringPair } from '@polkadot/types/types';
import { ApiObject, AbiMessage, ContractCallOutcome } from '../types';
@@ -12,10 +11,10 @@ import BN from 'bn.js';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { SubmittableResult } from '@polkadot/api';
import { assert, isFunction, isNumber } from '@polkadot/util';
import { assert, isFunction } from '@polkadot/util';
import Abi from '../Abi';
import { formatData } from '../util';
import { encodeMessage, formatData } from '../util';
import Base from './Base';
type ContractCallTypes = 'tx' | 'rpc';
@@ -47,44 +46,28 @@ export default class Contract<ApiType extends ApiTypes> extends Base<ApiType> {
return isFunction(this.api.rx.rpc.contracts?.call);
}
private _createInput (message: AbiMessage | number, params: CodecArg[]): [Uint8Array, AbiMessage] {
const fn = isNumber(message)
? this.abi.messages[message]
: message;
assert(fn, 'Attempted to call an invalid contract message');
return [fn(...params), fn];
public exec (messageOrIndex: AbiMessage | number, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]): SubmittableExtrinsic<ApiType> {
return this.api.tx.contracts.call(this.address, value, gasLimit, encodeMessage(this.registry, this.abi.findMessage(messageOrIndex), params)) as SubmittableExtrinsic<ApiType>;
}
public exec = (message: AbiMessage | number, value: BN | string | number, gasLimit: BN | string | number, ...params: CodecArg[]): SubmittableExtrinsic<ApiType> => {
const [inputData] = this._createInput(message, params);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore I give up
return this.api.tx.contracts.call(this.address, value, gasLimit, inputData);
}
public read = (message: AbiMessage | number, value: BN | string | number, gasLimit: BN | string | number, ...params: CodecArg[]): ContractRead<ApiType> => {
public read (messageOrIndex: AbiMessage | number, value: BigInt | BN | string | number, gasLimit: BigInt | BN | string | number, ...params: CodecArg[]): ContractRead<ApiType> {
assert(this.hasRpcContractsCall, 'Your node does not support contract RPC read calls');
const [inputData, messageFn] = this._createInput(message, params);
const message = this.abi.findMessage(messageOrIndex);
return {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
send: this._decorateMethod((account: IKeyringPair | string | AccountId): ContractCallResult<'rpc'> =>
this.api.rx.rpc.contracts.call(
this.registry.createType('ContractCallRequest', {
dest: this.address,
gasLimit,
inputData,
origin: account,
value
})
).pipe(
this.api.rx.rpc.contracts.call({
dest: this.address,
gasLimit,
inputData: encodeMessage(this.registry, message, params),
origin: account,
value
}).pipe(
map((result: ContractExecResult): ContractCallOutcome => ({
output: result.isSuccess && messageFn.returnType
? formatData(this.registry, result.asSuccess.data, messageFn.returnType)
output: result.isSuccess && message.returnType
? formatData(this.registry, result.asSuccess.data, message.returnType)
: null,
result
}))
-17
View File
@@ -1,17 +0,0 @@
// Copyright 2017-2020 @polkadot/api authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { SubmittableResult } from '@polkadot/api';
import { EventRecord } from '@polkadot/types/interfaces';
export function applyOnEvent <T> (result: SubmittableResult, type: 'CodeStored' | 'Instantiated', fn: (record: EventRecord) => T): T | undefined {
if (result.isInBlock || result.isFinalized) {
const record = result.findRecord('contract', 'CodeStored');
if (record) {
return fn(record);
}
}
return undefined;
}