@dedot/contracts 0.0.1-next.cfee875e.21 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Contract.d.ts +5 -2
- package/Contract.js +8 -2
- package/TypinkRegistry.d.ts +3 -1
- package/TypinkRegistry.js +59 -0
- package/cjs/Contract.js +7 -1
- package/cjs/TypinkRegistry.js +82 -0
- package/cjs/executor/ConstructorQueryExecutor.js +1 -1
- package/cjs/executor/EventExecutor.js +26 -0
- package/cjs/executor/index.js +1 -0
- package/cjs/utils.js +10 -10
- package/executor/ConstructorQueryExecutor.js +1 -1
- package/executor/EventExecutor.d.ts +7 -0
- package/executor/EventExecutor.js +22 -0
- package/executor/Executor.d.ts +2 -2
- package/executor/index.d.ts +1 -0
- package/executor/index.js +1 -0
- package/package.json +12 -6
- package/types/index.d.ts +26 -10
- package/types/shared.d.ts +7 -3
- package/types/v4.d.ts +4 -4
- package/types/v5.d.ts +2 -2
- package/utils.js +10 -10
package/Contract.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { ISubstrateClient } from '@dedot/api';
|
|
2
2
|
import { AccountId32, AccountId32Like } from '@dedot/codecs';
|
|
3
|
+
import { IEventRecord } from '@dedot/types';
|
|
3
4
|
import { TypinkRegistry } from './TypinkRegistry.js';
|
|
4
|
-
import { ContractMetadata, GenericContractApi } from './types/index.js';
|
|
5
|
+
import { ContractEvent, ContractMetadata, GenericContractApi } from './types/index.js';
|
|
5
6
|
export declare class Contract<ContractApi extends GenericContractApi = GenericContractApi> {
|
|
6
7
|
#private;
|
|
7
|
-
constructor(api: ISubstrateClient,
|
|
8
|
+
constructor(api: ISubstrateClient, metadata: ContractMetadata | string, address: AccountId32Like);
|
|
9
|
+
decodeEvent(eventRecord: IEventRecord): ContractEvent;
|
|
8
10
|
get metadata(): ContractMetadata;
|
|
9
11
|
get address(): AccountId32;
|
|
10
12
|
get registry(): TypinkRegistry;
|
|
11
13
|
get query(): ContractApi['query'];
|
|
12
14
|
get tx(): ContractApi['tx'];
|
|
15
|
+
get events(): ContractApi['events'];
|
|
13
16
|
}
|
package/Contract.js
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { AccountId32 } from '@dedot/codecs';
|
|
2
2
|
import { TypinkRegistry } from './TypinkRegistry.js';
|
|
3
|
-
import { QueryExecutor, TxExecutor } from './executor/index.js';
|
|
3
|
+
import { EventExecutor, QueryExecutor, TxExecutor } from './executor/index.js';
|
|
4
4
|
import { ensureSupportContractsPallet, newProxyChain, parseRawMetadata } from './utils.js';
|
|
5
5
|
export class Contract {
|
|
6
6
|
#api;
|
|
7
7
|
#registry;
|
|
8
8
|
#address;
|
|
9
9
|
#metadata;
|
|
10
|
-
constructor(api,
|
|
10
|
+
constructor(api, metadata, address) {
|
|
11
11
|
ensureSupportContractsPallet(api);
|
|
12
12
|
this.#api = api;
|
|
13
13
|
this.#address = new AccountId32(address);
|
|
14
14
|
this.#metadata = typeof metadata === 'string' ? parseRawMetadata(metadata) : metadata;
|
|
15
15
|
this.#registry = new TypinkRegistry(this.#metadata);
|
|
16
16
|
}
|
|
17
|
+
decodeEvent(eventRecord) {
|
|
18
|
+
return this.#registry.decodeEvent(eventRecord);
|
|
19
|
+
}
|
|
17
20
|
get metadata() {
|
|
18
21
|
return this.#metadata;
|
|
19
22
|
}
|
|
@@ -29,4 +32,7 @@ export class Contract {
|
|
|
29
32
|
get tx() {
|
|
30
33
|
return newProxyChain(new TxExecutor(this.#api, this.#registry, this.#address));
|
|
31
34
|
}
|
|
35
|
+
get events() {
|
|
36
|
+
return newProxyChain(new EventExecutor(this.#api, this.#registry, this.#address));
|
|
37
|
+
}
|
|
32
38
|
}
|
package/TypinkRegistry.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { TypeRegistry } from '@dedot/codecs';
|
|
2
|
-
import {
|
|
2
|
+
import { IEventRecord } from '@dedot/types';
|
|
3
|
+
import { ContractEvent, ContractMetadata } from './types/index.js';
|
|
3
4
|
export declare class TypinkRegistry extends TypeRegistry {
|
|
4
5
|
#private;
|
|
5
6
|
constructor(metadata: ContractMetadata);
|
|
6
7
|
get metadata(): ContractMetadata;
|
|
8
|
+
decodeEvent(eventRecord: IEventRecord): ContractEvent;
|
|
7
9
|
}
|
package/TypinkRegistry.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { TypeRegistry } from '@dedot/codecs';
|
|
2
|
+
import * as $ from '@dedot/shape';
|
|
3
|
+
import { DedotError, assert, hexToU8a, stringCamelCase, stringPascalCase } from '@dedot/utils';
|
|
2
4
|
import { extractContractTypes } from './utils.js';
|
|
3
5
|
export class TypinkRegistry extends TypeRegistry {
|
|
4
6
|
#metadata;
|
|
@@ -9,4 +11,61 @@ export class TypinkRegistry extends TypeRegistry {
|
|
|
9
11
|
get metadata() {
|
|
10
12
|
return this.#metadata;
|
|
11
13
|
}
|
|
14
|
+
decodeEvent(eventRecord) {
|
|
15
|
+
const { version } = this.#metadata;
|
|
16
|
+
switch (version) {
|
|
17
|
+
case 5:
|
|
18
|
+
return this.#decodeEventV5(eventRecord);
|
|
19
|
+
case '4':
|
|
20
|
+
return this.#decodeEventV4(eventRecord);
|
|
21
|
+
default:
|
|
22
|
+
throw new DedotError('Unsupported metadata version!');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
#isContractEmittedEvent(eventRecord) {
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
return eventRecord.pallet === 'Contracts' && eventRecord.palletEvent.name === 'ContractEmitted';
|
|
28
|
+
}
|
|
29
|
+
#decodeEventV4(eventRecord) {
|
|
30
|
+
assert(this.#metadata.version === '4', 'Invalid metadata version!');
|
|
31
|
+
assert(this.#isContractEmittedEvent(eventRecord.event), 'Event Record is not valid!');
|
|
32
|
+
const data = hexToU8a(eventRecord.event.palletEvent.data.data);
|
|
33
|
+
const index = data.at(0);
|
|
34
|
+
assert(index !== undefined, 'Unable to decode event index!');
|
|
35
|
+
const event = this.#metadata.spec.events[index];
|
|
36
|
+
assert(event, `Event index not found: ${index.toString()}`);
|
|
37
|
+
return this.#tryDecodeEvent(event, data.subarray(1));
|
|
38
|
+
}
|
|
39
|
+
#decodeEventV5(eventRecord) {
|
|
40
|
+
assert(this.#metadata.version === 5, 'Invalid metadata version!');
|
|
41
|
+
assert(this.#isContractEmittedEvent(eventRecord.event), 'Event Record is not valid!');
|
|
42
|
+
const data = hexToU8a(eventRecord.event.palletEvent.data.data);
|
|
43
|
+
const signatureTopic = eventRecord.topics.at(0);
|
|
44
|
+
let eventMeta;
|
|
45
|
+
if (signatureTopic) {
|
|
46
|
+
eventMeta = this.#metadata.spec.events.find((one) => one.signature_topic === signatureTopic);
|
|
47
|
+
}
|
|
48
|
+
// TODO: Handle multiple anonymous events
|
|
49
|
+
// If `event` does not exist, it means it's an anonymous event
|
|
50
|
+
// that does not contain a signature topic in the metadata.
|
|
51
|
+
if (!eventMeta) {
|
|
52
|
+
const potentialEvents = this.#metadata.spec.events.filter((one) => !one.signature_topic && one.args.filter((arg) => arg.indexed).length === eventRecord.topics.length);
|
|
53
|
+
assert(potentialEvents.length === 1, 'Unable to determine event!');
|
|
54
|
+
eventMeta = potentialEvents[0];
|
|
55
|
+
}
|
|
56
|
+
return this.#tryDecodeEvent(eventMeta, data);
|
|
57
|
+
}
|
|
58
|
+
#tryDecodeEvent(eventMeta, raw) {
|
|
59
|
+
const { args, label } = eventMeta;
|
|
60
|
+
const eventCodecFrame = args.reduce((frame, arg) => {
|
|
61
|
+
const { label, type: { type }, } = arg;
|
|
62
|
+
const $codec = this.findCodec(type);
|
|
63
|
+
Object.assign(frame, { [stringCamelCase(label)]: $codec });
|
|
64
|
+
return frame;
|
|
65
|
+
}, {});
|
|
66
|
+
const $eventCodec = $.Struct(eventCodecFrame);
|
|
67
|
+
const data = $eventCodec.decode(raw);
|
|
68
|
+
const name = stringPascalCase(label);
|
|
69
|
+
return args.length ? { name, data } : { name };
|
|
70
|
+
}
|
|
12
71
|
}
|
package/cjs/Contract.js
CHANGED
|
@@ -10,13 +10,16 @@ class Contract {
|
|
|
10
10
|
#registry;
|
|
11
11
|
#address;
|
|
12
12
|
#metadata;
|
|
13
|
-
constructor(api,
|
|
13
|
+
constructor(api, metadata, address) {
|
|
14
14
|
(0, utils_js_1.ensureSupportContractsPallet)(api);
|
|
15
15
|
this.#api = api;
|
|
16
16
|
this.#address = new codecs_1.AccountId32(address);
|
|
17
17
|
this.#metadata = typeof metadata === 'string' ? (0, utils_js_1.parseRawMetadata)(metadata) : metadata;
|
|
18
18
|
this.#registry = new TypinkRegistry_js_1.TypinkRegistry(this.#metadata);
|
|
19
19
|
}
|
|
20
|
+
decodeEvent(eventRecord) {
|
|
21
|
+
return this.#registry.decodeEvent(eventRecord);
|
|
22
|
+
}
|
|
20
23
|
get metadata() {
|
|
21
24
|
return this.#metadata;
|
|
22
25
|
}
|
|
@@ -32,5 +35,8 @@ class Contract {
|
|
|
32
35
|
get tx() {
|
|
33
36
|
return (0, utils_js_1.newProxyChain)(new index_js_1.TxExecutor(this.#api, this.#registry, this.#address));
|
|
34
37
|
}
|
|
38
|
+
get events() {
|
|
39
|
+
return (0, utils_js_1.newProxyChain)(new index_js_1.EventExecutor(this.#api, this.#registry, this.#address));
|
|
40
|
+
}
|
|
35
41
|
}
|
|
36
42
|
exports.Contract = Contract;
|
package/cjs/TypinkRegistry.js
CHANGED
|
@@ -1,7 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
exports.TypinkRegistry = void 0;
|
|
4
27
|
const codecs_1 = require("@dedot/codecs");
|
|
28
|
+
const $ = __importStar(require("@dedot/shape"));
|
|
29
|
+
const utils_1 = require("@dedot/utils");
|
|
5
30
|
const utils_js_1 = require("./utils.js");
|
|
6
31
|
class TypinkRegistry extends codecs_1.TypeRegistry {
|
|
7
32
|
#metadata;
|
|
@@ -12,5 +37,62 @@ class TypinkRegistry extends codecs_1.TypeRegistry {
|
|
|
12
37
|
get metadata() {
|
|
13
38
|
return this.#metadata;
|
|
14
39
|
}
|
|
40
|
+
decodeEvent(eventRecord) {
|
|
41
|
+
const { version } = this.#metadata;
|
|
42
|
+
switch (version) {
|
|
43
|
+
case 5:
|
|
44
|
+
return this.#decodeEventV5(eventRecord);
|
|
45
|
+
case '4':
|
|
46
|
+
return this.#decodeEventV4(eventRecord);
|
|
47
|
+
default:
|
|
48
|
+
throw new utils_1.DedotError('Unsupported metadata version!');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
#isContractEmittedEvent(eventRecord) {
|
|
52
|
+
// @ts-ignore
|
|
53
|
+
return eventRecord.pallet === 'Contracts' && eventRecord.palletEvent.name === 'ContractEmitted';
|
|
54
|
+
}
|
|
55
|
+
#decodeEventV4(eventRecord) {
|
|
56
|
+
(0, utils_1.assert)(this.#metadata.version === '4', 'Invalid metadata version!');
|
|
57
|
+
(0, utils_1.assert)(this.#isContractEmittedEvent(eventRecord.event), 'Event Record is not valid!');
|
|
58
|
+
const data = (0, utils_1.hexToU8a)(eventRecord.event.palletEvent.data.data);
|
|
59
|
+
const index = data.at(0);
|
|
60
|
+
(0, utils_1.assert)(index !== undefined, 'Unable to decode event index!');
|
|
61
|
+
const event = this.#metadata.spec.events[index];
|
|
62
|
+
(0, utils_1.assert)(event, `Event index not found: ${index.toString()}`);
|
|
63
|
+
return this.#tryDecodeEvent(event, data.subarray(1));
|
|
64
|
+
}
|
|
65
|
+
#decodeEventV5(eventRecord) {
|
|
66
|
+
(0, utils_1.assert)(this.#metadata.version === 5, 'Invalid metadata version!');
|
|
67
|
+
(0, utils_1.assert)(this.#isContractEmittedEvent(eventRecord.event), 'Event Record is not valid!');
|
|
68
|
+
const data = (0, utils_1.hexToU8a)(eventRecord.event.palletEvent.data.data);
|
|
69
|
+
const signatureTopic = eventRecord.topics.at(0);
|
|
70
|
+
let eventMeta;
|
|
71
|
+
if (signatureTopic) {
|
|
72
|
+
eventMeta = this.#metadata.spec.events.find((one) => one.signature_topic === signatureTopic);
|
|
73
|
+
}
|
|
74
|
+
// TODO: Handle multiple anonymous events
|
|
75
|
+
// If `event` does not exist, it means it's an anonymous event
|
|
76
|
+
// that does not contain a signature topic in the metadata.
|
|
77
|
+
if (!eventMeta) {
|
|
78
|
+
const potentialEvents = this.#metadata.spec.events.filter((one) => !one.signature_topic && one.args.filter((arg) => arg.indexed).length === eventRecord.topics.length);
|
|
79
|
+
(0, utils_1.assert)(potentialEvents.length === 1, 'Unable to determine event!');
|
|
80
|
+
eventMeta = potentialEvents[0];
|
|
81
|
+
}
|
|
82
|
+
return this.#tryDecodeEvent(eventMeta, data);
|
|
83
|
+
}
|
|
84
|
+
#tryDecodeEvent(eventMeta, raw) {
|
|
85
|
+
const { args, label } = eventMeta;
|
|
86
|
+
const eventCodecFrame = args.reduce((frame, arg) => {
|
|
87
|
+
const { label, type: { type }, } = arg;
|
|
88
|
+
const $codec = this.findCodec(type);
|
|
89
|
+
Object.assign(frame, { [(0, utils_1.stringCamelCase)(label)]: $codec });
|
|
90
|
+
return frame;
|
|
91
|
+
}, {});
|
|
92
|
+
const $eventCodec = $.Struct(eventCodecFrame);
|
|
93
|
+
const data = $eventCodec.decode(raw);
|
|
94
|
+
const name = (0, utils_1.stringPascalCase)(label);
|
|
95
|
+
return args.length ? { name, data } : { name };
|
|
96
|
+
}
|
|
15
97
|
}
|
|
16
98
|
exports.TypinkRegistry = TypinkRegistry;
|
|
@@ -23,7 +23,7 @@ class ConstructorQueryExecutor extends Executor_js_1.Executor {
|
|
|
23
23
|
const formattedInputs = args.map((arg, index) => this.tryEncode(arg, params[index]));
|
|
24
24
|
const bytes = (0, utils_1.u8aToHex)((0, utils_1.concatU8a)((0, utils_1.hexToU8a)(meta.selector), ...formattedInputs));
|
|
25
25
|
const code = {
|
|
26
|
-
|
|
26
|
+
type: (0, utils_1.isWasm)(this.code) ? 'Upload' : 'Existing',
|
|
27
27
|
value: this.code,
|
|
28
28
|
};
|
|
29
29
|
return this.api.call.contractsApi.instantiate(caller, value, gasLimit, storageDepositLimit, code, bytes, salt);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventExecutor = void 0;
|
|
4
|
+
const Executor_js_1 = require("./Executor.js");
|
|
5
|
+
const utils_1 = require("@dedot/utils");
|
|
6
|
+
class EventExecutor extends Executor_js_1.Executor {
|
|
7
|
+
doExecute(eventName) {
|
|
8
|
+
const eventMeta = this.#findEventMeta(eventName);
|
|
9
|
+
(0, utils_1.assert)(eventMeta, "Contract event metadata not found!");
|
|
10
|
+
const is = (event) => {
|
|
11
|
+
return event.name === eventName;
|
|
12
|
+
};
|
|
13
|
+
const as = (event) => {
|
|
14
|
+
return is(event) ? event : undefined;
|
|
15
|
+
};
|
|
16
|
+
return {
|
|
17
|
+
is,
|
|
18
|
+
as,
|
|
19
|
+
meta: eventMeta,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
#findEventMeta(eventName) {
|
|
23
|
+
return this.registry.metadata.spec.events.find(one => (0, utils_1.stringPascalCase)(one.label) === eventName);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.EventExecutor = EventExecutor;
|
package/cjs/executor/index.js
CHANGED
|
@@ -18,3 +18,4 @@ __exportStar(require("./Executor.js"), exports);
|
|
|
18
18
|
__exportStar(require("./TxExecutor.js"), exports);
|
|
19
19
|
__exportStar(require("./QueryExecutor.js"), exports);
|
|
20
20
|
__exportStar(require("./ConstructorTxExecutor.js"), exports);
|
|
21
|
+
__exportStar(require("./EventExecutor.js"), exports);
|
package/cjs/utils.js
CHANGED
|
@@ -6,7 +6,7 @@ const extractContractTypes = (contractMetadata) => {
|
|
|
6
6
|
const { types } = contractMetadata;
|
|
7
7
|
return types.map(({ type, id }) => ({
|
|
8
8
|
id,
|
|
9
|
-
|
|
9
|
+
typeDef: (0, exports.normalizeContractTypeDef)(type.def),
|
|
10
10
|
params: [],
|
|
11
11
|
path: type?.path || [],
|
|
12
12
|
docs: [],
|
|
@@ -14,10 +14,10 @@ const extractContractTypes = (contractMetadata) => {
|
|
|
14
14
|
};
|
|
15
15
|
exports.extractContractTypes = extractContractTypes;
|
|
16
16
|
const normalizeContractTypeDef = (def) => {
|
|
17
|
-
let
|
|
17
|
+
let type;
|
|
18
18
|
let value;
|
|
19
19
|
if (def.variant) {
|
|
20
|
-
|
|
20
|
+
type = 'Enum';
|
|
21
21
|
value = {
|
|
22
22
|
members: def.variant.variants?.map((variant) => ({
|
|
23
23
|
fields: variant.fields?.map((fields) => ({ typeId: fields.type, typeName: fields.typeName })) || [],
|
|
@@ -27,19 +27,19 @@ const normalizeContractTypeDef = (def) => {
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
else if (def.tuple) {
|
|
30
|
-
|
|
30
|
+
type = 'Tuple';
|
|
31
31
|
value = {
|
|
32
32
|
fields: def.tuple,
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
else if (def.sequence) {
|
|
36
|
-
|
|
36
|
+
type = 'Sequence';
|
|
37
37
|
value = {
|
|
38
38
|
typeParam: def.sequence.type,
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
else if (def.composite) {
|
|
42
|
-
|
|
42
|
+
type = 'Struct';
|
|
43
43
|
value = {
|
|
44
44
|
fields: def.composite.fields.map((one) => ({
|
|
45
45
|
typeId: one.type,
|
|
@@ -49,13 +49,13 @@ const normalizeContractTypeDef = (def) => {
|
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
51
|
else if (def.primitive) {
|
|
52
|
-
|
|
52
|
+
type = 'Primitive';
|
|
53
53
|
value = {
|
|
54
54
|
kind: def.primitive,
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
else if (def.array) {
|
|
58
|
-
|
|
58
|
+
type = 'SizedVec';
|
|
59
59
|
value = {
|
|
60
60
|
len: def.array.len,
|
|
61
61
|
typeParam: def.array.type,
|
|
@@ -64,11 +64,11 @@ const normalizeContractTypeDef = (def) => {
|
|
|
64
64
|
else {
|
|
65
65
|
throw Error(`Invalid contract type def: ${JSON.stringify(def)}`);
|
|
66
66
|
}
|
|
67
|
-
return {
|
|
67
|
+
return { type, value };
|
|
68
68
|
};
|
|
69
69
|
exports.normalizeContractTypeDef = normalizeContractTypeDef;
|
|
70
70
|
const UNSUPPORTED_VERSIONS = ['V3', 'V2', 'V1'];
|
|
71
|
-
const SUPPORTED_VERSIONS = [
|
|
71
|
+
const SUPPORTED_VERSIONS = [5, '4'];
|
|
72
72
|
const parseRawMetadata = (rawMetadata) => {
|
|
73
73
|
const metadata = JSON.parse(rawMetadata);
|
|
74
74
|
// This is for V1, V2, V3
|
|
@@ -20,7 +20,7 @@ export class ConstructorQueryExecutor extends Executor {
|
|
|
20
20
|
const formattedInputs = args.map((arg, index) => this.tryEncode(arg, params[index]));
|
|
21
21
|
const bytes = u8aToHex(concatU8a(hexToU8a(meta.selector), ...formattedInputs));
|
|
22
22
|
const code = {
|
|
23
|
-
|
|
23
|
+
type: isWasm(this.code) ? 'Upload' : 'Existing',
|
|
24
24
|
value: this.code,
|
|
25
25
|
};
|
|
26
26
|
return this.api.call.contractsApi.instantiate(caller, value, gasLimit, storageDepositLimit, code, bytes, salt);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { GenericSubstrateApi } from "@dedot/types";
|
|
2
|
+
import { Executor } from "./Executor.js";
|
|
3
|
+
import { GenericContractEvent } from "../types/index.js";
|
|
4
|
+
export declare class EventExecutor<ChainApi extends GenericSubstrateApi> extends Executor<ChainApi> {
|
|
5
|
+
#private;
|
|
6
|
+
doExecute(eventName: string): GenericContractEvent;
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Executor } from "./Executor.js";
|
|
2
|
+
import { assert, stringPascalCase } from "@dedot/utils";
|
|
3
|
+
export class EventExecutor extends Executor {
|
|
4
|
+
doExecute(eventName) {
|
|
5
|
+
const eventMeta = this.#findEventMeta(eventName);
|
|
6
|
+
assert(eventMeta, "Contract event metadata not found!");
|
|
7
|
+
const is = (event) => {
|
|
8
|
+
return event.name === eventName;
|
|
9
|
+
};
|
|
10
|
+
const as = (event) => {
|
|
11
|
+
return is(event) ? event : undefined;
|
|
12
|
+
};
|
|
13
|
+
return {
|
|
14
|
+
is,
|
|
15
|
+
as,
|
|
16
|
+
meta: eventMeta,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
#findEventMeta(eventName) {
|
|
20
|
+
return this.registry.metadata.spec.events.find(one => stringPascalCase(one.label) === eventName);
|
|
21
|
+
}
|
|
22
|
+
}
|
package/executor/Executor.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { SubstrateApi } from '@dedot/api/chaintypes';
|
|
|
3
3
|
import { AccountId32 } from '@dedot/codecs';
|
|
4
4
|
import { GenericSubstrateApi, RpcVersion } from '@dedot/types';
|
|
5
5
|
import { TypinkRegistry } from '../TypinkRegistry.js';
|
|
6
|
-
import { ContractMessageArg,
|
|
6
|
+
import { ContractMessageArg, ContractCallMessage } from '../types/index.js';
|
|
7
7
|
import { ContractMetadata } from '../types/index.js';
|
|
8
8
|
export declare abstract class Executor<ChainApi extends GenericSubstrateApi = SubstrateApi[RpcVersion]> {
|
|
9
9
|
#private;
|
|
@@ -14,5 +14,5 @@ export declare abstract class Executor<ChainApi extends GenericSubstrateApi = Su
|
|
|
14
14
|
get registry(): TypinkRegistry;
|
|
15
15
|
abstract doExecute(...paths: string[]): unknown;
|
|
16
16
|
tryEncode(param: ContractMessageArg, value: any): Uint8Array;
|
|
17
|
-
tryDecode(meta:
|
|
17
|
+
tryDecode(meta: ContractCallMessage, raw: any): unknown;
|
|
18
18
|
}
|
package/executor/index.d.ts
CHANGED
package/executor/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dedot/contracts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Delightful ink! Contract APIs",
|
|
5
5
|
"author": "Tung Vu <tung@coongcrafts.io>",
|
|
6
|
+
"homepage": "https://github.com/dedotdev/dedot/tree/main/packages/contracts",
|
|
7
|
+
"repository": {
|
|
8
|
+
"directory": "packages/contracts",
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/dedotdev/dedot.git"
|
|
11
|
+
},
|
|
6
12
|
"main": "./cjs/index.js",
|
|
7
13
|
"sideEffects": false,
|
|
8
14
|
"type": "module",
|
|
@@ -12,17 +18,17 @@
|
|
|
12
18
|
"test": "vitest --watch=false"
|
|
13
19
|
},
|
|
14
20
|
"dependencies": {
|
|
15
|
-
"@dedot/api": "0.
|
|
16
|
-
"@dedot/codecs": "0.
|
|
17
|
-
"@dedot/types": "0.
|
|
18
|
-
"@dedot/utils": "0.
|
|
21
|
+
"@dedot/api": "0.1.0",
|
|
22
|
+
"@dedot/codecs": "0.1.0",
|
|
23
|
+
"@dedot/types": "0.1.0",
|
|
24
|
+
"@dedot/utils": "0.1.0"
|
|
19
25
|
},
|
|
20
26
|
"publishConfig": {
|
|
21
27
|
"access": "public",
|
|
22
28
|
"directory": "dist"
|
|
23
29
|
},
|
|
24
30
|
"license": "Apache-2.0",
|
|
25
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "c8220a4ab4b171fe04adb49759318bde865d7c17",
|
|
26
32
|
"module": "./index.js",
|
|
27
33
|
"types": "./index.d.ts",
|
|
28
34
|
"exports": {
|
package/types/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { SubstrateApi } from '@dedot/api/chaintypes';
|
|
2
2
|
import { AccountId32Like, BytesLike, DispatchError, Weight } from '@dedot/codecs';
|
|
3
3
|
import { AnyFunc, AsyncMethod, GenericSubstrateApi, RpcVersion, VersionedGenericSubstrateApi } from '@dedot/types';
|
|
4
|
-
import {
|
|
5
|
-
import { ContractMetadataV4 } from './v4.js';
|
|
6
|
-
import { ContractMetadataV5 } from './v5.js';
|
|
4
|
+
import { ContractCallMessage, ContractConstructorMessage } from './shared.js';
|
|
5
|
+
import { ContractEventV4, ContractMetadataV4 } from './v4.js';
|
|
6
|
+
import { ContractEventV5, ContractMetadataV5 } from './v5.js';
|
|
7
7
|
export * from './shared.js';
|
|
8
|
+
export type ContractEventMeta = ContractEventV4 | ContractEventV5;
|
|
8
9
|
export type GenericContractCallResult<DecodedData, ContractResult> = ({
|
|
9
10
|
isOk: true;
|
|
10
11
|
data: DecodedData;
|
|
@@ -41,10 +42,10 @@ export type ContractTxOptions = CallOptions & {
|
|
|
41
42
|
gasLimit: Weight;
|
|
42
43
|
};
|
|
43
44
|
export type GenericContractQueryCall<ChainApi extends GenericSubstrateApi, F extends AsyncMethod = (...args: any[]) => Promise<GenericContractCallResult<any, ContractCallResult<ChainApi>>>> = F & {
|
|
44
|
-
meta:
|
|
45
|
+
meta: ContractCallMessage;
|
|
45
46
|
};
|
|
46
47
|
export type GenericContractTxCall<ChainApi extends GenericSubstrateApi, F extends AnyFunc = (...args: any[]) => ContractSubmittableExtrinsic<ChainApi>> = F & {
|
|
47
|
-
meta:
|
|
48
|
+
meta: ContractCallMessage;
|
|
48
49
|
};
|
|
49
50
|
export type GenericConstructorQueryCall<ChainApi extends GenericSubstrateApi, F extends AsyncMethod = (...args: any[]) => Promise<ContractInstantiateResult<ChainApi>>> = F & {
|
|
50
51
|
meta: ContractConstructorMessage;
|
|
@@ -64,9 +65,24 @@ export interface GenericConstructorQuery<ChainApi extends GenericSubstrateApi> {
|
|
|
64
65
|
export interface GenericConstructorTx<ChainApi extends GenericSubstrateApi> {
|
|
65
66
|
[method: string]: GenericConstructorTxCall<ChainApi>;
|
|
66
67
|
}
|
|
67
|
-
export
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
export type ContractEvent<EventName extends string = string, Data extends any = any> = Data extends undefined ? {
|
|
69
|
+
name: EventName;
|
|
70
|
+
} : {
|
|
71
|
+
name: EventName;
|
|
72
|
+
data: Data;
|
|
73
|
+
};
|
|
74
|
+
export interface GenericContractEvent<EventName extends string = string, Data extends any = any> {
|
|
75
|
+
is: (event: ContractEvent) => event is ContractEvent<EventName, Data>;
|
|
76
|
+
as: (event: ContractEvent) => ContractEvent<EventName, Data> | undefined;
|
|
77
|
+
meta: ContractEventMeta;
|
|
78
|
+
}
|
|
79
|
+
export interface GenericContractEvents<_ extends GenericSubstrateApi> {
|
|
80
|
+
[event: string]: GenericContractEvent;
|
|
81
|
+
}
|
|
82
|
+
export interface GenericContractApi<Rv extends RpcVersion = RpcVersion, ChainApi extends VersionedGenericSubstrateApi = SubstrateApi> {
|
|
83
|
+
query: GenericContractQuery<ChainApi[Rv]>;
|
|
84
|
+
tx: GenericContractTx<ChainApi[Rv]>;
|
|
85
|
+
constructorQuery: GenericConstructorQuery<ChainApi[Rv]>;
|
|
86
|
+
constructorTx: GenericConstructorTx<ChainApi[Rv]>;
|
|
87
|
+
events: GenericContractEvents<ChainApi[Rv]>;
|
|
72
88
|
}
|
package/types/shared.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export interface ContractTypeInfo {
|
|
|
28
28
|
displayName: string[];
|
|
29
29
|
type: number;
|
|
30
30
|
}
|
|
31
|
-
export interface
|
|
31
|
+
export interface ContractMessage {
|
|
32
32
|
args: ContractMessageArg[];
|
|
33
33
|
default: boolean;
|
|
34
34
|
docs: string[];
|
|
@@ -37,9 +37,9 @@ export interface Message {
|
|
|
37
37
|
returnType: ContractTypeInfo;
|
|
38
38
|
selector: string;
|
|
39
39
|
}
|
|
40
|
-
export interface ContractConstructorMessage extends
|
|
40
|
+
export interface ContractConstructorMessage extends ContractMessage {
|
|
41
41
|
}
|
|
42
|
-
export interface
|
|
42
|
+
export interface ContractCallMessage extends ContractMessage {
|
|
43
43
|
mutates: boolean;
|
|
44
44
|
}
|
|
45
45
|
export interface ContractType {
|
|
@@ -98,3 +98,7 @@ export interface ContractStorage {
|
|
|
98
98
|
root_key: string;
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
|
+
export interface ContractEventArg extends ContractMessageArg {
|
|
102
|
+
docs: string[];
|
|
103
|
+
indexed: boolean;
|
|
104
|
+
}
|
package/types/v4.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ContractConstructorMessage, ContractInformation,
|
|
1
|
+
import { ContractConstructorMessage, ContractEventArg, ContractInformation, ContractCallMessage, ContractSource, ContractStorage, ContractType, ContractTypeInfo } from './shared.js';
|
|
2
2
|
export interface ContractMetadataV4 {
|
|
3
3
|
source: ContractSource;
|
|
4
4
|
contract: ContractInformation;
|
|
@@ -13,12 +13,12 @@ export interface ContractSpecV4 {
|
|
|
13
13
|
environment: ContractEnvironmentV4;
|
|
14
14
|
events: ContractEventV4[];
|
|
15
15
|
lang_error: ContractTypeInfo;
|
|
16
|
-
messages:
|
|
16
|
+
messages: ContractCallMessage[];
|
|
17
17
|
}
|
|
18
18
|
export interface ContractEventV4 {
|
|
19
|
-
args:
|
|
19
|
+
args: ContractEventArg[];
|
|
20
20
|
docs: string[];
|
|
21
|
-
label: string
|
|
21
|
+
label: string;
|
|
22
22
|
}
|
|
23
23
|
export interface ContractEnvironmentV4 {
|
|
24
24
|
accountId: ContractTypeInfo;
|
package/types/v5.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export interface ContractMetadataV5 {
|
|
|
6
6
|
spec: ContractSpecV5;
|
|
7
7
|
storage: ContractStorage;
|
|
8
8
|
types: ContractType[];
|
|
9
|
-
version:
|
|
9
|
+
version: 5;
|
|
10
10
|
}
|
|
11
11
|
export interface ContractSpecV5 extends ContractSpecV4 {
|
|
12
12
|
environment: ContractEnvironmentV5;
|
|
@@ -14,7 +14,7 @@ export interface ContractSpecV5 extends ContractSpecV4 {
|
|
|
14
14
|
}
|
|
15
15
|
export interface ContractEventV5 extends ContractEventV4 {
|
|
16
16
|
module_path: string;
|
|
17
|
-
signature_topic
|
|
17
|
+
signature_topic?: string | null;
|
|
18
18
|
}
|
|
19
19
|
export interface ContractEnvironmentV5 extends ContractEnvironmentV4 {
|
|
20
20
|
staticBufferSize: number;
|
package/utils.js
CHANGED
|
@@ -3,17 +3,17 @@ export const extractContractTypes = (contractMetadata) => {
|
|
|
3
3
|
const { types } = contractMetadata;
|
|
4
4
|
return types.map(({ type, id }) => ({
|
|
5
5
|
id,
|
|
6
|
-
|
|
6
|
+
typeDef: normalizeContractTypeDef(type.def),
|
|
7
7
|
params: [],
|
|
8
8
|
path: type?.path || [],
|
|
9
9
|
docs: [],
|
|
10
10
|
}));
|
|
11
11
|
};
|
|
12
12
|
export const normalizeContractTypeDef = (def) => {
|
|
13
|
-
let
|
|
13
|
+
let type;
|
|
14
14
|
let value;
|
|
15
15
|
if (def.variant) {
|
|
16
|
-
|
|
16
|
+
type = 'Enum';
|
|
17
17
|
value = {
|
|
18
18
|
members: def.variant.variants?.map((variant) => ({
|
|
19
19
|
fields: variant.fields?.map((fields) => ({ typeId: fields.type, typeName: fields.typeName })) || [],
|
|
@@ -23,19 +23,19 @@ export const normalizeContractTypeDef = (def) => {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
else if (def.tuple) {
|
|
26
|
-
|
|
26
|
+
type = 'Tuple';
|
|
27
27
|
value = {
|
|
28
28
|
fields: def.tuple,
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
31
|
else if (def.sequence) {
|
|
32
|
-
|
|
32
|
+
type = 'Sequence';
|
|
33
33
|
value = {
|
|
34
34
|
typeParam: def.sequence.type,
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
else if (def.composite) {
|
|
38
|
-
|
|
38
|
+
type = 'Struct';
|
|
39
39
|
value = {
|
|
40
40
|
fields: def.composite.fields.map((one) => ({
|
|
41
41
|
typeId: one.type,
|
|
@@ -45,13 +45,13 @@ export const normalizeContractTypeDef = (def) => {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
else if (def.primitive) {
|
|
48
|
-
|
|
48
|
+
type = 'Primitive';
|
|
49
49
|
value = {
|
|
50
50
|
kind: def.primitive,
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
else if (def.array) {
|
|
54
|
-
|
|
54
|
+
type = 'SizedVec';
|
|
55
55
|
value = {
|
|
56
56
|
len: def.array.len,
|
|
57
57
|
typeParam: def.array.type,
|
|
@@ -60,10 +60,10 @@ export const normalizeContractTypeDef = (def) => {
|
|
|
60
60
|
else {
|
|
61
61
|
throw Error(`Invalid contract type def: ${JSON.stringify(def)}`);
|
|
62
62
|
}
|
|
63
|
-
return {
|
|
63
|
+
return { type, value };
|
|
64
64
|
};
|
|
65
65
|
const UNSUPPORTED_VERSIONS = ['V3', 'V2', 'V1'];
|
|
66
|
-
const SUPPORTED_VERSIONS = [
|
|
66
|
+
const SUPPORTED_VERSIONS = [5, '4'];
|
|
67
67
|
export const parseRawMetadata = (rawMetadata) => {
|
|
68
68
|
const metadata = JSON.parse(rawMetadata);
|
|
69
69
|
// This is for V1, V2, V3
|