@dedot/codegen 0.0.1-next.cfee875e.21 → 0.0.1-next.d731b849.13
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/chaintypes/generator/ApiGen.d.ts +12 -12
- package/chaintypes/generator/ErrorsGen.js +2 -2
- package/chaintypes/generator/EventsGen.js +2 -2
- package/chaintypes/generator/QueryGen.js +7 -7
- package/chaintypes/generator/TxGen.js +7 -7
- package/chaintypes/generator/TypesGen.js +1 -1
- package/cjs/chaintypes/generator/ErrorsGen.js +2 -2
- package/cjs/chaintypes/generator/EventsGen.js +2 -2
- package/cjs/chaintypes/generator/QueryGen.js +7 -7
- package/cjs/chaintypes/generator/TxGen.js +7 -7
- package/cjs/chaintypes/generator/TypesGen.js +1 -1
- package/cjs/shared/BaseTypesGen.js +26 -22
- package/cjs/typink/generator/ConstructorQueryGen.js +6 -3
- package/cjs/typink/generator/EventsGen.js +35 -0
- package/cjs/typink/generator/IndexGen.js +8 -3
- package/cjs/typink/generator/QueryGen.js +9 -7
- package/cjs/typink/generator/TypesGen.js +1 -8
- package/cjs/typink/generator/index.js +1 -0
- package/cjs/typink/index.js +4 -1
- package/cjs/typink/templates/events.hbs +8 -0
- package/cjs/typink/templates/index.hbs +12 -5
- package/cjs/utils.js +1 -1
- package/package.json +11 -11
- package/shared/BaseTypesGen.d.ts +1 -1
- package/shared/BaseTypesGen.js +26 -22
- package/typink/generator/ConstructorQueryGen.js +6 -3
- package/typink/generator/EventsGen.d.ts +7 -0
- package/typink/generator/EventsGen.js +31 -0
- package/typink/generator/IndexGen.d.ts +3 -1
- package/typink/generator/IndexGen.js +8 -3
- package/typink/generator/QueryGen.d.ts +3 -3
- package/typink/generator/QueryGen.js +9 -7
- package/typink/generator/TxGen.d.ts +2 -2
- package/typink/generator/TypesGen.d.ts +0 -1
- package/typink/generator/TypesGen.js +1 -8
- package/typink/generator/index.d.ts +1 -0
- package/typink/generator/index.js +1 -0
- package/typink/index.js +5 -2
- package/typink/templates/events.hbs +8 -0
- package/typink/templates/index.hbs +12 -5
- package/utils.js +1 -1
|
@@ -10,13 +10,13 @@ export declare abstract class ApiGen {
|
|
|
10
10
|
name: string;
|
|
11
11
|
typeId: number | undefined;
|
|
12
12
|
}[];
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
typeDef: {
|
|
14
|
+
type: "Struct";
|
|
15
15
|
value: {
|
|
16
16
|
fields: import("@dedot/codecs").Field[];
|
|
17
17
|
};
|
|
18
18
|
} | {
|
|
19
|
-
|
|
19
|
+
type: "Enum";
|
|
20
20
|
value: {
|
|
21
21
|
members: {
|
|
22
22
|
name: string;
|
|
@@ -26,33 +26,33 @@ export declare abstract class ApiGen {
|
|
|
26
26
|
}[];
|
|
27
27
|
};
|
|
28
28
|
} | {
|
|
29
|
-
|
|
29
|
+
type: "Sequence";
|
|
30
30
|
value: {
|
|
31
31
|
typeParam: number;
|
|
32
32
|
};
|
|
33
33
|
} | {
|
|
34
|
-
|
|
34
|
+
type: "SizedVec";
|
|
35
35
|
value: {
|
|
36
36
|
len: number;
|
|
37
37
|
typeParam: number;
|
|
38
38
|
};
|
|
39
39
|
} | {
|
|
40
|
-
|
|
40
|
+
type: "Tuple";
|
|
41
41
|
value: {
|
|
42
42
|
fields: number[];
|
|
43
43
|
};
|
|
44
44
|
} | {
|
|
45
|
-
|
|
45
|
+
type: "Primitive";
|
|
46
46
|
value: {
|
|
47
47
|
kind: "bool" | "u8" | "i8" | "u16" | "i16" | "u32" | "i32" | "u64" | "i64" | "u128" | "i128" | "u256" | "i256" | "str" | "char";
|
|
48
48
|
};
|
|
49
49
|
} | {
|
|
50
|
-
|
|
50
|
+
type: "Compact";
|
|
51
51
|
value: {
|
|
52
52
|
typeParam: number;
|
|
53
53
|
};
|
|
54
54
|
} | {
|
|
55
|
-
|
|
55
|
+
type: "BitSequence";
|
|
56
56
|
value: {
|
|
57
57
|
bitOrderType: number;
|
|
58
58
|
bitStoreType: number;
|
|
@@ -67,13 +67,13 @@ export declare abstract class ApiGen {
|
|
|
67
67
|
entries: {
|
|
68
68
|
name: string;
|
|
69
69
|
modifier: string;
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
storageType: {
|
|
71
|
+
type: "Plain";
|
|
72
72
|
value: {
|
|
73
73
|
valueTypeId: number;
|
|
74
74
|
};
|
|
75
75
|
} | {
|
|
76
|
-
|
|
76
|
+
type: "Map";
|
|
77
77
|
value: {
|
|
78
78
|
hashers: ("identity" | "blake2_128" | "blake2_256" | "blake2_128Concat" | "twox128" | "twox256" | "twox64Concat")[];
|
|
79
79
|
keyTypeId: number;
|
|
@@ -29,8 +29,8 @@ export class ErrorsGen extends ApiGen {
|
|
|
29
29
|
#getErrorDefs(errorTypeId) {
|
|
30
30
|
const def = this.metadata.types[errorTypeId];
|
|
31
31
|
assert(def, `Error def not found for id ${errorTypeId}`);
|
|
32
|
-
const {
|
|
33
|
-
assert(
|
|
32
|
+
const { type, value } = def.typeDef;
|
|
33
|
+
assert(type === 'Enum', 'Invalid pallet error type!');
|
|
34
34
|
return value.members;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -41,8 +41,8 @@ export class EventsGen extends ApiGen {
|
|
|
41
41
|
#getEventDefs(typeId) {
|
|
42
42
|
const def = this.metadata.types[typeId];
|
|
43
43
|
assert(def, `Event def not found for id ${typeId}`);
|
|
44
|
-
const {
|
|
45
|
-
assert(
|
|
44
|
+
const { type, value } = def.typeDef;
|
|
45
|
+
assert(type === 'Enum', 'Invalid pallet event type!');
|
|
46
46
|
return value.members;
|
|
47
47
|
}
|
|
48
48
|
#generateMemberDefType(fields) {
|
|
@@ -32,15 +32,15 @@ export class QueryGen extends ApiGen {
|
|
|
32
32
|
return beautifySourceCode(template({ importTypes, defTypeOut }));
|
|
33
33
|
}
|
|
34
34
|
#generateEntry(entry) {
|
|
35
|
-
const { name,
|
|
35
|
+
const { name, storageType, docs, modifier } = entry;
|
|
36
36
|
let valueType, keyTypeOut, keyTypeIn;
|
|
37
|
-
if (type
|
|
38
|
-
valueType = this.typesGen.generateType(
|
|
37
|
+
if (storageType.type === 'Plain') {
|
|
38
|
+
valueType = this.typesGen.generateType(storageType.value.valueTypeId, 1, true);
|
|
39
39
|
}
|
|
40
|
-
else if (type
|
|
41
|
-
valueType = this.typesGen.generateType(
|
|
42
|
-
keyTypeOut = this.typesGen.generateType(
|
|
43
|
-
keyTypeIn = this.typesGen.generateType(
|
|
40
|
+
else if (storageType.type === 'Map') {
|
|
41
|
+
valueType = this.typesGen.generateType(storageType.value.valueTypeId, 1, true);
|
|
42
|
+
keyTypeOut = this.typesGen.generateType(storageType.value.keyTypeId, 1, true);
|
|
43
|
+
keyTypeIn = this.typesGen.generateType(storageType.value.keyTypeId, 1);
|
|
44
44
|
}
|
|
45
45
|
else {
|
|
46
46
|
throw Error('Invalid entry type!');
|
|
@@ -5,7 +5,7 @@ export class TxGen extends ApiGen {
|
|
|
5
5
|
generate(useSubPaths = false) {
|
|
6
6
|
const { pallets, types } = this.metadata;
|
|
7
7
|
this.typesGen.clearCache();
|
|
8
|
-
this.typesGen.typeImports.addKnownType('GenericChainTx', 'GenericTxCall', 'ISubmittableExtrinsic', 'ISubmittableResult', 'IRuntimeTxCall', 'RpcVersion', 'RpcV2', 'ISubmittableExtrinsicLegacy'
|
|
8
|
+
this.typesGen.typeImports.addKnownType('GenericChainTx', 'GenericTxCall', 'ISubmittableExtrinsic', 'ISubmittableResult', 'IRuntimeTxCall', 'RpcVersion', 'RpcV2', 'ISubmittableExtrinsicLegacy');
|
|
9
9
|
const { callTypeId, addressTypeId, signatureTypeId } = this.metadata.extrinsic;
|
|
10
10
|
const callTypeIn = this.typesGen.generateType(callTypeId, 1);
|
|
11
11
|
const addressTypeIn = this.typesGen.generateType(addressTypeId, 1);
|
|
@@ -17,11 +17,11 @@ export class TxGen extends ApiGen {
|
|
|
17
17
|
for (let pallet of pallets) {
|
|
18
18
|
if (pallet.calls === undefined)
|
|
19
19
|
continue;
|
|
20
|
-
const {
|
|
21
|
-
if (type
|
|
20
|
+
const { typeDef } = types[pallet.calls];
|
|
21
|
+
if (typeDef.type !== 'Enum')
|
|
22
22
|
continue;
|
|
23
|
-
const isFlatEnum =
|
|
24
|
-
const typedTxs =
|
|
23
|
+
const isFlatEnum = typeDef.value.members.every((m) => m.fields.length === 0);
|
|
24
|
+
const typedTxs = typeDef.value.members
|
|
25
25
|
.map((one) => ({
|
|
26
26
|
functionName: stringCamelCase(one.name),
|
|
27
27
|
params: one.fields.map((f) => ({
|
|
@@ -53,8 +53,8 @@ export class TxGen extends ApiGen {
|
|
|
53
53
|
export type ChainSubmittableExtrinsic<Rv extends RpcVersion, T extends IRuntimeTxCall = ${callTypeIn}> =
|
|
54
54
|
Extrinsic<${addressTypeIn}, T, ${signatureTypeIn}, any[]> &
|
|
55
55
|
(Rv extends RpcV2
|
|
56
|
-
? ISubmittableExtrinsic<ISubmittableResult<FrameSystemEventRecord
|
|
57
|
-
: ISubmittableExtrinsicLegacy<ISubmittableResult<FrameSystemEventRecord
|
|
56
|
+
? ISubmittableExtrinsic<ISubmittableResult<FrameSystemEventRecord>>
|
|
57
|
+
: ISubmittableExtrinsicLegacy<ISubmittableResult<FrameSystemEventRecord>>)
|
|
58
58
|
|
|
59
59
|
export type TxCall<Rv extends RpcVersion> = (...args: any[]) => ChainSubmittableExtrinsic<Rv>;
|
|
60
60
|
`;
|
|
@@ -46,7 +46,7 @@ export class TypesGen extends BaseTypesGen {
|
|
|
46
46
|
}
|
|
47
47
|
shouldGenerateTypeIn(id) {
|
|
48
48
|
const { callTypeId } = this.metadata.extrinsic;
|
|
49
|
-
const palletCallTypeIds = this.registry.
|
|
49
|
+
const palletCallTypeIds = this.registry.getFieldTypeIdsFromEnum(callTypeId);
|
|
50
50
|
return callTypeId === id || palletCallTypeIds.includes(id);
|
|
51
51
|
}
|
|
52
52
|
getEnumOptions(typeId) {
|
|
@@ -32,8 +32,8 @@ class ErrorsGen extends ApiGen_js_1.ApiGen {
|
|
|
32
32
|
#getErrorDefs(errorTypeId) {
|
|
33
33
|
const def = this.metadata.types[errorTypeId];
|
|
34
34
|
(0, utils_1.assert)(def, `Error def not found for id ${errorTypeId}`);
|
|
35
|
-
const {
|
|
36
|
-
(0, utils_1.assert)(
|
|
35
|
+
const { type, value } = def.typeDef;
|
|
36
|
+
(0, utils_1.assert)(type === 'Enum', 'Invalid pallet error type!');
|
|
37
37
|
return value.members;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -44,8 +44,8 @@ class EventsGen extends ApiGen_js_1.ApiGen {
|
|
|
44
44
|
#getEventDefs(typeId) {
|
|
45
45
|
const def = this.metadata.types[typeId];
|
|
46
46
|
(0, utils_1.assert)(def, `Event def not found for id ${typeId}`);
|
|
47
|
-
const {
|
|
48
|
-
(0, utils_1.assert)(
|
|
47
|
+
const { type, value } = def.typeDef;
|
|
48
|
+
(0, utils_1.assert)(type === 'Enum', 'Invalid pallet event type!');
|
|
49
49
|
return value.members;
|
|
50
50
|
}
|
|
51
51
|
#generateMemberDefType(fields) {
|
|
@@ -35,15 +35,15 @@ class QueryGen extends ApiGen_js_1.ApiGen {
|
|
|
35
35
|
return (0, utils_js_1.beautifySourceCode)(template({ importTypes, defTypeOut }));
|
|
36
36
|
}
|
|
37
37
|
#generateEntry(entry) {
|
|
38
|
-
const { name,
|
|
38
|
+
const { name, storageType, docs, modifier } = entry;
|
|
39
39
|
let valueType, keyTypeOut, keyTypeIn;
|
|
40
|
-
if (type
|
|
41
|
-
valueType = this.typesGen.generateType(
|
|
40
|
+
if (storageType.type === 'Plain') {
|
|
41
|
+
valueType = this.typesGen.generateType(storageType.value.valueTypeId, 1, true);
|
|
42
42
|
}
|
|
43
|
-
else if (type
|
|
44
|
-
valueType = this.typesGen.generateType(
|
|
45
|
-
keyTypeOut = this.typesGen.generateType(
|
|
46
|
-
keyTypeIn = this.typesGen.generateType(
|
|
43
|
+
else if (storageType.type === 'Map') {
|
|
44
|
+
valueType = this.typesGen.generateType(storageType.value.valueTypeId, 1, true);
|
|
45
|
+
keyTypeOut = this.typesGen.generateType(storageType.value.keyTypeId, 1, true);
|
|
46
|
+
keyTypeIn = this.typesGen.generateType(storageType.value.keyTypeId, 1);
|
|
47
47
|
}
|
|
48
48
|
else {
|
|
49
49
|
throw Error('Invalid entry type!');
|
|
@@ -8,7 +8,7 @@ class TxGen extends index_js_1.ApiGen {
|
|
|
8
8
|
generate(useSubPaths = false) {
|
|
9
9
|
const { pallets, types } = this.metadata;
|
|
10
10
|
this.typesGen.clearCache();
|
|
11
|
-
this.typesGen.typeImports.addKnownType('GenericChainTx', 'GenericTxCall', 'ISubmittableExtrinsic', 'ISubmittableResult', 'IRuntimeTxCall', 'RpcVersion', 'RpcV2', 'ISubmittableExtrinsicLegacy'
|
|
11
|
+
this.typesGen.typeImports.addKnownType('GenericChainTx', 'GenericTxCall', 'ISubmittableExtrinsic', 'ISubmittableResult', 'IRuntimeTxCall', 'RpcVersion', 'RpcV2', 'ISubmittableExtrinsicLegacy');
|
|
12
12
|
const { callTypeId, addressTypeId, signatureTypeId } = this.metadata.extrinsic;
|
|
13
13
|
const callTypeIn = this.typesGen.generateType(callTypeId, 1);
|
|
14
14
|
const addressTypeIn = this.typesGen.generateType(addressTypeId, 1);
|
|
@@ -20,11 +20,11 @@ class TxGen extends index_js_1.ApiGen {
|
|
|
20
20
|
for (let pallet of pallets) {
|
|
21
21
|
if (pallet.calls === undefined)
|
|
22
22
|
continue;
|
|
23
|
-
const {
|
|
24
|
-
if (type
|
|
23
|
+
const { typeDef } = types[pallet.calls];
|
|
24
|
+
if (typeDef.type !== 'Enum')
|
|
25
25
|
continue;
|
|
26
|
-
const isFlatEnum =
|
|
27
|
-
const typedTxs =
|
|
26
|
+
const isFlatEnum = typeDef.value.members.every((m) => m.fields.length === 0);
|
|
27
|
+
const typedTxs = typeDef.value.members
|
|
28
28
|
.map((one) => ({
|
|
29
29
|
functionName: (0, utils_1.stringCamelCase)(one.name),
|
|
30
30
|
params: one.fields.map((f) => ({
|
|
@@ -56,8 +56,8 @@ class TxGen extends index_js_1.ApiGen {
|
|
|
56
56
|
export type ChainSubmittableExtrinsic<Rv extends RpcVersion, T extends IRuntimeTxCall = ${callTypeIn}> =
|
|
57
57
|
Extrinsic<${addressTypeIn}, T, ${signatureTypeIn}, any[]> &
|
|
58
58
|
(Rv extends RpcV2
|
|
59
|
-
? ISubmittableExtrinsic<ISubmittableResult<FrameSystemEventRecord
|
|
60
|
-
: ISubmittableExtrinsicLegacy<ISubmittableResult<FrameSystemEventRecord
|
|
59
|
+
? ISubmittableExtrinsic<ISubmittableResult<FrameSystemEventRecord>>
|
|
60
|
+
: ISubmittableExtrinsicLegacy<ISubmittableResult<FrameSystemEventRecord>>)
|
|
61
61
|
|
|
62
62
|
export type TxCall<Rv extends RpcVersion> = (...args: any[]) => ChainSubmittableExtrinsic<Rv>;
|
|
63
63
|
`;
|
|
@@ -49,7 +49,7 @@ class TypesGen extends index_js_1.BaseTypesGen {
|
|
|
49
49
|
}
|
|
50
50
|
shouldGenerateTypeIn(id) {
|
|
51
51
|
const { callTypeId } = this.metadata.extrinsic;
|
|
52
|
-
const palletCallTypeIds = this.registry.
|
|
52
|
+
const palletCallTypeIds = this.registry.getFieldTypeIdsFromEnum(callTypeId);
|
|
53
53
|
return callTypeId === id || palletCallTypeIds.includes(id);
|
|
54
54
|
}
|
|
55
55
|
getEnumOptions(typeId) {
|
|
@@ -20,6 +20,9 @@ class BaseTypesGen {
|
|
|
20
20
|
this.typeImports = new TypeImports_js_1.TypeImports();
|
|
21
21
|
this.skipTypes = [];
|
|
22
22
|
}
|
|
23
|
+
shouldGenerateTypeIn(_id) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
23
26
|
typeCache = {};
|
|
24
27
|
clearCache() {
|
|
25
28
|
this.typeCache = {};
|
|
@@ -122,9 +125,9 @@ class BaseTypesGen {
|
|
|
122
125
|
if (!def) {
|
|
123
126
|
throw new Error(`Type def not found ${JSON.stringify(def)}`);
|
|
124
127
|
}
|
|
125
|
-
const {
|
|
126
|
-
const {
|
|
127
|
-
switch (
|
|
128
|
+
const { typeDef, path, docs } = def;
|
|
129
|
+
const { type, value } = typeDef;
|
|
130
|
+
switch (type) {
|
|
128
131
|
case 'Primitive':
|
|
129
132
|
const $codec = (0, known_codecs_js_1.findKnownCodec)(value.kind);
|
|
130
133
|
if ($codec.nativeType) {
|
|
@@ -198,11 +201,11 @@ class BaseTypesGen {
|
|
|
198
201
|
const { tagKey, valueKey } = this.getEnumOptions(typeId);
|
|
199
202
|
return membersType
|
|
200
203
|
.map(([keyName, valueType, docs]) => ({
|
|
201
|
-
|
|
204
|
+
type: `${tagKey}: '${keyName}'`,
|
|
202
205
|
value: valueType ? `, ${valueKey}${this.#isOptionalType(valueType) ? '?' : ''}: ${valueType} ` : '',
|
|
203
206
|
docs,
|
|
204
207
|
}))
|
|
205
|
-
.map(({
|
|
208
|
+
.map(({ type, value, docs }) => `${(0, utils_js_1.commentBlock)(docs)}{ ${type}${value} }`)
|
|
206
209
|
.join(' | ');
|
|
207
210
|
}
|
|
208
211
|
}
|
|
@@ -224,9 +227,9 @@ class BaseTypesGen {
|
|
|
224
227
|
return this.generateType(value.typeParam, nestedLevel + 1, typeOut);
|
|
225
228
|
case 'Sequence':
|
|
226
229
|
case 'SizedVec': {
|
|
227
|
-
const fixedSize =
|
|
228
|
-
const $innerType = this.types[value.typeParam].
|
|
229
|
-
if ($innerType.
|
|
230
|
+
const fixedSize = type === 'SizedVec' ? `${value.len}` : null;
|
|
231
|
+
const $innerType = this.types[value.typeParam].typeDef;
|
|
232
|
+
if ($innerType.type === 'Primitive' && $innerType.value.kind === 'u8') {
|
|
230
233
|
return fixedSize ? `FixedBytes<${fixedSize}>` : typeOut ? 'Bytes' : 'BytesLike';
|
|
231
234
|
}
|
|
232
235
|
else {
|
|
@@ -235,7 +238,7 @@ class BaseTypesGen {
|
|
|
235
238
|
}
|
|
236
239
|
}
|
|
237
240
|
default:
|
|
238
|
-
throw new Error(`Invalid type! ${
|
|
241
|
+
throw new Error(`Invalid type! ${type}`);
|
|
239
242
|
}
|
|
240
243
|
}
|
|
241
244
|
generateObjectType(fields, nestedLevel = 0, typeOut = false) {
|
|
@@ -285,31 +288,32 @@ class BaseTypesGen {
|
|
|
285
288
|
const typeB = this.types[idB];
|
|
286
289
|
if (typeA.path.join('::') !== typeB.path.join('::'))
|
|
287
290
|
return false;
|
|
288
|
-
const {
|
|
289
|
-
const {
|
|
291
|
+
const { typeDef: defA, params: paramsA } = typeA;
|
|
292
|
+
const { typeDef: defB, params: paramsB } = typeB;
|
|
290
293
|
if (!this.#eqlArray(paramsA, paramsB, (valA, valB) => this.#eqlTypeParam(valA, valB))) {
|
|
291
294
|
return false;
|
|
292
295
|
}
|
|
293
|
-
if (defA.
|
|
296
|
+
if (defA.type !== defB.type)
|
|
294
297
|
return false;
|
|
295
|
-
if (defA.
|
|
298
|
+
if (defA.type === 'BitSequence')
|
|
296
299
|
return true;
|
|
297
|
-
if (defA.
|
|
300
|
+
if (defA.type === 'Primitive' && defB.type === 'Primitive') {
|
|
298
301
|
return defA.value.kind === defB.value.kind;
|
|
299
302
|
}
|
|
300
|
-
if ((defA.
|
|
303
|
+
if ((defA.type === 'Compact' && defB.type === 'Compact') ||
|
|
304
|
+
(defA.type === 'Sequence' && defB.type === 'Sequence')) {
|
|
301
305
|
return this.typeEql(defA.value.typeParam, defB.value.typeParam, lvl + 1);
|
|
302
306
|
}
|
|
303
|
-
if (defA.
|
|
307
|
+
if (defA.type === 'SizedVec' && defB.type === 'SizedVec') {
|
|
304
308
|
return defA.value.len === defB.value.len && this.typeEql(defA.value.typeParam, defB.value.typeParam, lvl + 1);
|
|
305
309
|
}
|
|
306
|
-
if (defA.
|
|
310
|
+
if (defA.type === 'Tuple' && defB.type === 'Tuple') {
|
|
307
311
|
return this.#eqlArray(defA.value.fields, defB.value.fields, (val1, val2) => this.typeEql(val1, val2, lvl + 1));
|
|
308
312
|
}
|
|
309
|
-
if (defA.
|
|
313
|
+
if (defA.type === 'Struct' && defB.type === 'Struct') {
|
|
310
314
|
return this.#eqlFields(defA.value.fields, defB.value.fields, lvl);
|
|
311
315
|
}
|
|
312
|
-
if (defA.
|
|
316
|
+
if (defA.type === 'Enum' && defB.type === 'Enum') {
|
|
313
317
|
return this.#eqlArray(defA.value.members, defB.value.members, (val1, val2) => val1.name === val2.name && val1.index === val2.index && this.#eqlFields(val1.fields, val2.fields, lvl));
|
|
314
318
|
}
|
|
315
319
|
return false;
|
|
@@ -335,8 +339,8 @@ class BaseTypesGen {
|
|
|
335
339
|
if (diffType.path.length > 0) {
|
|
336
340
|
return (0, utils_1.stringPascalCase)(diffType.path.at(-1));
|
|
337
341
|
}
|
|
338
|
-
else if (diffType.type
|
|
339
|
-
return (0, utils_1.stringPascalCase)(diffType.
|
|
342
|
+
else if (diffType.typeDef.type === 'Primitive') {
|
|
343
|
+
return (0, utils_1.stringPascalCase)(diffType.typeDef.value.kind);
|
|
340
344
|
}
|
|
341
345
|
}
|
|
342
346
|
// Last resort!
|
|
@@ -372,7 +376,7 @@ class BaseTypesGen {
|
|
|
372
376
|
this.typeImports.addOutType(typeName);
|
|
373
377
|
}
|
|
374
378
|
getEnumOptions(_typeId) {
|
|
375
|
-
return { tagKey: '
|
|
379
|
+
return { tagKey: 'type', valueKey: 'value' };
|
|
376
380
|
}
|
|
377
381
|
}
|
|
378
382
|
exports.BaseTypesGen = BaseTypesGen;
|
|
@@ -7,7 +7,7 @@ class ConstructorQueryGen extends QueryGen_js_1.QueryGen {
|
|
|
7
7
|
generate(useSubPaths = false) {
|
|
8
8
|
this.typesGen.clearCache();
|
|
9
9
|
this.typesGen.typeImports.addKnownType('GenericSubstrateApi');
|
|
10
|
-
this.typesGen.typeImports.addContractType('GenericConstructorQuery', 'GenericConstructorQueryCall', 'ConstructorCallOptions', 'ContractInstantiateResult');
|
|
10
|
+
this.typesGen.typeImports.addContractType('GenericConstructorQuery', 'GenericConstructorQueryCall', 'GenericConstructorCallResult', 'ConstructorCallOptions', 'ContractInstantiateResult');
|
|
11
11
|
const { constructors } = this.contractMetadata.spec;
|
|
12
12
|
const constructorsOut = this.doGenerate(constructors, 'ConstructorCallOptions');
|
|
13
13
|
const importTypes = this.typesGen.typeImports.toImports({ useSubPaths });
|
|
@@ -15,10 +15,13 @@ class ConstructorQueryGen extends QueryGen_js_1.QueryGen {
|
|
|
15
15
|
return (0, utils_js_1.beautifySourceCode)(template({ importTypes, constructorsOut }));
|
|
16
16
|
}
|
|
17
17
|
generateMethodDef(def) {
|
|
18
|
-
const { args } = def;
|
|
18
|
+
const { args, returnType } = def;
|
|
19
19
|
args.forEach(({ type: { type } }) => this.importType(type));
|
|
20
20
|
const paramsOut = this.generateParamsOut(args);
|
|
21
|
-
|
|
21
|
+
const typeOutRaw = this.typesGen.generateType(returnType.type, 0, true);
|
|
22
|
+
// Unwrap langError result
|
|
23
|
+
const typeOut = typeOutRaw.match(/^(\w+)<(.*), (.*)>$/).at(2);
|
|
24
|
+
return `GenericConstructorQueryCall<ChainApi, (${paramsOut && `${paramsOut},`} options: ConstructorCallOptions) => Promise<GenericConstructorCallResult<${typeOut}, ContractInstantiateResult<ChainApi>>>>`;
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
27
|
exports.ConstructorQueryGen = ConstructorQueryGen;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventsGen = void 0;
|
|
4
|
+
const utils_1 = require("@dedot/utils");
|
|
5
|
+
const utils_js_1 = require("../../utils.js");
|
|
6
|
+
const QueryGen_js_1 = require("./QueryGen.js");
|
|
7
|
+
class EventsGen extends QueryGen_js_1.QueryGen {
|
|
8
|
+
generate(useSubPaths = false) {
|
|
9
|
+
this.typesGen.clearCache();
|
|
10
|
+
this.typesGen.typeImports.addContractType('GenericContractEvents', 'GenericContractEvent');
|
|
11
|
+
const { events } = this.contractMetadata.spec;
|
|
12
|
+
let eventsOut = '';
|
|
13
|
+
events.forEach((event) => {
|
|
14
|
+
const { docs, label } = event;
|
|
15
|
+
const isV5 = 'signature_topic' in event;
|
|
16
|
+
eventsOut += `${(0, utils_js_1.commentBlock)(docs, '\n', isV5 ? event.signature_topic ? `@signature_topic: ${event.signature_topic}` : '- Anonymous event' : '')}`;
|
|
17
|
+
eventsOut += `${(0, utils_1.stringPascalCase)(label)}: ${this.#generateEventDef(event)};\n\n`;
|
|
18
|
+
});
|
|
19
|
+
const importTypes = this.typesGen.typeImports.toImports({ useSubPaths });
|
|
20
|
+
const template = (0, utils_js_1.compileTemplate)('typink/templates/events.hbs');
|
|
21
|
+
return (0, utils_js_1.beautifySourceCode)(template({ importTypes, eventsOut }));
|
|
22
|
+
}
|
|
23
|
+
#generateEventDef(event) {
|
|
24
|
+
const { args, label } = event;
|
|
25
|
+
args.forEach(({ type: { type } }) => this.importType(type));
|
|
26
|
+
const paramsOut = this.generateParamsOut(args);
|
|
27
|
+
return `GenericContractEvent<'${(0, utils_1.stringPascalCase)(label)}', {${paramsOut}}>`;
|
|
28
|
+
}
|
|
29
|
+
generateParamsOut(args) {
|
|
30
|
+
return args
|
|
31
|
+
.map(({ type: { type }, label, docs, indexed }) => `${(0, utils_js_1.commentBlock)(docs, '\n', `@indexed: ${indexed}`)}${(0, utils_1.stringCamelCase)(label)}: ${this.typesGen.generateType(type, 1)}`)
|
|
32
|
+
.join(', ');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.EventsGen = EventsGen;
|
|
@@ -7,18 +7,23 @@ const utils_js_1 = require("../../utils.js");
|
|
|
7
7
|
const SUFFIX = 'contract_api';
|
|
8
8
|
class IndexGen {
|
|
9
9
|
contractMetadata;
|
|
10
|
-
|
|
10
|
+
typesGen;
|
|
11
|
+
constructor(contractMetadata, typesGen) {
|
|
11
12
|
this.contractMetadata = contractMetadata;
|
|
13
|
+
this.typesGen = typesGen;
|
|
12
14
|
}
|
|
13
15
|
generate(useSubPaths = false) {
|
|
14
16
|
const contractName = (0, utils_1.stringPascalCase)(`${this.contractMetadata.contract.name}_${SUFFIX}`);
|
|
17
|
+
const langErrorId = this.contractMetadata.spec.lang_error.type;
|
|
18
|
+
const langErrorName = this.typesGen.cleanPath(this.contractMetadata.types[langErrorId].type.path);
|
|
15
19
|
const typeImports = new index_js_1.TypeImports();
|
|
16
|
-
typeImports.addKnownType('VersionedGenericSubstrateApi', 'RpcVersion');
|
|
20
|
+
typeImports.addKnownType('VersionedGenericSubstrateApi', 'RpcVersion', 'RpcV2');
|
|
17
21
|
typeImports.addContractType('GenericContractApi');
|
|
18
22
|
typeImports.addChainType('SubstrateApi');
|
|
23
|
+
typeImports.addPortableType(langErrorName);
|
|
19
24
|
const importTypes = typeImports.toImports({ useSubPaths });
|
|
20
25
|
const template = (0, utils_js_1.compileTemplate)('typink/templates/index.hbs');
|
|
21
|
-
return (0, utils_js_1.beautifySourceCode)(template({ contractName, importTypes }));
|
|
26
|
+
return (0, utils_js_1.beautifySourceCode)(template({ contractName, langErrorName, importTypes }));
|
|
22
27
|
}
|
|
23
28
|
}
|
|
24
29
|
exports.IndexGen = IndexGen;
|
|
@@ -35,7 +35,9 @@ class QueryGen {
|
|
|
35
35
|
this.importType(returnType.type);
|
|
36
36
|
args.forEach(({ type: { type } }) => this.importType(type));
|
|
37
37
|
const paramsOut = this.generateParamsOut(args);
|
|
38
|
-
const
|
|
38
|
+
const typeOutRaw = this.typesGen.generateType(returnType.type, 0, true);
|
|
39
|
+
// Unwrap langError result
|
|
40
|
+
const typeOut = typeOutRaw.match(/^(\w+)<(.*), (.*)>$/).at(2);
|
|
39
41
|
return `GenericContractQueryCall<ChainApi, (${paramsOut && `${paramsOut},`} options: ContractCallOptions) => Promise<GenericContractCallResult<${typeOut}, ContractCallResult<ChainApi>>>>`;
|
|
40
42
|
}
|
|
41
43
|
generateParamsOut(args) {
|
|
@@ -44,14 +46,14 @@ class QueryGen {
|
|
|
44
46
|
.join(', ');
|
|
45
47
|
}
|
|
46
48
|
importType(typeId) {
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
if (this.typesGen.includedTypes[
|
|
50
|
-
this.typesGen.addTypeImport(this.typesGen.includedTypes[
|
|
49
|
+
const contractType = this.contractMetadata.types[typeId];
|
|
50
|
+
const typeDef = (0, contracts_1.normalizeContractTypeDef)(this.contractMetadata.types[typeId].type.def);
|
|
51
|
+
if (this.typesGen.includedTypes[contractType.id]) {
|
|
52
|
+
this.typesGen.addTypeImport(this.typesGen.includedTypes[contractType.id].name);
|
|
51
53
|
return;
|
|
52
54
|
}
|
|
53
|
-
const {
|
|
54
|
-
switch (
|
|
55
|
+
const { type, value } = typeDef;
|
|
56
|
+
switch (type) {
|
|
55
57
|
case 'Compact':
|
|
56
58
|
case 'Primitive':
|
|
57
59
|
case 'BitSequence':
|
|
@@ -17,19 +17,12 @@ class TypesGen extends index_js_1.BaseTypesGen {
|
|
|
17
17
|
let defTypeOut = '';
|
|
18
18
|
Object.values(this.includedTypes)
|
|
19
19
|
.filter(({ skip, knownType }) => !(skip || knownType))
|
|
20
|
-
.forEach(({
|
|
20
|
+
.forEach(({ nameOut, id }) => {
|
|
21
21
|
defTypeOut += `export type ${nameOut} = ${this.generateType(id, 0, true)};\n\n`;
|
|
22
|
-
if (this.shouldGenerateTypeIn(id)) {
|
|
23
|
-
defTypeOut += `export type ${name} = ${this.generateType(id)};\n\n`;
|
|
24
|
-
}
|
|
25
22
|
});
|
|
26
23
|
const importTypes = this.typeImports.toImports({ excludeModules: ['./types'], useSubPaths });
|
|
27
24
|
const template = (0, utils_js_1.compileTemplate)('typink/templates/types.hbs');
|
|
28
25
|
return (0, utils_js_1.beautifySourceCode)(template({ importTypes, defTypeOut }));
|
|
29
26
|
}
|
|
30
|
-
shouldGenerateTypeIn(id) {
|
|
31
|
-
const { messages } = this.contractMetadata.spec;
|
|
32
|
-
return messages.some((message) => message.returnType.type === id);
|
|
33
|
-
}
|
|
34
27
|
}
|
|
35
28
|
exports.TypesGen = TypesGen;
|
|
@@ -20,3 +20,4 @@ __exportStar(require("./TypesGen.js"), exports);
|
|
|
20
20
|
__exportStar(require("./TxGen.js"), exports);
|
|
21
21
|
__exportStar(require("./ConstructorTxGen.js"), exports);
|
|
22
22
|
__exportStar(require("./ConstructorQueryGen.js"), exports);
|
|
23
|
+
__exportStar(require("./EventsGen.js"), exports);
|
package/cjs/typink/index.js
CHANGED
|
@@ -17,6 +17,7 @@ async function generateContractTypes(metadata, contract, outDir = '.', extension
|
|
|
17
17
|
const txTypesFileName = path_1.default.join(dirPath, `tx.${extension}`);
|
|
18
18
|
const constructorTxTypesFileName = path_1.default.join(dirPath, `constructor-tx.${extension}`);
|
|
19
19
|
const constructorQueryTypesFileName = path_1.default.join(dirPath, `constructor-query.${extension}`);
|
|
20
|
+
const eventsTypesFile = path_1.default.join(dirPath, `events.${extension}`);
|
|
20
21
|
const indexTypesFileName = path_1.default.join(dirPath, `index.${extension}`);
|
|
21
22
|
if (!fs_1.default.existsSync(dirPath)) {
|
|
22
23
|
fs_1.default.mkdirSync(dirPath, { recursive: true });
|
|
@@ -26,12 +27,14 @@ async function generateContractTypes(metadata, contract, outDir = '.', extension
|
|
|
26
27
|
const txGen = new index_js_1.TxGen(contractMetadata, typesGen);
|
|
27
28
|
const constructorTxGen = new index_js_1.ConstructorTxGen(contractMetadata, typesGen);
|
|
28
29
|
const constructorQueryGen = new index_js_1.ConstructorQueryGen(contractMetadata, typesGen);
|
|
29
|
-
const
|
|
30
|
+
const eventsGen = new index_js_1.EventsGen(contractMetadata, typesGen);
|
|
31
|
+
const indexGen = new index_js_1.IndexGen(contractMetadata, typesGen);
|
|
30
32
|
fs_1.default.writeFileSync(typesFileName, await typesGen.generate(useSubPaths));
|
|
31
33
|
fs_1.default.writeFileSync(queryTypesFileName, await queryGen.generate(useSubPaths));
|
|
32
34
|
fs_1.default.writeFileSync(txTypesFileName, await txGen.generate(useSubPaths));
|
|
33
35
|
fs_1.default.writeFileSync(constructorQueryTypesFileName, await constructorQueryGen.generate(useSubPaths));
|
|
34
36
|
fs_1.default.writeFileSync(constructorTxTypesFileName, await constructorTxGen.generate(useSubPaths));
|
|
37
|
+
fs_1.default.writeFileSync(eventsTypesFile, await eventsGen.generate(useSubPaths));
|
|
35
38
|
fs_1.default.writeFileSync(indexTypesFileName, await indexGen.generate(useSubPaths));
|
|
36
39
|
}
|
|
37
40
|
exports.generateContractTypes = generateContractTypes;
|
|
@@ -5,10 +5,17 @@ import { ContractQuery } from './query';
|
|
|
5
5
|
import { ContractTx } from './tx';
|
|
6
6
|
import { ConstructorQuery } from './constructor-query';
|
|
7
7
|
import { ConstructorTx } from './constructor-tx';
|
|
8
|
+
import { ContractEvents } from './events'
|
|
8
9
|
|
|
9
|
-
export interface {{{contractName}}}<ChainApi extends VersionedGenericSubstrateApi = SubstrateApi> extends GenericContractApi<ChainApi> {
|
|
10
|
-
query: ContractQuery<ChainApi[
|
|
11
|
-
tx: ContractTx<ChainApi[
|
|
12
|
-
constructorQuery: ConstructorQuery<ChainApi[
|
|
13
|
-
constructorTx: ConstructorTx<ChainApi[
|
|
10
|
+
export interface {{{contractName}}}<Rv extends RpcVersion = RpcV2, ChainApi extends VersionedGenericSubstrateApi = SubstrateApi> extends GenericContractApi<Rv, ChainApi> {
|
|
11
|
+
query: ContractQuery<ChainApi[Rv]>;
|
|
12
|
+
tx: ContractTx<ChainApi[Rv]>;
|
|
13
|
+
constructorQuery: ConstructorQuery<ChainApi[Rv]>;
|
|
14
|
+
constructorTx: ConstructorTx<ChainApi[Rv]>;
|
|
15
|
+
events: ContractEvents<ChainApi[Rv]>;
|
|
16
|
+
|
|
17
|
+
types: {
|
|
18
|
+
LangError: {{{langErrorName}}};
|
|
19
|
+
ChainApi: ChainApi[Rv];
|
|
20
|
+
};
|
|
14
21
|
}
|
package/cjs/utils.js
CHANGED
|
@@ -36,7 +36,7 @@ exports.WRAPPER_TYPE_REGEX = /^(\w+)<(.*)>$/;
|
|
|
36
36
|
exports.TUPLE_TYPE_REGEX = /^\[(.*)]$/;
|
|
37
37
|
const commentBlock = (...docs) => {
|
|
38
38
|
const flatLines = docs.flat();
|
|
39
|
-
if (flatLines.length === 0 || !flatLines.
|
|
39
|
+
if (flatLines.length === 0 || !flatLines.some((o) => !!o)) {
|
|
40
40
|
return '';
|
|
41
41
|
}
|
|
42
42
|
else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dedot/codegen",
|
|
3
|
-
"version": "0.0.1-next.
|
|
3
|
+
"version": "0.0.1-next.d731b849.13+d731b84",
|
|
4
4
|
"description": "Generate types",
|
|
5
5
|
"author": "Thang X. Vu <thang@coongcrafts.io>",
|
|
6
6
|
"homepage": "https://github.com/dedotdev/dedot/tree/main/packages/codegen",
|
|
@@ -18,22 +18,22 @@
|
|
|
18
18
|
"copy": "cp -R ./src/chaintypes/templates ./dist/chaintypes && cp -R ./src/chaintypes/templates ./dist/cjs/chaintypes && cp -R ./src/typink/templates ./dist/typink && cp -R ./src/typink/templates ./dist/cjs/typink"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@dedot/api": "0.0.1-next.
|
|
22
|
-
"@dedot/codecs": "0.0.1-next.
|
|
23
|
-
"@dedot/providers": "0.0.1-next.
|
|
24
|
-
"@dedot/runtime-specs": "0.0.1-next.
|
|
25
|
-
"@dedot/shape": "0.0.1-next.
|
|
26
|
-
"@dedot/types": "0.0.1-next.
|
|
27
|
-
"@dedot/utils": "0.0.1-next.
|
|
28
|
-
"handlebars": "^4.7.
|
|
29
|
-
"prettier": "^3.
|
|
21
|
+
"@dedot/api": "0.0.1-next.d731b849.13+d731b84",
|
|
22
|
+
"@dedot/codecs": "0.0.1-next.d731b849.13+d731b84",
|
|
23
|
+
"@dedot/providers": "0.0.1-next.d731b849.13+d731b84",
|
|
24
|
+
"@dedot/runtime-specs": "0.0.1-next.d731b849.13+d731b84",
|
|
25
|
+
"@dedot/shape": "0.0.1-next.d731b849.13+d731b84",
|
|
26
|
+
"@dedot/types": "0.0.1-next.d731b849.13+d731b84",
|
|
27
|
+
"@dedot/utils": "0.0.1-next.d731b849.13+d731b84",
|
|
28
|
+
"handlebars": "^4.7.8",
|
|
29
|
+
"prettier": "^3.3.3"
|
|
30
30
|
},
|
|
31
31
|
"publishConfig": {
|
|
32
32
|
"access": "public",
|
|
33
33
|
"directory": "dist"
|
|
34
34
|
},
|
|
35
35
|
"license": "Apache-2.0",
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "d731b849f66c92ca6fa69894e45792c49381d407",
|
|
37
37
|
"module": "./index.js",
|
|
38
38
|
"types": "./index.d.ts",
|
|
39
39
|
"exports": {
|
package/shared/BaseTypesGen.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare abstract class BaseTypesGen {
|
|
|
16
16
|
typeImports: TypeImports;
|
|
17
17
|
skipTypes: string[];
|
|
18
18
|
protected constructor(types: PortableType[]);
|
|
19
|
-
|
|
19
|
+
shouldGenerateTypeIn(_id: TypeId): boolean;
|
|
20
20
|
typeCache: Record<string, string>;
|
|
21
21
|
clearCache(): void;
|
|
22
22
|
includeTypes(): Record<TypeId, NamedType>;
|
package/shared/BaseTypesGen.js
CHANGED
|
@@ -17,6 +17,9 @@ export class BaseTypesGen {
|
|
|
17
17
|
this.typeImports = new TypeImports();
|
|
18
18
|
this.skipTypes = [];
|
|
19
19
|
}
|
|
20
|
+
shouldGenerateTypeIn(_id) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
20
23
|
typeCache = {};
|
|
21
24
|
clearCache() {
|
|
22
25
|
this.typeCache = {};
|
|
@@ -119,9 +122,9 @@ export class BaseTypesGen {
|
|
|
119
122
|
if (!def) {
|
|
120
123
|
throw new Error(`Type def not found ${JSON.stringify(def)}`);
|
|
121
124
|
}
|
|
122
|
-
const {
|
|
123
|
-
const {
|
|
124
|
-
switch (
|
|
125
|
+
const { typeDef, path, docs } = def;
|
|
126
|
+
const { type, value } = typeDef;
|
|
127
|
+
switch (type) {
|
|
125
128
|
case 'Primitive':
|
|
126
129
|
const $codec = findKnownCodec(value.kind);
|
|
127
130
|
if ($codec.nativeType) {
|
|
@@ -195,11 +198,11 @@ export class BaseTypesGen {
|
|
|
195
198
|
const { tagKey, valueKey } = this.getEnumOptions(typeId);
|
|
196
199
|
return membersType
|
|
197
200
|
.map(([keyName, valueType, docs]) => ({
|
|
198
|
-
|
|
201
|
+
type: `${tagKey}: '${keyName}'`,
|
|
199
202
|
value: valueType ? `, ${valueKey}${this.#isOptionalType(valueType) ? '?' : ''}: ${valueType} ` : '',
|
|
200
203
|
docs,
|
|
201
204
|
}))
|
|
202
|
-
.map(({
|
|
205
|
+
.map(({ type, value, docs }) => `${commentBlock(docs)}{ ${type}${value} }`)
|
|
203
206
|
.join(' | ');
|
|
204
207
|
}
|
|
205
208
|
}
|
|
@@ -221,9 +224,9 @@ export class BaseTypesGen {
|
|
|
221
224
|
return this.generateType(value.typeParam, nestedLevel + 1, typeOut);
|
|
222
225
|
case 'Sequence':
|
|
223
226
|
case 'SizedVec': {
|
|
224
|
-
const fixedSize =
|
|
225
|
-
const $innerType = this.types[value.typeParam].
|
|
226
|
-
if ($innerType.
|
|
227
|
+
const fixedSize = type === 'SizedVec' ? `${value.len}` : null;
|
|
228
|
+
const $innerType = this.types[value.typeParam].typeDef;
|
|
229
|
+
if ($innerType.type === 'Primitive' && $innerType.value.kind === 'u8') {
|
|
227
230
|
return fixedSize ? `FixedBytes<${fixedSize}>` : typeOut ? 'Bytes' : 'BytesLike';
|
|
228
231
|
}
|
|
229
232
|
else {
|
|
@@ -232,7 +235,7 @@ export class BaseTypesGen {
|
|
|
232
235
|
}
|
|
233
236
|
}
|
|
234
237
|
default:
|
|
235
|
-
throw new Error(`Invalid type! ${
|
|
238
|
+
throw new Error(`Invalid type! ${type}`);
|
|
236
239
|
}
|
|
237
240
|
}
|
|
238
241
|
generateObjectType(fields, nestedLevel = 0, typeOut = false) {
|
|
@@ -282,31 +285,32 @@ export class BaseTypesGen {
|
|
|
282
285
|
const typeB = this.types[idB];
|
|
283
286
|
if (typeA.path.join('::') !== typeB.path.join('::'))
|
|
284
287
|
return false;
|
|
285
|
-
const {
|
|
286
|
-
const {
|
|
288
|
+
const { typeDef: defA, params: paramsA } = typeA;
|
|
289
|
+
const { typeDef: defB, params: paramsB } = typeB;
|
|
287
290
|
if (!this.#eqlArray(paramsA, paramsB, (valA, valB) => this.#eqlTypeParam(valA, valB))) {
|
|
288
291
|
return false;
|
|
289
292
|
}
|
|
290
|
-
if (defA.
|
|
293
|
+
if (defA.type !== defB.type)
|
|
291
294
|
return false;
|
|
292
|
-
if (defA.
|
|
295
|
+
if (defA.type === 'BitSequence')
|
|
293
296
|
return true;
|
|
294
|
-
if (defA.
|
|
297
|
+
if (defA.type === 'Primitive' && defB.type === 'Primitive') {
|
|
295
298
|
return defA.value.kind === defB.value.kind;
|
|
296
299
|
}
|
|
297
|
-
if ((defA.
|
|
300
|
+
if ((defA.type === 'Compact' && defB.type === 'Compact') ||
|
|
301
|
+
(defA.type === 'Sequence' && defB.type === 'Sequence')) {
|
|
298
302
|
return this.typeEql(defA.value.typeParam, defB.value.typeParam, lvl + 1);
|
|
299
303
|
}
|
|
300
|
-
if (defA.
|
|
304
|
+
if (defA.type === 'SizedVec' && defB.type === 'SizedVec') {
|
|
301
305
|
return defA.value.len === defB.value.len && this.typeEql(defA.value.typeParam, defB.value.typeParam, lvl + 1);
|
|
302
306
|
}
|
|
303
|
-
if (defA.
|
|
307
|
+
if (defA.type === 'Tuple' && defB.type === 'Tuple') {
|
|
304
308
|
return this.#eqlArray(defA.value.fields, defB.value.fields, (val1, val2) => this.typeEql(val1, val2, lvl + 1));
|
|
305
309
|
}
|
|
306
|
-
if (defA.
|
|
310
|
+
if (defA.type === 'Struct' && defB.type === 'Struct') {
|
|
307
311
|
return this.#eqlFields(defA.value.fields, defB.value.fields, lvl);
|
|
308
312
|
}
|
|
309
|
-
if (defA.
|
|
313
|
+
if (defA.type === 'Enum' && defB.type === 'Enum') {
|
|
310
314
|
return this.#eqlArray(defA.value.members, defB.value.members, (val1, val2) => val1.name === val2.name && val1.index === val2.index && this.#eqlFields(val1.fields, val2.fields, lvl));
|
|
311
315
|
}
|
|
312
316
|
return false;
|
|
@@ -332,8 +336,8 @@ export class BaseTypesGen {
|
|
|
332
336
|
if (diffType.path.length > 0) {
|
|
333
337
|
return stringPascalCase(diffType.path.at(-1));
|
|
334
338
|
}
|
|
335
|
-
else if (diffType.type
|
|
336
|
-
return stringPascalCase(diffType.
|
|
339
|
+
else if (diffType.typeDef.type === 'Primitive') {
|
|
340
|
+
return stringPascalCase(diffType.typeDef.value.kind);
|
|
337
341
|
}
|
|
338
342
|
}
|
|
339
343
|
// Last resort!
|
|
@@ -369,6 +373,6 @@ export class BaseTypesGen {
|
|
|
369
373
|
this.typeImports.addOutType(typeName);
|
|
370
374
|
}
|
|
371
375
|
getEnumOptions(_typeId) {
|
|
372
|
-
return { tagKey: '
|
|
376
|
+
return { tagKey: 'type', valueKey: 'value' };
|
|
373
377
|
}
|
|
374
378
|
}
|
|
@@ -4,7 +4,7 @@ export class ConstructorQueryGen extends QueryGen {
|
|
|
4
4
|
generate(useSubPaths = false) {
|
|
5
5
|
this.typesGen.clearCache();
|
|
6
6
|
this.typesGen.typeImports.addKnownType('GenericSubstrateApi');
|
|
7
|
-
this.typesGen.typeImports.addContractType('GenericConstructorQuery', 'GenericConstructorQueryCall', 'ConstructorCallOptions', 'ContractInstantiateResult');
|
|
7
|
+
this.typesGen.typeImports.addContractType('GenericConstructorQuery', 'GenericConstructorQueryCall', 'GenericConstructorCallResult', 'ConstructorCallOptions', 'ContractInstantiateResult');
|
|
8
8
|
const { constructors } = this.contractMetadata.spec;
|
|
9
9
|
const constructorsOut = this.doGenerate(constructors, 'ConstructorCallOptions');
|
|
10
10
|
const importTypes = this.typesGen.typeImports.toImports({ useSubPaths });
|
|
@@ -12,9 +12,12 @@ export class ConstructorQueryGen extends QueryGen {
|
|
|
12
12
|
return beautifySourceCode(template({ importTypes, constructorsOut }));
|
|
13
13
|
}
|
|
14
14
|
generateMethodDef(def) {
|
|
15
|
-
const { args } = def;
|
|
15
|
+
const { args, returnType } = def;
|
|
16
16
|
args.forEach(({ type: { type } }) => this.importType(type));
|
|
17
17
|
const paramsOut = this.generateParamsOut(args);
|
|
18
|
-
|
|
18
|
+
const typeOutRaw = this.typesGen.generateType(returnType.type, 0, true);
|
|
19
|
+
// Unwrap langError result
|
|
20
|
+
const typeOut = typeOutRaw.match(/^(\w+)<(.*), (.*)>$/).at(2);
|
|
21
|
+
return `GenericConstructorQueryCall<ChainApi, (${paramsOut && `${paramsOut},`} options: ConstructorCallOptions) => Promise<GenericConstructorCallResult<${typeOut}, ContractInstantiateResult<ChainApi>>>>`;
|
|
19
22
|
}
|
|
20
23
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ContractEventArg } from '@dedot/contracts';
|
|
2
|
+
import { QueryGen } from './QueryGen.js';
|
|
3
|
+
export declare class EventsGen extends QueryGen {
|
|
4
|
+
#private;
|
|
5
|
+
generate(useSubPaths?: boolean): Promise<string>;
|
|
6
|
+
generateParamsOut(args: ContractEventArg[]): string;
|
|
7
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { stringCamelCase, stringPascalCase } from '@dedot/utils';
|
|
2
|
+
import { beautifySourceCode, commentBlock, compileTemplate } from '../../utils.js';
|
|
3
|
+
import { QueryGen } from './QueryGen.js';
|
|
4
|
+
export class EventsGen extends QueryGen {
|
|
5
|
+
generate(useSubPaths = false) {
|
|
6
|
+
this.typesGen.clearCache();
|
|
7
|
+
this.typesGen.typeImports.addContractType('GenericContractEvents', 'GenericContractEvent');
|
|
8
|
+
const { events } = this.contractMetadata.spec;
|
|
9
|
+
let eventsOut = '';
|
|
10
|
+
events.forEach((event) => {
|
|
11
|
+
const { docs, label } = event;
|
|
12
|
+
const isV5 = 'signature_topic' in event;
|
|
13
|
+
eventsOut += `${commentBlock(docs, '\n', isV5 ? event.signature_topic ? `@signature_topic: ${event.signature_topic}` : '- Anonymous event' : '')}`;
|
|
14
|
+
eventsOut += `${stringPascalCase(label)}: ${this.#generateEventDef(event)};\n\n`;
|
|
15
|
+
});
|
|
16
|
+
const importTypes = this.typesGen.typeImports.toImports({ useSubPaths });
|
|
17
|
+
const template = compileTemplate('typink/templates/events.hbs');
|
|
18
|
+
return beautifySourceCode(template({ importTypes, eventsOut }));
|
|
19
|
+
}
|
|
20
|
+
#generateEventDef(event) {
|
|
21
|
+
const { args, label } = event;
|
|
22
|
+
args.forEach(({ type: { type } }) => this.importType(type));
|
|
23
|
+
const paramsOut = this.generateParamsOut(args);
|
|
24
|
+
return `GenericContractEvent<'${stringPascalCase(label)}', {${paramsOut}}>`;
|
|
25
|
+
}
|
|
26
|
+
generateParamsOut(args) {
|
|
27
|
+
return args
|
|
28
|
+
.map(({ type: { type }, label, docs, indexed }) => `${commentBlock(docs, '\n', `@indexed: ${indexed}`)}${stringCamelCase(label)}: ${this.typesGen.generateType(type, 1)}`)
|
|
29
|
+
.join(', ');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ContractMetadata } from '@dedot/contracts';
|
|
2
|
+
import { TypesGen } from './TypesGen.js';
|
|
2
3
|
export declare class IndexGen {
|
|
3
4
|
contractMetadata: ContractMetadata;
|
|
4
|
-
|
|
5
|
+
typesGen: TypesGen;
|
|
6
|
+
constructor(contractMetadata: ContractMetadata, typesGen: TypesGen);
|
|
5
7
|
generate(useSubPaths?: boolean): Promise<string>;
|
|
6
8
|
}
|
|
@@ -4,17 +4,22 @@ import { beautifySourceCode, compileTemplate } from '../../utils.js';
|
|
|
4
4
|
const SUFFIX = 'contract_api';
|
|
5
5
|
export class IndexGen {
|
|
6
6
|
contractMetadata;
|
|
7
|
-
|
|
7
|
+
typesGen;
|
|
8
|
+
constructor(contractMetadata, typesGen) {
|
|
8
9
|
this.contractMetadata = contractMetadata;
|
|
10
|
+
this.typesGen = typesGen;
|
|
9
11
|
}
|
|
10
12
|
generate(useSubPaths = false) {
|
|
11
13
|
const contractName = stringPascalCase(`${this.contractMetadata.contract.name}_${SUFFIX}`);
|
|
14
|
+
const langErrorId = this.contractMetadata.spec.lang_error.type;
|
|
15
|
+
const langErrorName = this.typesGen.cleanPath(this.contractMetadata.types[langErrorId].type.path);
|
|
12
16
|
const typeImports = new TypeImports();
|
|
13
|
-
typeImports.addKnownType('VersionedGenericSubstrateApi', 'RpcVersion');
|
|
17
|
+
typeImports.addKnownType('VersionedGenericSubstrateApi', 'RpcVersion', 'RpcV2');
|
|
14
18
|
typeImports.addContractType('GenericContractApi');
|
|
15
19
|
typeImports.addChainType('SubstrateApi');
|
|
20
|
+
typeImports.addPortableType(langErrorName);
|
|
16
21
|
const importTypes = typeImports.toImports({ useSubPaths });
|
|
17
22
|
const template = compileTemplate('typink/templates/index.hbs');
|
|
18
|
-
return beautifySourceCode(template({ contractName, importTypes }));
|
|
23
|
+
return beautifySourceCode(template({ contractName, langErrorName, importTypes }));
|
|
19
24
|
}
|
|
20
25
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { ContractMetadata,
|
|
1
|
+
import { ContractMetadata, ContractMessage, ContractMessageArg } from '@dedot/contracts';
|
|
2
2
|
import { TypesGen } from './TypesGen.js';
|
|
3
3
|
export declare class QueryGen {
|
|
4
4
|
contractMetadata: ContractMetadata;
|
|
5
5
|
typesGen: TypesGen;
|
|
6
6
|
constructor(contractMetadata: ContractMetadata, typeGen: TypesGen);
|
|
7
7
|
generate(useSubPaths?: boolean): Promise<string>;
|
|
8
|
-
doGenerate(messages:
|
|
9
|
-
generateMethodDef(def:
|
|
8
|
+
doGenerate(messages: ContractMessage[], optionsTypeName?: string): string;
|
|
9
|
+
generateMethodDef(def: ContractMessage): string;
|
|
10
10
|
generateParamsOut(args: ContractMessageArg[]): string;
|
|
11
11
|
importType(typeId: number): any;
|
|
12
12
|
}
|
|
@@ -32,7 +32,9 @@ export class QueryGen {
|
|
|
32
32
|
this.importType(returnType.type);
|
|
33
33
|
args.forEach(({ type: { type } }) => this.importType(type));
|
|
34
34
|
const paramsOut = this.generateParamsOut(args);
|
|
35
|
-
const
|
|
35
|
+
const typeOutRaw = this.typesGen.generateType(returnType.type, 0, true);
|
|
36
|
+
// Unwrap langError result
|
|
37
|
+
const typeOut = typeOutRaw.match(/^(\w+)<(.*), (.*)>$/).at(2);
|
|
36
38
|
return `GenericContractQueryCall<ChainApi, (${paramsOut && `${paramsOut},`} options: ContractCallOptions) => Promise<GenericContractCallResult<${typeOut}, ContractCallResult<ChainApi>>>>`;
|
|
37
39
|
}
|
|
38
40
|
generateParamsOut(args) {
|
|
@@ -41,14 +43,14 @@ export class QueryGen {
|
|
|
41
43
|
.join(', ');
|
|
42
44
|
}
|
|
43
45
|
importType(typeId) {
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
if (this.typesGen.includedTypes[
|
|
47
|
-
this.typesGen.addTypeImport(this.typesGen.includedTypes[
|
|
46
|
+
const contractType = this.contractMetadata.types[typeId];
|
|
47
|
+
const typeDef = normalizeContractTypeDef(this.contractMetadata.types[typeId].type.def);
|
|
48
|
+
if (this.typesGen.includedTypes[contractType.id]) {
|
|
49
|
+
this.typesGen.addTypeImport(this.typesGen.includedTypes[contractType.id].name);
|
|
48
50
|
return;
|
|
49
51
|
}
|
|
50
|
-
const {
|
|
51
|
-
switch (
|
|
52
|
+
const { type, value } = typeDef;
|
|
53
|
+
switch (type) {
|
|
52
54
|
case 'Compact':
|
|
53
55
|
case 'Primitive':
|
|
54
56
|
case 'BitSequence':
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ContractMessage } from '@dedot/contracts';
|
|
2
2
|
import { QueryGen } from './QueryGen.js';
|
|
3
3
|
export declare class TxGen extends QueryGen {
|
|
4
4
|
generate(useSubPaths?: boolean): Promise<string>;
|
|
5
|
-
generateMethodDef(def:
|
|
5
|
+
generateMethodDef(def: ContractMessage): string;
|
|
6
6
|
}
|
|
@@ -14,18 +14,11 @@ export class TypesGen extends BaseTypesGen {
|
|
|
14
14
|
let defTypeOut = '';
|
|
15
15
|
Object.values(this.includedTypes)
|
|
16
16
|
.filter(({ skip, knownType }) => !(skip || knownType))
|
|
17
|
-
.forEach(({
|
|
17
|
+
.forEach(({ nameOut, id }) => {
|
|
18
18
|
defTypeOut += `export type ${nameOut} = ${this.generateType(id, 0, true)};\n\n`;
|
|
19
|
-
if (this.shouldGenerateTypeIn(id)) {
|
|
20
|
-
defTypeOut += `export type ${name} = ${this.generateType(id)};\n\n`;
|
|
21
|
-
}
|
|
22
19
|
});
|
|
23
20
|
const importTypes = this.typeImports.toImports({ excludeModules: ['./types'], useSubPaths });
|
|
24
21
|
const template = compileTemplate('typink/templates/types.hbs');
|
|
25
22
|
return beautifySourceCode(template({ importTypes, defTypeOut }));
|
|
26
23
|
}
|
|
27
|
-
shouldGenerateTypeIn(id) {
|
|
28
|
-
const { messages } = this.contractMetadata.spec;
|
|
29
|
-
return messages.some((message) => message.returnType.type === id);
|
|
30
|
-
}
|
|
31
24
|
}
|
package/typink/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parseRawMetadata } from '@dedot/contracts';
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
|
-
import { IndexGen, QueryGen, TxGen, TypesGen, ConstructorTxGen, ConstructorQueryGen } from './generator/index.js';
|
|
4
|
+
import { IndexGen, QueryGen, EventsGen, TxGen, TypesGen, ConstructorTxGen, ConstructorQueryGen, } from './generator/index.js';
|
|
5
5
|
export async function generateContractTypes(metadata, contract, outDir = '.', extension = 'd.ts', useSubPaths = false) {
|
|
6
6
|
let contractMetadata = typeof metadata === 'string' ? parseRawMetadata(metadata) : metadata;
|
|
7
7
|
contract = contract || contractMetadata.contract.name;
|
|
@@ -11,6 +11,7 @@ export async function generateContractTypes(metadata, contract, outDir = '.', ex
|
|
|
11
11
|
const txTypesFileName = path.join(dirPath, `tx.${extension}`);
|
|
12
12
|
const constructorTxTypesFileName = path.join(dirPath, `constructor-tx.${extension}`);
|
|
13
13
|
const constructorQueryTypesFileName = path.join(dirPath, `constructor-query.${extension}`);
|
|
14
|
+
const eventsTypesFile = path.join(dirPath, `events.${extension}`);
|
|
14
15
|
const indexTypesFileName = path.join(dirPath, `index.${extension}`);
|
|
15
16
|
if (!fs.existsSync(dirPath)) {
|
|
16
17
|
fs.mkdirSync(dirPath, { recursive: true });
|
|
@@ -20,11 +21,13 @@ export async function generateContractTypes(metadata, contract, outDir = '.', ex
|
|
|
20
21
|
const txGen = new TxGen(contractMetadata, typesGen);
|
|
21
22
|
const constructorTxGen = new ConstructorTxGen(contractMetadata, typesGen);
|
|
22
23
|
const constructorQueryGen = new ConstructorQueryGen(contractMetadata, typesGen);
|
|
23
|
-
const
|
|
24
|
+
const eventsGen = new EventsGen(contractMetadata, typesGen);
|
|
25
|
+
const indexGen = new IndexGen(contractMetadata, typesGen);
|
|
24
26
|
fs.writeFileSync(typesFileName, await typesGen.generate(useSubPaths));
|
|
25
27
|
fs.writeFileSync(queryTypesFileName, await queryGen.generate(useSubPaths));
|
|
26
28
|
fs.writeFileSync(txTypesFileName, await txGen.generate(useSubPaths));
|
|
27
29
|
fs.writeFileSync(constructorQueryTypesFileName, await constructorQueryGen.generate(useSubPaths));
|
|
28
30
|
fs.writeFileSync(constructorTxTypesFileName, await constructorTxGen.generate(useSubPaths));
|
|
31
|
+
fs.writeFileSync(eventsTypesFile, await eventsGen.generate(useSubPaths));
|
|
29
32
|
fs.writeFileSync(indexTypesFileName, await indexGen.generate(useSubPaths));
|
|
30
33
|
}
|
|
@@ -5,10 +5,17 @@ import { ContractQuery } from './query';
|
|
|
5
5
|
import { ContractTx } from './tx';
|
|
6
6
|
import { ConstructorQuery } from './constructor-query';
|
|
7
7
|
import { ConstructorTx } from './constructor-tx';
|
|
8
|
+
import { ContractEvents } from './events'
|
|
8
9
|
|
|
9
|
-
export interface {{{contractName}}}<ChainApi extends VersionedGenericSubstrateApi = SubstrateApi> extends GenericContractApi<ChainApi> {
|
|
10
|
-
query: ContractQuery<ChainApi[
|
|
11
|
-
tx: ContractTx<ChainApi[
|
|
12
|
-
constructorQuery: ConstructorQuery<ChainApi[
|
|
13
|
-
constructorTx: ConstructorTx<ChainApi[
|
|
10
|
+
export interface {{{contractName}}}<Rv extends RpcVersion = RpcV2, ChainApi extends VersionedGenericSubstrateApi = SubstrateApi> extends GenericContractApi<Rv, ChainApi> {
|
|
11
|
+
query: ContractQuery<ChainApi[Rv]>;
|
|
12
|
+
tx: ContractTx<ChainApi[Rv]>;
|
|
13
|
+
constructorQuery: ConstructorQuery<ChainApi[Rv]>;
|
|
14
|
+
constructorTx: ConstructorTx<ChainApi[Rv]>;
|
|
15
|
+
events: ContractEvents<ChainApi[Rv]>;
|
|
16
|
+
|
|
17
|
+
types: {
|
|
18
|
+
LangError: {{{langErrorName}}};
|
|
19
|
+
ChainApi: ChainApi[Rv];
|
|
20
|
+
};
|
|
14
21
|
}
|
package/utils.js
CHANGED
|
@@ -7,7 +7,7 @@ export const WRAPPER_TYPE_REGEX = /^(\w+)<(.*)>$/;
|
|
|
7
7
|
export const TUPLE_TYPE_REGEX = /^\[(.*)]$/;
|
|
8
8
|
export const commentBlock = (...docs) => {
|
|
9
9
|
const flatLines = docs.flat();
|
|
10
|
-
if (flatLines.length === 0 || !flatLines.
|
|
10
|
+
if (flatLines.length === 0 || !flatLines.some((o) => !!o)) {
|
|
11
11
|
return '';
|
|
12
12
|
}
|
|
13
13
|
else {
|