@alephium/web3 0.0.3

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.
Files changed (59) hide show
  1. package/.gitattributes +1 -0
  2. package/LICENSE +165 -0
  3. package/README.md +136 -0
  4. package/contracts/add.ral +12 -0
  5. package/contracts/greeter-main.ral +8 -0
  6. package/contracts/greeter.ral +5 -0
  7. package/contracts/main.ral +8 -0
  8. package/contracts/sub.ral +9 -0
  9. package/dev/user.conf +24 -0
  10. package/dist/alephium-web3.min.js +3 -0
  11. package/dist/alephium-web3.min.js.LICENSE.txt +27 -0
  12. package/dist/alephium-web3.min.js.map +1 -0
  13. package/dist/api/api-alephium.d.ts +1292 -0
  14. package/dist/api/api-alephium.js +761 -0
  15. package/dist/api/api-explorer.d.ts +350 -0
  16. package/dist/api/api-explorer.js +297 -0
  17. package/dist/cli/create-project.d.ts +2 -0
  18. package/dist/cli/create-project.js +87 -0
  19. package/dist/lib/address.d.ts +1 -0
  20. package/dist/lib/address.js +42 -0
  21. package/dist/lib/bs58.d.ts +4 -0
  22. package/dist/lib/bs58.js +26 -0
  23. package/dist/lib/clique.d.ts +23 -0
  24. package/dist/lib/clique.js +149 -0
  25. package/dist/lib/constants.d.ts +2 -0
  26. package/dist/lib/constants.js +22 -0
  27. package/dist/lib/contract.d.ts +152 -0
  28. package/dist/lib/contract.js +711 -0
  29. package/dist/lib/djb2.d.ts +1 -0
  30. package/dist/lib/djb2.js +27 -0
  31. package/dist/lib/explorer.d.ts +8 -0
  32. package/dist/lib/explorer.js +46 -0
  33. package/dist/lib/index.d.ts +12 -0
  34. package/dist/lib/index.js +60 -0
  35. package/dist/lib/node.d.ts +10 -0
  36. package/dist/lib/node.js +64 -0
  37. package/dist/lib/numbers.d.ts +7 -0
  38. package/dist/lib/numbers.js +128 -0
  39. package/dist/lib/password-crypto.d.ts +2 -0
  40. package/dist/lib/password-crypto.js +68 -0
  41. package/dist/lib/signer.d.ts +17 -0
  42. package/dist/lib/signer.js +70 -0
  43. package/dist/lib/storage-browser.d.ts +9 -0
  44. package/dist/lib/storage-browser.js +52 -0
  45. package/dist/lib/storage-node.d.ts +9 -0
  46. package/dist/lib/storage-node.js +65 -0
  47. package/dist/lib/utils.d.ts +11 -0
  48. package/dist/lib/utils.js +135 -0
  49. package/dist/lib/wallet.d.ts +30 -0
  50. package/dist/lib/wallet.js +142 -0
  51. package/gitignore +9 -0
  52. package/package.json +113 -0
  53. package/scripts/check-versions.js +45 -0
  54. package/scripts/rename-gitignore.js +24 -0
  55. package/scripts/start-devnet.js +141 -0
  56. package/scripts/stop-devnet.js +32 -0
  57. package/templates/README.md +34 -0
  58. package/templates/package.json +29 -0
  59. package/webpack.config.js +57 -0
@@ -0,0 +1,711 @@
1
+ "use strict";
2
+ /*
3
+ Copyright 2018 - 2022 The Alephium Authors
4
+ This file is part of the alephium project.
5
+
6
+ The library is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Lesser General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ The library is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU Lesser General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Lesser General Public License
17
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
28
+ }) : function(o, v) {
29
+ o["default"] = v;
30
+ });
31
+ var __importStar = (this && this.__importStar) || function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
39
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
40
+ return new (P || (P = Promise))(function (resolve, reject) {
41
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
42
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
43
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
44
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
45
+ });
46
+ };
47
+ var __importDefault = (this && this.__importDefault) || function (mod) {
48
+ return (mod && mod.__esModule) ? mod : { "default": mod };
49
+ };
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.extractArray = exports.Script = exports.Contract = exports.Common = void 0;
52
+ const cryptojs = __importStar(require("crypto-js"));
53
+ const crypto = __importStar(require("crypto"));
54
+ const bs58_1 = __importDefault(require("./bs58"));
55
+ const fs_1 = __importDefault(require("fs"));
56
+ const fs_2 = require("fs");
57
+ const clique_1 = require("./clique");
58
+ class Common {
59
+ constructor(fileName, sourceCodeSha256, bytecode, codeHash, functions) {
60
+ this.fileName = fileName;
61
+ this.sourceCodeSha256 = sourceCodeSha256;
62
+ this.bytecode = bytecode;
63
+ this.codeHash = codeHash;
64
+ this.functions = functions;
65
+ }
66
+ static _contractPath(fileName) {
67
+ return `./contracts/${fileName}`;
68
+ }
69
+ static _artifactPath(fileName) {
70
+ return `./artifacts/${fileName}.json`;
71
+ }
72
+ static _artifactsFolder() {
73
+ return './artifacts/';
74
+ }
75
+ static handleImports(contractStr, importsCache) {
76
+ return __awaiter(this, void 0, void 0, function* () {
77
+ const localImportsCache = [];
78
+ let result = contractStr.replace(Common.importRegex, (match) => {
79
+ localImportsCache.push(match);
80
+ return '';
81
+ });
82
+ for (const myImport of localImportsCache) {
83
+ const fileName = myImport.slice(8, -1);
84
+ if (!importsCache.includes(fileName)) {
85
+ importsCache.push(fileName);
86
+ const importContractStr = yield Common._loadContractStr(fileName, importsCache, (code) => Contract.checkCodeType(fileName, code));
87
+ result = result.concat('\n', importContractStr);
88
+ }
89
+ }
90
+ return result;
91
+ });
92
+ }
93
+ static _replaceVariables(contractStr, variables) {
94
+ if (variables) {
95
+ return contractStr.replace(Common.variableRegex, (match) => {
96
+ const variableName = match.split(/(\s+)/)[2];
97
+ if (variableName in variables) {
98
+ return variables[variableName].toString();
99
+ }
100
+ else {
101
+ throw new Error(`The value of variable ${variableName} is not provided`);
102
+ }
103
+ });
104
+ }
105
+ else {
106
+ return contractStr;
107
+ }
108
+ }
109
+ static _loadContractStr(fileName, importsCache, validate) {
110
+ return __awaiter(this, void 0, void 0, function* () {
111
+ const contractPath = this._contractPath(fileName);
112
+ const contractBuffer = yield fs_2.promises.readFile(contractPath);
113
+ const contractStr = contractBuffer.toString();
114
+ validate(contractStr);
115
+ return Common.handleImports(contractStr, importsCache);
116
+ });
117
+ }
118
+ static checkFileNameExtension(fileName) {
119
+ if (!fileName.endsWith('.ral')) {
120
+ throw new Error('Smart contract file name should end with ".ral"');
121
+ }
122
+ }
123
+ static _from(client, fileName, loadContractStr, loadContract, __from) {
124
+ return __awaiter(this, void 0, void 0, function* () {
125
+ Common.checkFileNameExtension(fileName);
126
+ const contractStr = yield loadContractStr(fileName, []);
127
+ const contractHash = cryptojs.SHA256(contractStr).toString();
128
+ try {
129
+ const existingContract = yield loadContract(fileName);
130
+ return existingContract.sourceCodeSha256 === contractHash
131
+ ? existingContract
132
+ : __from(client, fileName, contractStr, contractHash);
133
+ }
134
+ catch (_) {
135
+ return __from(client, fileName, contractStr, contractHash);
136
+ }
137
+ });
138
+ }
139
+ static load(fileName) {
140
+ return __awaiter(this, void 0, void 0, function* () {
141
+ return Contract.loadContract(fileName).catch(() => Script.loadContract(fileName));
142
+ });
143
+ }
144
+ _saveToFile() {
145
+ const artifactPath = Common._artifactPath(this.fileName);
146
+ return fs_2.promises.writeFile(artifactPath, this.toString());
147
+ }
148
+ }
149
+ exports.Common = Common;
150
+ Common.importRegex = new RegExp('^import "[a-z][a-z_0-9]*.ral"', 'mg');
151
+ Common.contractRegex = new RegExp('^TxContract [A-Z][a-zA-Z0-9]*\\(', 'mg');
152
+ Common.scriptRegex = new RegExp('^TxScript [A-Z][a-zA-Z0-9]* \\{', 'mg');
153
+ Common.variableRegex = new RegExp('\\{\\{\\s+[a-z][a-zA-Z0-9]*\\s+\\}\\}', 'g');
154
+ class Contract extends Common {
155
+ constructor(fileName, sourceCodeSha256, bytecode, codeHash, fields, functions, events) {
156
+ super(fileName, sourceCodeSha256, bytecode, codeHash, functions);
157
+ this.fields = fields;
158
+ this.events = events;
159
+ this._contractAddresses = new Map();
160
+ }
161
+ static checkCodeType(fileName, contractStr) {
162
+ const contractMatches = contractStr.match(Contract.contractRegex);
163
+ if (contractMatches === null) {
164
+ throw new Error(`No contract found in: ${fileName}`);
165
+ }
166
+ else if (contractMatches.length > 1) {
167
+ throw new Error(`Multiple contracts in: ${fileName}`);
168
+ }
169
+ else {
170
+ return;
171
+ }
172
+ }
173
+ static loadContractStr(fileName, importsCache, variables) {
174
+ return __awaiter(this, void 0, void 0, function* () {
175
+ const result = yield Common._loadContractStr(fileName, importsCache, (code) => Contract.checkCodeType(fileName, code));
176
+ return Common._replaceVariables(result, variables);
177
+ });
178
+ }
179
+ static from(client, fileName, variables) {
180
+ return __awaiter(this, void 0, void 0, function* () {
181
+ if (!fs_1.default.existsSync(Common._artifactsFolder())) {
182
+ fs_1.default.mkdirSync(Common._artifactsFolder(), { recursive: true });
183
+ }
184
+ return Common._from(client, fileName, (fileName, importCaches) => Contract.loadContractStr(fileName, importCaches, variables), Contract.loadContract, Contract.__from);
185
+ });
186
+ }
187
+ static __from(client, fileName, contractStr, contractHash) {
188
+ return __awaiter(this, void 0, void 0, function* () {
189
+ const compiled = (yield client.contracts.postContractsCompileContract({ code: contractStr })).data;
190
+ const artifact = new Contract(fileName, contractHash, compiled.bytecode, compiled.codeHash, compiled.fields, compiled.functions, compiled.events);
191
+ yield artifact._saveToFile();
192
+ return artifact;
193
+ });
194
+ }
195
+ static loadContract(fileName) {
196
+ return __awaiter(this, void 0, void 0, function* () {
197
+ const artifactPath = Contract._artifactPath(fileName);
198
+ const content = yield fs_2.promises.readFile(artifactPath);
199
+ const artifact = JSON.parse(content.toString());
200
+ if (artifact.bytecode == null || artifact.fields == null || artifact.functions == null || artifact.events == null) {
201
+ throw new Event('Compilation did not return the right data');
202
+ }
203
+ return new Contract(fileName, artifact.sourceCodeSha256, artifact.bytecode, artifact.codeHash, artifact.fields, artifact.functions, artifact.events);
204
+ });
205
+ }
206
+ toString() {
207
+ return JSON.stringify({
208
+ sourceCodeSha256: this.sourceCodeSha256,
209
+ bytecode: this.bytecode,
210
+ codeHash: this.codeHash,
211
+ fields: this.fields,
212
+ functions: this.functions,
213
+ events: this.events
214
+ }, null, 2);
215
+ }
216
+ toState(fields, asset, address) {
217
+ return {
218
+ fileName: this.fileName,
219
+ address: address,
220
+ bytecode: this.bytecode,
221
+ codeHash: this.codeHash,
222
+ fields: fields,
223
+ fieldTypes: this.fields.types,
224
+ asset: asset
225
+ };
226
+ }
227
+ static randomAddress() {
228
+ const bytes = crypto.randomBytes(33);
229
+ bytes[0] = 3;
230
+ return bs58_1.default.encode(bytes);
231
+ }
232
+ _randomAddressWithCache(fileName) {
233
+ const address = Contract.randomAddress();
234
+ this._contractAddresses.set(address, fileName);
235
+ return address;
236
+ }
237
+ test(client, funcName, params) {
238
+ return __awaiter(this, void 0, void 0, function* () {
239
+ this._contractAddresses.clear();
240
+ const apiParams = this.toTestContract(funcName, params);
241
+ const response = yield client.contracts.postContractsTestContract(apiParams);
242
+ const methodIndex = params.testMethodIndex ? params.testMethodIndex : this.getMethodIndex(funcName);
243
+ const result = yield this.fromTestContractResult(methodIndex, response.data);
244
+ this._contractAddresses.clear();
245
+ return result;
246
+ });
247
+ }
248
+ toApiFields(fields) {
249
+ return fields ? toApiFields(fields, this.fields.types) : [];
250
+ }
251
+ toApiArgs(funcName, args) {
252
+ if (args) {
253
+ const func = this.functions.find((func) => func.name == funcName);
254
+ if (func == null) {
255
+ throw new Error(`Invalid function name: ${funcName}`);
256
+ }
257
+ if (args.length === func.argTypes.length) {
258
+ return args.map((arg, index) => toApiVal(arg, func.argTypes[index]));
259
+ }
260
+ else {
261
+ throw new Error(`Invalid number of arguments: ${args}`);
262
+ }
263
+ }
264
+ else {
265
+ return [];
266
+ }
267
+ }
268
+ getMethodIndex(funcName) {
269
+ return this.functions.findIndex((func) => func.name === funcName);
270
+ }
271
+ toApiContractState(state) {
272
+ if (state.address) {
273
+ this._contractAddresses.set(state.address, state.fileName);
274
+ return toApiContractState(state, state.address);
275
+ }
276
+ else {
277
+ const address = this._randomAddressWithCache(state.fileName);
278
+ return toApiContractState(state, address);
279
+ }
280
+ }
281
+ toApiContractStates(states) {
282
+ return states ? states.map((state) => this.toApiContractState(state)) : undefined;
283
+ }
284
+ toTestContract(funcName, params) {
285
+ const address = params.address
286
+ ? (this._contractAddresses.set(params.address, this.fileName), params.address)
287
+ : this._randomAddressWithCache(this.fileName);
288
+ return {
289
+ group: params.group,
290
+ address: address,
291
+ bytecode: this.bytecode,
292
+ initialFields: this.toApiFields(params.initialFields),
293
+ initialAsset: params.initialAsset ? toApiAsset(params.initialAsset) : undefined,
294
+ testMethodIndex: this.getMethodIndex(funcName),
295
+ testArgs: this.toApiArgs(funcName, params.testArgs),
296
+ existingContracts: this.toApiContractStates(params.existingContracts),
297
+ inputAssets: toApiInputAssets(params.inputAssets)
298
+ };
299
+ }
300
+ static getContract(codeHash) {
301
+ return __awaiter(this, void 0, void 0, function* () {
302
+ const files = yield fs_2.promises.readdir(Common._artifactsFolder());
303
+ for (const file of files) {
304
+ if (file.endsWith('.ral.json')) {
305
+ const fileName = file.slice(0, -5);
306
+ const contract = yield Common.load(fileName);
307
+ if (contract.codeHash === codeHash) {
308
+ return contract;
309
+ }
310
+ }
311
+ }
312
+ throw new Error(`Unknown code with codeHash: ${codeHash}`);
313
+ });
314
+ }
315
+ static getFieldTypes(codeHash) {
316
+ return __awaiter(this, void 0, void 0, function* () {
317
+ return Contract.getContract(codeHash).then((contract) => contract.fields.types);
318
+ });
319
+ }
320
+ fromApiContractState(state) {
321
+ return __awaiter(this, void 0, void 0, function* () {
322
+ const contract = yield Contract.getContract(state.codeHash);
323
+ return {
324
+ fileName: contract.fileName,
325
+ address: state.address,
326
+ bytecode: state.bytecode,
327
+ codeHash: state.codeHash,
328
+ fields: fromApiVals(state.fields, contract.fields.types),
329
+ fieldTypes: yield Contract.getFieldTypes(state.codeHash),
330
+ asset: fromApiAsset(state.asset)
331
+ };
332
+ });
333
+ }
334
+ static fromApiEvent(event, fileName) {
335
+ return __awaiter(this, void 0, void 0, function* () {
336
+ let fieldTypes;
337
+ let name;
338
+ if (event.eventIndex == -1) {
339
+ name = 'ContractCreated';
340
+ fieldTypes = ['Address'];
341
+ }
342
+ else if (event.eventIndex == -2) {
343
+ name = 'ContractDestroyed';
344
+ fieldTypes = ['Address'];
345
+ }
346
+ else {
347
+ const contract = yield Contract.loadContract(fileName);
348
+ const eventDef = yield contract.events[event.eventIndex];
349
+ name = eventDef.name;
350
+ fieldTypes = eventDef.fieldTypes;
351
+ }
352
+ if (event.type === 'ContractEvent') {
353
+ return {
354
+ blockHash: event.blockHash,
355
+ contractAddress: event.contractAddress,
356
+ txId: event.txId,
357
+ name: name,
358
+ fields: fromApiVals(event.fields, fieldTypes)
359
+ };
360
+ }
361
+ else {
362
+ throw new Error(`Expected ContractEvent only, but got ${event.type}`);
363
+ }
364
+ });
365
+ }
366
+ fromTestContractResult(methodIndex, result) {
367
+ return __awaiter(this, void 0, void 0, function* () {
368
+ return {
369
+ returns: fromApiVals(result.returns, this.functions[methodIndex].returnTypes),
370
+ gasUsed: result.gasUsed,
371
+ contracts: yield Promise.all(result.contracts.map((contract) => this.fromApiContractState(contract))),
372
+ txOutputs: result.txOutputs.map(fromApiOutput),
373
+ events: yield Promise.all(result.events.map((event) => {
374
+ const contractAddress = event.contractAddress;
375
+ return Contract.fromApiEvent(event, this._contractAddresses.get(contractAddress));
376
+ }))
377
+ };
378
+ });
379
+ }
380
+ transactionForDeployment(signer, initialFields, issueTokenAmount) {
381
+ return __awaiter(this, void 0, void 0, function* () {
382
+ const params = {
383
+ fromPublicKey: yield signer.getPublicKey(),
384
+ bytecode: this.bytecode,
385
+ initialFields: this.toApiFields(initialFields),
386
+ issueTokenAmount: issueTokenAmount
387
+ };
388
+ const response = yield signer.client.contracts.postContractsUnsignedTxBuildContract(params);
389
+ return fromApiDeployContractUnsignedTx(clique_1.CliqueClient.convert(response));
390
+ });
391
+ }
392
+ }
393
+ exports.Contract = Contract;
394
+ class Script extends Common {
395
+ constructor(fileName, sourceCodeSha256, bytecode, codeHash, functions) {
396
+ super(fileName, sourceCodeSha256, bytecode, codeHash, functions);
397
+ }
398
+ static checkCodeType(fileName, contractStr) {
399
+ const scriptMatches = contractStr.match(this.scriptRegex);
400
+ if (scriptMatches === null) {
401
+ throw new Error(`No script found in: ${fileName}`);
402
+ }
403
+ else if (scriptMatches.length > 1) {
404
+ throw new Error(`Multiple scripts in: ${fileName}`);
405
+ }
406
+ else {
407
+ return;
408
+ }
409
+ }
410
+ static loadContractStr(fileName, importsCache, variables) {
411
+ return __awaiter(this, void 0, void 0, function* () {
412
+ const result = yield Common._loadContractStr(fileName, importsCache, (code) => Script.checkCodeType(fileName, code));
413
+ return yield Common._replaceVariables(result, variables);
414
+ });
415
+ }
416
+ static from(client, fileName, variables) {
417
+ return __awaiter(this, void 0, void 0, function* () {
418
+ return Common._from(client, fileName, (fileName, importsCache) => Script.loadContractStr(fileName, importsCache, variables), Script.loadContract, Script.__from);
419
+ });
420
+ }
421
+ static __from(client, fileName, scriptStr, contractHash) {
422
+ return __awaiter(this, void 0, void 0, function* () {
423
+ const compiled = (yield client.contracts.postContractsCompileScript({ code: scriptStr })).data;
424
+ const artifact = new Script(fileName, contractHash, compiled.bytecode, compiled.codeHash, compiled.functions);
425
+ yield artifact._saveToFile();
426
+ return artifact;
427
+ });
428
+ }
429
+ static loadContract(fileName) {
430
+ return __awaiter(this, void 0, void 0, function* () {
431
+ const artifactPath = Common._artifactPath(fileName);
432
+ const content = yield fs_2.promises.readFile(artifactPath);
433
+ const artifact = JSON.parse(content.toString());
434
+ if (artifact.bytecode == null || artifact.functions == null) {
435
+ throw new Event('= Compilation did not return the right data');
436
+ }
437
+ return new Script(fileName, artifact.sourceCodeSha256, artifact.bytecode, artifact.codeHash, artifact.functions);
438
+ });
439
+ }
440
+ toString() {
441
+ return JSON.stringify({
442
+ sourceCodeSha256: this.sourceCodeSha256,
443
+ bytecode: this.bytecode,
444
+ codeHash: this.codeHash,
445
+ functions: this.functions
446
+ }, null, 2);
447
+ }
448
+ transactionForDeployment(signer, params) {
449
+ return __awaiter(this, void 0, void 0, function* () {
450
+ const apiParams = {
451
+ fromPublicKey: yield signer.getPublicKey(),
452
+ bytecode: this.bytecode,
453
+ alphAmount: params && params.alphAmount ? extractNumber256(params.alphAmount) : undefined,
454
+ tokens: params && params.tokens ? params.tokens.map(toApiToken) : undefined,
455
+ gas: params && params.gas ? params.gas : undefined,
456
+ gasPrice: params && params.gasPrice ? extractNumber256(params.gasPrice) : undefined,
457
+ utxosLimit: params && params.utxosLimit ? params.utxosLimit : undefined
458
+ };
459
+ const response = yield signer.client.contracts.postContractsUnsignedTxBuildScript(apiParams);
460
+ return clique_1.CliqueClient.convert(response);
461
+ });
462
+ }
463
+ }
464
+ exports.Script = Script;
465
+ function extractBoolean(v) {
466
+ if (typeof v === 'boolean') {
467
+ return v;
468
+ }
469
+ else {
470
+ throw new Error(`Invalid boolean value: ${v}`);
471
+ }
472
+ }
473
+ // TODO: check integer bounds
474
+ function extractNumber256(v) {
475
+ if ((typeof v === 'number' && Number.isInteger(v)) || typeof v === 'bigint') {
476
+ return v.toString();
477
+ }
478
+ else if (typeof v === 'string') {
479
+ return v;
480
+ }
481
+ else {
482
+ throw new Error(`Invalid 256 bit number: ${v}`);
483
+ }
484
+ }
485
+ // TODO: check hex string
486
+ function extractByteVec(v) {
487
+ if (typeof v === 'string') {
488
+ // try to convert from address to contract id
489
+ try {
490
+ const address = bs58_1.default.decode(v);
491
+ if (address.length == 33 && address[0] == 3) {
492
+ return Buffer.from(address.slice(1)).toString('hex');
493
+ }
494
+ }
495
+ catch (_) {
496
+ return v;
497
+ }
498
+ return v;
499
+ }
500
+ else {
501
+ throw new Error(`Invalid string: ${v}`);
502
+ }
503
+ }
504
+ function extractBs58(v) {
505
+ if (typeof v === 'string') {
506
+ try {
507
+ bs58_1.default.decode(v);
508
+ return v;
509
+ }
510
+ catch (error) {
511
+ throw new Error(`Invalid base58 string: ${v}`);
512
+ }
513
+ }
514
+ else {
515
+ throw new Error(`Invalid string: ${v}`);
516
+ }
517
+ }
518
+ function decodeNumber256(n) {
519
+ if (Number.isSafeInteger(Number.parseInt(n))) {
520
+ return Number(n);
521
+ }
522
+ else {
523
+ return BigInt(n);
524
+ }
525
+ }
526
+ function extractArray(tpe, v) {
527
+ if (!Array.isArray(v)) {
528
+ throw new Error(`Expected array, got ${v}`);
529
+ }
530
+ const semiColonIndex = tpe.lastIndexOf(';');
531
+ if (semiColonIndex == -1) {
532
+ throw new Error(`Invalid Val type: ${tpe}`);
533
+ }
534
+ const subType = tpe.slice(1, semiColonIndex);
535
+ const dim = parseInt(tpe.slice(semiColonIndex + 1, -1));
536
+ if (v.length != dim) {
537
+ throw new Error(`Invalid val dimension: ${v}`);
538
+ }
539
+ else {
540
+ return { value: v.map((v) => toApiVal(v, subType)), type: 'Array' };
541
+ }
542
+ }
543
+ exports.extractArray = extractArray;
544
+ function toApiVal(v, tpe) {
545
+ if (tpe === 'Bool') {
546
+ return { value: extractBoolean(v), type: tpe };
547
+ }
548
+ else if (tpe === 'U256' || tpe === 'I256') {
549
+ return { value: extractNumber256(v), type: tpe };
550
+ }
551
+ else if (tpe === 'ByteVec') {
552
+ return { value: extractByteVec(v), type: tpe };
553
+ }
554
+ else if (tpe === 'Address') {
555
+ return { value: extractBs58(v), type: tpe };
556
+ }
557
+ else {
558
+ return extractArray(tpe, v);
559
+ }
560
+ }
561
+ function decodeArrayType(tpe) {
562
+ const semiColonIndex = tpe.lastIndexOf(';');
563
+ if (semiColonIndex === -1) {
564
+ throw new Error(`Invalid Val type: ${tpe}`);
565
+ }
566
+ const subType = tpe.slice(1, semiColonIndex);
567
+ const dim = parseInt(tpe.slice(semiColonIndex + 1, -1));
568
+ if (subType[0] == '[') {
569
+ const [baseType, subDim] = decodeArrayType(subType);
570
+ return [baseType, (subDim.unshift(dim), subDim)];
571
+ }
572
+ else {
573
+ return [subType, [dim]];
574
+ }
575
+ }
576
+ function foldVals(vals, dims) {
577
+ if (dims.length == 1) {
578
+ return vals;
579
+ }
580
+ else {
581
+ const result = [];
582
+ const chunkSize = vals.length / dims[0];
583
+ const chunkDims = dims.slice(1);
584
+ for (let i = 0; i < vals.length; i += chunkSize) {
585
+ const chunk = vals.slice(i, i + chunkSize);
586
+ result.push(foldVals(chunk, chunkDims));
587
+ }
588
+ return result;
589
+ }
590
+ }
591
+ function _fromApiVal(vals, valIndex, tpe) {
592
+ if (vals.length === 0) {
593
+ throw new Error('Not enough Vals');
594
+ }
595
+ const firstVal = vals[valIndex];
596
+ if (tpe === 'Bool' && firstVal.type === tpe) {
597
+ return [firstVal.value, valIndex + 1];
598
+ }
599
+ else if ((tpe === 'U256' || tpe === 'I256') && firstVal.type === tpe) {
600
+ return [decodeNumber256(firstVal.value), valIndex + 1];
601
+ }
602
+ else if ((tpe === 'ByteVec' || tpe === 'Address') && firstVal.type === tpe) {
603
+ return [firstVal.value, valIndex + 1];
604
+ }
605
+ else {
606
+ const [baseType, dims] = decodeArrayType(tpe);
607
+ const arraySize = dims.reduce((a, b) => a * b);
608
+ const nextIndex = valIndex + arraySize;
609
+ const valsToUse = vals.slice(valIndex, nextIndex);
610
+ if (valsToUse.length == arraySize && valsToUse.every((val) => val.type === baseType)) {
611
+ const localVals = valsToUse.map((val) => fromApiVal(val, baseType));
612
+ return [foldVals(localVals, dims), nextIndex];
613
+ }
614
+ else {
615
+ throw new Error(`Invalid array Val type: ${valsToUse}, ${tpe}`);
616
+ }
617
+ }
618
+ }
619
+ function fromApiVals(vals, types) {
620
+ let valIndex = 0;
621
+ const result = [];
622
+ for (const currentType of types) {
623
+ const [val, nextIndex] = _fromApiVal(vals, valIndex, currentType);
624
+ result.push(val);
625
+ valIndex = nextIndex;
626
+ }
627
+ return result;
628
+ }
629
+ function fromApiVal(v, tpe) {
630
+ if (v.type === 'Bool' && v.type === tpe) {
631
+ return v.value;
632
+ }
633
+ else if ((v.type === 'U256' || v.type === 'I256') && v.type === tpe) {
634
+ return decodeNumber256(v.value);
635
+ }
636
+ else if ((v.type === 'ByteVec' || v.type === 'Address') && v.type === tpe) {
637
+ return v.value;
638
+ }
639
+ else {
640
+ throw new Error(`Invalid api.Val type: ${v}`);
641
+ }
642
+ }
643
+ function toApiToken(token) {
644
+ return { id: token.id, amount: extractNumber256(token.amount) };
645
+ }
646
+ function fromApiToken(token) {
647
+ return { id: token.id, amount: decodeNumber256(token.amount) };
648
+ }
649
+ function toApiAsset(asset) {
650
+ return {
651
+ alphAmount: extractNumber256(asset.alphAmount),
652
+ tokens: asset.tokens ? asset.tokens.map(toApiToken) : []
653
+ };
654
+ }
655
+ function fromApiAsset(asset) {
656
+ return {
657
+ alphAmount: decodeNumber256(asset.alphAmount),
658
+ tokens: asset.tokens ? asset.tokens.map(fromApiToken) : undefined
659
+ };
660
+ }
661
+ function toApiContractState(state, address) {
662
+ return {
663
+ address: address,
664
+ bytecode: state.bytecode,
665
+ codeHash: state.codeHash,
666
+ fields: toApiFields(state.fields, state.fieldTypes),
667
+ asset: toApiAsset(state.asset)
668
+ };
669
+ }
670
+ function toApiFields(fields, fieldTypes) {
671
+ if (fields.length === fieldTypes.length) {
672
+ return fields.map((field, index) => toApiVal(field, fieldTypes[index]));
673
+ }
674
+ else {
675
+ throw new Error(`Invalid number of fields: ${fields}`);
676
+ }
677
+ }
678
+ function toApiInputAsset(inputAsset) {
679
+ return { address: inputAsset.address, asset: toApiAsset(inputAsset.asset) };
680
+ }
681
+ function toApiInputAssets(inputAssets) {
682
+ return inputAssets ? inputAssets.map(toApiInputAsset) : undefined;
683
+ }
684
+ function fromApiOutput(output) {
685
+ if (output.type === 'AssetOutput') {
686
+ const asset = output;
687
+ return {
688
+ type: 'AssetOutput',
689
+ address: asset.address,
690
+ alphAmount: decodeNumber256(asset.alphAmount),
691
+ tokens: asset.tokens.map(fromApiToken),
692
+ lockTime: asset.lockTime,
693
+ additionalData: asset.additionalData
694
+ };
695
+ }
696
+ else if (output.type === 'ContractOutput') {
697
+ const asset = output;
698
+ return {
699
+ type: 'ContractOutput',
700
+ address: asset.address,
701
+ alphAmount: decodeNumber256(asset.alphAmount),
702
+ tokens: asset.tokens.map(fromApiToken)
703
+ };
704
+ }
705
+ else {
706
+ throw new Error(`Unknown output type: ${output}`);
707
+ }
708
+ }
709
+ function fromApiDeployContractUnsignedTx(result) {
710
+ return result;
711
+ }