@alephium/web3 0.2.0-rc.1 → 0.2.0-rc.12
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/.eslintignore +2 -2
- package/README.md +2 -135
- package/contracts/greeter/greeter.ral +2 -2
- package/contracts/greeter/greeter_interface.ral +1 -0
- package/contracts/greeter_main.ral +1 -3
- package/dist/alephium-web3.min.js +1 -1
- package/dist/alephium-web3.min.js.LICENSE.txt +0 -17
- package/dist/alephium-web3.min.js.map +1 -1
- package/dist/scripts/create-project.js +3 -2
- package/dist/src/api/api-alephium.d.ts +44 -11
- package/dist/src/api/api-alephium.js +81 -74
- package/dist/src/api/api-explorer.d.ts +16 -16
- package/dist/src/api/api-explorer.js +24 -33
- package/dist/src/api/index.d.ts +3 -2
- package/dist/src/api/index.js +22 -3
- package/dist/src/api/types.d.ts +23 -0
- package/dist/src/api/types.js +240 -0
- package/dist/src/api/utils.d.ts +6 -0
- package/{src/utils/djb2.test.ts → dist/src/api/utils.js} +11 -17
- package/dist/src/contract/contract.d.ts +104 -64
- package/dist/src/contract/contract.js +370 -426
- package/dist/src/contract/events.d.ts +4 -4
- package/dist/src/contract/index.js +5 -1
- package/dist/src/contract/ralph.d.ts +4 -4
- package/dist/src/global.d.ts +4 -0
- package/dist/src/global.js +38 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +20 -1
- package/dist/src/signer/index.d.ts +0 -1
- package/dist/src/signer/index.js +5 -2
- package/dist/src/signer/signer.d.ts +21 -11
- package/dist/src/signer/signer.js +46 -9
- package/dist/src/transaction/index.d.ts +0 -1
- package/dist/src/transaction/index.js +5 -2
- package/dist/src/transaction/status.d.ts +2 -1
- package/dist/src/utils/index.d.ts +0 -1
- package/dist/src/utils/index.js +5 -2
- package/dist/src/utils/subscription.d.ts +0 -1
- package/dist/src/utils/subscription.js +2 -1
- package/dist/src/utils/utils.d.ts +5 -11
- package/dist/src/utils/utils.js +17 -25
- package/jest-config.json +11 -0
- package/package.json +8 -36
- package/scripts/create-project.ts +3 -2
- package/src/api/api-alephium.ts +54 -16
- package/src/api/api-explorer.ts +1 -11
- package/src/api/index.ts +14 -3
- package/src/api/types.ts +233 -0
- package/src/{utils/password-crypto.test.ts → api/utils.ts} +7 -9
- package/src/contract/contract.ts +537 -526
- package/src/contract/events.ts +6 -6
- package/src/contract/ralph.ts +4 -4
- package/src/{transaction/sign-verify.ts → global.ts} +14 -15
- package/src/index.ts +3 -0
- package/src/signer/index.ts +0 -1
- package/src/signer/signer.ts +70 -19
- package/src/transaction/index.ts +0 -1
- package/src/transaction/status.ts +4 -2
- package/src/utils/index.ts +0 -1
- package/src/utils/subscription.ts +3 -3
- package/src/utils/utils.ts +10 -20
- package/templates/base/package.json +2 -2
- package/templates/base/src/greeter.ts +10 -9
- package/templates/react/package.json +2 -2
- package/templates/react/src/App.tsx +2 -2
- package/.eslintrc.json +0 -21
- package/LICENSE +0 -165
- package/contracts/add/add.ral +0 -16
- package/contracts/main.ral +0 -6
- package/contracts/sub/sub.ral +0 -9
- package/dist/src/signer/node-wallet.d.ts +0 -13
- package/dist/src/signer/node-wallet.js +0 -60
- package/dist/src/test/index.d.ts +0 -7
- package/dist/src/test/index.js +0 -41
- package/dist/src/test/privatekey-wallet.d.ts +0 -12
- package/dist/src/test/privatekey-wallet.js +0 -68
- package/dist/src/transaction/sign-verify.d.ts +0 -2
- package/dist/src/transaction/sign-verify.js +0 -58
- package/dist/src/utils/password-crypto.d.ts +0 -2
- package/dist/src/utils/password-crypto.js +0 -69
- package/gitignore +0 -10
- package/src/contract/ralph.test.ts +0 -178
- package/src/fixtures/address.json +0 -36
- package/src/fixtures/balance.json +0 -9
- package/src/fixtures/self-clique.json +0 -19
- package/src/fixtures/transaction.json +0 -13
- package/src/fixtures/transactions.json +0 -179
- package/src/signer/fixtures/genesis.json +0 -26
- package/src/signer/fixtures/wallets.json +0 -26
- package/src/signer/node-wallet.ts +0 -74
- package/src/test/index.ts +0 -32
- package/src/test/privatekey-wallet.ts +0 -58
- package/src/transaction/sign-verify.test.ts +0 -50
- package/src/utils/address.test.ts +0 -47
- package/src/utils/password-crypto.ts +0 -77
- package/src/utils/utils.test.ts +0 -161
- package/test/contract.test.ts +0 -178
- package/test/events.test.ts +0 -138
- package/test/transaction.test.ts +0 -72
|
@@ -18,7 +18,11 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
18
18
|
*/
|
|
19
19
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
20
20
|
if (k2 === undefined) k2 = k;
|
|
21
|
-
Object.
|
|
21
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
22
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
23
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
24
|
+
}
|
|
25
|
+
Object.defineProperty(o, k2, desc);
|
|
22
26
|
}) : (function(o, m, k, k2) {
|
|
23
27
|
if (k2 === undefined) k2 = k;
|
|
24
28
|
o[k2] = m[k];
|
|
@@ -39,178 +43,356 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
39
43
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
44
|
};
|
|
41
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.
|
|
46
|
+
exports.Script = exports.Contract = exports.Artifact = exports.Project = exports.DEFAULT_COMPILER_OPTIONS = exports.DEFAULT_NODE_COMPILER_OPTIONS = void 0;
|
|
43
47
|
const buffer_1 = require("buffer/");
|
|
44
|
-
const
|
|
45
|
-
const crypto = __importStar(require("crypto"));
|
|
48
|
+
const crypto_1 = require("crypto");
|
|
46
49
|
const fs_1 = __importDefault(require("fs"));
|
|
47
50
|
const fs_2 = require("fs");
|
|
51
|
+
const api_1 = require("../api");
|
|
48
52
|
const ralph = __importStar(require("./ralph"));
|
|
49
53
|
const utils_1 = require("../utils");
|
|
54
|
+
const global_1 = require("../global");
|
|
55
|
+
var SourceType;
|
|
56
|
+
(function (SourceType) {
|
|
57
|
+
SourceType[SourceType["Contract"] = 0] = "Contract";
|
|
58
|
+
SourceType[SourceType["Script"] = 1] = "Script";
|
|
59
|
+
SourceType[SourceType["AbstractContract"] = 2] = "AbstractContract";
|
|
60
|
+
SourceType[SourceType["Interface"] = 3] = "Interface";
|
|
61
|
+
})(SourceType || (SourceType = {}));
|
|
62
|
+
exports.DEFAULT_NODE_COMPILER_OPTIONS = {
|
|
63
|
+
ignoreUnusedConstantsWarnings: false,
|
|
64
|
+
ignoreUnusedVariablesWarnings: false,
|
|
65
|
+
ignoreUnusedFieldsWarnings: false,
|
|
66
|
+
ignoreUnusedPrivateFunctionsWarnings: false,
|
|
67
|
+
ignoreReadonlyCheckWarnings: false,
|
|
68
|
+
ignoreExternalCallCheckWarnings: false
|
|
69
|
+
};
|
|
70
|
+
exports.DEFAULT_COMPILER_OPTIONS = { errorOnWarnings: true, ...exports.DEFAULT_NODE_COMPILER_OPTIONS };
|
|
71
|
+
class TypedMatcher {
|
|
72
|
+
constructor(pattern, type) {
|
|
73
|
+
this.matcher = new RegExp(pattern, 'mg');
|
|
74
|
+
this.type = type;
|
|
75
|
+
}
|
|
76
|
+
match(str) {
|
|
77
|
+
const results = str.match(this.matcher);
|
|
78
|
+
return results === null ? 0 : results.length;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
50
81
|
class SourceFile {
|
|
51
|
-
constructor(
|
|
52
|
-
this.
|
|
53
|
-
this.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
82
|
+
constructor(type, sourceCode, sourceCodeHash, contractPath) {
|
|
83
|
+
this.type = type;
|
|
84
|
+
this.sourceCode = sourceCode;
|
|
85
|
+
this.sourceCodeHash = sourceCodeHash;
|
|
86
|
+
this.contractPath = contractPath;
|
|
87
|
+
}
|
|
88
|
+
getArtifactPath(artifactsRootPath) {
|
|
89
|
+
return artifactsRootPath + this.contractPath.slice(this.contractPath.indexOf('/')) + '.json';
|
|
90
|
+
}
|
|
91
|
+
static async from(type, sourceCode, contractPath) {
|
|
92
|
+
const sourceCodeHash = await crypto_1.webcrypto.subtle.digest('SHA-256', buffer_1.Buffer.from(sourceCode));
|
|
93
|
+
return new SourceFile(type, sourceCode, buffer_1.Buffer.from(sourceCodeHash).toString('hex'), contractPath);
|
|
62
94
|
}
|
|
63
95
|
}
|
|
64
|
-
class
|
|
65
|
-
constructor(
|
|
66
|
-
this.
|
|
67
|
-
this.
|
|
96
|
+
class Compiled {
|
|
97
|
+
constructor(sourceFile, artifact, warnings) {
|
|
98
|
+
this.sourceFile = sourceFile;
|
|
99
|
+
this.artifact = artifact;
|
|
100
|
+
this.warnings = warnings;
|
|
68
101
|
}
|
|
69
|
-
|
|
70
|
-
|
|
102
|
+
}
|
|
103
|
+
class ProjectArtifact {
|
|
104
|
+
constructor(compilerOptionsUsed, infos) {
|
|
105
|
+
ProjectArtifact.checkCompilerOptionsParameter(compilerOptionsUsed);
|
|
106
|
+
this.compilerOptionsUsed = compilerOptionsUsed;
|
|
107
|
+
this.infos = infos;
|
|
71
108
|
}
|
|
72
|
-
static
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
109
|
+
static checkCompilerOptionsParameter(compilerOptions) {
|
|
110
|
+
if (Object.keys(compilerOptions).length != Object.keys(exports.DEFAULT_NODE_COMPILER_OPTIONS).length) {
|
|
111
|
+
throw Error(`Not all compiler options are set: ${compilerOptions}`);
|
|
112
|
+
}
|
|
113
|
+
const combined = { ...compilerOptions, ...exports.DEFAULT_NODE_COMPILER_OPTIONS };
|
|
114
|
+
if (Object.keys(combined).length !== Object.keys(exports.DEFAULT_NODE_COMPILER_OPTIONS).length) {
|
|
115
|
+
throw Error(`There are unknown compiler options: ${compilerOptions}`);
|
|
79
116
|
}
|
|
80
117
|
}
|
|
81
|
-
|
|
82
|
-
|
|
118
|
+
async saveToFile(rootPath) {
|
|
119
|
+
const filepath = rootPath + '/' + ProjectArtifact.artifactFileName;
|
|
120
|
+
const artifact = { compilerOptionsUsed: this.compilerOptionsUsed, infos: Object.fromEntries(this.infos) };
|
|
121
|
+
const content = JSON.stringify(artifact, null, 2);
|
|
122
|
+
return fs_2.promises.writeFile(filepath, content);
|
|
83
123
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
return
|
|
124
|
+
needToReCompile(compilerOptions, files) {
|
|
125
|
+
ProjectArtifact.checkCompilerOptionsParameter(compilerOptions);
|
|
126
|
+
const optionsMatched = Object.entries(compilerOptions).every(([key, inputOption]) => {
|
|
127
|
+
const usedOption = this.compilerOptionsUsed[`${key}`];
|
|
128
|
+
return usedOption === inputOption;
|
|
129
|
+
});
|
|
130
|
+
if (!optionsMatched) {
|
|
131
|
+
return true;
|
|
89
132
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
throw new Error('Invalid file path: ' + path);
|
|
98
|
-
}
|
|
99
|
-
dirs.pop();
|
|
100
|
-
break;
|
|
101
|
-
}
|
|
102
|
-
default: {
|
|
103
|
-
dirs.push(part);
|
|
104
|
-
}
|
|
133
|
+
if (files.length !== this.infos.size) {
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
for (const file of files) {
|
|
137
|
+
const info = this.infos.get(file.contractPath);
|
|
138
|
+
if (typeof info === 'undefined' || info.sourceCodeHash !== file.sourceCodeHash) {
|
|
139
|
+
return true;
|
|
105
140
|
}
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
static async from(rootPath) {
|
|
145
|
+
const filepath = rootPath + '/' + ProjectArtifact.artifactFileName;
|
|
146
|
+
if (!fs_1.default.existsSync(filepath)) {
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
const content = await fs_2.promises.readFile(filepath);
|
|
150
|
+
const json = JSON.parse(content.toString());
|
|
151
|
+
const compilerOptionsUsed = json.compilerOptionsUsed;
|
|
152
|
+
const files = new Map(Object.entries(json.infos));
|
|
153
|
+
return new ProjectArtifact(compilerOptionsUsed, files);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
ProjectArtifact.artifactFileName = '.project.json';
|
|
157
|
+
class Project {
|
|
158
|
+
constructor(provider, contractsRootPath, artifactsRootPath, sourceFiles, contracts, scripts, errorOnWarnings, projectArtifact) {
|
|
159
|
+
this.nodeProvider = provider;
|
|
160
|
+
this.contractsRootPath = contractsRootPath;
|
|
161
|
+
this.artifactsRootPath = artifactsRootPath;
|
|
162
|
+
this.sourceFiles = sourceFiles;
|
|
163
|
+
this.contracts = contracts;
|
|
164
|
+
this.scripts = scripts;
|
|
165
|
+
this.projectArtifact = projectArtifact;
|
|
166
|
+
if (errorOnWarnings) {
|
|
167
|
+
Project.checkCompilerWarnings([...contracts.map((c) => c.warnings).flat(), ...scripts.map((s) => s.warnings).flat()], errorOnWarnings);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
static buildProjectArtifact(sourceFiles, contracts, scripts, compilerOptions) {
|
|
171
|
+
const files = new Map();
|
|
172
|
+
contracts.forEach((c) => {
|
|
173
|
+
files.set(c.sourceFile.contractPath, {
|
|
174
|
+
sourceCodeHash: c.sourceFile.sourceCodeHash,
|
|
175
|
+
warnings: c.warnings
|
|
176
|
+
});
|
|
106
177
|
});
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
localImportsCache.push(match);
|
|
113
|
-
return '';
|
|
178
|
+
scripts.forEach((s) => {
|
|
179
|
+
files.set(s.sourceFile.contractPath, {
|
|
180
|
+
sourceCodeHash: s.sourceFile.sourceCodeHash,
|
|
181
|
+
warnings: s.warnings
|
|
182
|
+
});
|
|
114
183
|
});
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
184
|
+
const compiledSize = contracts.length + scripts.length;
|
|
185
|
+
sourceFiles.slice(compiledSize).forEach((c) => {
|
|
186
|
+
files.set(c.contractPath, {
|
|
187
|
+
sourceCodeHash: c.sourceCodeHash,
|
|
188
|
+
warnings: []
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
return new ProjectArtifact(compilerOptions, files);
|
|
192
|
+
}
|
|
193
|
+
getContractPath(path) {
|
|
194
|
+
return path.startsWith(`./${this.contractsRootPath}`)
|
|
195
|
+
? path.slice(2)
|
|
196
|
+
: path.startsWith(this.contractsRootPath)
|
|
197
|
+
? path
|
|
198
|
+
: this.contractsRootPath + '/' + path;
|
|
199
|
+
}
|
|
200
|
+
static checkCompilerWarnings(warnings, errorOnWarnings) {
|
|
201
|
+
if (warnings.length !== 0) {
|
|
202
|
+
const prefixPerWarning = ' - ';
|
|
203
|
+
const warningString = prefixPerWarning + warnings.join('\n' + prefixPerWarning);
|
|
204
|
+
const output = `Compilation warnings:\n` + warningString + '\n';
|
|
205
|
+
if (errorOnWarnings) {
|
|
206
|
+
throw new Error(output);
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
console.log(output);
|
|
122
210
|
}
|
|
123
211
|
}
|
|
124
|
-
return result;
|
|
125
212
|
}
|
|
126
|
-
static
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return
|
|
213
|
+
static contract(name) {
|
|
214
|
+
const contract = Project.currentProject.contracts.find((c) => c.artifact.name === name);
|
|
215
|
+
if (typeof contract === 'undefined') {
|
|
216
|
+
throw new Error(`Contract "${name}" does not exist`);
|
|
217
|
+
}
|
|
218
|
+
return contract.artifact;
|
|
132
219
|
}
|
|
133
|
-
static
|
|
134
|
-
|
|
135
|
-
|
|
220
|
+
static script(name) {
|
|
221
|
+
const script = Project.currentProject.scripts.find((c) => c.artifact.name === name);
|
|
222
|
+
if (typeof script === 'undefined') {
|
|
223
|
+
throw new Error(`Script "${name}" does not exist`);
|
|
136
224
|
}
|
|
225
|
+
return script.artifact;
|
|
137
226
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
227
|
+
async saveArtifactsToFile() {
|
|
228
|
+
const artifactsRootPath = this.artifactsRootPath;
|
|
229
|
+
const saveToFile = async function (compiled) {
|
|
230
|
+
const artifactPath = compiled.sourceFile.getArtifactPath(artifactsRootPath);
|
|
231
|
+
const folder = artifactPath.slice(0, artifactPath.lastIndexOf('/'));
|
|
232
|
+
if (!fs_1.default.existsSync(folder)) {
|
|
233
|
+
fs_1.default.mkdirSync(folder, { recursive: true });
|
|
234
|
+
}
|
|
235
|
+
return fs_2.promises.writeFile(artifactPath, compiled.artifact.toString());
|
|
236
|
+
};
|
|
237
|
+
for (const contract of this.contracts) {
|
|
238
|
+
await saveToFile(contract);
|
|
145
239
|
}
|
|
146
|
-
|
|
147
|
-
|
|
240
|
+
for (const script of this.scripts) {
|
|
241
|
+
await saveToFile(script);
|
|
148
242
|
}
|
|
243
|
+
await this.projectArtifact.saveToFile(this.artifactsRootPath);
|
|
149
244
|
}
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
if (
|
|
153
|
-
|
|
245
|
+
contractByCodeHash(codeHash) {
|
|
246
|
+
const contract = this.contracts.find((c) => c.artifact.codeHash === codeHash);
|
|
247
|
+
if (typeof contract === 'undefined') {
|
|
248
|
+
throw new Error(`Unknown code with code hash: ${codeHash}`);
|
|
154
249
|
}
|
|
155
|
-
return
|
|
250
|
+
return contract.artifact;
|
|
156
251
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
252
|
+
static async compile(provider, files, contractsRootPath, artifactsRootPath, errorOnWarnings, compilerOptions) {
|
|
253
|
+
const sourceStr = files.map((f) => f.sourceCode).join('\n');
|
|
254
|
+
const result = await provider.contracts.postContractsCompileProject({
|
|
255
|
+
code: sourceStr,
|
|
256
|
+
compilerOptions: compilerOptions
|
|
257
|
+
});
|
|
258
|
+
const contracts = [];
|
|
259
|
+
const scripts = [];
|
|
260
|
+
result.contracts.forEach((contractResult, index) => {
|
|
261
|
+
const sourceFile = files[`${index}`];
|
|
262
|
+
const contract = Contract.fromCompileResult(contractResult);
|
|
263
|
+
contracts.push(new Compiled(sourceFile, contract, contractResult.warnings));
|
|
264
|
+
});
|
|
265
|
+
result.scripts.forEach((scriptResult, index) => {
|
|
266
|
+
const sourceFile = files[index + contracts.length];
|
|
267
|
+
const script = Script.fromCompileResult(scriptResult);
|
|
268
|
+
scripts.push(new Compiled(sourceFile, script, scriptResult.warnings));
|
|
269
|
+
});
|
|
270
|
+
const projectArtifact = Project.buildProjectArtifact(files, contracts, scripts, compilerOptions);
|
|
271
|
+
const project = new Project(provider, contractsRootPath, artifactsRootPath, files, contracts, scripts, errorOnWarnings, projectArtifact);
|
|
272
|
+
await project.saveArtifactsToFile();
|
|
273
|
+
return project;
|
|
172
274
|
}
|
|
173
|
-
static
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
275
|
+
static async loadArtifacts(provider, files, projectArtifact, contractsRootPath, artifactsRootPath, errorOnWarnings, compilerOptions) {
|
|
276
|
+
try {
|
|
277
|
+
const contracts = [];
|
|
278
|
+
const scripts = [];
|
|
279
|
+
for (const file of files) {
|
|
280
|
+
const info = projectArtifact.infos.get(file.contractPath);
|
|
281
|
+
if (typeof info === 'undefined') {
|
|
282
|
+
throw Error(`Unable to find project info for ${file.contractPath}, please rebuild the project`);
|
|
283
|
+
}
|
|
284
|
+
const warnings = info.warnings;
|
|
285
|
+
const artifactPath = file.getArtifactPath(artifactsRootPath);
|
|
286
|
+
if (file.type === SourceType.Contract) {
|
|
287
|
+
const artifact = await Contract.fromArtifactFile(artifactPath);
|
|
288
|
+
contracts.push(new Compiled(file, artifact, warnings));
|
|
289
|
+
}
|
|
290
|
+
else if (file.type === SourceType.Script) {
|
|
291
|
+
const artifact = await Script.fromArtifactFile(artifactPath);
|
|
292
|
+
scripts.push(new Compiled(file, artifact, warnings));
|
|
293
|
+
}
|
|
185
294
|
}
|
|
295
|
+
return new Project(provider, contractsRootPath, artifactsRootPath, files, contracts, scripts, errorOnWarnings, projectArtifact);
|
|
186
296
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
297
|
+
catch (error) {
|
|
298
|
+
console.log(`Failed to load artifacts, error: ${error}, try to re-compile contracts...`);
|
|
299
|
+
return Project.compile(provider, files, contractsRootPath, artifactsRootPath, errorOnWarnings, compilerOptions);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
static async loadSourceFile(dirPath, filename) {
|
|
303
|
+
const contractPath = dirPath + '/' + filename;
|
|
304
|
+
if (!filename.endsWith('.ral')) {
|
|
305
|
+
throw new Error(`Invalid filename: ${contractPath}, smart contract file name should end with ".ral"`);
|
|
306
|
+
}
|
|
307
|
+
const sourceBuffer = await fs_2.promises.readFile(contractPath);
|
|
308
|
+
const sourceStr = sourceBuffer.toString();
|
|
309
|
+
const results = this.matchers.map((m) => m.match(sourceStr));
|
|
310
|
+
const matchNumber = results.reduce((a, b) => a + b, 0);
|
|
311
|
+
if (matchNumber === 0) {
|
|
312
|
+
throw new Error(`No contract defined in file: ${contractPath}`);
|
|
313
|
+
}
|
|
314
|
+
if (matchNumber > 1) {
|
|
315
|
+
throw new Error(`Multiple definitions in file: ${contractPath}`);
|
|
316
|
+
}
|
|
317
|
+
const matcherIndex = results.indexOf(1);
|
|
318
|
+
const type = this.matchers[`${matcherIndex}`].type;
|
|
319
|
+
return SourceFile.from(type, sourceStr, contractPath);
|
|
320
|
+
}
|
|
321
|
+
static async loadSourceFiles(contractsRootPath) {
|
|
322
|
+
const loadDir = async function (dirPath, results) {
|
|
323
|
+
const dirents = await fs_2.promises.readdir(dirPath, { withFileTypes: true });
|
|
324
|
+
for (const dirent of dirents) {
|
|
325
|
+
if (dirent.isFile()) {
|
|
326
|
+
const file = await Project.loadSourceFile(dirPath, dirent.name);
|
|
327
|
+
results.push(file);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
const newPath = dirPath + '/' + dirent.name;
|
|
331
|
+
await loadDir(newPath, results);
|
|
332
|
+
}
|
|
190
333
|
}
|
|
334
|
+
};
|
|
335
|
+
const sourceFiles = [];
|
|
336
|
+
await loadDir(contractsRootPath, sourceFiles);
|
|
337
|
+
const contractAndScriptSize = sourceFiles.filter((f) => f.type === SourceType.Contract || f.type === SourceType.Script).length;
|
|
338
|
+
if (sourceFiles.length === 0 || contractAndScriptSize === 0) {
|
|
339
|
+
throw new Error('Project have no source files');
|
|
340
|
+
}
|
|
341
|
+
return sourceFiles.sort((a, b) => a.type - b.type);
|
|
342
|
+
}
|
|
343
|
+
static async build(compilerOptionsPartial = {}, contractsRootPath = 'contracts', artifactsRootPath = 'artifacts') {
|
|
344
|
+
const provider = (0, global_1.getCurrentNodeProvider)();
|
|
345
|
+
const sourceFiles = await Project.loadSourceFiles(contractsRootPath);
|
|
346
|
+
const { errorOnWarnings, ...nodeCompilerOptions } = { ...exports.DEFAULT_COMPILER_OPTIONS, ...compilerOptionsPartial };
|
|
347
|
+
const projectArtifact = await ProjectArtifact.from(artifactsRootPath);
|
|
348
|
+
if (typeof projectArtifact === 'undefined' || projectArtifact.needToReCompile(nodeCompilerOptions, sourceFiles)) {
|
|
349
|
+
console.log(`Compile contracts in folder "${contractsRootPath}"`);
|
|
350
|
+
Project.currentProject = await Project.compile(provider, sourceFiles, contractsRootPath, artifactsRootPath, errorOnWarnings, nodeCompilerOptions);
|
|
191
351
|
}
|
|
352
|
+
else {
|
|
353
|
+
console.log(`Load compiled contracts from folder "${artifactsRootPath}"`);
|
|
354
|
+
Project.currentProject = await Project.loadArtifacts(provider, sourceFiles, projectArtifact, contractsRootPath, artifactsRootPath, errorOnWarnings, nodeCompilerOptions);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
exports.Project = Project;
|
|
359
|
+
Project.abstractContractMatcher = new TypedMatcher('^Abstract Contract [A-Z][a-zA-Z0-9]*', SourceType.AbstractContract);
|
|
360
|
+
Project.contractMatcher = new TypedMatcher('^Contract [A-Z][a-zA-Z0-9]*', SourceType.Contract);
|
|
361
|
+
Project.interfaceMatcher = new TypedMatcher('^Interface [A-Z][a-zA-Z0-9]* \\{', SourceType.Interface);
|
|
362
|
+
Project.scriptMatcher = new TypedMatcher('^TxScript [A-Z][a-zA-Z0-9]*', SourceType.Script);
|
|
363
|
+
Project.matchers = [
|
|
364
|
+
Project.abstractContractMatcher,
|
|
365
|
+
Project.contractMatcher,
|
|
366
|
+
Project.interfaceMatcher,
|
|
367
|
+
Project.scriptMatcher
|
|
368
|
+
];
|
|
369
|
+
class Artifact {
|
|
370
|
+
constructor(name, functions) {
|
|
371
|
+
this.name = name;
|
|
372
|
+
this.functions = functions;
|
|
192
373
|
}
|
|
193
|
-
|
|
194
|
-
return
|
|
374
|
+
publicFunctions() {
|
|
375
|
+
return this.functions.filter((func) => func.isPublic).map((func) => func.name);
|
|
195
376
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
fs_1.default.mkdirSync(Common._artifactsFolder(), { recursive: true });
|
|
199
|
-
}
|
|
200
|
-
const sourceFile = this.getSourceFile(path, []);
|
|
201
|
-
const contract = await Common._from(provider, sourceFile, (sourceFile) => Contract.loadContractStr(sourceFile), Contract.compile);
|
|
202
|
-
this._putArtifactToCache(contract);
|
|
203
|
-
return contract;
|
|
377
|
+
usingPreapprovedAssetsFunctions() {
|
|
378
|
+
return this.functions.filter((func) => func.usePreapprovedAssets).map((func) => func.name);
|
|
204
379
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
380
|
+
usingAssetsInContractFunctions() {
|
|
381
|
+
return this.functions.filter((func) => func.useAssetsInContract).map((func) => func.name);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
exports.Artifact = Artifact;
|
|
385
|
+
class Contract extends Artifact {
|
|
386
|
+
constructor(name, bytecode, codeHash, fieldsSig, eventsSig, functions) {
|
|
387
|
+
super(name, functions);
|
|
388
|
+
this.bytecode = bytecode;
|
|
389
|
+
this.codeHash = codeHash;
|
|
390
|
+
this.fieldsSig = fieldsSig;
|
|
391
|
+
this.eventsSig = eventsSig;
|
|
210
392
|
}
|
|
211
393
|
// TODO: safely parse json
|
|
212
394
|
static fromJson(artifact) {
|
|
213
|
-
if (artifact.
|
|
395
|
+
if (artifact.name == null ||
|
|
214
396
|
artifact.bytecode == null ||
|
|
215
397
|
artifact.codeHash == null ||
|
|
216
398
|
artifact.fieldsSig == null ||
|
|
@@ -218,31 +400,34 @@ class Contract extends Common {
|
|
|
218
400
|
artifact.functions == null) {
|
|
219
401
|
throw Error('The artifact JSON for contract is incomplete');
|
|
220
402
|
}
|
|
221
|
-
const contract = new Contract(artifact.
|
|
222
|
-
this._putArtifactToCache(contract);
|
|
403
|
+
const contract = new Contract(artifact.name, artifact.bytecode, artifact.codeHash, artifact.fieldsSig, artifact.eventsSig, artifact.functions);
|
|
223
404
|
return contract;
|
|
224
405
|
}
|
|
406
|
+
static fromCompileResult(result) {
|
|
407
|
+
return new Contract(result.name, result.bytecode, result.codeHash, result.fields, result.events, result.functions);
|
|
408
|
+
}
|
|
225
409
|
// support both 'code.ral' and 'code.ral.json'
|
|
226
410
|
static async fromArtifactFile(path) {
|
|
227
|
-
const
|
|
228
|
-
const artifactPath = sourceFile.artifactPath;
|
|
229
|
-
const content = await fs_2.promises.readFile(artifactPath);
|
|
411
|
+
const content = await fs_2.promises.readFile(path);
|
|
230
412
|
const artifact = JSON.parse(content.toString());
|
|
231
413
|
return Contract.fromJson(artifact);
|
|
232
414
|
}
|
|
233
|
-
async fetchState(
|
|
234
|
-
const state = await
|
|
415
|
+
async fetchState(address, group) {
|
|
416
|
+
const state = await Project.currentProject.nodeProvider.contracts.getContractsAddressState(address, {
|
|
417
|
+
group: group
|
|
418
|
+
});
|
|
235
419
|
return this.fromApiContractState(state);
|
|
236
420
|
}
|
|
237
421
|
toString() {
|
|
238
|
-
|
|
239
|
-
|
|
422
|
+
const object = {
|
|
423
|
+
name: this.name,
|
|
240
424
|
bytecode: this.bytecode,
|
|
241
425
|
codeHash: this.codeHash,
|
|
242
426
|
fieldsSig: this.fieldsSig,
|
|
243
427
|
eventsSig: this.eventsSig,
|
|
244
428
|
functions: this.functions
|
|
245
|
-
}
|
|
429
|
+
};
|
|
430
|
+
return JSON.stringify(object, null, 2);
|
|
246
431
|
}
|
|
247
432
|
toState(fields, asset, address) {
|
|
248
433
|
const addressDef = typeof address !== 'undefined' ? address : Contract.randomAddress();
|
|
@@ -256,16 +441,18 @@ class Contract extends Common {
|
|
|
256
441
|
asset: asset
|
|
257
442
|
};
|
|
258
443
|
}
|
|
444
|
+
// no need to be cryptographically strong random
|
|
259
445
|
static randomAddress() {
|
|
260
|
-
const bytes =
|
|
446
|
+
const bytes = new Uint8Array(33);
|
|
447
|
+
crypto_1.webcrypto.getRandomValues(bytes);
|
|
261
448
|
bytes[0] = 3;
|
|
262
449
|
return utils_1.bs58.encode(bytes);
|
|
263
450
|
}
|
|
264
|
-
async _test(
|
|
451
|
+
async _test(funcName, params, expectPublic, accessType) {
|
|
265
452
|
const apiParams = this.toTestContract(funcName, params);
|
|
266
|
-
const apiResult = await
|
|
453
|
+
const apiResult = await Project.currentProject.nodeProvider.contracts.postContractsTestContract(apiParams);
|
|
267
454
|
const methodIndex = typeof params.testMethodIndex !== 'undefined' ? params.testMethodIndex : this.getMethodIndex(funcName);
|
|
268
|
-
const isPublic = this.functions[`${methodIndex}`].
|
|
455
|
+
const isPublic = this.functions[`${methodIndex}`].isPublic;
|
|
269
456
|
if (isPublic === expectPublic) {
|
|
270
457
|
const result = await this.fromTestContractResult(methodIndex, apiResult);
|
|
271
458
|
return result;
|
|
@@ -274,11 +461,11 @@ class Contract extends Common {
|
|
|
274
461
|
throw new Error(`The test method ${funcName} is not ${accessType}`);
|
|
275
462
|
}
|
|
276
463
|
}
|
|
277
|
-
async testPublicMethod(
|
|
278
|
-
return this._test(
|
|
464
|
+
async testPublicMethod(funcName, params) {
|
|
465
|
+
return this._test(funcName, params, true, 'public');
|
|
279
466
|
}
|
|
280
|
-
async testPrivateMethod(
|
|
281
|
-
return this._test(
|
|
467
|
+
async testPrivateMethod(funcName, params) {
|
|
468
|
+
return this._test(funcName, params, false, 'private');
|
|
282
469
|
}
|
|
283
470
|
toApiFields(fields) {
|
|
284
471
|
if (typeof fields === 'undefined') {
|
|
@@ -319,30 +506,8 @@ class Contract extends Common {
|
|
|
319
506
|
inputAssets: toApiInputAssets(params.inputAssets)
|
|
320
507
|
};
|
|
321
508
|
}
|
|
322
|
-
static async fromCodeHash(codeHash) {
|
|
323
|
-
const cached = this._getArtifactFromCache(codeHash);
|
|
324
|
-
if (typeof cached !== 'undefined') {
|
|
325
|
-
return cached;
|
|
326
|
-
}
|
|
327
|
-
const files = await fs_2.promises.readdir(Common._artifactsFolder());
|
|
328
|
-
for (const file of files) {
|
|
329
|
-
if (file.endsWith('.ral.json')) {
|
|
330
|
-
try {
|
|
331
|
-
const contract = await Contract.fromArtifactFile(file);
|
|
332
|
-
if (contract.codeHash === codeHash) {
|
|
333
|
-
return contract;
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
catch (_) { }
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
throw new Error(`Unknown code with code hash: ${codeHash}`);
|
|
340
|
-
}
|
|
341
|
-
static async getFieldsSig(state) {
|
|
342
|
-
return Contract.fromCodeHash(state.codeHash).then((contract) => contract.fieldsSig);
|
|
343
|
-
}
|
|
344
509
|
async fromApiContractState(state) {
|
|
345
|
-
const contract =
|
|
510
|
+
const contract = Project.currentProject.contractByCodeHash(state.codeHash);
|
|
346
511
|
return {
|
|
347
512
|
address: state.address,
|
|
348
513
|
contractId: (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(state.address)),
|
|
@@ -350,7 +515,7 @@ class Contract extends Common {
|
|
|
350
515
|
initialStateHash: state.initialStateHash,
|
|
351
516
|
codeHash: state.codeHash,
|
|
352
517
|
fields: fromApiFields(state.fields, contract.fieldsSig),
|
|
353
|
-
fieldsSig:
|
|
518
|
+
fieldsSig: contract.fieldsSig,
|
|
354
519
|
asset: fromApiAsset(state.asset)
|
|
355
520
|
};
|
|
356
521
|
}
|
|
@@ -363,7 +528,7 @@ class Contract extends Common {
|
|
|
363
528
|
eventSig = this.ContractDestroyedEvent;
|
|
364
529
|
}
|
|
365
530
|
else {
|
|
366
|
-
const contract =
|
|
531
|
+
const contract = Project.currentProject.contractByCodeHash(codeHash);
|
|
367
532
|
eventSig = contract.eventsSig[event.eventIndex];
|
|
368
533
|
}
|
|
369
534
|
return {
|
|
@@ -380,7 +545,7 @@ class Contract extends Common {
|
|
|
380
545
|
return {
|
|
381
546
|
address: result.address,
|
|
382
547
|
contractId: (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(result.address)),
|
|
383
|
-
returns: fromApiArray(result.returns, this.functions[`${methodIndex}`].returnTypes),
|
|
548
|
+
returns: (0, api_1.fromApiArray)(result.returns, this.functions[`${methodIndex}`].returnTypes),
|
|
384
549
|
gasUsed: result.gasUsed,
|
|
385
550
|
contracts: await Promise.all(result.contracts.map((contract) => this.fromApiContractState(contract))),
|
|
386
551
|
txOutputs: result.txOutputs.map(fromApiOutput),
|
|
@@ -403,7 +568,7 @@ class Contract extends Common {
|
|
|
403
568
|
bytecode: bytecode,
|
|
404
569
|
initialAttoAlphAmount: extractOptionalNumber256(params.initialAttoAlphAmount),
|
|
405
570
|
issueTokenAmount: extractOptionalNumber256(params.issueTokenAmount),
|
|
406
|
-
initialTokenAmounts: params.initialTokenAmounts
|
|
571
|
+
initialTokenAmounts: (0, api_1.toApiTokens)(params.initialTokenAmounts),
|
|
407
572
|
gasAmount: params.gasAmount,
|
|
408
573
|
gasPrice: extractOptionalNumber256(params.gasPrice)
|
|
409
574
|
};
|
|
@@ -424,78 +589,53 @@ class Contract extends Common {
|
|
|
424
589
|
exports.Contract = Contract;
|
|
425
590
|
Contract.ContractCreatedEvent = {
|
|
426
591
|
name: 'ContractCreated',
|
|
427
|
-
signature: 'event ContractCreated(address:Address)',
|
|
428
592
|
fieldNames: ['address'],
|
|
429
593
|
fieldTypes: ['Address']
|
|
430
594
|
};
|
|
431
595
|
Contract.ContractDestroyedEvent = {
|
|
432
596
|
name: 'ContractDestroyed',
|
|
433
|
-
signature: 'event ContractDestroyed(address:Address)',
|
|
434
597
|
fieldNames: ['address'],
|
|
435
598
|
fieldTypes: ['Address']
|
|
436
599
|
};
|
|
437
|
-
class Script extends
|
|
438
|
-
constructor(
|
|
439
|
-
super(
|
|
600
|
+
class Script extends Artifact {
|
|
601
|
+
constructor(name, bytecodeTemplate, fieldsSig, functions) {
|
|
602
|
+
super(name, functions);
|
|
440
603
|
this.bytecodeTemplate = bytecodeTemplate;
|
|
441
604
|
this.fieldsSig = fieldsSig;
|
|
442
605
|
}
|
|
443
|
-
static
|
|
444
|
-
|
|
445
|
-
if (scriptMatches === null) {
|
|
446
|
-
throw new Error(`No script found in: ${fileName}`);
|
|
447
|
-
}
|
|
448
|
-
else if (scriptMatches.length > 1) {
|
|
449
|
-
throw new Error(`Multiple scripts in: ${fileName}`);
|
|
450
|
-
}
|
|
451
|
-
else {
|
|
452
|
-
return;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
static async loadContractStr(sourceFile) {
|
|
456
|
-
return Common._loadContractStr(sourceFile, [], (code) => Script.checkCodeType(sourceFile.contractPath, code));
|
|
457
|
-
}
|
|
458
|
-
static async fromSource(provider, path) {
|
|
459
|
-
const sourceFile = this.getSourceFile(path, []);
|
|
460
|
-
return Common._from(provider, sourceFile, (sourceFile) => Script.loadContractStr(sourceFile), Script.compile);
|
|
461
|
-
}
|
|
462
|
-
static async compile(provider, sourceFile, scriptStr, contractHash) {
|
|
463
|
-
const compiled = await provider.contracts.postContractsCompileScript({ code: scriptStr });
|
|
464
|
-
const artifact = new Script(contractHash, compiled.bytecodeTemplate, compiled.fields, compiled.functions);
|
|
465
|
-
await artifact._saveToFile(sourceFile);
|
|
466
|
-
return artifact;
|
|
606
|
+
static fromCompileResult(result) {
|
|
607
|
+
return new Script(result.name, result.bytecodeTemplate, result.fields, result.functions);
|
|
467
608
|
}
|
|
468
609
|
// TODO: safely parse json
|
|
469
610
|
static fromJson(artifact) {
|
|
470
|
-
if (artifact.
|
|
611
|
+
if (artifact.name == null ||
|
|
471
612
|
artifact.bytecodeTemplate == null ||
|
|
472
613
|
artifact.fieldsSig == null ||
|
|
473
614
|
artifact.functions == null) {
|
|
474
615
|
throw Error('The artifact JSON for script is incomplete');
|
|
475
616
|
}
|
|
476
|
-
return new Script(artifact.
|
|
617
|
+
return new Script(artifact.name, artifact.bytecodeTemplate, artifact.fieldsSig, artifact.functions);
|
|
477
618
|
}
|
|
478
619
|
static async fromArtifactFile(path) {
|
|
479
|
-
const
|
|
480
|
-
const artifactPath = sourceFile.artifactPath;
|
|
481
|
-
const content = await fs_2.promises.readFile(artifactPath);
|
|
620
|
+
const content = await fs_2.promises.readFile(path);
|
|
482
621
|
const artifact = JSON.parse(content.toString());
|
|
483
622
|
return this.fromJson(artifact);
|
|
484
623
|
}
|
|
485
624
|
toString() {
|
|
486
|
-
|
|
487
|
-
|
|
625
|
+
const object = {
|
|
626
|
+
name: this.name,
|
|
488
627
|
bytecodeTemplate: this.bytecodeTemplate,
|
|
489
628
|
fieldsSig: this.fieldsSig,
|
|
490
629
|
functions: this.functions
|
|
491
|
-
}
|
|
630
|
+
};
|
|
631
|
+
return JSON.stringify(object, null, 2);
|
|
492
632
|
}
|
|
493
633
|
async paramsForDeployment(params) {
|
|
494
634
|
const signerParams = {
|
|
495
635
|
signerAddress: params.signerAddress,
|
|
496
636
|
bytecode: this.buildByteCodeToDeploy(params.initialFields ? params.initialFields : {}),
|
|
497
637
|
attoAlphAmount: extractOptionalNumber256(params.attoAlphAmount),
|
|
498
|
-
tokens:
|
|
638
|
+
tokens: (0, api_1.toApiTokens)(params.tokens),
|
|
499
639
|
gasAmount: params.gasAmount,
|
|
500
640
|
gasPrice: extractOptionalNumber256(params.gasPrice)
|
|
501
641
|
};
|
|
@@ -513,221 +653,25 @@ class Script extends Common {
|
|
|
513
653
|
}
|
|
514
654
|
}
|
|
515
655
|
exports.Script = Script;
|
|
516
|
-
function extractBoolean(v) {
|
|
517
|
-
if (typeof v === 'boolean') {
|
|
518
|
-
return v;
|
|
519
|
-
}
|
|
520
|
-
else {
|
|
521
|
-
throw new Error(`Invalid boolean value: ${v}`);
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
// TODO: check integer bounds
|
|
525
|
-
function extractNumber256(v) {
|
|
526
|
-
if ((typeof v === 'number' && Number.isInteger(v)) || typeof v === 'bigint') {
|
|
527
|
-
return v.toString();
|
|
528
|
-
}
|
|
529
|
-
else if (typeof v === 'string') {
|
|
530
|
-
return v;
|
|
531
|
-
}
|
|
532
|
-
else {
|
|
533
|
-
throw new Error(`Invalid 256 bit number: ${v}`);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
656
|
function extractOptionalNumber256(v) {
|
|
537
|
-
return typeof v !== 'undefined' ?
|
|
538
|
-
}
|
|
539
|
-
// TODO: check hex string
|
|
540
|
-
function extractByteVec(v) {
|
|
541
|
-
if (typeof v === 'string') {
|
|
542
|
-
// try to convert from address to contract id
|
|
543
|
-
try {
|
|
544
|
-
const address = utils_1.bs58.decode(v);
|
|
545
|
-
if (address.length == 33 && address[0] == 3) {
|
|
546
|
-
return buffer_1.Buffer.from(address.slice(1)).toString('hex');
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
catch (_) {
|
|
550
|
-
return v;
|
|
551
|
-
}
|
|
552
|
-
return v;
|
|
553
|
-
}
|
|
554
|
-
else {
|
|
555
|
-
throw new Error(`Invalid string: ${v}`);
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
function extractBs58(v) {
|
|
559
|
-
if (typeof v === 'string') {
|
|
560
|
-
try {
|
|
561
|
-
utils_1.bs58.decode(v);
|
|
562
|
-
return v;
|
|
563
|
-
}
|
|
564
|
-
catch (error) {
|
|
565
|
-
throw new Error(`Invalid base58 string: ${v}`);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
else {
|
|
569
|
-
throw new Error(`Invalid string: ${v}`);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
function decodeNumber256(n) {
|
|
573
|
-
if (Number.isSafeInteger(Number.parseInt(n))) {
|
|
574
|
-
return Number(n);
|
|
575
|
-
}
|
|
576
|
-
else {
|
|
577
|
-
return BigInt(n);
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
function extractArray(tpe, v) {
|
|
581
|
-
if (!Array.isArray(v)) {
|
|
582
|
-
throw new Error(`Expected array, got ${v}`);
|
|
583
|
-
}
|
|
584
|
-
const semiColonIndex = tpe.lastIndexOf(';');
|
|
585
|
-
if (semiColonIndex == -1) {
|
|
586
|
-
throw new Error(`Invalid Val type: ${tpe}`);
|
|
587
|
-
}
|
|
588
|
-
const subType = tpe.slice(1, semiColonIndex);
|
|
589
|
-
const dim = parseInt(tpe.slice(semiColonIndex + 1, -1));
|
|
590
|
-
if (v.length != dim) {
|
|
591
|
-
throw new Error(`Invalid val dimension: ${v}`);
|
|
592
|
-
}
|
|
593
|
-
else {
|
|
594
|
-
return { value: v.map((v) => toApiVal(v, subType)), type: 'Array' };
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
exports.extractArray = extractArray;
|
|
598
|
-
function toApiVal(v, tpe) {
|
|
599
|
-
if (tpe === 'Bool') {
|
|
600
|
-
return { value: extractBoolean(v), type: tpe };
|
|
601
|
-
}
|
|
602
|
-
else if (tpe === 'U256' || tpe === 'I256') {
|
|
603
|
-
return { value: extractNumber256(v), type: tpe };
|
|
604
|
-
}
|
|
605
|
-
else if (tpe === 'ByteVec') {
|
|
606
|
-
return { value: extractByteVec(v), type: tpe };
|
|
607
|
-
}
|
|
608
|
-
else if (tpe === 'Address') {
|
|
609
|
-
return { value: extractBs58(v), type: tpe };
|
|
610
|
-
}
|
|
611
|
-
else {
|
|
612
|
-
return extractArray(tpe, v);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
exports.toApiVal = toApiVal;
|
|
616
|
-
function decodeArrayType(tpe) {
|
|
617
|
-
const semiColonIndex = tpe.lastIndexOf(';');
|
|
618
|
-
if (semiColonIndex === -1) {
|
|
619
|
-
throw new Error(`Invalid Val type: ${tpe}`);
|
|
620
|
-
}
|
|
621
|
-
const subType = tpe.slice(1, semiColonIndex);
|
|
622
|
-
const dim = parseInt(tpe.slice(semiColonIndex + 1, -1));
|
|
623
|
-
if (subType[0] == '[') {
|
|
624
|
-
const [baseType, subDim] = decodeArrayType(subType);
|
|
625
|
-
return [baseType, (subDim.unshift(dim), subDim)];
|
|
626
|
-
}
|
|
627
|
-
else {
|
|
628
|
-
return [subType, [dim]];
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
function foldVals(vals, dims) {
|
|
632
|
-
if (dims.length == 1) {
|
|
633
|
-
return vals;
|
|
634
|
-
}
|
|
635
|
-
else {
|
|
636
|
-
const result = [];
|
|
637
|
-
const chunkSize = vals.length / dims[0];
|
|
638
|
-
const chunkDims = dims.slice(1);
|
|
639
|
-
for (let i = 0; i < vals.length; i += chunkSize) {
|
|
640
|
-
const chunk = vals.slice(i, i + chunkSize);
|
|
641
|
-
result.push(foldVals(chunk, chunkDims));
|
|
642
|
-
}
|
|
643
|
-
return result;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
function _fromApiVal(vals, valIndex, tpe) {
|
|
647
|
-
if (vals.length === 0) {
|
|
648
|
-
throw new Error('Not enough Vals');
|
|
649
|
-
}
|
|
650
|
-
const firstVal = vals[`${valIndex}`];
|
|
651
|
-
if (tpe === 'Bool' && firstVal.type === tpe) {
|
|
652
|
-
return [firstVal.value, valIndex + 1];
|
|
653
|
-
}
|
|
654
|
-
else if ((tpe === 'U256' || tpe === 'I256') && firstVal.type === tpe) {
|
|
655
|
-
return [decodeNumber256(firstVal.value), valIndex + 1];
|
|
656
|
-
}
|
|
657
|
-
else if ((tpe === 'ByteVec' || tpe === 'Address') && firstVal.type === tpe) {
|
|
658
|
-
return [firstVal.value, valIndex + 1];
|
|
659
|
-
}
|
|
660
|
-
else {
|
|
661
|
-
const [baseType, dims] = decodeArrayType(tpe);
|
|
662
|
-
const arraySize = dims.reduce((a, b) => a * b);
|
|
663
|
-
const nextIndex = valIndex + arraySize;
|
|
664
|
-
const valsToUse = vals.slice(valIndex, nextIndex);
|
|
665
|
-
if (valsToUse.length == arraySize && valsToUse.every((val) => val.type === baseType)) {
|
|
666
|
-
const localVals = valsToUse.map((val) => fromApiVal(val, baseType));
|
|
667
|
-
return [foldVals(localVals, dims), nextIndex];
|
|
668
|
-
}
|
|
669
|
-
else {
|
|
670
|
-
throw new Error(`Invalid array Val type: ${valsToUse}, ${tpe}`);
|
|
671
|
-
}
|
|
672
|
-
}
|
|
657
|
+
return typeof v !== 'undefined' ? (0, api_1.toApiNumber256)(v) : undefined;
|
|
673
658
|
}
|
|
674
659
|
function fromApiFields(vals, fieldsSig) {
|
|
675
|
-
return fromApiVals(vals, fieldsSig.names, fieldsSig.types);
|
|
660
|
+
return (0, api_1.fromApiVals)(vals, fieldsSig.names, fieldsSig.types);
|
|
676
661
|
}
|
|
677
662
|
function fromApiEventFields(vals, eventSig) {
|
|
678
|
-
return fromApiVals(vals, eventSig.fieldNames, eventSig.fieldTypes);
|
|
679
|
-
}
|
|
680
|
-
function fromApiVals(vals, names, types) {
|
|
681
|
-
let valIndex = 0;
|
|
682
|
-
const result = {};
|
|
683
|
-
types.forEach((currentType, index) => {
|
|
684
|
-
const currentName = names[`${index}`];
|
|
685
|
-
const [val, nextIndex] = _fromApiVal(vals, valIndex, currentType);
|
|
686
|
-
valIndex = nextIndex;
|
|
687
|
-
result[`${currentName}`] = val;
|
|
688
|
-
});
|
|
689
|
-
return result;
|
|
690
|
-
}
|
|
691
|
-
function fromApiArray(vals, types) {
|
|
692
|
-
let valIndex = 0;
|
|
693
|
-
const result = [];
|
|
694
|
-
for (const currentType of types) {
|
|
695
|
-
const [val, nextIndex] = _fromApiVal(vals, valIndex, currentType);
|
|
696
|
-
result.push(val);
|
|
697
|
-
valIndex = nextIndex;
|
|
698
|
-
}
|
|
699
|
-
return result;
|
|
700
|
-
}
|
|
701
|
-
function fromApiVal(v, tpe) {
|
|
702
|
-
if (v.type === 'Bool' && v.type === tpe) {
|
|
703
|
-
return v.value;
|
|
704
|
-
}
|
|
705
|
-
else if ((v.type === 'U256' || v.type === 'I256') && v.type === tpe) {
|
|
706
|
-
return decodeNumber256(v.value);
|
|
707
|
-
}
|
|
708
|
-
else if ((v.type === 'ByteVec' || v.type === 'Address') && v.type === tpe) {
|
|
709
|
-
return v.value;
|
|
710
|
-
}
|
|
711
|
-
else {
|
|
712
|
-
throw new Error(`Invalid node.Val type: ${v}`);
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
function toApiToken(token) {
|
|
716
|
-
return { id: token.id, amount: extractNumber256(token.amount) };
|
|
717
|
-
}
|
|
718
|
-
function fromApiToken(token) {
|
|
719
|
-
return { id: token.id, amount: decodeNumber256(token.amount) };
|
|
663
|
+
return (0, api_1.fromApiVals)(vals, eventSig.fieldNames, eventSig.fieldTypes);
|
|
720
664
|
}
|
|
721
665
|
function toApiAsset(asset) {
|
|
722
666
|
return {
|
|
723
|
-
attoAlphAmount:
|
|
724
|
-
tokens: typeof asset.tokens !== 'undefined' ? asset.tokens.map(toApiToken) : []
|
|
667
|
+
attoAlphAmount: (0, api_1.toApiNumber256)(asset.alphAmount),
|
|
668
|
+
tokens: typeof asset.tokens !== 'undefined' ? asset.tokens.map(api_1.toApiToken) : []
|
|
725
669
|
};
|
|
726
670
|
}
|
|
727
671
|
function fromApiAsset(asset) {
|
|
728
672
|
return {
|
|
729
|
-
alphAmount:
|
|
730
|
-
tokens:
|
|
673
|
+
alphAmount: (0, api_1.fromApiNumber256)(asset.attoAlphAmount),
|
|
674
|
+
tokens: (0, api_1.fromApiTokens)(asset.tokens)
|
|
731
675
|
};
|
|
732
676
|
}
|
|
733
677
|
function getVal(vals, name) {
|
|
@@ -752,13 +696,13 @@ function toApiFields(fields, fieldsSig) {
|
|
|
752
696
|
return toApiVals(fields, fieldsSig.names, fieldsSig.types);
|
|
753
697
|
}
|
|
754
698
|
function toApiArgs(args, funcSig) {
|
|
755
|
-
return toApiVals(args, funcSig.
|
|
699
|
+
return toApiVals(args, funcSig.paramNames, funcSig.paramTypes);
|
|
756
700
|
}
|
|
757
701
|
function toApiVals(fields, names, types) {
|
|
758
702
|
return names.map((name, index) => {
|
|
759
703
|
const val = getVal(fields, name);
|
|
760
704
|
const tpe = types[`${index}`];
|
|
761
|
-
return toApiVal(val, tpe);
|
|
705
|
+
return (0, api_1.toApiVal)(val, tpe);
|
|
762
706
|
});
|
|
763
707
|
}
|
|
764
708
|
function toApiInputAsset(inputAsset) {
|
|
@@ -773,8 +717,8 @@ function fromApiOutput(output) {
|
|
|
773
717
|
return {
|
|
774
718
|
type: 'AssetOutput',
|
|
775
719
|
address: asset.address,
|
|
776
|
-
alphAmount:
|
|
777
|
-
tokens: asset.tokens
|
|
720
|
+
alphAmount: (0, api_1.fromApiNumber256)(asset.attoAlphAmount),
|
|
721
|
+
tokens: (0, api_1.fromApiTokens)(asset.tokens),
|
|
778
722
|
lockTime: asset.lockTime,
|
|
779
723
|
message: asset.message
|
|
780
724
|
};
|
|
@@ -784,8 +728,8 @@ function fromApiOutput(output) {
|
|
|
784
728
|
return {
|
|
785
729
|
type: 'ContractOutput',
|
|
786
730
|
address: asset.address,
|
|
787
|
-
alphAmount:
|
|
788
|
-
tokens: asset.tokens
|
|
731
|
+
alphAmount: (0, api_1.fromApiNumber256)(asset.attoAlphAmount),
|
|
732
|
+
tokens: (0, api_1.fromApiTokens)(asset.tokens)
|
|
789
733
|
};
|
|
790
734
|
}
|
|
791
735
|
else {
|