@dedot/codegen 0.17.0 → 0.17.1-next.6d398d60.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/cjs/index.js +1 -0
- package/cjs/sol/generator/ConstructorQueryGen.js +55 -0
- package/cjs/sol/generator/ConstructorTxGen.js +21 -0
- package/cjs/sol/generator/EventsGen.js +38 -0
- package/cjs/sol/generator/IndexGen.js +27 -0
- package/cjs/sol/generator/QueryGen.js +50 -0
- package/cjs/sol/generator/TxGen.js +21 -0
- package/cjs/sol/generator/TypesGen.js +216 -0
- package/cjs/sol/generator/index.js +23 -0
- package/cjs/sol/index.js +42 -0
- package/cjs/typink/generator/ConstructorQueryGen.js +2 -2
- package/cjs/typink/generator/ConstructorTxGen.js +2 -2
- package/cjs/typink/generator/EventsGen.js +2 -2
- package/cjs/typink/generator/IndexGen.js +1 -1
- package/cjs/typink/generator/QueryGen.js +2 -2
- package/cjs/typink/generator/TxGen.js +2 -2
- package/cjs/typink/templates/constructor-query.hbs +1 -1
- package/cjs/typink/templates/constructor-tx.hbs +3 -2
- package/cjs/typink/templates/events.hbs +1 -1
- package/cjs/typink/templates/index.hbs +8 -7
- package/cjs/typink/templates/query.hbs +1 -1
- package/cjs/typink/templates/tx.hbs +1 -1
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +11 -10
- package/sol/generator/ConstructorQueryGen.d.ts +12 -0
- package/sol/generator/ConstructorQueryGen.js +51 -0
- package/sol/generator/ConstructorTxGen.d.ts +6 -0
- package/sol/generator/ConstructorTxGen.js +17 -0
- package/sol/generator/EventsGen.d.ts +10 -0
- package/sol/generator/EventsGen.js +34 -0
- package/sol/generator/IndexGen.d.ts +7 -0
- package/sol/generator/IndexGen.js +23 -0
- package/sol/generator/QueryGen.d.ts +11 -0
- package/sol/generator/QueryGen.js +46 -0
- package/sol/generator/TxGen.d.ts +6 -0
- package/sol/generator/TxGen.js +17 -0
- package/sol/generator/TypesGen.d.ts +15 -0
- package/sol/generator/TypesGen.js +212 -0
- package/sol/generator/index.d.ts +7 -0
- package/sol/generator/index.js +7 -0
- package/sol/index.d.ts +3 -0
- package/sol/index.js +35 -0
- package/typink/generator/ConstructorQueryGen.js +2 -2
- package/typink/generator/ConstructorTxGen.js +2 -2
- package/typink/generator/EventsGen.js +2 -2
- package/typink/generator/IndexGen.js +1 -1
- package/typink/generator/QueryGen.js +2 -2
- package/typink/generator/TxGen.js +2 -2
- package/typink/templates/constructor-query.hbs +1 -1
- package/typink/templates/constructor-tx.hbs +3 -2
- package/typink/templates/events.hbs +1 -1
- package/typink/templates/index.hbs +8 -7
- package/typink/templates/query.hbs +1 -1
- package/typink/templates/tx.hbs +1 -1
|
@@ -9,21 +9,22 @@ import { ContractEvents } from './events.js';
|
|
|
9
9
|
|
|
10
10
|
export * from './types.js';
|
|
11
11
|
|
|
12
|
-
{{{interfaceDocs}}}export interface {{{interfaceName}}}<Rv extends RpcVersion = RpcVersion, ChainApi extends VersionedGenericSubstrateApi = SubstrateApi> extends
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
{{{interfaceDocs}}}export interface {{{interfaceName}}}<Rv extends RpcVersion = RpcVersion, ChainApi extends VersionedGenericSubstrateApi = SubstrateApi> extends InkGenericContractApi<Rv, ChainApi> {
|
|
13
|
+
metadataType: 'ink';
|
|
14
|
+
query: ContractQuery<ChainApi[Rv], 'ink'>;
|
|
15
|
+
tx: ContractTx<ChainApi[Rv], 'ink'>;
|
|
16
|
+
constructorQuery: ConstructorQuery<ChainApi[Rv], 'ink'>;
|
|
17
|
+
constructorTx: ConstructorTx<ChainApi[Rv], {{{interfaceName}}}, 'ink'>;
|
|
18
|
+
events: ContractEvents<ChainApi[Rv], 'ink'>;
|
|
18
19
|
storage: {
|
|
19
20
|
root(): Promise<{{{rootStorageName}}}>;
|
|
20
21
|
lazy(): {{{lazyStorageName}}};
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
types: {
|
|
25
|
+
ChainApi: ChainApi[Rv];
|
|
24
26
|
RootStorage: {{{rootStorageName}}};
|
|
25
27
|
LazyStorage: {{{lazyStorageName}}};
|
|
26
28
|
LangError: {{{langErrorName}}};
|
|
27
|
-
ChainApi: ChainApi[Rv];
|
|
28
29
|
};
|
|
29
30
|
}
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
{{{ importTypes }}}
|
|
4
4
|
|
|
5
|
-
export interface ContractQuery<ChainApi extends GenericSubstrateApi> extends GenericContractQuery<ChainApi> {
|
|
5
|
+
export interface ContractQuery<ChainApi extends GenericSubstrateApi, Type extends MetadataType> extends GenericContractQuery<ChainApi, Type> {
|
|
6
6
|
{{{ queryCallsOut }}}
|
|
7
7
|
}
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
{{{ importTypes }}}
|
|
4
4
|
|
|
5
|
-
export interface ContractTx<ChainApi extends GenericSubstrateApi> extends GenericContractTx<ChainApi> {
|
|
5
|
+
export interface ContractTx<ChainApi extends GenericSubstrateApi, Type extends MetadataType> extends GenericContractTx<ChainApi, Type> {
|
|
6
6
|
{{{ txCallsOut }}}
|
|
7
7
|
}
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dedot/codegen",
|
|
3
|
-
"version": "0.17.0",
|
|
3
|
+
"version": "0.17.1-next.6d398d60.0+6d398d60",
|
|
4
4
|
"description": "Generate types",
|
|
5
5
|
"author": "Thang X. Vu <thang@dedot.dev>",
|
|
6
6
|
"homepage": "https://dedot.dev",
|
|
@@ -14,18 +14,19 @@
|
|
|
14
14
|
"type": "module",
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build": "tsc --project tsconfig.build.json && tsc --project tsconfig.build.cjs.json && yarn copy",
|
|
17
|
+
"test": "npx vitest --watch=false",
|
|
17
18
|
"clean": "rm -rf ./dist && rm -rf ./tsconfig.tsbuildinfo ./tsconfig.build.tsbuildinfo",
|
|
18
19
|
"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
20
|
},
|
|
20
21
|
"dependencies": {
|
|
21
|
-
"@dedot/api": "0.17.0",
|
|
22
|
-
"@dedot/codecs": "0.17.0",
|
|
23
|
-
"@dedot/contracts": "0.17.0",
|
|
24
|
-
"@dedot/providers": "0.17.0",
|
|
25
|
-
"@dedot/runtime-specs": "0.17.0",
|
|
26
|
-
"@dedot/shape": "0.17.0",
|
|
27
|
-
"@dedot/types": "0.17.0",
|
|
28
|
-
"@dedot/utils": "0.17.0",
|
|
22
|
+
"@dedot/api": "0.17.1-next.6d398d60.0+6d398d60",
|
|
23
|
+
"@dedot/codecs": "0.17.1-next.6d398d60.0+6d398d60",
|
|
24
|
+
"@dedot/contracts": "0.17.1-next.6d398d60.0+6d398d60",
|
|
25
|
+
"@dedot/providers": "0.17.1-next.6d398d60.0+6d398d60",
|
|
26
|
+
"@dedot/runtime-specs": "0.17.1-next.6d398d60.0+6d398d60",
|
|
27
|
+
"@dedot/shape": "0.17.1-next.6d398d60.0+6d398d60",
|
|
28
|
+
"@dedot/types": "0.17.1-next.6d398d60.0+6d398d60",
|
|
29
|
+
"@dedot/utils": "0.17.1-next.6d398d60.0+6d398d60",
|
|
29
30
|
"handlebars": "^4.7.8",
|
|
30
31
|
"prettier": "^3.6.2"
|
|
31
32
|
},
|
|
@@ -37,7 +38,7 @@
|
|
|
37
38
|
"node": ">=18"
|
|
38
39
|
},
|
|
39
40
|
"license": "Apache-2.0",
|
|
40
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "6d398d6002387fa7e78ca6df194e5f30595a6be8",
|
|
41
42
|
"module": "./index.js",
|
|
42
43
|
"types": "./index.d.ts",
|
|
43
44
|
"exports": {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TypesGen } from '@dedot/codegen/sol/generator/TypesGen';
|
|
2
|
+
import { SolAbi, SolAbiConstructor } from '@dedot/contracts';
|
|
3
|
+
export declare class ConstructorQueryGen {
|
|
4
|
+
readonly abi: SolAbi;
|
|
5
|
+
readonly typesGen: TypesGen;
|
|
6
|
+
constructor(abi: SolAbi, typesGen: TypesGen);
|
|
7
|
+
generate(useSubPaths?: boolean): Promise<string>;
|
|
8
|
+
doGenerateConstructorFragment(abiItem: SolAbiConstructor, optionsTypeName?: string): string;
|
|
9
|
+
generateMethodDef(abiItem: SolAbiConstructor, optionsParamName?: string): string;
|
|
10
|
+
generateParamsOut(abiItem: SolAbiConstructor): string;
|
|
11
|
+
protected findConstructor(): SolAbiConstructor;
|
|
12
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { stringCamelCase } from '@dedot/utils';
|
|
2
|
+
import { beautifySourceCode, commentBlock, compileTemplate } from '../../utils.js';
|
|
3
|
+
export class ConstructorQueryGen {
|
|
4
|
+
abi;
|
|
5
|
+
typesGen;
|
|
6
|
+
constructor(abi, typesGen) {
|
|
7
|
+
this.abi = abi;
|
|
8
|
+
this.typesGen = typesGen;
|
|
9
|
+
}
|
|
10
|
+
generate(useSubPaths = false) {
|
|
11
|
+
this.typesGen.typeImports.addKnownType('GenericSubstrateApi');
|
|
12
|
+
this.typesGen.typeImports.addContractType('GenericConstructorQuery', 'GenericConstructorQueryCall', 'GenericConstructorCallResult', 'ConstructorCallOptions', 'ContractInstantiateResult', 'MetadataType');
|
|
13
|
+
let constructor = this.findConstructor();
|
|
14
|
+
const constructorsOut = this.doGenerateConstructorFragment(constructor, 'ConstructorCallOptions');
|
|
15
|
+
const importTypes = this.typesGen.typeImports.toImports({ useSubPaths });
|
|
16
|
+
const template = compileTemplate('sol/templates/constructor-query.hbs');
|
|
17
|
+
return beautifySourceCode(template({ importTypes, constructorsOut }));
|
|
18
|
+
}
|
|
19
|
+
doGenerateConstructorFragment(abiItem, optionsTypeName) {
|
|
20
|
+
let callsOut = '';
|
|
21
|
+
const { inputs = [] } = abiItem;
|
|
22
|
+
// In case there is an arg has label `options`,
|
|
23
|
+
// we use the name `_options` for the last options param
|
|
24
|
+
// This is just and edge case, so this approach works for now
|
|
25
|
+
const optionsParamName = inputs.some(({ name }) => name === 'options') ? '_options' : 'options';
|
|
26
|
+
callsOut += `${commentBlock(inputs.map((input, idx) => `@param {${this.typesGen.generateType(input, abiItem, 1)}} ${stringCamelCase(input.name || `arg${idx}`)}`), optionsTypeName ? `@param {${optionsTypeName}} ${optionsParamName}` : '')}`;
|
|
27
|
+
callsOut += `new: ${this.generateMethodDef(abiItem, optionsParamName)};\n\n`;
|
|
28
|
+
return callsOut;
|
|
29
|
+
}
|
|
30
|
+
generateMethodDef(abiItem, optionsParamName = 'options') {
|
|
31
|
+
const paramsOut = this.generateParamsOut(abiItem);
|
|
32
|
+
return `GenericConstructorQueryCall<ChainApi, (${paramsOut && `${paramsOut},`} ${optionsParamName}?: ConstructorCallOptions) => Promise<GenericConstructorCallResult<[], ContractInstantiateResult<ChainApi>>>, Type>`;
|
|
33
|
+
}
|
|
34
|
+
generateParamsOut(abiItem) {
|
|
35
|
+
return abiItem.inputs
|
|
36
|
+
.map((input, idx) => `${stringCamelCase(input.name || `arg${idx}`)}: ${this.typesGen.generateType(input, abiItem, 1)}`)
|
|
37
|
+
.join(', ');
|
|
38
|
+
}
|
|
39
|
+
findConstructor() {
|
|
40
|
+
let constructor = this.abi.find((item) => item.type === 'constructor');
|
|
41
|
+
// Fallback to default constructor
|
|
42
|
+
if (!constructor) {
|
|
43
|
+
constructor = {
|
|
44
|
+
inputs: [],
|
|
45
|
+
stateMutability: 'nonpayable',
|
|
46
|
+
type: 'constructor',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return constructor;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SolAbiConstructor } from '@dedot/contracts';
|
|
2
|
+
import { ConstructorQueryGen } from './ConstructorQueryGen.js';
|
|
3
|
+
export declare class ConstructorTxGen extends ConstructorQueryGen {
|
|
4
|
+
generate(useSubPaths?: boolean): Promise<string>;
|
|
5
|
+
generateMethodDef(abiItem: SolAbiConstructor, optionsParamName?: string): string;
|
|
6
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { beautifySourceCode, compileTemplate } from '../../utils.js';
|
|
2
|
+
import { ConstructorQueryGen } from './ConstructorQueryGen.js';
|
|
3
|
+
export class ConstructorTxGen extends ConstructorQueryGen {
|
|
4
|
+
generate(useSubPaths = false) {
|
|
5
|
+
this.typesGen.typeImports.addKnownType('GenericSubstrateApi');
|
|
6
|
+
this.typesGen.typeImports.addContractType('GenericConstructorTx', 'SolGenericContractApi', 'GenericConstructorTxCall', 'ConstructorTxOptions', 'GenericInstantiateSubmittableExtrinsic', 'MetadataType');
|
|
7
|
+
let constructor = this.findConstructor();
|
|
8
|
+
const constructorsOut = this.doGenerateConstructorFragment(constructor, 'ConstructorTxOptions');
|
|
9
|
+
const importTypes = this.typesGen.typeImports.toImports({ useSubPaths });
|
|
10
|
+
const template = compileTemplate('sol/templates/constructor-tx.hbs');
|
|
11
|
+
return beautifySourceCode(template({ importTypes, constructorsOut }));
|
|
12
|
+
}
|
|
13
|
+
generateMethodDef(abiItem, optionsParamName = 'options') {
|
|
14
|
+
const paramsOut = this.generateParamsOut(abiItem);
|
|
15
|
+
return `GenericConstructorTxCall<ChainApi, (${paramsOut && `${paramsOut},`} ${optionsParamName}?: ConstructorTxOptions) => GenericInstantiateSubmittableExtrinsic<ChainApi, ContractApi>, Type>`;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SolAbi, SolAbiEvent } from '@dedot/contracts';
|
|
2
|
+
import { TypesGen } from './TypesGen.js';
|
|
3
|
+
export declare class EventsGen {
|
|
4
|
+
#private;
|
|
5
|
+
readonly abi: SolAbi;
|
|
6
|
+
readonly typesGen: TypesGen;
|
|
7
|
+
constructor(abi: SolAbi, typesGen: TypesGen);
|
|
8
|
+
generate(useSubPaths?: boolean): Promise<string>;
|
|
9
|
+
generateParamsOut(abiItem: SolAbiEvent): string;
|
|
10
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { stringCamelCase, stringPascalCase } from '@dedot/utils';
|
|
2
|
+
import { beautifySourceCode, commentBlock, compileTemplate } from '../../utils.js';
|
|
3
|
+
export class EventsGen {
|
|
4
|
+
abi;
|
|
5
|
+
typesGen;
|
|
6
|
+
constructor(abi, typesGen) {
|
|
7
|
+
this.abi = abi;
|
|
8
|
+
this.typesGen = typesGen;
|
|
9
|
+
}
|
|
10
|
+
generate(useSubPaths = false) {
|
|
11
|
+
this.typesGen.typeImports.addKnownType('GenericSubstrateApi');
|
|
12
|
+
this.typesGen.typeImports.addContractType('GenericContractEvents', 'GenericContractEvent', 'MetadataType');
|
|
13
|
+
const events = this.abi.filter((o) => o.type === 'event');
|
|
14
|
+
let eventsOut = '';
|
|
15
|
+
events.forEach((event) => {
|
|
16
|
+
const { name, anonymous } = event;
|
|
17
|
+
eventsOut += `${stringPascalCase(name)}: ${this.#generateEventDef(event)};\n\n`;
|
|
18
|
+
});
|
|
19
|
+
const importTypes = this.typesGen.typeImports.toImports({ useSubPaths });
|
|
20
|
+
const template = compileTemplate('sol/templates/events.hbs');
|
|
21
|
+
return beautifySourceCode(template({ importTypes, eventsOut }));
|
|
22
|
+
}
|
|
23
|
+
#generateEventDef(abiItem) {
|
|
24
|
+
const { name } = abiItem;
|
|
25
|
+
const paramsOut = this.generateParamsOut(abiItem);
|
|
26
|
+
return `GenericContractEvent<'${stringPascalCase(name)}', {${paramsOut}}, Type>`;
|
|
27
|
+
}
|
|
28
|
+
generateParamsOut(abiItem) {
|
|
29
|
+
const { inputs } = abiItem;
|
|
30
|
+
return inputs
|
|
31
|
+
.map((o, idx) => `${commentBlock(`@indexed: ${o.indexed}`)}${stringCamelCase(o.name || `arg${idx}`)}: ${this.typesGen.generateType(o, abiItem, 1)}`)
|
|
32
|
+
.join(', ');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { TypeImports } from '../../shared/index.js';
|
|
2
|
+
import { beautifySourceCode, compileTemplate } from '../../utils.js';
|
|
3
|
+
export class IndexGen {
|
|
4
|
+
interfaceName;
|
|
5
|
+
typesGen;
|
|
6
|
+
constructor(interfaceName, typesGen) {
|
|
7
|
+
this.interfaceName = interfaceName;
|
|
8
|
+
this.typesGen = typesGen;
|
|
9
|
+
}
|
|
10
|
+
generate(useSubPaths = false) {
|
|
11
|
+
const interfaceName = this.interfaceName;
|
|
12
|
+
const typeImports = new TypeImports();
|
|
13
|
+
typeImports.addKnownType('VersionedGenericSubstrateApi', 'RpcVersion', 'RpcV2');
|
|
14
|
+
typeImports.addContractType('SolGenericContractApi', 'SolRegistry');
|
|
15
|
+
typeImports.addChainType('SubstrateApi');
|
|
16
|
+
const importTypes = typeImports.toImports({ useSubPaths });
|
|
17
|
+
const template = compileTemplate('sol/templates/index.hbs');
|
|
18
|
+
return beautifySourceCode(template({
|
|
19
|
+
interfaceName,
|
|
20
|
+
importTypes,
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SolAbi, SolAbiFunction } from '@dedot/contracts';
|
|
2
|
+
import { TypesGen } from './TypesGen.js';
|
|
3
|
+
export declare class QueryGen {
|
|
4
|
+
readonly abi: SolAbi;
|
|
5
|
+
readonly typesGen: TypesGen;
|
|
6
|
+
constructor(abi: SolAbi, typesGen: TypesGen);
|
|
7
|
+
generate(useSubPaths?: boolean): Promise<string>;
|
|
8
|
+
doGenerate(functions: SolAbiFunction[], optionsTypeName?: string): string;
|
|
9
|
+
generateMethodDef(abiItem: SolAbiFunction, optionsParamName?: string): string;
|
|
10
|
+
generateParamsOut(abiItem: SolAbiFunction): string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { normalizeLabel } from '@dedot/contracts';
|
|
2
|
+
import { stringCamelCase } from '@dedot/utils';
|
|
3
|
+
import { beautifySourceCode, commentBlock, compileTemplate } from '../../utils.js';
|
|
4
|
+
export class QueryGen {
|
|
5
|
+
abi;
|
|
6
|
+
typesGen;
|
|
7
|
+
constructor(abi, typesGen) {
|
|
8
|
+
this.abi = abi;
|
|
9
|
+
this.typesGen = typesGen;
|
|
10
|
+
}
|
|
11
|
+
generate(useSubPaths = false) {
|
|
12
|
+
this.typesGen.typeImports.addKnownType('GenericSubstrateApi');
|
|
13
|
+
this.typesGen.typeImports.addContractType('GenericContractQuery', 'GenericContractQueryCall', 'ContractCallOptions', 'GenericContractCallResult', 'ContractCallResult', 'MetadataType');
|
|
14
|
+
const functions = this.abi.filter((item) => item.type === 'function');
|
|
15
|
+
const queryCallsOut = this.doGenerate(functions, 'ContractCallOptions');
|
|
16
|
+
const importTypes = this.typesGen.typeImports.toImports({ useSubPaths });
|
|
17
|
+
const template = compileTemplate('sol/templates/query.hbs');
|
|
18
|
+
return beautifySourceCode(template({ importTypes, queryCallsOut }));
|
|
19
|
+
}
|
|
20
|
+
doGenerate(functions, optionsTypeName) {
|
|
21
|
+
let callsOut = '';
|
|
22
|
+
functions.forEach((def) => {
|
|
23
|
+
const { inputs, name } = def;
|
|
24
|
+
// In case there is an arg has label `options`,
|
|
25
|
+
// we use the name `_options` for the last options param
|
|
26
|
+
// This is just and edge case, so this approach works for now
|
|
27
|
+
const optionsParamName = inputs.some(({ name }) => name === 'options') ? '_options' : 'options';
|
|
28
|
+
callsOut += `${commentBlock(inputs.map((input, idx) => `@param {${this.typesGen.generateType(input, def, 1)}} ${stringCamelCase(input.name || `arg${idx}`)}`), optionsTypeName ? `@param {${optionsTypeName}} ${optionsParamName}` : '')}`;
|
|
29
|
+
callsOut += `${normalizeLabel(name)}: ${this.generateMethodDef(def, optionsParamName)};\n\n`;
|
|
30
|
+
});
|
|
31
|
+
return callsOut;
|
|
32
|
+
}
|
|
33
|
+
generateMethodDef(abiItem, optionsParamName = 'options') {
|
|
34
|
+
const { outputs } = abiItem;
|
|
35
|
+
const paramsOut = this.generateParamsOut(abiItem);
|
|
36
|
+
const typeOutInner = `${outputs.map((o) => this.typesGen.generateType(o, abiItem, 1, true)).join(',')}`;
|
|
37
|
+
// If there is only one output, we don't need to wrap it in a tuple, for user-friendly
|
|
38
|
+
const typeOut = outputs.length === 1 ? typeOutInner : `[${typeOutInner}]`;
|
|
39
|
+
return `GenericContractQueryCall<ChainApi, (${paramsOut && `${paramsOut},`} ${optionsParamName}?: ContractCallOptions) => Promise<GenericContractCallResult<${typeOut}, ContractCallResult<ChainApi>>>, Type>`;
|
|
40
|
+
}
|
|
41
|
+
generateParamsOut(abiItem) {
|
|
42
|
+
return abiItem.inputs
|
|
43
|
+
.map((input, idx) => `${stringCamelCase(input.name || `arg${idx}`)}: ${this.typesGen.generateType(input, abiItem, 1)}`)
|
|
44
|
+
.join(', ');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SolAbiFunction } from '@dedot/contracts';
|
|
2
|
+
import { QueryGen } from './QueryGen.js';
|
|
3
|
+
export declare class TxGen extends QueryGen {
|
|
4
|
+
generate(useSubPaths?: boolean): Promise<string>;
|
|
5
|
+
generateMethodDef(abiItem: SolAbiFunction, optionsParamName?: string): string;
|
|
6
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { beautifySourceCode, compileTemplate } from '../../utils.js';
|
|
2
|
+
import { QueryGen } from './QueryGen.js';
|
|
3
|
+
export class TxGen extends QueryGen {
|
|
4
|
+
generate(useSubPaths = false) {
|
|
5
|
+
this.typesGen.typeImports.addKnownType('GenericSubstrateApi');
|
|
6
|
+
this.typesGen.typeImports.addContractType('GenericContractTx', 'GenericContractTxCall', 'ContractTxOptions', 'ContractSubmittableExtrinsic', 'MetadataType');
|
|
7
|
+
const txFunctions = this.abi.filter((item) => item.type === 'function' && item.stateMutability !== 'view');
|
|
8
|
+
const txCallsOut = this.doGenerate(txFunctions, 'ContractTxOptions');
|
|
9
|
+
const importTypes = this.typesGen.typeImports.toImports({ useSubPaths });
|
|
10
|
+
const template = compileTemplate('sol/templates/tx.hbs');
|
|
11
|
+
return beautifySourceCode(template({ importTypes, txCallsOut }));
|
|
12
|
+
}
|
|
13
|
+
generateMethodDef(abiItem, optionsParamName = 'options') {
|
|
14
|
+
const paramsOut = this.generateParamsOut(abiItem);
|
|
15
|
+
return `GenericContractTxCall<ChainApi, (${paramsOut && `${paramsOut},`} ${optionsParamName}?: ContractTxOptions) => ContractSubmittableExtrinsic<ChainApi>, Type>`;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SolAbi, SolAbiItem, SolAbiTypeDef } from '@dedot/contracts';
|
|
2
|
+
import { TypeImports } from '../../shared/TypeImports.js';
|
|
3
|
+
export declare const SUPPORTED_SOLIDITY_TYPES: RegExp[];
|
|
4
|
+
export declare const BASIC_KNOWN_TYPES: RegExp[];
|
|
5
|
+
export declare class TypesGen {
|
|
6
|
+
#private;
|
|
7
|
+
readonly abi: SolAbi;
|
|
8
|
+
typeImports: TypeImports;
|
|
9
|
+
constructor(abi: SolAbi);
|
|
10
|
+
generate(useSubPaths?: boolean): Promise<string>;
|
|
11
|
+
generateTypeName(typeDef: SolAbiTypeDef, abiItem: SolAbiItem, typeOut?: boolean): string;
|
|
12
|
+
generateType(typeDef: SolAbiTypeDef, abiItem?: SolAbiItem, nestedLevel?: number, typeOut?: boolean): string;
|
|
13
|
+
generateObjectType(components: SolAbiTypeDef[], nestedLevel?: number, typeOut?: boolean): string;
|
|
14
|
+
addTypeImport(typeName: string | string[]): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { stringPascalCase } from '@dedot/utils';
|
|
2
|
+
import { TypeImports } from '../../shared/TypeImports.js';
|
|
3
|
+
import { beautifySourceCode, compileTemplate, isNativeType } from '../../utils.js';
|
|
4
|
+
const INT_TYPES = /^int(\d+)?(\[(\d+)?])*?$/;
|
|
5
|
+
const UINT_TYPES = /^uint(\d+)?(\[(\d+)?])*?$/;
|
|
6
|
+
const BYTES_TYPES = /^bytes(\d+)?(\[(\d+)?])*?$/;
|
|
7
|
+
const FIXED_TYPES = /^fixed(\d+x\d+)?(\[(\d+)?])*?$/;
|
|
8
|
+
const UNFIXED_TYPES = /^ufixed(\d+x\d+)?(\[(\d+)?])*?$/;
|
|
9
|
+
const STRING_TYPES = /^string(\[(\d+)?])*?$/;
|
|
10
|
+
const BOOL_TYPES = /^bool(\[(\d+)?])*?$/;
|
|
11
|
+
const ADDRESS_TYPES = /^address(\[(\d+)?])*?$/;
|
|
12
|
+
const FUNCTION_TYPES = /^function(\[(\d+)?])*?$/;
|
|
13
|
+
const COMPONENT_TYPES = /^tuple(\[(\d+)?])*?$/;
|
|
14
|
+
const ARRAY_DIM = /\[(\d+)?]/g;
|
|
15
|
+
const ONLY_ARRAY_DIM = /^\[(\d+)?]$/;
|
|
16
|
+
export const SUPPORTED_SOLIDITY_TYPES = [
|
|
17
|
+
INT_TYPES,
|
|
18
|
+
UINT_TYPES,
|
|
19
|
+
BYTES_TYPES,
|
|
20
|
+
FIXED_TYPES,
|
|
21
|
+
UNFIXED_TYPES,
|
|
22
|
+
STRING_TYPES,
|
|
23
|
+
BOOL_TYPES,
|
|
24
|
+
ADDRESS_TYPES,
|
|
25
|
+
FUNCTION_TYPES,
|
|
26
|
+
COMPONENT_TYPES,
|
|
27
|
+
];
|
|
28
|
+
export const BASIC_KNOWN_TYPES = [
|
|
29
|
+
/^(H160)$/,
|
|
30
|
+
/^(FixedBytes)<(\d+)>$/,
|
|
31
|
+
/^(Bytes)$/,
|
|
32
|
+
/^(BytesLike)$/,
|
|
33
|
+
/^(Fixed)<(\d+),(\d+)>$/,
|
|
34
|
+
/^(UFixed)<(\d+),(\d+)>$/,
|
|
35
|
+
/^(FixedArray)$/,
|
|
36
|
+
];
|
|
37
|
+
export class TypesGen {
|
|
38
|
+
abi;
|
|
39
|
+
typeImports;
|
|
40
|
+
constructor(abi) {
|
|
41
|
+
this.abi = abi;
|
|
42
|
+
this.typeImports = new TypeImports();
|
|
43
|
+
}
|
|
44
|
+
generate(useSubPaths = false) {
|
|
45
|
+
let defTypeOut = '';
|
|
46
|
+
this.abi.forEach((abiItem) => {
|
|
47
|
+
if (abiItem.type === 'fallback' || abiItem.type === 'receive')
|
|
48
|
+
return;
|
|
49
|
+
if (abiItem.type === 'function' || abiItem.type === 'constructor' || abiItem.type === 'event') {
|
|
50
|
+
const { inputs } = abiItem;
|
|
51
|
+
inputs
|
|
52
|
+
.filter((o) => o.components && o.components.length > 0)
|
|
53
|
+
.forEach((o) => {
|
|
54
|
+
defTypeOut += `export type ${this.generateTypeName(o, abiItem)} = ${this.generateType(o, abiItem, 0)};\n\n`;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
if (abiItem.type === 'function') {
|
|
58
|
+
const { outputs } = abiItem;
|
|
59
|
+
outputs
|
|
60
|
+
.filter((o) => o.components && o.components.length > 0)
|
|
61
|
+
.forEach((o) => {
|
|
62
|
+
defTypeOut += `export type ${this.generateTypeName(o, abiItem, true)} = ${this.generateType(o, abiItem, 0, true)};\n\n`;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
const importTypes = this.typeImports.toImports({ excludeModules: ['./types.js'], useSubPaths });
|
|
67
|
+
const template = compileTemplate('sol/templates/types.hbs');
|
|
68
|
+
return beautifySourceCode(template({ importTypes, defTypeOut }));
|
|
69
|
+
}
|
|
70
|
+
generateTypeName(typeDef, abiItem, typeOut = false) {
|
|
71
|
+
if (abiItem.type === 'fallback' || abiItem.type === 'receive')
|
|
72
|
+
return '';
|
|
73
|
+
if (COMPONENT_TYPES.test(typeDef.type)) {
|
|
74
|
+
const baseName = abiItem.type === 'constructor'
|
|
75
|
+
? `${typeDef.name}_input`
|
|
76
|
+
: `${abiItem.name}_${typeDef.name}_${typeOut ? 'output' : 'input'}`;
|
|
77
|
+
return stringPascalCase(baseName);
|
|
78
|
+
}
|
|
79
|
+
return '';
|
|
80
|
+
}
|
|
81
|
+
generateType(typeDef, abiItem, nestedLevel = 0, typeOut = false) {
|
|
82
|
+
if (nestedLevel > 0 && abiItem) {
|
|
83
|
+
let typeName = this.generateTypeName(typeDef, abiItem, typeOut);
|
|
84
|
+
if (typeName.length === 0) {
|
|
85
|
+
typeName = this.#generateType(typeDef, nestedLevel, typeOut);
|
|
86
|
+
return typeName;
|
|
87
|
+
}
|
|
88
|
+
this.addTypeImport(typeName);
|
|
89
|
+
return typeName;
|
|
90
|
+
}
|
|
91
|
+
return this.#generateType(typeDef, nestedLevel, typeOut);
|
|
92
|
+
}
|
|
93
|
+
#generateType(typeDef, nestedLevel = 0, typeOut = false) {
|
|
94
|
+
const { type } = typeDef;
|
|
95
|
+
let baseType = this.#generateBaseType(typeDef, nestedLevel, typeOut);
|
|
96
|
+
if (!COMPONENT_TYPES.test(type)) {
|
|
97
|
+
// baseType of component types are all generated types, eg: { a: bigint, b: string }
|
|
98
|
+
// So we don't import them here.
|
|
99
|
+
this.addTypeImport(baseType);
|
|
100
|
+
}
|
|
101
|
+
// Match all array dimensions
|
|
102
|
+
const dimensions = type.match(ARRAY_DIM);
|
|
103
|
+
dimensions
|
|
104
|
+
// Match each dimension to see if fixed array or dynamic array (eg: [3] vs [])
|
|
105
|
+
?.map((o) => o.match(ONLY_ARRAY_DIM))
|
|
106
|
+
.forEach(([_, n]) => {
|
|
107
|
+
if (n) {
|
|
108
|
+
this.addTypeImport('FixedArray');
|
|
109
|
+
baseType = `FixedArray<${baseType}, ${n}>`;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
baseType = isNativeType(baseType.replaceAll('[]', '')) ? `${baseType}[]` : `Array<${baseType}>`;
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
return baseType;
|
|
116
|
+
}
|
|
117
|
+
#generateBaseType(typeDef, nestedLevel = 0, typeOut = false) {
|
|
118
|
+
const { type } = typeDef;
|
|
119
|
+
if (INT_TYPES.test(type)) {
|
|
120
|
+
const [_, bitsStr] = type.match(INT_TYPES);
|
|
121
|
+
// Default to 256 when unspecified
|
|
122
|
+
const bits = bitsStr ? parseInt(bitsStr) : 256;
|
|
123
|
+
const isSafeNumber = bits <= 48;
|
|
124
|
+
return isSafeNumber ? `number` : 'bigint';
|
|
125
|
+
}
|
|
126
|
+
else if (UINT_TYPES.test(type)) {
|
|
127
|
+
const [_, bitsStr] = type.match(UINT_TYPES);
|
|
128
|
+
// Default to 256 when unspecified
|
|
129
|
+
const bits = bitsStr ? parseInt(bitsStr) : 256;
|
|
130
|
+
const isSafeNumber = bits <= 48;
|
|
131
|
+
return isSafeNumber ? `number` : 'bigint';
|
|
132
|
+
}
|
|
133
|
+
else if (BYTES_TYPES.test(type)) {
|
|
134
|
+
const [_, n] = type.match(BYTES_TYPES);
|
|
135
|
+
if (n) {
|
|
136
|
+
return `FixedBytes<${n}>`;
|
|
137
|
+
}
|
|
138
|
+
if (typeOut) {
|
|
139
|
+
return `Bytes`;
|
|
140
|
+
}
|
|
141
|
+
return `BytesLike`;
|
|
142
|
+
}
|
|
143
|
+
else if (BOOL_TYPES.test(type)) {
|
|
144
|
+
return 'boolean';
|
|
145
|
+
}
|
|
146
|
+
else if (STRING_TYPES.test(type)) {
|
|
147
|
+
return 'string';
|
|
148
|
+
}
|
|
149
|
+
else if (COMPONENT_TYPES.test(type)) {
|
|
150
|
+
const { components = [] } = typeDef;
|
|
151
|
+
if (components.length === 0) {
|
|
152
|
+
return '[]';
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
const objectType = this.generateObjectType(components, nestedLevel + 1, typeOut);
|
|
156
|
+
return `${objectType}`;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else if (ADDRESS_TYPES.test(type)) {
|
|
160
|
+
return `H160`;
|
|
161
|
+
}
|
|
162
|
+
else if (FUNCTION_TYPES.test(type)) {
|
|
163
|
+
// Function type is an address (20 bytes) followed by a function selector (4 bytes).
|
|
164
|
+
// Ref: https://docs.soliditylang.org/en/latest/abi-spec.html#:~:text=function%3A%20an%20address%20(20%20bytes)%20followed%20by%20a%20function%20selector%20(4%20bytes).%20Encoded%20identical%20to%20bytes24.
|
|
165
|
+
return `FixedBytes<24>`;
|
|
166
|
+
}
|
|
167
|
+
else if (FIXED_TYPES.test(type)) {
|
|
168
|
+
const [_, denotation] = type.match(FIXED_TYPES);
|
|
169
|
+
// Ref: https://docs.soliditylang.org/en/latest/abi-spec.html#:~:text=fixed%2C%20ufixed%3A%20synonyms%20for%20fixed128x18%2C%20ufixed128x18%20respectively.%20For%20computing%20the%20function%20selector%2C%20fixed128x18%20and%20ufixed128x18%20have%20to%20be%20used.
|
|
170
|
+
const [m, n] = denotation ? denotation.split('x').map((s) => parseInt(s)) : [128, 18];
|
|
171
|
+
return `Fixed<${m},${n}>`;
|
|
172
|
+
}
|
|
173
|
+
else if (UNFIXED_TYPES.test(type)) {
|
|
174
|
+
const [_, denotation] = type.match(UNFIXED_TYPES);
|
|
175
|
+
// Ref: https://docs.soliditylang.org/en/latest/abi-spec.html#:~:text=fixed%2C%20ufixed%3A%20synonyms%20for%20fixed128x18%2C%20ufixed128x18%20respectively.%20For%20computing%20the%20function%20selector%2C%20fixed128x18%20and%20ufixed128x18%20have%20to%20be%20used.
|
|
176
|
+
const [m, n] = denotation ? denotation.split('x').map((s) => parseInt(s)) : [128, 18];
|
|
177
|
+
return `UFixed<${m},${n}>`;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
throw new Error(`Unsupported Solidity type: ${type}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
generateObjectType(components, nestedLevel = 0, typeOut = false) {
|
|
184
|
+
const props = components.map((typeDef) => {
|
|
185
|
+
const type = this.generateType(typeDef, undefined, nestedLevel + 1, typeOut);
|
|
186
|
+
return {
|
|
187
|
+
name: typeDef.name,
|
|
188
|
+
type,
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
if (props.length > 0 && props.at(0).name.length === 0) {
|
|
192
|
+
return `[${props.map(({ type }) => `${type}`).join(', ')}]`;
|
|
193
|
+
}
|
|
194
|
+
return `{${props.map(({ name, type }) => `${name}: ${type}`).join(',\n')}}`;
|
|
195
|
+
}
|
|
196
|
+
addTypeImport(typeName) {
|
|
197
|
+
if (Array.isArray(typeName)) {
|
|
198
|
+
typeName.forEach((one) => this.addTypeImport(one));
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (isNativeType(typeName)) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const re = BASIC_KNOWN_TYPES.find((re) => typeName.match(re));
|
|
205
|
+
if (re) {
|
|
206
|
+
const typeBase = typeName.match(re)[1];
|
|
207
|
+
this.typeImports.addCodecType(typeBase);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
this.typeImports.addPortableType(typeName);
|
|
211
|
+
}
|
|
212
|
+
}
|
package/sol/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { SolAbi } from '@dedot/contracts';
|
|
2
|
+
import { GeneratedResult } from '../types.js';
|
|
3
|
+
export declare function generateSolContractTypes(abi: SolAbi | string, contract?: string | undefined, outDir?: string, extension?: string, useSubPaths?: boolean): Promise<GeneratedResult>;
|