Add suport for latest ink! metadata (#5650)

* add v5

* add environment

* tov5

* use correct version

* decode env types

* fix tests

* remove unnecesary checks

* update fixtures

* add maxEventTopics

* get type defs for environment

* fix conversion to v4
This commit is contained in:
Andreea Eftene
2023-05-29 20:19:55 +03:00
committed by GitHub
parent 2f07e1c45f
commit 0be50b285b
11 changed files with 741 additions and 139 deletions
+28 -5
View File
@@ -3,7 +3,7 @@
import type { Bytes } from '@polkadot/types';
import type { ChainProperties, ContractConstructorSpecLatest, ContractEventSpecLatest, ContractMessageParamSpecLatest, ContractMessageSpecLatest, ContractMetadata, ContractMetadataLatest, ContractProjectInfo } from '@polkadot/types/interfaces';
import type { Codec, Registry } from '@polkadot/types/types';
import type { Codec, Registry, TypeDef } from '@polkadot/types/types';
import type { AbiConstructor, AbiEvent, AbiMessage, AbiParam, DecodedEvent, DecodedMessage } from '../types.js';
import { TypeRegistry } from '@polkadot/types';
@@ -82,6 +82,7 @@ export class Abi {
readonly messages: AbiMessage[];
readonly metadata: ContractMetadataLatest;
readonly registry: Registry;
readonly environment: Map<string, TypeDef | number> = new Map();
constructor (abiJson: Record<string, unknown> | string, chainProperties?: ChainProperties) {
[this.json, this.registry, this.metadata, this.info] = parseJson(
@@ -90,11 +91,18 @@ export class Abi {
: abiJson,
chainProperties
);
this.constructors = this.metadata.spec.constructors.map((spec: ContractConstructorSpecLatest, index) =>
this.#createMessage(spec, index, {
this.constructors = this.metadata.spec.constructors.map((spec: ContractConstructorSpecLatest, index) => {
const typeSpec = spec.returnType.unwrapOr(null);
return this.#createMessage(spec, index, {
isConstructor: true,
isPayable: spec.payable.isTrue
})
isDefault: spec.default.isTrue,
isPayable: spec.payable.isTrue,
returnType: typeSpec
? this.registry.lookup.getTypeDef(typeSpec.type)
: null
});
}
);
this.events = this.metadata.spec.events.map((spec: ContractEventSpecLatest, index) =>
this.#createEvent(spec, index)
@@ -103,6 +111,7 @@ export class Abi {
const typeSpec = spec.returnType.unwrapOr(null);
return this.#createMessage(spec, index, {
isDefault: spec.default.isTrue,
isMutating: spec.mutates.isTrue,
isPayable: spec.payable.isTrue,
returnType: typeSpec
@@ -110,6 +119,19 @@ export class Abi {
: null
});
});
const rawEnv = this.metadata.spec.environment.unwrapOr(null);
if (rawEnv) {
for (const [key, value] of rawEnv.entries()) {
const typeSpec = value.toPrimitive();
if (typeof typeSpec === 'object' && typeSpec !== null && 'type' in typeSpec) {
this.environment.set(key, this.registry.lookup.getTypeDef(typeSpec.type as number));
} else {
this.environment.set(key, typeSpec as number);
}
}
}
}
/**
@@ -215,6 +237,7 @@ export class Abi {
}),
identifier,
index,
isDefault: spec.default.isTrue,
method: stringCamelCase(identifier),
path: identifier.split('::').map((s) => stringCamelCase(s)),
selector: spec.selector,
+13 -2
View File
@@ -4,6 +4,17 @@
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;
import { objectSpread } from '@polkadot/util';
export function v3ToV4 (registry: Registry, v3: ContractMetadataV3): ContractMetadataV4 {
return registry.createType('ContractMetadataV4', objectSpread({}, v3, {
spec: objectSpread({}, v3.spec, {
constructors: v3.spec.constructors.map((c) =>
registry.createType('ContractConstructorSpecV4', objectSpread({}, c))
),
messages: v3.spec.messages.map((m) =>
registry.createType('ContractMessageSpecV3', objectSpread({}, m))
)
})
}));
}
@@ -5,5 +5,151 @@
"type": "bool",
"docs": [],
"namespace": ""
},
{
"info": "Result",
"lookupIndex": 1,
"type": "Result<Null, InkPrimitivesLangError>",
"docs": [],
"namespace": "Result",
"sub": [
{
"name": "Ok",
"info": "Null",
"lookupIndex": 2,
"type": "Null",
"docs": [],
"namespace": ""
},
{
"name": "Error",
"docs": [],
"info": "Si",
"lookupIndex": 3,
"lookupName": "InkPrimitivesLangError",
"type": "Lookup3"
}
]
},
{
"info": "Null",
"lookupIndex": 2,
"type": "Null",
"docs": [],
"namespace": ""
},
{
"info": "Enum",
"lookupIndex": 3,
"lookupName": "InkPrimitivesLangError",
"type": "{\"_enum\":[\"__Unused0\",\"CouldNotReadInput\"]}",
"docs": [],
"namespace": "ink_primitives::LangError",
"sub": [
{
"index": 0,
"info": "Null",
"name": "__Unused0",
"type": "Null"
},
{
"info": "Null",
"type": "Null",
"index": 1,
"name": "CouldNotReadInput"
}
]
},
{
"info": "Result",
"lookupIndex": 4,
"type": "Result<bool, InkPrimitivesLangError>",
"docs": [],
"namespace": "Result",
"sub": [
{
"name": "Ok",
"info": "Plain",
"lookupIndex": 0,
"type": "bool",
"docs": [],
"namespace": ""
},
{
"name": "Error",
"docs": [],
"info": "Si",
"lookupIndex": 3,
"lookupName": "InkPrimitivesLangError",
"type": "Lookup3"
}
]
},
{
"info": "Plain",
"lookupIndex": 5,
"type": "AccountId",
"docs": [],
"namespace": "ink_primitives::types::AccountId",
"lookupNameRoot": "InkPrimitivesAccountId"
},
{
"info": "VecFixed",
"lookupIndex": 6,
"type": "[u8;32]",
"docs": [],
"namespace": "",
"length": 32,
"sub": {
"info": "Plain",
"lookupIndex": 7,
"type": "u8",
"docs": [],
"namespace": ""
}
},
{
"info": "Plain",
"lookupIndex": 7,
"type": "u8",
"docs": [],
"namespace": ""
},
{
"info": "Plain",
"lookupIndex": 8,
"type": "u128",
"docs": [],
"namespace": ""
},
{
"info": "Plain",
"lookupIndex": 9,
"type": "Hash",
"docs": [],
"namespace": "ink_primitives::types::Hash",
"lookupNameRoot": "InkPrimitivesHash"
},
{
"info": "Plain",
"lookupIndex": 10,
"type": "u64",
"docs": [],
"namespace": ""
},
{
"info": "Plain",
"lookupIndex": 11,
"type": "u32",
"docs": [],
"namespace": ""
},
{
"info": "Plain",
"lookupIndex": 12,
"type": "NoChainExtension",
"docs": [],
"namespace": "ink_env::types::NoChainExtension",
"lookupNameRoot": "InkEnvNoChainExtension"
}
]
@@ -5,5 +5,151 @@
"type": "bool",
"docs": [],
"namespace": ""
},
{
"info": "Result",
"lookupIndex": 1,
"type": "Result<Null, InkPrimitivesLangError>",
"docs": [],
"namespace": "Result",
"sub": [
{
"name": "Ok",
"info": "Null",
"lookupIndex": 2,
"type": "Null",
"docs": [],
"namespace": ""
},
{
"name": "Error",
"docs": [],
"info": "Si",
"lookupIndex": 3,
"lookupName": "InkPrimitivesLangError",
"type": "Lookup3"
}
]
},
{
"info": "Null",
"lookupIndex": 2,
"type": "Null",
"docs": [],
"namespace": ""
},
{
"info": "Enum",
"lookupIndex": 3,
"lookupName": "InkPrimitivesLangError",
"type": "{\"_enum\":[\"__Unused0\",\"CouldNotReadInput\"]}",
"docs": [],
"namespace": "ink_primitives::LangError",
"sub": [
{
"index": 0,
"info": "Null",
"name": "__Unused0",
"type": "Null"
},
{
"info": "Null",
"type": "Null",
"index": 1,
"name": "CouldNotReadInput"
}
]
},
{
"info": "Result",
"lookupIndex": 4,
"type": "Result<bool, InkPrimitivesLangError>",
"docs": [],
"namespace": "Result",
"sub": [
{
"name": "Ok",
"info": "Plain",
"lookupIndex": 0,
"type": "bool",
"docs": [],
"namespace": ""
},
{
"name": "Error",
"docs": [],
"info": "Si",
"lookupIndex": 3,
"lookupName": "InkPrimitivesLangError",
"type": "Lookup3"
}
]
},
{
"info": "Plain",
"lookupIndex": 5,
"type": "AccountId",
"docs": [],
"namespace": "ink_primitives::types::AccountId",
"lookupNameRoot": "InkPrimitivesAccountId"
},
{
"info": "VecFixed",
"lookupIndex": 6,
"type": "[u8;32]",
"docs": [],
"namespace": "",
"length": 32,
"sub": {
"info": "Plain",
"lookupIndex": 7,
"type": "u8",
"docs": [],
"namespace": ""
}
},
{
"info": "Plain",
"lookupIndex": 7,
"type": "u8",
"docs": [],
"namespace": ""
},
{
"info": "Plain",
"lookupIndex": 8,
"type": "u128",
"docs": [],
"namespace": ""
},
{
"info": "Plain",
"lookupIndex": 9,
"type": "Hash",
"docs": [],
"namespace": "ink_primitives::types::Hash",
"lookupNameRoot": "InkPrimitivesHash"
},
{
"info": "Plain",
"lookupIndex": 10,
"type": "u64",
"docs": [],
"namespace": ""
},
{
"info": "Plain",
"lookupIndex": 11,
"type": "u32",
"docs": [],
"namespace": ""
},
{
"info": "Plain",
"lookupIndex": 12,
"type": "NoChainExtension",
"docs": [],
"namespace": "ink_env::types::NoChainExtension",
"lookupNameRoot": "InkEnvNoChainExtension"
}
]
File diff suppressed because one or more lines are too long
@@ -1,12 +1,21 @@
{
"source": {
"hash": "0xf051c631190ac47f82e280ba763df932210f6e2447978e24cbe0dcc6d6903c7a",
"language": "ink! 4.0.0-alpha.1",
"compiler": "rustc 1.63.0"
"hash": "0xa5b19cb655755feba8e34ab5b413ac6593ecc7e24e19af485a4d30036be9d577",
"language": "ink! 4.2.0",
"compiler": "rustc 1.69.0",
"build_info": {
"build_mode": "Debug",
"cargo_contract_version": "2.2.1",
"rust_toolchain": "stable-x86_64-apple-darwin",
"wasm_opt_settings": {
"keep_debug_symbols": false,
"optimization_passes": "Z"
}
}
},
"contract": {
"name": "flipper",
"version": "4.0.0-alpha.1",
"version": "4.2.0",
"authors": [
"Parity Technologies <admin@parity.io>"
]
@@ -25,39 +34,109 @@
}
}
],
"default": false,
"docs": [
"Creates a new flipper smart contract initialized with the given value."
],
"label": "new",
"payable": false,
"returnType": {
"displayName": [
"ink_primitives",
"ConstructorResult"
],
"type": 1
},
"selector": "0x9bae9d5e"
},
{
"args": [],
"default": false,
"docs": [
"Creates a new flipper smart contract initialized to `false`."
],
"label": "default",
"label": "new_default",
"payable": false,
"selector": "0xed4b9d1b"
"returnType": {
"displayName": [
"ink_primitives",
"ConstructorResult"
],
"type": 1
},
"selector": "0x61ef7e3e"
}
],
"docs": [],
"environment": {
"accountId": {
"displayName": [
"AccountId"
],
"type": 5
},
"balance": {
"displayName": [
"Balance"
],
"type": 8
},
"blockNumber": {
"displayName": [
"BlockNumber"
],
"type": 11
},
"chainExtension": {
"displayName": [
"ChainExtension"
],
"type": 12
},
"hash": {
"displayName": [
"Hash"
],
"type": 9
},
"maxEventTopics": 4,
"timestamp": {
"displayName": [
"Timestamp"
],
"type": 10
}
},
"events": [],
"lang_error": {
"displayName": [
"ink",
"LangError"
],
"type": 3
},
"messages": [
{
"args": [],
"default": false,
"docs": [
" Flips the current value of the Flipper's boolean."
],
"label": "flip",
"mutates": true,
"payable": false,
"returnType": null,
"returnType": {
"displayName": [
"ink",
"MessageResult"
],
"type": 1
},
"selector": "0x633aa551"
},
{
"args": [],
"default": false,
"docs": [
" Returns the current value of the Flipper's boolean."
],
@@ -66,27 +145,34 @@
"payable": false,
"returnType": {
"displayName": [
"bool"
"ink",
"MessageResult"
],
"type": 0
"type": 4
},
"selector": "0x2f865bd9"
}
]
},
"storage": {
"struct": {
"fields": [
{
"layout": {
"cell": {
"key": "0x0000000000000000000000000000000000000000000000000000000000000000",
"ty": 0
"root": {
"layout": {
"struct": {
"fields": [
{
"layout": {
"leaf": {
"key": "0x00000000",
"ty": 0
}
},
"name": "value"
}
},
"name": "value"
],
"name": "Flipper"
}
]
},
"root_key": "0x00000000"
}
},
"types": [
@@ -97,6 +183,213 @@
"primitive": "bool"
}
}
},
{
"id": 1,
"type": {
"def": {
"variant": {
"variants": [
{
"fields": [
{
"type": 2
}
],
"index": 0,
"name": "Ok"
},
{
"fields": [
{
"type": 3
}
],
"index": 1,
"name": "Err"
}
]
}
},
"params": [
{
"name": "T",
"type": 2
},
{
"name": "E",
"type": 3
}
],
"path": [
"Result"
]
}
},
{
"id": 2,
"type": {
"def": {
"tuple": []
}
}
},
{
"id": 3,
"type": {
"def": {
"variant": {
"variants": [
{
"index": 1,
"name": "CouldNotReadInput"
}
]
}
},
"path": [
"ink_primitives",
"LangError"
]
}
},
{
"id": 4,
"type": {
"def": {
"variant": {
"variants": [
{
"fields": [
{
"type": 0
}
],
"index": 0,
"name": "Ok"
},
{
"fields": [
{
"type": 3
}
],
"index": 1,
"name": "Err"
}
]
}
},
"params": [
{
"name": "T",
"type": 0
},
{
"name": "E",
"type": 3
}
],
"path": [
"Result"
]
}
},
{
"id": 5,
"type": {
"def": {
"composite": {
"fields": [
{
"type": 6,
"typeName": "[u8; 32]"
}
]
}
},
"path": [
"ink_primitives",
"types",
"AccountId"
]
}
},
{
"id": 6,
"type": {
"def": {
"array": {
"len": 32,
"type": 7
}
}
}
},
{
"id": 7,
"type": {
"def": {
"primitive": "u8"
}
}
},
{
"id": 8,
"type": {
"def": {
"primitive": "u128"
}
}
},
{
"id": 9,
"type": {
"def": {
"composite": {
"fields": [
{
"type": 6,
"typeName": "[u8; 32]"
}
]
}
},
"path": [
"ink_primitives",
"types",
"Hash"
]
}
},
{
"id": 10,
"type": {
"def": {
"primitive": "u64"
}
}
},
{
"id": 11,
"type": {
"def": {
"primitive": "u32"
}
}
},
{
"id": 12,
"type": {
"def": {
"variant": {}
},
"path": [
"ink_env",
"types",
"NoChainExtension"
]
}
}
],
"version": "4"
+1
View File
@@ -37,6 +37,7 @@ export interface AbiMessage {
identifier: string;
index: number;
isConstructor?: boolean;
isDefault?: boolean;
isMutating?: boolean;
isPayable?: boolean;
method: string;