Contract ABI (extended)

This commit is contained in:
Jaco Greeff
2019-05-27 15:45:50 +12:00
committed by ian.he
parent 73a184ec7d
commit ac5bfeda39
4 changed files with 124 additions and 63 deletions
Binary file not shown.
+44
View File
@@ -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"
}
]
}
+65 -50
View File
@@ -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']
);
});
});
});
+15 -13
View File
@@ -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);