Support for ink! v4 metadata (#5195)

* Support for ink! v4 metadata

* Adjust

* Export v4ToLatest

* Adjust expectations
This commit is contained in:
Jaco
2022-09-02 08:25:12 +03:00
committed by GitHub
parent 8992e7f2e8
commit 79da77234e
12 changed files with 94 additions and 16 deletions
+4 -1
View File
@@ -35,6 +35,9 @@ interface JSONAbi {
},
V3: {
spec: SpecDef;
},
V4: {
spec: SpecDef;
}
}
@@ -59,7 +62,7 @@ describe('Abi', (): void => {
it(`initializes from a contract ABI (${abiName})`, (): void => {
try {
const messageIds = (abi.V3 || abi.V2 || abi.V1 || abi).spec.messages.map(({ label, name }) =>
const messageIds = (abi.V4 || abi.V3 || abi.V2 || abi.V1 || abi).spec.messages.map(({ label, name }) =>
label || (
Array.isArray(name)
? name.join('::')
+14 -3
View File
@@ -27,12 +27,23 @@ function findMessage <T extends AbiMessage> (list: T[], messageOrId: T | string
}
function getLatestMeta (registry: Registry, json: Record<string, unknown>): ContractMetadataLatest {
// this is for V1, V2, V3
const vx = enumVersions.find((v) => isObject(json[v]));
const metadata = registry.createType('ContractMetadata',
// this was added in V4
const jsonVersion = json.version as string;
if (!vx && jsonVersion && !enumVersions.find((v) => v === `V${jsonVersion}`)) {
throw new Error(`Unable to handle version ${jsonVersion}`);
}
const metadata = registry.createType<ContractMetadata>('ContractMetadata',
vx
? { [vx]: json[vx] }
: { V0: json }
) as unknown as ContractMetadata;
: jsonVersion
? { [`V${jsonVersion}`]: json }
: { V0: json }
);
const converter = convertVersions.find(([v]) => metadata[`is${v}`]);
if (!converter) {
+16 -1
View File
@@ -1,10 +1,10 @@
// Copyright 2017-2022 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { v0ToLatest, v1ToLatest, v2ToLatest, v3ToLatest } from '@polkadot/api-contract/Abi/toLatest';
import { TypeRegistry } from '@polkadot/types';
import abis from '../test/contracts';
import { v0ToLatest, v1ToLatest, v2ToLatest, v3ToLatest, v4ToLatest } from './toLatest';
describe('v0ToLatest', (): void => {
const registry = new TypeRegistry();
@@ -120,3 +120,18 @@ describe('v3ToLatest', (): void => {
]);
});
});
describe('v4ToLatest', (): void => {
const registry = new TypeRegistry();
const contract = registry.createType('ContractMetadata', { V4: abis.ink_v4_flipperContract });
const latest = v4ToLatest(registry, contract.asV4);
it('has the correct constructor flags', (): void => {
expect(
latest.spec.constructors[0].payable.isTrue
).toEqual(false);
expect(
latest.spec.constructors[1].payable.isTrue
).toEqual(false);
});
});
+7 -4
View File
@@ -1,16 +1,17 @@
// Copyright 2017-2022 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { ContractMetadataLatest, ContractMetadataV3 } from '@polkadot/types/interfaces';
import type { ContractMetadataLatest, ContractMetadataV4 } from '@polkadot/types/interfaces';
import type { Registry } from '@polkadot/types/types';
import { v0ToV1 } from './toV1';
import { v1ToV2 } from './toV2';
import { v2ToV3 } from './toV3';
import { v3ToV4 } from './toV4';
// The versions where an enum is used, aka V0 is missing
// (Order from newest, i.e. we expect more on newest vs oldest)
export const enumVersions = <const> ['V3', 'V2', 'V1'];
export const enumVersions = <const> ['V4', 'V3', 'V2', 'V1'];
type Versions = typeof enumVersions[number] | 'V0';
@@ -22,15 +23,17 @@ function createConverter <I, O> (next: (registry: Registry, input: O) => Contrac
next(registry, step(registry, input));
}
export function v3ToLatest (registry: Registry, v3: ContractMetadataV3): ContractMetadataLatest {
return v3;
export function v4ToLatest (registry: Registry, v4: ContractMetadataV4): ContractMetadataLatest {
return v4;
}
export const v3ToLatest = createConverter(v4ToLatest, v3ToV4);
export const v2ToLatest = createConverter(v3ToLatest, v2ToV3);
export const v1ToLatest = createConverter(v2ToLatest, v1ToV2);
export const v0ToLatest = createConverter(v1ToLatest, v0ToV1);
export const convertVersions: [Versions, Converter][] = [
['V4', v4ToLatest],
['V3', v3ToLatest],
['V2', v2ToLatest],
['V1', v1ToLatest],
+9
View File
@@ -0,0 +1,9 @@
// Copyright 2017-2022 @polkadot/api-contract authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { ContractMetadataV3, ContractMetadataV4 } from '@polkadot/types/interfaces';
import type { Registry } from '@polkadot/types/types';
export function v3ToV4 (registry: Registry, v3: ContractMetadataV3): ContractMetadataV4 {
return v3;
}
@@ -0,0 +1,9 @@
[
{
"info": "Plain",
"lookupIndex": 0,
"type": "bool",
"docs": [],
"namespace": ""
}
]
@@ -0,0 +1,9 @@
[
{
"info": "Plain",
"lookupIndex": 0,
"type": "bool",
"docs": [],
"namespace": ""
}
]
@@ -6,6 +6,6 @@ import * as v0 from './v0';
import * as v1 from './v1';
import * as v2 from './v2';
import * as v3 from './v3';
// import * as v4 from './v4';
import * as v4 from './v4';
export default createVersionedExport({ v0, v1, v2, v3 });
export default createVersionedExport({ v0, v1, v2, v3, v4 });
@@ -24,7 +24,7 @@ import type { StatementKind } from '@polkadot/types/interfaces/claims';
import type { CollectiveOrigin, MemberCount, ProposalIndex, Votes, VotesTo230 } from '@polkadot/types/interfaces/collective';
import type { AuthorityId, RawVRFOutput } from '@polkadot/types/interfaces/consensus';
import type { AliveContractInfo, CodeHash, CodeSource, CodeUploadRequest, CodeUploadResult, CodeUploadResultValue, ContractCallFlags, ContractCallRequest, ContractExecResult, ContractExecResultOk, ContractExecResultResult, ContractExecResultSuccessTo255, ContractExecResultSuccessTo260, ContractExecResultTo255, ContractExecResultTo260, ContractExecResultTo267, ContractInfo, ContractInstantiateResult, ContractInstantiateResultTo267, ContractInstantiateResultTo299, ContractReturnFlags, ContractStorageKey, DeletedContract, ExecReturnValue, Gas, HostFnWeights, HostFnWeightsTo264, InstantiateRequest, InstantiateRequestV1, InstantiateRequestV2, InstantiateReturnValue, InstantiateReturnValueOk, InstantiateReturnValueTo267, InstructionWeights, Limits, LimitsTo264, PrefabWasmModule, RentProjection, Schedule, ScheduleTo212, ScheduleTo258, ScheduleTo264, SeedOf, StorageDeposit, TombstoneContractInfo, TrieId } from '@polkadot/types/interfaces/contracts';
import type { ContractConstructorSpecLatest, ContractConstructorSpecV0, ContractConstructorSpecV1, ContractConstructorSpecV2, ContractConstructorSpecV3, ContractContractSpecV0, ContractContractSpecV1, ContractContractSpecV2, ContractContractSpecV3, ContractCryptoHasher, ContractDiscriminant, ContractDisplayName, ContractEventParamSpecLatest, ContractEventParamSpecV0, ContractEventParamSpecV2, ContractEventSpecLatest, ContractEventSpecV0, ContractEventSpecV1, ContractEventSpecV2, ContractLayoutArray, ContractLayoutCell, ContractLayoutEnum, ContractLayoutHash, ContractLayoutHashingStrategy, ContractLayoutKey, ContractLayoutStruct, ContractLayoutStructField, ContractMessageParamSpecLatest, ContractMessageParamSpecV0, ContractMessageParamSpecV2, ContractMessageSpecLatest, ContractMessageSpecV0, ContractMessageSpecV1, ContractMessageSpecV2, ContractMetadata, ContractMetadataLatest, ContractMetadataV0, ContractMetadataV1, ContractMetadataV2, ContractMetadataV3, ContractProject, ContractProjectContract, ContractProjectInfo, ContractProjectSource, ContractProjectV0, ContractSelector, ContractStorageLayout, ContractTypeSpec } from '@polkadot/types/interfaces/contractsAbi';
import type { ContractConstructorSpecLatest, ContractConstructorSpecV0, ContractConstructorSpecV1, ContractConstructorSpecV2, ContractConstructorSpecV3, ContractContractSpecV0, ContractContractSpecV1, ContractContractSpecV2, ContractContractSpecV3, ContractContractSpecV4, ContractCryptoHasher, ContractDiscriminant, ContractDisplayName, ContractEventParamSpecLatest, ContractEventParamSpecV0, ContractEventParamSpecV2, ContractEventSpecLatest, ContractEventSpecV0, ContractEventSpecV1, ContractEventSpecV2, ContractLayoutArray, ContractLayoutCell, ContractLayoutEnum, ContractLayoutHash, ContractLayoutHashingStrategy, ContractLayoutKey, ContractLayoutStruct, ContractLayoutStructField, ContractMessageParamSpecLatest, ContractMessageParamSpecV0, ContractMessageParamSpecV2, ContractMessageSpecLatest, ContractMessageSpecV0, ContractMessageSpecV1, ContractMessageSpecV2, ContractMetadata, ContractMetadataLatest, ContractMetadataV0, ContractMetadataV1, ContractMetadataV2, ContractMetadataV3, ContractMetadataV4, ContractProject, ContractProjectContract, ContractProjectInfo, ContractProjectSource, ContractProjectV0, ContractSelector, ContractStorageLayout, ContractTypeSpec } from '@polkadot/types/interfaces/contractsAbi';
import type { FundIndex, FundInfo, LastContribution, TrieIndex } from '@polkadot/types/interfaces/crowdloan';
import type { CollationInfo, CollationInfoV1, ConfigData, MessageId, OverweightIndex, PageCounter, PageIndexData } from '@polkadot/types/interfaces/cumulus';
import type { AccountVote, AccountVoteSplit, AccountVoteStandard, Conviction, Delegations, PreimageStatus, PreimageStatusAvailable, PriorLock, PropIndex, Proposal, ProxyState, ReferendumIndex, ReferendumInfo, ReferendumInfoFinished, ReferendumInfoTo239, ReferendumStatus, Tally, Voting, VotingDelegating, VotingDirect, VotingDirectVote } from '@polkadot/types/interfaces/democracy';
@@ -253,6 +253,7 @@ declare module '@polkadot/types/types/registry' {
ContractContractSpecV1: ContractContractSpecV1;
ContractContractSpecV2: ContractContractSpecV2;
ContractContractSpecV3: ContractContractSpecV3;
ContractContractSpecV4: ContractContractSpecV4;
ContractCryptoHasher: ContractCryptoHasher;
ContractDiscriminant: ContractDiscriminant;
ContractDisplayName: ContractDisplayName;
@@ -296,6 +297,7 @@ declare module '@polkadot/types/types/registry' {
ContractMetadataV1: ContractMetadataV1;
ContractMetadataV2: ContractMetadataV2;
ContractMetadataV3: ContractMetadataV3;
ContractMetadataV4: ContractMetadataV4;
ContractProject: ContractProject;
ContractProjectContract: ContractProjectContract;
ContractProjectInfo: ContractProjectInfo;
@@ -106,6 +106,7 @@ const spec = {
events: 'Vec<ContractEventSpecV2>',
docs: 'Vec<Text>'
},
ContractContractSpecV4: 'ContractContractSpecV3',
ContractDisplayName: 'SiPath',
ContractEventParamSpecV0: {
name: 'Text',
@@ -197,6 +198,8 @@ const ContractMetadataV3 = {
spec: 'ContractContractSpecV3'
};
const ContractMetadataV4 = ContractMetadataV3;
const ContractProjectInfo = {
source: 'ContractProjectSource',
contract: 'ContractProjectContract'
@@ -208,7 +211,7 @@ const latest = {
ContractEventParamSpecLatest: 'ContractEventParamSpecV2',
ContractMessageParamSpecLatest: 'ContractMessageParamSpecV2',
ContractMessageSpecLatest: 'ContractMessageSpecV2',
ContractMetadataLatest: 'ContractMetadataV3'
ContractMetadataLatest: 'ContractMetadataV4'
};
export default {
@@ -219,12 +222,14 @@ export default {
ContractMetadataV1,
ContractMetadataV2,
ContractMetadataV3,
ContractMetadataV4,
ContractMetadata: {
_enum: {
V0: 'ContractMetadataV0',
V1: 'ContractMetadataV1',
V2: 'ContractMetadataV2',
V3: 'ContractMetadataV3'
V3: 'ContractMetadataV3',
V4: 'ContractMetadataV4'
}
},
ContractProjectV0: objectSpread({ metadataVersion: 'Text' }, ContractProjectInfo, ContractMetadataV0),
@@ -74,6 +74,9 @@ export interface ContractContractSpecV3 extends Struct {
readonly docs: Vec<Text>;
}
/** @name ContractContractSpecV4 */
export interface ContractContractSpecV4 extends ContractContractSpecV3 {}
/** @name ContractCryptoHasher */
export interface ContractCryptoHasher extends Enum {
readonly isBlake2x256: boolean;
@@ -240,11 +243,13 @@ export interface ContractMetadata extends Enum {
readonly asV2: ContractMetadataV2;
readonly isV3: boolean;
readonly asV3: ContractMetadataV3;
readonly type: 'V0' | 'V1' | 'V2' | 'V3';
readonly isV4: boolean;
readonly asV4: ContractMetadataV4;
readonly type: 'V0' | 'V1' | 'V2' | 'V3' | 'V4';
}
/** @name ContractMetadataLatest */
export interface ContractMetadataLatest extends ContractMetadataV3 {}
export interface ContractMetadataLatest extends ContractMetadataV4 {}
/** @name ContractMetadataV0 */
export interface ContractMetadataV0 extends Struct {
@@ -271,6 +276,12 @@ export interface ContractMetadataV3 extends Struct {
readonly spec: ContractContractSpecV3;
}
/** @name ContractMetadataV4 */
export interface ContractMetadataV4 extends Struct {
readonly types: Vec<PortableType>;
readonly spec: ContractContractSpecV3;
}
/** @name ContractProject */
export interface ContractProject extends ITuple<[ContractProjectInfo, ContractMetadata]> {}