Skip to content

Commit

Permalink
adds testcases for decoding payload data of a ink!v4 and ink!v5 event
Browse files Browse the repository at this point in the history
  • Loading branch information
peetzweg committed Feb 23, 2024
1 parent cc946da commit 54fd609
Show file tree
Hide file tree
Showing 18 changed files with 3,204 additions and 1,049 deletions.
66 changes: 66 additions & 0 deletions packages/api-contract/src/Abi/Abi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import fs from 'node:fs';
import process from 'node:process';

import { TypeDefInfo } from '@polkadot/types/types';
import { hexToU8a } from '@polkadot/util';
import { blake2AsHex } from '@polkadot/util-crypto';

import abis from '../test/contracts/index.js';
Expand Down Expand Up @@ -122,4 +123,69 @@ describe('Abi', (): void => {
// the hash as per the actual Abi
expect(bundle.source.hash).toEqual(abi.info.source.wasmHash.toHex());
});

it('decoding <=ink!v4 events', (): void => {
const abi = new Abi(abis['ink_v4_erc20Metadata']);

const dataHex = '0x0001d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d018eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a4800505a4f7e9f4eb10600000000000000';
const dataU8A = hexToU8a(dataHex);

const decodedEvent = abi.decodeEvent(dataU8A);

expect(decodedEvent.event.args.length).toEqual(3);
expect(decodedEvent.args.length).toEqual(3);
expect(decodedEvent.event.identifier).toEqual('Transfer');

const decodedEventHuman = decodedEvent.event.args.reduce((prev, cur, index) => {
return {
...prev,
[cur.name]: decodedEvent.args[index].toHuman()
};
}, {});

const expectedEvent = {
from: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
to: '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty',
value: '123.4567 MUnit'
};

expect(decodedEventHuman).toEqual(expectedEvent);
});

it('decoding <=ink!v5 events', (): void => {
const metadataJson = abis['ink_v5_erc20Metadata'];

expect(metadataJson).toBeDefined();
const abi = new Abi(metadataJson);

const dataHex = '0x01d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d018eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a4800505a4f7e9f4eb10600000000000000';
const dataU8A = hexToU8a(dataHex);

const signatureTopicHex = '0xb5b61a3e6a21a16be4f044b517c28ac692492f73c5bfd3f60178ad98c767f4cb';

expect(abi.events.length).toEqual(2);
expect(abi.events[0].signatureTopic).toEqual(signatureTopicHex);

const signatureTopicHash = abi.registry.createType('Hash', signatureTopicHex);
const decodedEvent = abi.decodeEvent(dataU8A, signatureTopicHash);

expect(decodedEvent.event.args.length).toEqual(3);
expect(decodedEvent.args.length).toEqual(3);
expect(decodedEvent.event.identifier).toEqual('erc20::erc20::Transfer');

const decodedEventHuman = decodedEvent.event.args.reduce((prev, cur, index) => {
return {
...prev,
[cur.name]: decodedEvent.args[index].toHuman()
};
}, {});

const expectedEvent = {
from: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
to: '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty',
value: '123.4567 MUnit'
};

expect(decodedEventHuman).toEqual(expectedEvent);
});
});
38 changes: 21 additions & 17 deletions packages/api-contract/src/Abi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
// SPDX-License-Identifier: Apache-2.0

import type { Bytes } from '@polkadot/types';
import { Option, TypeRegistry } from '@polkadot/types';
import { TypeDefInfo } from '@polkadot/types-create';
import type { ChainProperties, ContractConstructorSpecLatest, ContractEventSpecLatest, ContractMessageParamSpecLatest, ContractMessageSpecLatest, ContractMetadata, ContractMetadataLatest, ContractProjectInfo, ContractTypeSpec } from '@polkadot/types/interfaces';
import type { Hash } from '@polkadot/types/interfaces/runtime';
import type { Codec, Registry, TypeDef } from '@polkadot/types/types';
import { assertReturn, compactAddLength, compactStripLength, isBn, isNumber, isObject, isString, isUndefined, logger, stringCamelCase, stringify, u8aConcat, u8aToHex } from '@polkadot/util';
import type { AbiConstructor, AbiEvent, AbiMessage, AbiParam, DecodedEvent, DecodedMessage } from '../types.js';

import { Option, TypeRegistry } from '@polkadot/types';
import { TypeDefInfo } from '@polkadot/types-create';
import { assertReturn, compactAddLength, compactStripLength, isBn, isNumber, isObject, isString, isUndefined, logger, stringCamelCase, stringify, u8aConcat, u8aToHex } from '@polkadot/util';

import { convertVersions, enumVersions } from './toLatest.js';

interface AbiJson {
Expand Down Expand Up @@ -162,24 +163,27 @@ export class Abi {
/**
* Warning: Unstable API, bound to change
*/
public decodeEvent (data: Bytes | Uint8Array, signatureTopic: Hash): DecodedEvent {
// try to find a topic signature match - ink! v5 upwards
let event = this.events.find((e) => e.signatureTopic === signatureTopic.toHex());

if (event) {
return event.fromU8a(data.subarray(0));
}
public decodeEvent (data: Bytes | Uint8Array, signatureTopic?: Hash): DecodedEvent {
if (signatureTopic !== undefined) {
const event = this.events.find((e) => e.signatureTopic !== undefined && e.signatureTopic === signatureTopic.toHex());

if (event) {
return event.fromU8a(data.subarray(0));
} else {
throw new Error(`Unable to find event with signature_topic ${signatureTopic.toHex()}`);
}
} else {
// otherwise fallback to using the index to determine event - ink! v4 downwards
const index = data[0];
const index = data[0];

event = this.events[index];
const event = this.events[index];

if (!event) {
throw new Error(`Unable to find event with index ${index}`);
}
if (!event) {
throw new Error(`Unable to find event with index ${index}`);
}

return event.fromU8a(data.subarray(1));
return event.fromU8a(data.subarray(1));
}
}

/**
Expand Down Expand Up @@ -252,7 +256,7 @@ export class Abi {
args: this.#decodeArgs(args, data),
event
}),
identifier: [spec.module_path, spec.label.toString()].join('::'),
identifier: [spec.module_path, spec.label].filter((t) => !t.isEmpty).join('::'),
index,
signatureTopic: spec.signature_topic.toHex() || undefined
};
Expand Down
16 changes: 15 additions & 1 deletion packages/api-contract/src/Abi/toLatest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,16 +140,30 @@ describe('v4ToLatest', (): void => {

describe('v5ToLatest', (): void => {
const registry = new TypeRegistry();
const contract = registry.createType('ContractMetadata', { V5: abis['ink_v5_erc20'] });
const contract = registry.createType('ContractMetadata', { V5: abis['ink_v5_erc20Metadata'] });
const latest = v5ToLatest(registry, contract.asV5);

it('has the correct messages', (): void => {
expect(
latest.spec.messages.map(({ label }) => label.toString())
).toEqual(['total_supply', 'balance_of', 'allowance', 'transfer', 'approve', 'transfer_from']);
});

it('has new event fields', (): void => {
expect(
latest.spec.events.length
).toEqual(2);

expect(
latest.spec.events.every((e) => e.has('module_path'))
).toEqual(true);

expect(latest.spec.events[0].module_path.toString()).toEqual('erc20::erc20');

expect(
latest.spec.events.every((e) => e.has('signature_topic'))
).toEqual(true);

expect(latest.spec.events[0].signature_topic.toHex()).toEqual('0xb5b61a3e6a21a16be4f044b517c28ac692492f73c5bfd3f60178ad98c767f4cb');
});
});
Loading

0 comments on commit 54fd609

Please sign in to comment.