@algorandfoundation/algokit-client-generator 2.6.0 → 2.6.1-beta.1
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/bin/cli.mjs +4 -0
- package/cli.cjs +75 -0
- package/cli.d.ts +0 -1
- package/cli.mjs +54 -0
- package/client/app-types.cjs +152 -0
- package/client/app-types.d.ts +0 -1
- package/client/app-types.mjs +131 -0
- package/client/call-client.cjs +332 -0
- package/client/call-client.d.ts +0 -1
- package/client/{call-client.js → call-client.mjs} +107 -135
- package/client/call-composer-types.cjs +141 -0
- package/client/call-composer-types.d.ts +0 -1
- package/client/{call-composer-types.js → call-composer-types.mjs} +33 -58
- package/client/call-composer.cjs +145 -0
- package/client/call-composer.d.ts +0 -1
- package/client/call-composer.mjs +124 -0
- package/client/call-factory.cjs +138 -0
- package/client/call-factory.d.ts +0 -1
- package/client/{call-factory.js → call-factory.mjs} +31 -56
- package/client/deploy-types.cjs +94 -0
- package/client/deploy-types.d.ts +0 -1
- package/client/deploy-types.mjs +91 -0
- package/client/generate.cjs +37 -0
- package/client/generate.d.ts +0 -1
- package/client/generate.mjs +35 -0
- package/client/generator-context.cjs +37 -0
- package/client/generator-context.d.ts +0 -1
- package/client/generator-context.mjs +16 -0
- package/client/helpers/{get-call-config-summary.js → get-call-config-summary.cjs} +7 -25
- package/client/helpers/get-call-config-summary.d.ts +1 -2
- package/client/helpers/get-call-config-summary.mjs +54 -0
- package/client/helpers/{get-equivalent-type.js → get-equivalent-type.cjs} +20 -20
- package/client/helpers/get-equivalent-type.d.ts +0 -1
- package/client/helpers/get-equivalent-type.mjs +56 -0
- package/client/{imports.js → imports.cjs} +3 -4
- package/client/imports.d.ts +0 -1
- package/client/imports.mjs +27 -0
- package/client/{utility-types.js → utility-types.cjs} +26 -25
- package/client/utility-types.d.ts +0 -1
- package/client/utility-types.mjs +47 -0
- package/dev.d.ts +0 -1
- package/index.cjs +13 -0
- package/index.d.ts +0 -1
- package/index.mjs +3 -0
- package/output/{writer.js → writer.cjs} +44 -38
- package/output/writer.d.ts +0 -1
- package/output/writer.mjs +139 -0
- package/package.json +7 -4
- package/schema/application.schema.json.cjs +374 -0
- package/schema/application.schema.json.mjs +363 -0
- package/schema/contract.schema.json.cjs +159 -0
- package/schema/contract.schema.json.mjs +148 -0
- package/schema/load.cjs +25 -0
- package/schema/load.d.ts +0 -1
- package/schema/load.mjs +22 -0
- package/tests/approval-tests.spec.d.ts +0 -1
- package/tests/util.d.ts +1 -0
- package/util/boom.cjs +7 -0
- package/util/boom.d.ts +0 -1
- package/util/boom.mjs +5 -0
- package/util/color-console.cjs +18 -0
- package/util/color-console.d.ts +0 -1
- package/util/color-console.mjs +16 -0
- package/util/not-falsy.d.ts +0 -1
- package/util/sanitization.cjs +17 -0
- package/util/sanitization.d.ts +0 -1
- package/util/sanitization.mjs +11 -0
- package/bin/cli.js +0 -4
- package/cli.d.ts.map +0 -1
- package/cli.js +0 -79
- package/cli.js.map +0 -1
- package/client/app-types.d.ts.map +0 -1
- package/client/app-types.js +0 -161
- package/client/app-types.js.map +0 -1
- package/client/call-client.d.ts.map +0 -1
- package/client/call-client.js.map +0 -1
- package/client/call-composer-types.d.ts.map +0 -1
- package/client/call-composer-types.js.map +0 -1
- package/client/call-composer.d.ts.map +0 -1
- package/client/call-composer.js +0 -151
- package/client/call-composer.js.map +0 -1
- package/client/call-factory.d.ts.map +0 -1
- package/client/call-factory.js.map +0 -1
- package/client/deploy-types.d.ts.map +0 -1
- package/client/deploy-types.js +0 -95
- package/client/deploy-types.js.map +0 -1
- package/client/generate.d.ts.map +0 -1
- package/client/generate.js +0 -37
- package/client/generate.js.map +0 -1
- package/client/generator-context.d.ts.map +0 -1
- package/client/generator-context.js +0 -41
- package/client/generator-context.js.map +0 -1
- package/client/helpers/get-call-config-summary.d.ts.map +0 -1
- package/client/helpers/get-call-config-summary.js.map +0 -1
- package/client/helpers/get-equivalent-type.d.ts.map +0 -1
- package/client/helpers/get-equivalent-type.js.map +0 -1
- package/client/imports.d.ts.map +0 -1
- package/client/imports.js.map +0 -1
- package/client/utility-types.d.ts.map +0 -1
- package/client/utility-types.js.map +0 -1
- package/dev.d.ts.map +0 -1
- package/dev.js +0 -5
- package/dev.js.map +0 -1
- package/index.d.ts.map +0 -1
- package/index.js +0 -12
- package/index.js.map +0 -1
- package/output/writer.d.ts.map +0 -1
- package/output/writer.js.map +0 -1
- package/schema/application.schema.json +0 -354
- package/schema/contract.schema.json +0 -139
- package/schema/load.d.ts.map +0 -1
- package/schema/load.js +0 -51
- package/schema/load.js.map +0 -1
- package/tests/approval-tests.spec.d.ts.map +0 -1
- package/tests/approval-tests.spec.js +0 -24
- package/tests/approval-tests.spec.js.map +0 -1
- package/util/boom.d.ts.map +0 -1
- package/util/boom.js +0 -8
- package/util/boom.js.map +0 -1
- package/util/color-console.d.ts.map +0 -1
- package/util/color-console.js +0 -20
- package/util/color-console.js.map +0 -1
- package/util/not-falsy.d.ts.map +0 -1
- package/util/not-falsy.js +0 -6
- package/util/not-falsy.js.map +0 -1
- package/util/sanitization.d.ts.map +0 -1
- package/util/sanitization.js +0 -17
- package/util/sanitization.js.map +0 -1
package/bin/cli.mjs
ADDED
package/cli.cjs
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var commander = require('commander');
|
|
4
|
+
var load = require('./schema/load.cjs');
|
|
5
|
+
var path = require('path');
|
|
6
|
+
var generate = require('./client/generate.cjs');
|
|
7
|
+
var writer = require('./output/writer.cjs');
|
|
8
|
+
var colorConsole = require('./util/color-console.cjs');
|
|
9
|
+
|
|
10
|
+
function _interopNamespaceDefault(e) {
|
|
11
|
+
var n = Object.create(null);
|
|
12
|
+
if (e) {
|
|
13
|
+
Object.keys(e).forEach(function (k) {
|
|
14
|
+
if (k !== 'default') {
|
|
15
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return e[k]; }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
n.default = e;
|
|
24
|
+
return Object.freeze(n);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
28
|
+
|
|
29
|
+
function cli(workingDirectory, args) {
|
|
30
|
+
const program = new commander.Command();
|
|
31
|
+
program
|
|
32
|
+
.command('generate')
|
|
33
|
+
.description('Generates a TypeScript client for the given application.json file')
|
|
34
|
+
.requiredOption('-a --application <path>', 'Specifies the application.json file')
|
|
35
|
+
.requiredOption('-o --output <path>', 'Specifies the output file path')
|
|
36
|
+
.action(async ({ application, output }) => {
|
|
37
|
+
const fs = await import('fs');
|
|
38
|
+
const resolvedAppJsonPath = path__namespace.resolve(workingDirectory, application);
|
|
39
|
+
const resolvedOutPath = path__namespace.resolve(workingDirectory, output);
|
|
40
|
+
const resolvedOutDir = path__namespace.dirname(resolvedOutPath);
|
|
41
|
+
colorConsole.colorConsole.info `Reading application.json file from path ${resolvedAppJsonPath}`;
|
|
42
|
+
const spec = await load.loadApplicationJson(resolvedAppJsonPath);
|
|
43
|
+
colorConsole.colorConsole.info `Generating TS client for ${spec.contract.name}`;
|
|
44
|
+
const parts = generate.generate(spec);
|
|
45
|
+
if (!fs.existsSync(resolvedOutDir)) {
|
|
46
|
+
colorConsole.colorConsole.warn `Output directory ${resolvedOutDir} does not exist and will be created.`;
|
|
47
|
+
fs.mkdirSync(resolvedOutDir, { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
colorConsole.colorConsole.info `Writing TS client to ${resolvedOutPath}`;
|
|
50
|
+
const file = fs.createWriteStream(resolvedOutPath, {
|
|
51
|
+
flags: 'w',
|
|
52
|
+
});
|
|
53
|
+
writer.writeDocumentPartsToStream(parts, file);
|
|
54
|
+
colorConsole.colorConsole.success `Operation completed successfully`;
|
|
55
|
+
})
|
|
56
|
+
.configureOutput({
|
|
57
|
+
writeErr(str) {
|
|
58
|
+
colorConsole.colorConsole.error `${str}`;
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
try {
|
|
62
|
+
program.parse(args);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
if (err instanceof Error) {
|
|
66
|
+
colorConsole.colorConsole.error `Unhandled error: \n\n${err.stack}`;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
colorConsole.colorConsole.error `Unhandled error: \n\n${err}`;
|
|
70
|
+
}
|
|
71
|
+
process.exit(-1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
exports.cli = cli;
|
package/cli.d.ts
CHANGED
package/cli.mjs
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { loadApplicationJson } from './schema/load.mjs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { generate } from './client/generate.mjs';
|
|
5
|
+
import { writeDocumentPartsToStream } from './output/writer.mjs';
|
|
6
|
+
import { colorConsole } from './util/color-console.mjs';
|
|
7
|
+
|
|
8
|
+
function cli(workingDirectory, args) {
|
|
9
|
+
const program = new Command();
|
|
10
|
+
program
|
|
11
|
+
.command('generate')
|
|
12
|
+
.description('Generates a TypeScript client for the given application.json file')
|
|
13
|
+
.requiredOption('-a --application <path>', 'Specifies the application.json file')
|
|
14
|
+
.requiredOption('-o --output <path>', 'Specifies the output file path')
|
|
15
|
+
.action(async ({ application, output }) => {
|
|
16
|
+
const fs = await import('fs');
|
|
17
|
+
const resolvedAppJsonPath = path.resolve(workingDirectory, application);
|
|
18
|
+
const resolvedOutPath = path.resolve(workingDirectory, output);
|
|
19
|
+
const resolvedOutDir = path.dirname(resolvedOutPath);
|
|
20
|
+
colorConsole.info `Reading application.json file from path ${resolvedAppJsonPath}`;
|
|
21
|
+
const spec = await loadApplicationJson(resolvedAppJsonPath);
|
|
22
|
+
colorConsole.info `Generating TS client for ${spec.contract.name}`;
|
|
23
|
+
const parts = generate(spec);
|
|
24
|
+
if (!fs.existsSync(resolvedOutDir)) {
|
|
25
|
+
colorConsole.warn `Output directory ${resolvedOutDir} does not exist and will be created.`;
|
|
26
|
+
fs.mkdirSync(resolvedOutDir, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
colorConsole.info `Writing TS client to ${resolvedOutPath}`;
|
|
29
|
+
const file = fs.createWriteStream(resolvedOutPath, {
|
|
30
|
+
flags: 'w',
|
|
31
|
+
});
|
|
32
|
+
writeDocumentPartsToStream(parts, file);
|
|
33
|
+
colorConsole.success `Operation completed successfully`;
|
|
34
|
+
})
|
|
35
|
+
.configureOutput({
|
|
36
|
+
writeErr(str) {
|
|
37
|
+
colorConsole.error `${str}`;
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
try {
|
|
41
|
+
program.parse(args);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
if (err instanceof Error) {
|
|
45
|
+
colorConsole.error `Unhandled error: \n\n${err.stack}`;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
colorConsole.error `Unhandled error: \n\n${err}`;
|
|
49
|
+
}
|
|
50
|
+
process.exit(-1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { cli };
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var writer = require('../output/writer.cjs');
|
|
4
|
+
var algokit = require('@algorandfoundation/algokit-utils');
|
|
5
|
+
var getEquivalentType = require('./helpers/get-equivalent-type.cjs');
|
|
6
|
+
var sanitization = require('../util/sanitization.cjs');
|
|
7
|
+
|
|
8
|
+
function _interopNamespaceDefault(e) {
|
|
9
|
+
var n = Object.create(null);
|
|
10
|
+
if (e) {
|
|
11
|
+
Object.keys(e).forEach(function (k) {
|
|
12
|
+
if (k !== 'default') {
|
|
13
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
14
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function () { return e[k]; }
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
n.default = e;
|
|
22
|
+
return Object.freeze(n);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
var algokit__namespace = /*#__PURE__*/_interopNamespaceDefault(algokit);
|
|
26
|
+
|
|
27
|
+
function* appTypes(ctx) {
|
|
28
|
+
const { app, methodSignatureToUniqueName, name } = ctx;
|
|
29
|
+
yield* writer.jsDoc(`Defines the types of available calls and state of the ${name} smart contract.`);
|
|
30
|
+
yield `export type ${name} = {`;
|
|
31
|
+
yield writer.IncIndent;
|
|
32
|
+
yield* writer.jsDoc('Maps method signatures / names to their argument and return types.');
|
|
33
|
+
yield 'methods:';
|
|
34
|
+
yield writer.IncIndent;
|
|
35
|
+
for (const method of app.contract.methods) {
|
|
36
|
+
const methodSig = algokit__namespace.getABIMethodSignature(method);
|
|
37
|
+
const uniqueName = methodSignatureToUniqueName[methodSig];
|
|
38
|
+
yield `& Record<'${methodSig}'${methodSig !== uniqueName ? ` | '${uniqueName}'` : ''}, {`;
|
|
39
|
+
yield writer.IncIndent;
|
|
40
|
+
yield `argsObj: {`;
|
|
41
|
+
yield writer.IncIndent;
|
|
42
|
+
const argsMeta = method.args.map((arg) => ({
|
|
43
|
+
...arg,
|
|
44
|
+
hasDefault: app.hints?.[methodSig]?.default_arguments?.[arg.name],
|
|
45
|
+
tsType: getEquivalentType.getEquivalentType(arg.type, 'input'),
|
|
46
|
+
}));
|
|
47
|
+
for (const arg of argsMeta) {
|
|
48
|
+
if (arg.desc)
|
|
49
|
+
yield* writer.jsDoc(arg.desc);
|
|
50
|
+
yield `${sanitization.makeSafePropertyIdentifier(arg.name)}${arg.hasDefault ? '?' : ''}: ${arg.tsType}`;
|
|
51
|
+
}
|
|
52
|
+
yield writer.DecIndentAndCloseBlock;
|
|
53
|
+
yield* writer.inline(`argsTuple: [`, argsMeta
|
|
54
|
+
.map((arg) => `${sanitization.makeSafeVariableIdentifier(arg.name)}: ${getEquivalentType.getEquivalentType(arg.type, 'input')}${arg.hasDefault ? ' | undefined' : ''}`)
|
|
55
|
+
.join(', '), ']');
|
|
56
|
+
const outputStruct = ctx.app.hints?.[methodSig]?.structs?.output;
|
|
57
|
+
if (method.returns.desc)
|
|
58
|
+
yield* writer.jsDoc(method.returns.desc);
|
|
59
|
+
if (outputStruct) {
|
|
60
|
+
yield `returns: ${sanitization.makeSafeTypeIdentifier(outputStruct.name)}`;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
yield `returns: ${getEquivalentType.getEquivalentType(method.returns.type ?? 'void', 'output')}`;
|
|
64
|
+
}
|
|
65
|
+
yield writer.DecIndent;
|
|
66
|
+
yield '}>';
|
|
67
|
+
}
|
|
68
|
+
yield writer.DecIndent;
|
|
69
|
+
yield* appState(ctx);
|
|
70
|
+
yield writer.DecIndentAndCloseBlock;
|
|
71
|
+
yield* writer.jsDoc('Defines the possible abi call signatures');
|
|
72
|
+
yield `export type ${name}Sig = keyof ${name}['methods']`;
|
|
73
|
+
yield* writer.jsDoc('Defines an object containing all relevant parameters for a single call to the contract. Where TSignature is undefined, a' +
|
|
74
|
+
' bare call is made');
|
|
75
|
+
yield `export type TypedCallParams<TSignature extends ${name}Sig | undefined> = {`;
|
|
76
|
+
yield writer.IncIndent;
|
|
77
|
+
yield 'method: TSignature';
|
|
78
|
+
yield 'methodArgs: TSignature extends undefined ? undefined : Array<ABIAppCallArg | undefined>';
|
|
79
|
+
yield writer.DecIndent;
|
|
80
|
+
yield '} & AppClientCallCoreParams & CoreAppCallArgs';
|
|
81
|
+
yield* writer.jsDoc('Defines the arguments required for a bare call');
|
|
82
|
+
yield `export type BareCallArgs = Omit<RawAppCallArgs, keyof CoreAppCallArgs>`;
|
|
83
|
+
yield* structs(ctx);
|
|
84
|
+
yield* writer.jsDoc(`Maps a method signature from the ${name} smart contract to the method's arguments in either tuple of struct form`);
|
|
85
|
+
yield `export type MethodArgs<TSignature extends ${name}Sig> = ${name}['methods'][TSignature]['argsObj' | 'argsTuple']`;
|
|
86
|
+
yield* writer.jsDoc(`Maps a method signature from the ${name} smart contract to the method's return type`);
|
|
87
|
+
yield `export type MethodReturn<TSignature extends ${name}Sig> = ${name}['methods'][TSignature]['returns']`;
|
|
88
|
+
yield writer.NewLine;
|
|
89
|
+
}
|
|
90
|
+
function* structs({ app }) {
|
|
91
|
+
if (app.hints === undefined)
|
|
92
|
+
return;
|
|
93
|
+
for (const methodHint of Object.values(app.hints)) {
|
|
94
|
+
if (methodHint.structs === undefined)
|
|
95
|
+
continue;
|
|
96
|
+
for (const struct of Object.values(methodHint.structs)) {
|
|
97
|
+
yield* writer.jsDoc(`Represents a ${struct.name} result as a struct`);
|
|
98
|
+
yield `export type ${sanitization.makeSafeTypeIdentifier(struct.name)} = {`;
|
|
99
|
+
yield writer.IncIndent;
|
|
100
|
+
for (const [key, type] of struct.elements) {
|
|
101
|
+
yield `${sanitization.makeSafePropertyIdentifier(key)}: ${getEquivalentType.getEquivalentType(type, 'output')}`;
|
|
102
|
+
}
|
|
103
|
+
yield writer.DecIndentAndCloseBlock;
|
|
104
|
+
yield* writer.jsDoc(`Converts the tuple representation of a ${struct.name} to the struct representation`);
|
|
105
|
+
yield* writer.inline(`export function ${sanitization.makeSafeTypeIdentifier(struct.name)}(`, `[${struct.elements.map(([key]) => sanitization.makeSafeVariableIdentifier(key)).join(', ')}]: `, `[${struct.elements.map(([_, type]) => getEquivalentType.getEquivalentType(type, 'output')).join(', ')}] ) {`);
|
|
106
|
+
yield writer.IncIndent;
|
|
107
|
+
yield `return {`;
|
|
108
|
+
yield writer.IncIndent;
|
|
109
|
+
for (const [key] of struct.elements) {
|
|
110
|
+
const prop = sanitization.makeSafePropertyIdentifier(key);
|
|
111
|
+
const param = sanitization.makeSafeVariableIdentifier(key);
|
|
112
|
+
yield `${prop}${prop !== param ? `: ${param}` : ''},`;
|
|
113
|
+
}
|
|
114
|
+
yield writer.DecIndentAndCloseBlock;
|
|
115
|
+
yield writer.DecIndentAndCloseBlock;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function* appState({ app }) {
|
|
120
|
+
const hasLocal = app.schema.local?.declared && Object.keys(app.schema.local.declared).length;
|
|
121
|
+
const hasGlobal = app.schema.global?.declared && Object.keys(app.schema.global.declared).length;
|
|
122
|
+
if (hasLocal || hasGlobal) {
|
|
123
|
+
yield* writer.jsDoc('Defines the shape of the global and local state of the application.');
|
|
124
|
+
yield 'state: {';
|
|
125
|
+
yield writer.IncIndent;
|
|
126
|
+
if (hasGlobal) {
|
|
127
|
+
yield 'global: {';
|
|
128
|
+
yield writer.IncIndent;
|
|
129
|
+
for (const prop of Object.values(app.schema.global.declared)) {
|
|
130
|
+
if (prop.descr) {
|
|
131
|
+
yield* writer.jsDoc(prop.descr);
|
|
132
|
+
}
|
|
133
|
+
yield `'${prop.key}'?: ${prop.type === 'uint64' ? 'IntegerState' : 'BinaryState'}`;
|
|
134
|
+
}
|
|
135
|
+
yield writer.DecIndentAndCloseBlock;
|
|
136
|
+
}
|
|
137
|
+
if (hasLocal) {
|
|
138
|
+
yield 'local: {';
|
|
139
|
+
yield writer.IncIndent;
|
|
140
|
+
for (const prop of Object.values(app.schema.local.declared)) {
|
|
141
|
+
if (prop.descr) {
|
|
142
|
+
yield* writer.jsDoc(prop.descr);
|
|
143
|
+
}
|
|
144
|
+
yield `'${prop.key}'?: ${prop.type === 'uint64' ? 'IntegerState' : 'BinaryState'}`;
|
|
145
|
+
}
|
|
146
|
+
yield writer.DecIndentAndCloseBlock;
|
|
147
|
+
}
|
|
148
|
+
yield writer.DecIndentAndCloseBlock;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
exports.appTypes = appTypes;
|
package/client/app-types.d.ts
CHANGED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { jsDoc, IncIndent, DecIndentAndCloseBlock, inline, DecIndent, NewLine } from '../output/writer.mjs';
|
|
2
|
+
import * as algokit from '@algorandfoundation/algokit-utils';
|
|
3
|
+
import { getEquivalentType } from './helpers/get-equivalent-type.mjs';
|
|
4
|
+
import { makeSafePropertyIdentifier, makeSafeVariableIdentifier, makeSafeTypeIdentifier } from '../util/sanitization.mjs';
|
|
5
|
+
|
|
6
|
+
function* appTypes(ctx) {
|
|
7
|
+
const { app, methodSignatureToUniqueName, name } = ctx;
|
|
8
|
+
yield* jsDoc(`Defines the types of available calls and state of the ${name} smart contract.`);
|
|
9
|
+
yield `export type ${name} = {`;
|
|
10
|
+
yield IncIndent;
|
|
11
|
+
yield* jsDoc('Maps method signatures / names to their argument and return types.');
|
|
12
|
+
yield 'methods:';
|
|
13
|
+
yield IncIndent;
|
|
14
|
+
for (const method of app.contract.methods) {
|
|
15
|
+
const methodSig = algokit.getABIMethodSignature(method);
|
|
16
|
+
const uniqueName = methodSignatureToUniqueName[methodSig];
|
|
17
|
+
yield `& Record<'${methodSig}'${methodSig !== uniqueName ? ` | '${uniqueName}'` : ''}, {`;
|
|
18
|
+
yield IncIndent;
|
|
19
|
+
yield `argsObj: {`;
|
|
20
|
+
yield IncIndent;
|
|
21
|
+
const argsMeta = method.args.map((arg) => ({
|
|
22
|
+
...arg,
|
|
23
|
+
hasDefault: app.hints?.[methodSig]?.default_arguments?.[arg.name],
|
|
24
|
+
tsType: getEquivalentType(arg.type, 'input'),
|
|
25
|
+
}));
|
|
26
|
+
for (const arg of argsMeta) {
|
|
27
|
+
if (arg.desc)
|
|
28
|
+
yield* jsDoc(arg.desc);
|
|
29
|
+
yield `${makeSafePropertyIdentifier(arg.name)}${arg.hasDefault ? '?' : ''}: ${arg.tsType}`;
|
|
30
|
+
}
|
|
31
|
+
yield DecIndentAndCloseBlock;
|
|
32
|
+
yield* inline(`argsTuple: [`, argsMeta
|
|
33
|
+
.map((arg) => `${makeSafeVariableIdentifier(arg.name)}: ${getEquivalentType(arg.type, 'input')}${arg.hasDefault ? ' | undefined' : ''}`)
|
|
34
|
+
.join(', '), ']');
|
|
35
|
+
const outputStruct = ctx.app.hints?.[methodSig]?.structs?.output;
|
|
36
|
+
if (method.returns.desc)
|
|
37
|
+
yield* jsDoc(method.returns.desc);
|
|
38
|
+
if (outputStruct) {
|
|
39
|
+
yield `returns: ${makeSafeTypeIdentifier(outputStruct.name)}`;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
yield `returns: ${getEquivalentType(method.returns.type ?? 'void', 'output')}`;
|
|
43
|
+
}
|
|
44
|
+
yield DecIndent;
|
|
45
|
+
yield '}>';
|
|
46
|
+
}
|
|
47
|
+
yield DecIndent;
|
|
48
|
+
yield* appState(ctx);
|
|
49
|
+
yield DecIndentAndCloseBlock;
|
|
50
|
+
yield* jsDoc('Defines the possible abi call signatures');
|
|
51
|
+
yield `export type ${name}Sig = keyof ${name}['methods']`;
|
|
52
|
+
yield* jsDoc('Defines an object containing all relevant parameters for a single call to the contract. Where TSignature is undefined, a' +
|
|
53
|
+
' bare call is made');
|
|
54
|
+
yield `export type TypedCallParams<TSignature extends ${name}Sig | undefined> = {`;
|
|
55
|
+
yield IncIndent;
|
|
56
|
+
yield 'method: TSignature';
|
|
57
|
+
yield 'methodArgs: TSignature extends undefined ? undefined : Array<ABIAppCallArg | undefined>';
|
|
58
|
+
yield DecIndent;
|
|
59
|
+
yield '} & AppClientCallCoreParams & CoreAppCallArgs';
|
|
60
|
+
yield* jsDoc('Defines the arguments required for a bare call');
|
|
61
|
+
yield `export type BareCallArgs = Omit<RawAppCallArgs, keyof CoreAppCallArgs>`;
|
|
62
|
+
yield* structs(ctx);
|
|
63
|
+
yield* jsDoc(`Maps a method signature from the ${name} smart contract to the method's arguments in either tuple of struct form`);
|
|
64
|
+
yield `export type MethodArgs<TSignature extends ${name}Sig> = ${name}['methods'][TSignature]['argsObj' | 'argsTuple']`;
|
|
65
|
+
yield* jsDoc(`Maps a method signature from the ${name} smart contract to the method's return type`);
|
|
66
|
+
yield `export type MethodReturn<TSignature extends ${name}Sig> = ${name}['methods'][TSignature]['returns']`;
|
|
67
|
+
yield NewLine;
|
|
68
|
+
}
|
|
69
|
+
function* structs({ app }) {
|
|
70
|
+
if (app.hints === undefined)
|
|
71
|
+
return;
|
|
72
|
+
for (const methodHint of Object.values(app.hints)) {
|
|
73
|
+
if (methodHint.structs === undefined)
|
|
74
|
+
continue;
|
|
75
|
+
for (const struct of Object.values(methodHint.structs)) {
|
|
76
|
+
yield* jsDoc(`Represents a ${struct.name} result as a struct`);
|
|
77
|
+
yield `export type ${makeSafeTypeIdentifier(struct.name)} = {`;
|
|
78
|
+
yield IncIndent;
|
|
79
|
+
for (const [key, type] of struct.elements) {
|
|
80
|
+
yield `${makeSafePropertyIdentifier(key)}: ${getEquivalentType(type, 'output')}`;
|
|
81
|
+
}
|
|
82
|
+
yield DecIndentAndCloseBlock;
|
|
83
|
+
yield* jsDoc(`Converts the tuple representation of a ${struct.name} to the struct representation`);
|
|
84
|
+
yield* inline(`export function ${makeSafeTypeIdentifier(struct.name)}(`, `[${struct.elements.map(([key]) => makeSafeVariableIdentifier(key)).join(', ')}]: `, `[${struct.elements.map(([_, type]) => getEquivalentType(type, 'output')).join(', ')}] ) {`);
|
|
85
|
+
yield IncIndent;
|
|
86
|
+
yield `return {`;
|
|
87
|
+
yield IncIndent;
|
|
88
|
+
for (const [key] of struct.elements) {
|
|
89
|
+
const prop = makeSafePropertyIdentifier(key);
|
|
90
|
+
const param = makeSafeVariableIdentifier(key);
|
|
91
|
+
yield `${prop}${prop !== param ? `: ${param}` : ''},`;
|
|
92
|
+
}
|
|
93
|
+
yield DecIndentAndCloseBlock;
|
|
94
|
+
yield DecIndentAndCloseBlock;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function* appState({ app }) {
|
|
99
|
+
const hasLocal = app.schema.local?.declared && Object.keys(app.schema.local.declared).length;
|
|
100
|
+
const hasGlobal = app.schema.global?.declared && Object.keys(app.schema.global.declared).length;
|
|
101
|
+
if (hasLocal || hasGlobal) {
|
|
102
|
+
yield* jsDoc('Defines the shape of the global and local state of the application.');
|
|
103
|
+
yield 'state: {';
|
|
104
|
+
yield IncIndent;
|
|
105
|
+
if (hasGlobal) {
|
|
106
|
+
yield 'global: {';
|
|
107
|
+
yield IncIndent;
|
|
108
|
+
for (const prop of Object.values(app.schema.global.declared)) {
|
|
109
|
+
if (prop.descr) {
|
|
110
|
+
yield* jsDoc(prop.descr);
|
|
111
|
+
}
|
|
112
|
+
yield `'${prop.key}'?: ${prop.type === 'uint64' ? 'IntegerState' : 'BinaryState'}`;
|
|
113
|
+
}
|
|
114
|
+
yield DecIndentAndCloseBlock;
|
|
115
|
+
}
|
|
116
|
+
if (hasLocal) {
|
|
117
|
+
yield 'local: {';
|
|
118
|
+
yield IncIndent;
|
|
119
|
+
for (const prop of Object.values(app.schema.local.declared)) {
|
|
120
|
+
if (prop.descr) {
|
|
121
|
+
yield* jsDoc(prop.descr);
|
|
122
|
+
}
|
|
123
|
+
yield `'${prop.key}'?: ${prop.type === 'uint64' ? 'IntegerState' : 'BinaryState'}`;
|
|
124
|
+
}
|
|
125
|
+
yield DecIndentAndCloseBlock;
|
|
126
|
+
}
|
|
127
|
+
yield DecIndentAndCloseBlock;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export { appTypes };
|