@mimicprotocol/cli 0.0.1-rc.18 → 0.0.1-rc.20
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/dist/commands/compile.js +6 -9
- package/dist/commands/deploy.js +17 -6
- package/dist/commands/init.js +8 -7
- package/dist/lib/AbisInterfaceGenerator/ContractClassGenerator.js +18 -5
- package/dist/lib/AbisInterfaceGenerator/EventHandler.js +138 -0
- package/dist/lib/AbisInterfaceGenerator/FunctionHandler.js +42 -93
- package/dist/lib/AbisInterfaceGenerator/TupleHandler.js +11 -11
- package/dist/lib/AbisInterfaceGenerator/UtilsHandler.js +150 -0
- package/dist/templates/manifest.yaml +1 -1
- package/package.json +1 -1
package/dist/commands/compile.js
CHANGED
|
@@ -46,23 +46,20 @@ class Compile extends core_1.Command {
|
|
|
46
46
|
async run() {
|
|
47
47
|
const { flags } = await this.parse(Compile);
|
|
48
48
|
const { task: taskFile, output: outputDir, manifest: manifestDir } = flags;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const absTaskFile = path.resolve(taskFile);
|
|
50
|
+
const absOutputDir = path.resolve(outputDir);
|
|
51
|
+
if (!fs.existsSync(absOutputDir))
|
|
52
|
+
fs.mkdirSync(absOutputDir, { recursive: true });
|
|
52
53
|
log_1.default.startAction('Verifying Manifest');
|
|
53
54
|
const manifest = ManifestHandler_1.default.load(this, manifestDir);
|
|
54
55
|
log_1.default.startAction('Compiling');
|
|
55
|
-
const wasmPath = path.join(outputDir, 'task.wasm');
|
|
56
|
-
const watPath = path.join(outputDir, 'task.wat');
|
|
57
56
|
const ascArgs = [
|
|
58
57
|
'asc',
|
|
59
|
-
|
|
58
|
+
absTaskFile,
|
|
60
59
|
'--target',
|
|
61
60
|
'release',
|
|
62
61
|
'--outFile',
|
|
63
|
-
|
|
64
|
-
'--textFile',
|
|
65
|
-
watPath,
|
|
62
|
+
path.join(absOutputDir, 'task.wasm'),
|
|
66
63
|
'--optimize',
|
|
67
64
|
'--exportRuntime',
|
|
68
65
|
'--transform',
|
package/dist/commands/deploy.js
CHANGED
|
@@ -38,19 +38,28 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
const core_1 = require("@oclif/core");
|
|
40
40
|
const axios_1 = __importStar(require("axios"));
|
|
41
|
+
const child_process_1 = require("child_process");
|
|
41
42
|
const form_data_1 = __importDefault(require("form-data"));
|
|
42
43
|
const fs = __importStar(require("fs"));
|
|
43
44
|
const path_1 = require("path");
|
|
44
45
|
const errors_1 = require("../errors");
|
|
45
46
|
const log_1 = __importDefault(require("../log"));
|
|
46
|
-
const
|
|
47
|
+
const MIMIC_REGISTRY_DEFAULT = 'https://api-protocol.mimic.fi';
|
|
47
48
|
class Deploy extends core_1.Command {
|
|
48
49
|
async run() {
|
|
49
50
|
const { flags } = await this.parse(Deploy);
|
|
50
|
-
const { key, input: inputDir, output: outputDir } = flags;
|
|
51
|
-
log_1.default.startAction('Validating');
|
|
51
|
+
const { key, input: inputDir, output: outputDir, 'skip-compile': skipCompile, url: registryUrl } = flags;
|
|
52
52
|
const fullInputDir = (0, path_1.resolve)(inputDir);
|
|
53
53
|
const fullOutputDir = (0, path_1.resolve)(outputDir);
|
|
54
|
+
if (!skipCompile) {
|
|
55
|
+
const codegen = (0, child_process_1.spawnSync)('yarn', ['mimic', 'codegen'], { stdio: 'inherit' });
|
|
56
|
+
if (codegen.status !== 0)
|
|
57
|
+
this.error('Code generation failed', { code: 'CodegenError', suggestions: ['Fix manifest and ABI files'] });
|
|
58
|
+
const compile = (0, child_process_1.spawnSync)('yarn', ['mimic', 'compile', '--output', fullInputDir], { stdio: 'inherit' });
|
|
59
|
+
if (compile.status !== 0)
|
|
60
|
+
this.error('Compilation failed', { code: 'BuildError', suggestions: ['Check the task source code'] });
|
|
61
|
+
}
|
|
62
|
+
log_1.default.startAction('Validating');
|
|
54
63
|
if (!fs.existsSync(fullInputDir))
|
|
55
64
|
this.error(`Directory ${log_1.default.highlightText(fullInputDir)} does not exist`, {
|
|
56
65
|
code: 'Directory Not Found',
|
|
@@ -65,7 +74,7 @@ class Deploy extends core_1.Command {
|
|
|
65
74
|
});
|
|
66
75
|
}
|
|
67
76
|
log_1.default.startAction('Uploading to Mimic Registry');
|
|
68
|
-
const CID = await this.uploadToRegistry(neededFiles, key);
|
|
77
|
+
const CID = await this.uploadToRegistry(neededFiles, key, registryUrl);
|
|
69
78
|
console.log(`IPFS CID: ${log_1.default.highlightText(CID)}`);
|
|
70
79
|
log_1.default.stopAction();
|
|
71
80
|
if (!fs.existsSync(fullOutputDir))
|
|
@@ -74,10 +83,10 @@ class Deploy extends core_1.Command {
|
|
|
74
83
|
console.log(`CID saved at ${log_1.default.highlightText(fullOutputDir)}`);
|
|
75
84
|
console.log(`Task deployed!`);
|
|
76
85
|
}
|
|
77
|
-
async uploadToRegistry(files, key) {
|
|
86
|
+
async uploadToRegistry(files, key, registryUrl) {
|
|
78
87
|
try {
|
|
79
88
|
const form = filesToForm(files);
|
|
80
|
-
const { data } = await axios_1.default.post(`${
|
|
89
|
+
const { data } = await axios_1.default.post(`${registryUrl}/tasks`, form, {
|
|
81
90
|
headers: {
|
|
82
91
|
'x-api-key': key,
|
|
83
92
|
'Content-Type': `multipart/form-data; boundary=${form.getBoundary()}`,
|
|
@@ -110,6 +119,8 @@ Deploy.flags = {
|
|
|
110
119
|
key: core_1.Flags.string({ char: 'k', description: 'Your account deployment key', required: true }),
|
|
111
120
|
input: core_1.Flags.string({ char: 'i', description: 'Directory containing the compiled artifacts', default: './build' }),
|
|
112
121
|
output: core_1.Flags.string({ char: 'o', description: 'Output directory for deployment CID', default: './build' }),
|
|
122
|
+
url: core_1.Flags.string({ char: 'u', description: `Mimic Registry base URL`, default: MIMIC_REGISTRY_DEFAULT }),
|
|
123
|
+
'skip-compile': core_1.Flags.boolean({ description: 'Skip codegen and compile steps before uploading', default: false }),
|
|
113
124
|
};
|
|
114
125
|
exports.default = Deploy;
|
|
115
126
|
const filesToForm = (files) => {
|
package/dist/commands/init.js
CHANGED
|
@@ -48,19 +48,20 @@ class Init extends core_1.Command {
|
|
|
48
48
|
const { directory, force } = flags;
|
|
49
49
|
const fullDirectory = path.resolve(directory);
|
|
50
50
|
const templateDirectory = path.join(__dirname, '../templates');
|
|
51
|
-
if (force) {
|
|
52
|
-
const shouldDelete =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
if (force && fs.existsSync(fullDirectory) && fs.readdirSync(fullDirectory).length > 0) {
|
|
52
|
+
const shouldDelete = process.env.NODE_ENV === 'test'
|
|
53
|
+
? true
|
|
54
|
+
: await (0, prompts_1.confirm)({
|
|
55
|
+
message: `Are you sure you want to ${log_1.default.warnText('delete')} all the contents in ${log_1.default.highlightText(fullDirectory)}. This action is ${log_1.default.warnText('irreversible')}`,
|
|
56
|
+
default: false,
|
|
57
|
+
});
|
|
56
58
|
if (!shouldDelete) {
|
|
57
59
|
console.log('You can remove the --force flag from your command');
|
|
58
60
|
console.log('Stopping initialization...');
|
|
59
61
|
this.exit(0);
|
|
60
62
|
}
|
|
61
63
|
log_1.default.startAction(`Deleting contents of ${fullDirectory}`);
|
|
62
|
-
|
|
63
|
-
fs.rmSync(fullDirectory, { recursive: true });
|
|
64
|
+
fs.rmSync(fullDirectory, { recursive: true });
|
|
64
65
|
}
|
|
65
66
|
log_1.default.startAction('Creating files');
|
|
66
67
|
if (fs.existsSync(fullDirectory) && fs.readdirSync(fullDirectory).length > 0) {
|
|
@@ -5,37 +5,50 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const types_1 = require("../../types");
|
|
7
7
|
const AbiTypeConverter_1 = __importDefault(require("./AbiTypeConverter"));
|
|
8
|
+
const EventHandler_1 = __importDefault(require("./EventHandler"));
|
|
8
9
|
const FunctionHandler_1 = __importDefault(require("./FunctionHandler"));
|
|
9
10
|
const ImportManager_1 = __importDefault(require("./ImportManager"));
|
|
10
11
|
const NameManager_1 = __importDefault(require("./NameManager"));
|
|
11
12
|
const TupleHandler_1 = __importDefault(require("./TupleHandler"));
|
|
13
|
+
const UtilsHandler_1 = __importDefault(require("./UtilsHandler"));
|
|
12
14
|
class ContractClassGenerator {
|
|
13
15
|
constructor(abi) {
|
|
14
16
|
this.abi = abi;
|
|
15
17
|
this.importManager = new ImportManager_1.default();
|
|
16
18
|
this.tupleDefinitions = TupleHandler_1.default.extractTupleDefinitions(this.abi);
|
|
19
|
+
this.eventDefinitions = EventHandler_1.default.extractEventDefinitions(this.abi);
|
|
17
20
|
this.abiTypeConverter = new AbiTypeConverter_1.default(this.importManager, this.tupleDefinitions);
|
|
18
21
|
}
|
|
19
22
|
generate(contractName) {
|
|
20
|
-
const
|
|
23
|
+
const functions = NameManager_1.default.resolveMethodNames(this.getFunctions());
|
|
24
|
+
const mainClassCode = this.generateMainClass(contractName, functions);
|
|
25
|
+
const utilsClassCode = this.generateUtilsClass(contractName, functions);
|
|
21
26
|
const tupleClassesCode = TupleHandler_1.default.generateTupleClassesCode(this.tupleDefinitions, this.importManager, this.abiTypeConverter);
|
|
27
|
+
const eventClassesCode = EventHandler_1.default.generateEventClassesCode(this.eventDefinitions, this.importManager, this.abiTypeConverter);
|
|
22
28
|
// Note: this should be generated after any other generation
|
|
23
29
|
const importsCode = this.importManager.generateImportsCode();
|
|
30
|
+
const ignoreLint = '/* eslint-disable @typescript-eslint/no-unused-vars */';
|
|
24
31
|
const notice = '// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE MANUALLY.';
|
|
25
32
|
const separator = '\n\n';
|
|
26
|
-
let result =
|
|
33
|
+
let result = ignoreLint + separator + notice + separator + importsCode;
|
|
34
|
+
result += separator + mainClassCode;
|
|
35
|
+
result += separator + utilsClassCode;
|
|
27
36
|
if (tupleClassesCode)
|
|
28
37
|
result += separator + tupleClassesCode;
|
|
38
|
+
if (eventClassesCode)
|
|
39
|
+
result += separator + eventClassesCode;
|
|
29
40
|
return result.trim();
|
|
30
41
|
}
|
|
31
|
-
generateMainClass(contractName) {
|
|
42
|
+
generateMainClass(contractName, functions) {
|
|
32
43
|
const lines = [];
|
|
33
44
|
this.appendClassDefinition(lines, contractName);
|
|
34
|
-
|
|
35
|
-
functions.forEach((fn) => FunctionHandler_1.default.appendMethod(lines, fn, this.importManager, this.tupleDefinitions, this.abiTypeConverter));
|
|
45
|
+
functions.forEach((fn) => FunctionHandler_1.default.appendMethod(lines, fn, this.importManager, this.tupleDefinitions, this.abiTypeConverter, contractName));
|
|
36
46
|
lines.push('}');
|
|
37
47
|
return lines.join('\n');
|
|
38
48
|
}
|
|
49
|
+
generateUtilsClass(contractName, functions) {
|
|
50
|
+
return UtilsHandler_1.default.generate(contractName, functions, this.importManager, this.tupleDefinitions, this.abiTypeConverter);
|
|
51
|
+
}
|
|
39
52
|
appendClassDefinition(lines, contractName) {
|
|
40
53
|
this.importManager.addType(types_1.LibTypes.Address);
|
|
41
54
|
this.importManager.addType(types_1.LibTypes.ChainId);
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const types_1 = require("../../types");
|
|
40
|
+
const NameManager_1 = __importStar(require("./NameManager"));
|
|
41
|
+
const TupleHandler_1 = __importDefault(require("./TupleHandler"));
|
|
42
|
+
class EventHandler {
|
|
43
|
+
static extractEventDefinitions(abi) {
|
|
44
|
+
const eventDefinitions = new Map();
|
|
45
|
+
abi.forEach((item) => {
|
|
46
|
+
if (item.type !== 'event')
|
|
47
|
+
return;
|
|
48
|
+
const components = NameManager_1.default.resolveParameterNames(item.inputs || [], NameManager_1.NameContext.CLASS_PROPERTY);
|
|
49
|
+
const componentsWithIndexed = components.map((comp, index) => ({
|
|
50
|
+
...comp,
|
|
51
|
+
indexed: item.inputs?.[index]?.indexed || false,
|
|
52
|
+
}));
|
|
53
|
+
eventDefinitions.set(item.name, {
|
|
54
|
+
className: `${item.name}Event`,
|
|
55
|
+
components: componentsWithIndexed,
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
return eventDefinitions;
|
|
59
|
+
}
|
|
60
|
+
static generateEventClassesCode(eventDefinitions, importManager, abiTypeConverter) {
|
|
61
|
+
if (eventDefinitions.size === 0)
|
|
62
|
+
return '';
|
|
63
|
+
const lines = [];
|
|
64
|
+
eventDefinitions.forEach((def) => {
|
|
65
|
+
lines.push(`export class ${def.className} {`);
|
|
66
|
+
const components = def.components;
|
|
67
|
+
components.forEach((comp) => {
|
|
68
|
+
const fieldName = comp.escapedName;
|
|
69
|
+
const componentType = abiTypeConverter.mapAbiType(comp);
|
|
70
|
+
lines.push(` readonly ${fieldName}: ${componentType}`);
|
|
71
|
+
});
|
|
72
|
+
lines.push('');
|
|
73
|
+
const constructorParams = components
|
|
74
|
+
.map((comp) => `${comp.escapedName}: ${abiTypeConverter.mapAbiType(comp)}`)
|
|
75
|
+
.join(', ');
|
|
76
|
+
lines.push(` constructor(${constructorParams}) {`);
|
|
77
|
+
components.forEach((comp) => {
|
|
78
|
+
const fieldName = comp.escapedName;
|
|
79
|
+
lines.push(` this.${fieldName} = ${fieldName}`);
|
|
80
|
+
});
|
|
81
|
+
lines.push(` }`);
|
|
82
|
+
lines.push('');
|
|
83
|
+
const indexedParams = def.components.filter((c) => c.indexed);
|
|
84
|
+
const nonIndexedParams = def.components.filter((c) => !c.indexed);
|
|
85
|
+
importManager.addType('evm');
|
|
86
|
+
importManager.addType('EvmDecodeParam');
|
|
87
|
+
const topicsParam = indexedParams.length > 0 ? 'topics' : '_topics';
|
|
88
|
+
const dataParam = nonIndexedParams.length > 0 ? 'data' : '_data';
|
|
89
|
+
lines.push(` static decode(${topicsParam}: ${types_1.AssemblyPrimitiveTypes.string}[], ${dataParam}: ${types_1.AssemblyPrimitiveTypes.string}): ${def.className} {`);
|
|
90
|
+
const localVarMap = new Map();
|
|
91
|
+
// Decode indexed parameters from topics
|
|
92
|
+
if (indexedParams.length > 0) {
|
|
93
|
+
lines.push(` // Decode indexed parameters from topics`);
|
|
94
|
+
NameManager_1.default.resolveParameterNames(indexedParams, NameManager_1.NameContext.LOCAL_VARIABLE).forEach((param, index) => {
|
|
95
|
+
const varName = param.escapedName;
|
|
96
|
+
localVarMap.set(indexedParams[index].escapedName, varName);
|
|
97
|
+
const mappedType = abiTypeConverter.mapAbiType(param);
|
|
98
|
+
const rawValue = `evm.decode(new EvmDecodeParam('${param.type}', topics[${index + 1}]))`; // Skip topics[0] which is event signature
|
|
99
|
+
lines.push(` const ${varName}: ${mappedType} = ${abiTypeConverter.generateTypeConversion(mappedType, rawValue, false, false)}`);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
// Decode non-indexed parameters from data
|
|
103
|
+
if (nonIndexedParams.length > 0) {
|
|
104
|
+
lines.push(` // Decode non-indexed parameters from data`);
|
|
105
|
+
const dataAbiType = nonIndexedParams.length === 1
|
|
106
|
+
? nonIndexedParams[0].type
|
|
107
|
+
: TupleHandler_1.default.generateTupleTypeString('tuple', nonIndexedParams.map((c) => ({ type: c.type, components: c.components })));
|
|
108
|
+
lines.push(` const decodedData = evm.decode(new EvmDecodeParam('${dataAbiType}', data))`);
|
|
109
|
+
const nonIndexedWithVarNames = NameManager_1.default.resolveParameterNames(nonIndexedParams, NameManager_1.NameContext.LOCAL_VARIABLE);
|
|
110
|
+
if (nonIndexedParams.length === 1) {
|
|
111
|
+
const param = nonIndexedWithVarNames[0];
|
|
112
|
+
const varName = param.escapedName;
|
|
113
|
+
localVarMap.set(nonIndexedParams[0].escapedName, varName);
|
|
114
|
+
const mappedType = abiTypeConverter.mapAbiType(param);
|
|
115
|
+
lines.push(` const ${varName}: ${mappedType} = ${abiTypeConverter.generateTypeConversion(mappedType, 'decodedData', false, false)}`);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
importManager.addType('JSON');
|
|
119
|
+
lines.push(` const dataParts = JSON.parse<${types_1.AssemblyPrimitiveTypes.string}[]>(decodedData)`);
|
|
120
|
+
nonIndexedWithVarNames.forEach((param, index) => {
|
|
121
|
+
const varName = param.escapedName;
|
|
122
|
+
localVarMap.set(nonIndexedParams[index].escapedName, varName);
|
|
123
|
+
const mappedType = abiTypeConverter.mapAbiType(param);
|
|
124
|
+
const parseLogic = TupleHandler_1.default.buildFieldParseLogic(`dataParts[${index}]`, param, mappedType, abiTypeConverter, importManager);
|
|
125
|
+
lines.push(` const ${varName}: ${mappedType} = ${parseLogic}`);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const constructorArgs = def.components.map((c) => localVarMap.get(c.escapedName) || c.escapedName).join(', ');
|
|
130
|
+
lines.push(` return new ${def.className}(${constructorArgs})`);
|
|
131
|
+
lines.push(` }`);
|
|
132
|
+
lines.push(`}`);
|
|
133
|
+
lines.push('');
|
|
134
|
+
});
|
|
135
|
+
return lines.join('\n');
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
exports.default = EventHandler;
|
|
@@ -36,23 +36,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
const helpers_1 = require("../../helpers");
|
|
40
39
|
const types_1 = require("../../types");
|
|
41
|
-
const ArrayHandler_1 = __importDefault(require("./ArrayHandler"));
|
|
42
40
|
const NameManager_1 = __importStar(require("./NameManager"));
|
|
43
41
|
const TupleHandler_1 = __importDefault(require("./TupleHandler"));
|
|
44
42
|
const types_2 = require("./types");
|
|
45
43
|
class FunctionHandler {
|
|
46
|
-
static appendMethod(lines, fn, importManager, tupleDefinitions, abiTypeConverter) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
44
|
+
static appendMethod(lines, fn, importManager, tupleDefinitions, abiTypeConverter, contractName) {
|
|
45
|
+
if (this.isWriteFunction(fn)) {
|
|
46
|
+
this.appendWriteMethod(lines, fn, importManager, tupleDefinitions, abiTypeConverter, contractName);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
this.appendReadMethod(lines, fn, importManager, tupleDefinitions, abiTypeConverter, contractName);
|
|
50
|
+
}
|
|
51
|
+
static getCapitalizedName(fn) {
|
|
52
|
+
const baseName = fn.escapedName || fn.name;
|
|
53
|
+
return `${baseName.charAt(0).toUpperCase()}${baseName.slice(1)}`;
|
|
54
|
+
}
|
|
55
|
+
static isWriteFunction(fn) {
|
|
56
|
+
return ['nonpayable', 'payable'].includes(fn.stateMutability || '');
|
|
56
57
|
}
|
|
57
58
|
static getReturnType(fn, tupleDefinitions, abiTypeConverter) {
|
|
58
59
|
if (this.isWriteFunction(fn))
|
|
@@ -83,91 +84,39 @@ class FunctionHandler {
|
|
|
83
84
|
})
|
|
84
85
|
.join(', ');
|
|
85
86
|
}
|
|
86
|
-
static
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
internalType: paramDefinition.internalType
|
|
100
|
-
? ArrayHandler_1.default.getArrayType(paramDefinition.internalType)
|
|
101
|
-
: undefined,
|
|
102
|
-
};
|
|
103
|
-
const nestedEvmParam = FunctionHandler.buildEvmEncodeParamCode(elementLambdaVar, elementAbiDefinition, abiTypeConverter, importManager, depth + 1);
|
|
104
|
-
return `EvmEncodeParam.fromValues('${currentAbiTypeSignature}', ${valueIdentifier}.map<EvmEncodeParam>((${elementLambdaVar}) => ${nestedEvmParam}))`;
|
|
105
|
-
}
|
|
106
|
-
if (TupleHandler_1.default.isBaseTypeATuple(paramDefinition.type)) {
|
|
107
|
-
return `EvmEncodeParam.fromValues('${currentAbiTypeSignature}', ${valueIdentifier}.toEvmEncodeParams())`;
|
|
108
|
-
}
|
|
109
|
-
const mappedParamType = abiTypeConverter.mapAbiType(paramDefinition);
|
|
110
|
-
const convertedValue = abiTypeConverter.toLibType(mappedParamType, valueIdentifier);
|
|
111
|
-
return `EvmEncodeParam.fromValue('${currentAbiTypeSignature}', ${convertedValue})`;
|
|
112
|
-
}
|
|
113
|
-
static generateCallArguments(inputs, importManager, abiTypeConverter) {
|
|
114
|
-
return inputs
|
|
115
|
-
.map((input) => {
|
|
116
|
-
const paramName = input.escapedName;
|
|
117
|
-
return FunctionHandler.buildEvmEncodeParamCode(paramName, input, abiTypeConverter, importManager, 0);
|
|
118
|
-
})
|
|
119
|
-
.join(', ');
|
|
120
|
-
}
|
|
121
|
-
static getDecodeAbiType(fn) {
|
|
122
|
-
const outputs = fn.outputs ?? [];
|
|
123
|
-
if (outputs.length === 0)
|
|
124
|
-
return '()';
|
|
125
|
-
if (outputs.length === 1) {
|
|
126
|
-
const [output] = outputs;
|
|
127
|
-
const { type, components } = output;
|
|
128
|
-
if (TupleHandler_1.default.isBaseTypeATuple(type) && components)
|
|
129
|
-
return TupleHandler_1.default.generateTupleTypeString(type, components);
|
|
130
|
-
return type;
|
|
131
|
-
}
|
|
132
|
-
return TupleHandler_1.default.generateTupleTypeString(types_2.TUPLE_ABI_TYPE, outputs);
|
|
133
|
-
}
|
|
134
|
-
static getReturnExpression(currentType, dataAccessString, importManager, abiTypeConverter, depth = 0) {
|
|
135
|
-
if (ArrayHandler_1.default.isArrayType(currentType)) {
|
|
136
|
-
importManager.addType('JSON');
|
|
137
|
-
const elementType = ArrayHandler_1.default.getArrayType(currentType);
|
|
138
|
-
const itemVar = `item${depth}`;
|
|
139
|
-
const subLogic = this.getReturnExpression(elementType, itemVar, importManager, abiTypeConverter, depth + 1);
|
|
140
|
-
return `${dataAccessString} === '' ? [] : JSON.parse<${types_1.AssemblyPrimitiveTypes.string}[]>(${dataAccessString}).map<${elementType}>(((${itemVar}: ${types_1.AssemblyPrimitiveTypes.string}) => ${subLogic}))`;
|
|
141
|
-
}
|
|
142
|
-
return abiTypeConverter.generateTypeConversion(currentType, dataAccessString, false, false);
|
|
87
|
+
static appendWriteMethod(lines, fn, importManager, tupleDefinitions, abiTypeConverter, contractName) {
|
|
88
|
+
const inputs = NameManager_1.default.resolveParameterNames(fn.inputs || [], NameManager_1.NameContext.FUNCTION_PARAMETER, 'param');
|
|
89
|
+
const methodParams = this.generateMethodParams(inputs, abiTypeConverter);
|
|
90
|
+
const returnType = this.getReturnType(fn, tupleDefinitions, abiTypeConverter);
|
|
91
|
+
const methodName = fn.escapedName || fn.name;
|
|
92
|
+
const capitalizedName = this.getCapitalizedName(fn);
|
|
93
|
+
lines.push(` ${methodName}(${methodParams}): ${returnType} {`);
|
|
94
|
+
lines.push(` const encodedData = ${contractName}Utils.encode${capitalizedName}(${inputs.map((p) => p.escapedName).join(', ')})`);
|
|
95
|
+
importManager.addType(types_1.LibTypes.Bytes);
|
|
96
|
+
importManager.addType('CallBuilder');
|
|
97
|
+
lines.push(` return CallBuilder.forChain(this._chainId).addCall(this._address, encodedData)`);
|
|
98
|
+
lines.push(` }`);
|
|
99
|
+
lines.push('');
|
|
143
100
|
}
|
|
144
|
-
static
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
lines.push(` const encodedData = Bytes.fromHexString(${encodedCall})`);
|
|
153
|
-
lines.push(` return CallBuilder.forChain(this._chainId).addCall(this._address, encodedData)`);
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
101
|
+
static appendReadMethod(lines, fn, importManager, tupleDefinitions, abiTypeConverter, contractName) {
|
|
102
|
+
const inputs = NameManager_1.default.resolveParameterNames(fn.inputs || [], NameManager_1.NameContext.FUNCTION_PARAMETER, 'param');
|
|
103
|
+
const methodParams = this.generateMethodParams(inputs, abiTypeConverter);
|
|
104
|
+
const returnType = this.getReturnType(fn, tupleDefinitions, abiTypeConverter);
|
|
105
|
+
const methodName = fn.escapedName || fn.name;
|
|
106
|
+
const capitalizedName = this.getCapitalizedName(fn);
|
|
107
|
+
lines.push(` ${methodName}(${methodParams}): ${returnType} {`);
|
|
108
|
+
lines.push(` const encodedData = ${contractName}Utils.encode${capitalizedName}(${inputs.map((p) => p.escapedName).join(', ')})`);
|
|
156
109
|
importManager.addType('environment');
|
|
157
|
-
const
|
|
110
|
+
const contractCallLine = `environment.contractCall(this._address, this._chainId, this._timestamp, encodedData.toHexString())`;
|
|
158
111
|
if (returnType === 'void') {
|
|
159
|
-
lines.push(` ${
|
|
160
|
-
return;
|
|
112
|
+
lines.push(` ${contractCallLine}`);
|
|
161
113
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
lines.push(
|
|
168
|
-
}
|
|
169
|
-
static isWriteFunction(fn) {
|
|
170
|
-
return ['nonpayable', 'payable'].includes(fn.stateMutability || '');
|
|
114
|
+
else {
|
|
115
|
+
lines.push(` const response = ${contractCallLine}`);
|
|
116
|
+
lines.push(` return ${contractName}Utils.decode${capitalizedName}(response)`);
|
|
117
|
+
}
|
|
118
|
+
lines.push(` }`);
|
|
119
|
+
lines.push('');
|
|
171
120
|
}
|
|
172
121
|
}
|
|
173
122
|
exports.default = FunctionHandler;
|
|
@@ -39,9 +39,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
const helpers_1 = require("../../helpers");
|
|
40
40
|
const types_1 = require("../../types");
|
|
41
41
|
const ArrayHandler_1 = __importDefault(require("./ArrayHandler"));
|
|
42
|
-
const FunctionHandler_1 = __importDefault(require("./FunctionHandler"));
|
|
43
42
|
const NameManager_1 = __importStar(require("./NameManager"));
|
|
44
43
|
const types_2 = require("./types");
|
|
44
|
+
const UtilsHandler_1 = __importDefault(require("./UtilsHandler"));
|
|
45
45
|
class TupleHandler {
|
|
46
46
|
/**
|
|
47
47
|
* Checks if the given ABI type string ultimately represents a tuple.
|
|
@@ -206,15 +206,6 @@ class TupleHandler {
|
|
|
206
206
|
return 'UnnamedFunctionOutputs';
|
|
207
207
|
return `${(0, helpers_1.pascalCase)(fnNamePart)}Outputs`;
|
|
208
208
|
}
|
|
209
|
-
static getTupleParseMethodBody(def, abiTypeConverter, importManager) {
|
|
210
|
-
return def.components.map((comp, index) => {
|
|
211
|
-
const fieldName = comp.escapedName;
|
|
212
|
-
const mappedComponentType = abiTypeConverter.mapAbiType(comp);
|
|
213
|
-
const dataAccess = `parts[${index}]`;
|
|
214
|
-
const parseLogic = this.buildFieldParseLogic(dataAccess, comp, mappedComponentType, abiTypeConverter, importManager);
|
|
215
|
-
return ` const ${fieldName}: ${mappedComponentType} = ${parseLogic};`;
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
209
|
static buildFieldParseLogic(dataAccessString, componentAbiParam, mappedTargetType, abiTypeConverter, importManager, depth = 0) {
|
|
219
210
|
importManager.addType('JSON');
|
|
220
211
|
const isAbiArray = ArrayHandler_1.default.isArrayType(componentAbiParam.type);
|
|
@@ -236,11 +227,20 @@ class TupleHandler {
|
|
|
236
227
|
}
|
|
237
228
|
return abiTypeConverter.generateTypeConversion(mappedTargetType, dataAccessString, false, false);
|
|
238
229
|
}
|
|
230
|
+
static getTupleParseMethodBody(def, abiTypeConverter, importManager) {
|
|
231
|
+
return def.components.map((comp, index) => {
|
|
232
|
+
const fieldName = comp.escapedName;
|
|
233
|
+
const mappedComponentType = abiTypeConverter.mapAbiType(comp);
|
|
234
|
+
const dataAccess = `parts[${index}]`;
|
|
235
|
+
const parseLogic = this.buildFieldParseLogic(dataAccess, comp, mappedComponentType, abiTypeConverter, importManager);
|
|
236
|
+
return ` const ${fieldName}: ${mappedComponentType} = ${parseLogic};`;
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
239
|
static getTupleToEvmParamsMethodBody(def, abiTypeConverter, importManager) {
|
|
240
240
|
return def.components.map((comp) => {
|
|
241
241
|
const fieldName = comp.escapedName;
|
|
242
242
|
const valueAccessPath = `this.${fieldName}`;
|
|
243
|
-
const paramCode =
|
|
243
|
+
const paramCode = UtilsHandler_1.default.buildEvmEncodeParamCode(valueAccessPath, comp, abiTypeConverter, importManager);
|
|
244
244
|
return ` ${paramCode},`;
|
|
245
245
|
});
|
|
246
246
|
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const helpers_1 = require("../../helpers");
|
|
40
|
+
const types_1 = require("../../types");
|
|
41
|
+
const ArrayHandler_1 = __importDefault(require("./ArrayHandler"));
|
|
42
|
+
const FunctionHandler_1 = __importDefault(require("./FunctionHandler"));
|
|
43
|
+
const NameManager_1 = __importStar(require("./NameManager"));
|
|
44
|
+
const TupleHandler_1 = __importDefault(require("./TupleHandler"));
|
|
45
|
+
const types_2 = require("./types");
|
|
46
|
+
class UtilsHandler {
|
|
47
|
+
static generate(contractName, functions, importManager, tupleDefinitions, abiTypeConverter) {
|
|
48
|
+
const methods = [];
|
|
49
|
+
functions.forEach((fn) => {
|
|
50
|
+
methods.push(this.generateEncodeMethod(fn, importManager, abiTypeConverter));
|
|
51
|
+
methods.push(this.generateDecodeMethod(fn, importManager, tupleDefinitions, abiTypeConverter));
|
|
52
|
+
});
|
|
53
|
+
const nonEmptyMethods = methods.filter((method) => method.trim() !== '');
|
|
54
|
+
return `export class ${contractName}Utils {\n${nonEmptyMethods.join('\n')}\n}`;
|
|
55
|
+
}
|
|
56
|
+
static buildEvmEncodeParamCode(valueIdentifier, paramDefinition, abiTypeConverter, importManager, depth = 0) {
|
|
57
|
+
importManager.addType('EvmEncodeParam');
|
|
58
|
+
const currentAbiTypeSignature = TupleHandler_1.default.isBaseTypeATuple(paramDefinition.type)
|
|
59
|
+
? TupleHandler_1.default.mapTupleType(paramDefinition.type)
|
|
60
|
+
: paramDefinition.type;
|
|
61
|
+
if (ArrayHandler_1.default.isArrayType(paramDefinition.type)) {
|
|
62
|
+
const elementLambdaVar = `s${depth}`;
|
|
63
|
+
const elementAbiDefinition = {
|
|
64
|
+
name: elementLambdaVar,
|
|
65
|
+
type: ArrayHandler_1.default.getArrayType(paramDefinition.type),
|
|
66
|
+
components: TupleHandler_1.default.isBaseTypeATuple(ArrayHandler_1.default.getArrayType(paramDefinition.type))
|
|
67
|
+
? paramDefinition.components
|
|
68
|
+
: undefined,
|
|
69
|
+
internalType: paramDefinition.internalType
|
|
70
|
+
? ArrayHandler_1.default.getArrayType(paramDefinition.internalType)
|
|
71
|
+
: undefined,
|
|
72
|
+
};
|
|
73
|
+
const nestedEvmParam = UtilsHandler.buildEvmEncodeParamCode(elementLambdaVar, elementAbiDefinition, abiTypeConverter, importManager, depth + 1);
|
|
74
|
+
return `EvmEncodeParam.fromValues('${currentAbiTypeSignature}', ${valueIdentifier}.map<EvmEncodeParam>((${elementLambdaVar}) => ${nestedEvmParam}))`;
|
|
75
|
+
}
|
|
76
|
+
if (TupleHandler_1.default.isBaseTypeATuple(paramDefinition.type)) {
|
|
77
|
+
return `EvmEncodeParam.fromValues('${currentAbiTypeSignature}', ${valueIdentifier}.toEvmEncodeParams())`;
|
|
78
|
+
}
|
|
79
|
+
const mappedParamType = abiTypeConverter.mapAbiType(paramDefinition);
|
|
80
|
+
const convertedValue = abiTypeConverter.toLibType(mappedParamType, valueIdentifier);
|
|
81
|
+
return `EvmEncodeParam.fromValue('${currentAbiTypeSignature}', ${convertedValue})`;
|
|
82
|
+
}
|
|
83
|
+
static generateEncodeMethod(fn, importManager, abiTypeConverter) {
|
|
84
|
+
const inputs = NameManager_1.default.resolveParameterNames(fn.inputs || [], NameManager_1.NameContext.FUNCTION_PARAMETER, 'param');
|
|
85
|
+
const methodParams = FunctionHandler_1.default.generateMethodParams(inputs, abiTypeConverter);
|
|
86
|
+
const capitalizedName = FunctionHandler_1.default.getCapitalizedName(fn);
|
|
87
|
+
importManager.addType(types_1.LibTypes.Bytes);
|
|
88
|
+
const lines = [];
|
|
89
|
+
lines.push(` static encode${capitalizedName}(${methodParams}): Bytes {`);
|
|
90
|
+
const callArgs = this.generateCallArguments(inputs, importManager, abiTypeConverter);
|
|
91
|
+
const selector = (0, helpers_1.getFunctionSelector)(fn);
|
|
92
|
+
if (callArgs)
|
|
93
|
+
importManager.addType('evm');
|
|
94
|
+
const encodedCall = `'${selector}'${callArgs ? ` + evm.encode([${callArgs}])` : ''}`;
|
|
95
|
+
lines.push(` return Bytes.fromHexString(${encodedCall})`);
|
|
96
|
+
lines.push(` }`);
|
|
97
|
+
lines.push('');
|
|
98
|
+
return lines.join('\n');
|
|
99
|
+
}
|
|
100
|
+
static generateDecodeMethod(fn, importManager, tupleDefinitions, abiTypeConverter) {
|
|
101
|
+
const capitalizedName = FunctionHandler_1.default.getCapitalizedName(fn);
|
|
102
|
+
// Skip decode method for write functions or void returns
|
|
103
|
+
const returnType = FunctionHandler_1.default.getReturnType(fn, tupleDefinitions, abiTypeConverter);
|
|
104
|
+
if (FunctionHandler_1.default.isWriteFunction(fn) || returnType === 'void')
|
|
105
|
+
return '';
|
|
106
|
+
importManager.addType('EvmDecodeParam');
|
|
107
|
+
importManager.addType('evm');
|
|
108
|
+
const lines = [];
|
|
109
|
+
lines.push(` static decode${capitalizedName}(encodedResponse: string): ${returnType} {`);
|
|
110
|
+
const decodeAbiType = this.getDecodeAbiType(fn);
|
|
111
|
+
lines.push(` const decodedResponse = evm.decode(new EvmDecodeParam('${decodeAbiType}', encodedResponse))`);
|
|
112
|
+
const returnExpression = this.getReturnExpression(returnType, 'decodedResponse', importManager, abiTypeConverter);
|
|
113
|
+
lines.push(` return ${returnExpression}`);
|
|
114
|
+
lines.push(` }`);
|
|
115
|
+
lines.push('');
|
|
116
|
+
return lines.join('\n');
|
|
117
|
+
}
|
|
118
|
+
static generateCallArguments(inputs, importManager, abiTypeConverter) {
|
|
119
|
+
return inputs
|
|
120
|
+
.map((input) => {
|
|
121
|
+
const paramName = input.escapedName;
|
|
122
|
+
return UtilsHandler.buildEvmEncodeParamCode(paramName, input, abiTypeConverter, importManager, 0);
|
|
123
|
+
})
|
|
124
|
+
.join(', ');
|
|
125
|
+
}
|
|
126
|
+
static getDecodeAbiType(fn) {
|
|
127
|
+
const outputs = fn.outputs ?? [];
|
|
128
|
+
if (outputs.length === 0)
|
|
129
|
+
return '()';
|
|
130
|
+
if (outputs.length === 1) {
|
|
131
|
+
const [output] = outputs;
|
|
132
|
+
const { type, components } = output;
|
|
133
|
+
if (TupleHandler_1.default.isBaseTypeATuple(type) && components)
|
|
134
|
+
return TupleHandler_1.default.generateTupleTypeString(type, components);
|
|
135
|
+
return type;
|
|
136
|
+
}
|
|
137
|
+
return TupleHandler_1.default.generateTupleTypeString(types_2.TUPLE_ABI_TYPE, outputs);
|
|
138
|
+
}
|
|
139
|
+
static getReturnExpression(currentType, dataAccessString, importManager, abiTypeConverter, depth = 0) {
|
|
140
|
+
if (ArrayHandler_1.default.isArrayType(currentType)) {
|
|
141
|
+
importManager.addType('JSON');
|
|
142
|
+
const elementType = ArrayHandler_1.default.getArrayType(currentType);
|
|
143
|
+
const itemVar = `item${depth}`;
|
|
144
|
+
const subLogic = this.getReturnExpression(elementType, itemVar, importManager, abiTypeConverter, depth + 1);
|
|
145
|
+
return `${dataAccessString} === '' ? [] : JSON.parse<${types_1.AssemblyPrimitiveTypes.string}[]>(${dataAccessString}).map<${elementType}>(((${itemVar}: ${types_1.AssemblyPrimitiveTypes.string}) => ${subLogic}))`;
|
|
146
|
+
}
|
|
147
|
+
return abiTypeConverter.generateTypeConversion(currentType, dataAccessString, false, false);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
exports.default = UtilsHandler;
|