@alephium/web3 0.2.0-rc.2 → 0.2.0-rc.21

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