Contract ABI (extended)
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "Incrementer",
|
||||
"deploy": {
|
||||
"args": [
|
||||
{
|
||||
"name": "init_value",
|
||||
"type": "u32"
|
||||
}
|
||||
]
|
||||
},
|
||||
"messages": [
|
||||
{
|
||||
"name": "inc",
|
||||
"selector": 257544423,
|
||||
"mutates": true,
|
||||
"args": [
|
||||
{
|
||||
"name": "by",
|
||||
"type": "u32"
|
||||
}
|
||||
],
|
||||
"return_type": null
|
||||
},
|
||||
{
|
||||
"name": "get",
|
||||
"selector": 4266279973,
|
||||
"mutates": false,
|
||||
"args": [],
|
||||
"return_type": "u32"
|
||||
},
|
||||
{
|
||||
"name": "compare",
|
||||
"selector": 363906316,
|
||||
"mutates": false,
|
||||
"args": [
|
||||
{
|
||||
"name": "with",
|
||||
"type": "u32"
|
||||
}
|
||||
],
|
||||
"return_type": "bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -8,21 +8,20 @@ import path from 'path';
|
||||
import { ContractAbi } from '@plugnet/types';
|
||||
import testingPairs from '@plugnet/keyring/testingPairs';
|
||||
|
||||
import json from '../data/erc20.json';
|
||||
import incrementer from '../data/incrementer.json';
|
||||
import erc20 from '../data/erc20.json';
|
||||
import Api from '../../src/promise';
|
||||
|
||||
describe.skip('e2e contracts', () => {
|
||||
let address;
|
||||
let codeHash;
|
||||
let keyring;
|
||||
let abi;
|
||||
let api;
|
||||
|
||||
beforeEach(async (done) => {
|
||||
if (!api) {
|
||||
api = await Api.create();
|
||||
|
||||
abi = new ContractAbi(json);
|
||||
keyring = testingPairs({ type: 'sr25519' });
|
||||
}
|
||||
|
||||
@@ -30,63 +29,79 @@ describe.skip('e2e contracts', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
it('has the attached methods', () => {
|
||||
expect(Object.keys(abi.messages)).toEqual(
|
||||
['totalSupply', 'balanceOf', 'allowance', 'transfer', 'approve', 'transferFrom']
|
||||
);
|
||||
});
|
||||
describe('incrementer', () => {
|
||||
let abi;
|
||||
|
||||
it('allows putCode', (done) => {
|
||||
const code = fs.readFileSync(path.join(__dirname, '../data/erc20.wasm')).toString('hex');
|
||||
beforeAll(() => {
|
||||
abi = new ContractAbi(incrementer);
|
||||
});
|
||||
|
||||
api.tx.contract
|
||||
.putCode(200000, `0x${code}`)
|
||||
.signAndSend(keyring.eve, (result) => {
|
||||
console.error('putCode', JSON.stringify(result));
|
||||
it('allows putCode', (done) => {
|
||||
const code = fs.readFileSync(path.join(__dirname, '../data/incrementer-opt.wasm')).toString('hex');
|
||||
|
||||
if (result.status.isFinalized) {
|
||||
const record = result.findRecord('contract', 'CodeStored');
|
||||
api.tx.contract
|
||||
.putCode(200000, `0x${code}`)
|
||||
.signAndSend(keyring.eve, (result) => {
|
||||
console.error('putCode', JSON.stringify(result));
|
||||
|
||||
if (record) {
|
||||
codeHash = record.event.data[0];
|
||||
if (result.status.isFinalized) {
|
||||
const record = result.findRecord('contract', 'CodeStored');
|
||||
|
||||
if (record) {
|
||||
codeHash = record.event.data[0];
|
||||
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('allows contract create', (done) => {
|
||||
expect(codeHash).toBeDefined();
|
||||
|
||||
api.tx.contract
|
||||
.create(12345, 500000, codeHash, abi.deploy(12345))
|
||||
.signAndSend(keyring.bob, (result) => {
|
||||
console.error('create', JSON.stringify(result));
|
||||
|
||||
if (result.status.isFinalized) {
|
||||
const record = result.findRecord('contract', 'Instantiated');
|
||||
|
||||
if (record) {
|
||||
address = record.event.data[1];
|
||||
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('allows contract call', (done) => {
|
||||
expect(address).toBeDefined();
|
||||
|
||||
api.tx.contract
|
||||
.call(address, 12345, 500000, abi.messages.inc(123))
|
||||
.signAndSend(keyring.bob, (result) => {
|
||||
console.error('call', JSON.stringify(result));
|
||||
|
||||
if (result.status.isFinalized && result.findRecord('system', 'ExtrinsicSuccess')) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('allows contract create', (done) => {
|
||||
expect(codeHash).toBeDefined();
|
||||
describe('erc20', () => {
|
||||
let abi;
|
||||
|
||||
api.tx.contract
|
||||
.create(1234, 12345, codeHash, abi.deploy(12345))
|
||||
.signAndSend(keyring.bob, (result) => {
|
||||
console.error('create', JSON.stringify(result));
|
||||
beforeAll(() => {
|
||||
abi = abi = new ContractAbi(erc20);
|
||||
});
|
||||
|
||||
if (result.status.isFinalized) {
|
||||
const record = result.findRecord('contract', 'Instantiated');
|
||||
|
||||
if (record) {
|
||||
address = record.event.data[1];
|
||||
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('allows contract call', (done) => {
|
||||
expect(address).toBeDefined();
|
||||
|
||||
api.tx.contract
|
||||
.call(address, 123, 12345, abi.messages.balanceOf(keyring.alice.address()))
|
||||
.signAndSend(keyring.bob, (result) => {
|
||||
console.error('call', JSON.stringify(result));
|
||||
|
||||
if (result.status.isFinalized && result.findRecord('system', 'ExtrinsicSuccess')) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
it('has the attached methods', () => {
|
||||
expect(Object.keys(abi.messages)).toEqual(
|
||||
['totalSupply', 'balanceOf', 'allowance', 'transfer', 'approve', 'transferFrom']
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import { CodecArg, Constructor } from './types';
|
||||
|
||||
import { assert, isNumber, isNull, isString, isUndefined, stringCamelCase } from '@plugnet/util';
|
||||
import { assert, isNumber, isNull, isString, isUndefined, stringCamelCase, u8aToHex } from '@plugnet/util';
|
||||
|
||||
import Compact from './codec/Compact';
|
||||
import { createClass } from './codec/createType';
|
||||
@@ -104,14 +104,14 @@ export default class ContractAbi implements Contract {
|
||||
});
|
||||
}
|
||||
|
||||
private _createClazz (args: ContractABIArgs, isDeploy: boolean): Constructor {
|
||||
private _createClazz (args: ContractABIArgs, baseDef: { [index: string]: string }): Constructor {
|
||||
return createClass(
|
||||
JSON.stringify(
|
||||
args.reduce((base: { [index: string]: string }, { name, type }) => {
|
||||
base[name] = type;
|
||||
|
||||
return base;
|
||||
}, isDeploy ? {} : { __selector: 'u32' })
|
||||
}, baseDef)
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -121,20 +121,22 @@ export default class ContractAbi implements Contract {
|
||||
name: stringCamelCase(name),
|
||||
type
|
||||
}));
|
||||
const Clazz = this._createClazz(args, isUndefined(method.selector));
|
||||
const base: { [index: string]: any } = { __selector: method.selector };
|
||||
const Clazz = this._createClazz(args, isUndefined(method.selector) ? {} : { __selector: 'u32' });
|
||||
const baseStruct: { [index: string]: any } = { __selector: method.selector };
|
||||
const encoder = (...params: Array<CodecArg>): Uint8Array => {
|
||||
assert(params.length === args.length, `Expected ${args.length} arguments to contract ${name}, found ${params.length}`);
|
||||
|
||||
return Compact.addLengthPrefix(
|
||||
new Clazz(
|
||||
args.reduce((mapped, { name }, index) => {
|
||||
mapped[name] = params[index];
|
||||
const u8a = new Clazz(
|
||||
args.reduce((mapped, { name }, index) => {
|
||||
mapped[name] = params[index];
|
||||
|
||||
return mapped;
|
||||
}, { ...base })
|
||||
).toU8a()
|
||||
);
|
||||
return mapped;
|
||||
}, { ...baseStruct })
|
||||
).toU8a();
|
||||
|
||||
console.error('hexToU8a(encoded)', u8aToHex(u8a));
|
||||
|
||||
return Compact.addLengthPrefix(u8a);
|
||||
};
|
||||
|
||||
const fn = (encoder as ContractABIFn);
|
||||
|
||||
Reference in New Issue
Block a user