@alephium/web3 0.0.1-test.0

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 (137) hide show
  1. package/.editorconfig +13 -0
  2. package/.eslintignore +2 -0
  3. package/.eslintrc.json +21 -0
  4. package/.gitattributes +1 -0
  5. package/LICENSE +165 -0
  6. package/README.md +136 -0
  7. package/contracts/add.ral +16 -0
  8. package/contracts/greeter.ral +7 -0
  9. package/contracts/greeter_interface.ral +3 -0
  10. package/contracts/greeter_main.ral +9 -0
  11. package/contracts/main.ral +6 -0
  12. package/contracts/sub.ral +9 -0
  13. package/dev/user.conf +29 -0
  14. package/dist/alephium-web3.min.js +3 -0
  15. package/dist/alephium-web3.min.js.LICENSE.txt +27 -0
  16. package/dist/alephium-web3.min.js.map +1 -0
  17. package/dist/scripts/check-versions.d.ts +1 -0
  18. package/dist/scripts/check-versions.js +39 -0
  19. package/dist/scripts/create-project.d.ts +2 -0
  20. package/dist/scripts/create-project.js +124 -0
  21. package/dist/scripts/header.d.ts +0 -0
  22. package/dist/scripts/header.js +18 -0
  23. package/dist/scripts/rename-gitignore.d.ts +1 -0
  24. package/dist/scripts/rename-gitignore.js +24 -0
  25. package/dist/scripts/start-devnet.d.ts +1 -0
  26. package/dist/scripts/start-devnet.js +131 -0
  27. package/dist/scripts/stop-devnet.d.ts +1 -0
  28. package/dist/scripts/stop-devnet.js +32 -0
  29. package/dist/src/api/api-alephium.d.ts +1473 -0
  30. package/dist/src/api/api-alephium.js +1143 -0
  31. package/dist/src/api/api-explorer.d.ts +475 -0
  32. package/dist/src/api/api-explorer.js +457 -0
  33. package/dist/src/api/index.d.ts +10 -0
  34. package/dist/src/api/index.js +55 -0
  35. package/dist/src/constants.d.ts +2 -0
  36. package/dist/src/constants.js +22 -0
  37. package/dist/src/contract/contract.d.ts +182 -0
  38. package/dist/src/contract/contract.js +760 -0
  39. package/dist/src/contract/events.d.ts +11 -0
  40. package/dist/src/contract/events.js +64 -0
  41. package/dist/src/contract/index.d.ts +3 -0
  42. package/dist/src/contract/index.js +32 -0
  43. package/dist/src/contract/ralph.d.ts +12 -0
  44. package/dist/src/contract/ralph.js +362 -0
  45. package/dist/src/index.d.ts +6 -0
  46. package/dist/src/index.js +35 -0
  47. package/dist/src/signer/index.d.ts +2 -0
  48. package/dist/src/signer/index.js +31 -0
  49. package/dist/src/signer/node-wallet.d.ts +13 -0
  50. package/dist/src/signer/node-wallet.js +60 -0
  51. package/dist/src/signer/signer.d.ts +143 -0
  52. package/dist/src/signer/signer.js +184 -0
  53. package/dist/src/test/index.d.ts +7 -0
  54. package/dist/src/test/index.js +41 -0
  55. package/dist/src/test/privatekey-wallet.d.ts +12 -0
  56. package/dist/src/test/privatekey-wallet.js +68 -0
  57. package/dist/src/transaction/index.d.ts +2 -0
  58. package/dist/src/transaction/index.js +31 -0
  59. package/dist/src/transaction/sign-verify.d.ts +2 -0
  60. package/dist/src/transaction/sign-verify.js +58 -0
  61. package/dist/src/transaction/status.d.ts +10 -0
  62. package/dist/src/transaction/status.js +48 -0
  63. package/dist/src/utils/address.d.ts +1 -0
  64. package/dist/src/utils/address.js +42 -0
  65. package/dist/src/utils/bs58.d.ts +4 -0
  66. package/dist/src/utils/bs58.js +28 -0
  67. package/dist/src/utils/djb2.d.ts +1 -0
  68. package/dist/src/utils/djb2.js +27 -0
  69. package/dist/src/utils/index.d.ts +6 -0
  70. package/dist/src/utils/index.js +35 -0
  71. package/dist/src/utils/password-crypto.d.ts +2 -0
  72. package/dist/src/utils/password-crypto.js +69 -0
  73. package/dist/src/utils/subscription.d.ts +24 -0
  74. package/dist/src/utils/subscription.js +52 -0
  75. package/dist/src/utils/utils.d.ts +30 -0
  76. package/dist/src/utils/utils.js +199 -0
  77. package/gitignore +10 -0
  78. package/package.json +127 -0
  79. package/scripts/check-versions.js +45 -0
  80. package/scripts/create-project.ts +136 -0
  81. package/scripts/header.js +17 -0
  82. package/scripts/rename-gitignore.js +24 -0
  83. package/scripts/start-devnet.js +141 -0
  84. package/scripts/stop-devnet.js +32 -0
  85. package/src/api/api-alephium.ts +2430 -0
  86. package/src/api/api-explorer.ts +852 -0
  87. package/src/api/index.ts +35 -0
  88. package/src/constants.ts +20 -0
  89. package/src/contract/contract.ts +1014 -0
  90. package/src/contract/events.ts +75 -0
  91. package/src/contract/index.ts +21 -0
  92. package/src/contract/ralph.test.ts +178 -0
  93. package/src/contract/ralph.ts +362 -0
  94. package/src/fixtures/address.json +36 -0
  95. package/src/fixtures/balance.json +9 -0
  96. package/src/fixtures/self-clique.json +19 -0
  97. package/src/fixtures/transaction.json +13 -0
  98. package/src/fixtures/transactions.json +179 -0
  99. package/src/index.ts +25 -0
  100. package/src/signer/fixtures/genesis.json +26 -0
  101. package/src/signer/fixtures/wallets.json +26 -0
  102. package/src/signer/index.ts +20 -0
  103. package/src/signer/node-wallet.ts +74 -0
  104. package/src/signer/signer.ts +313 -0
  105. package/src/test/index.ts +32 -0
  106. package/src/test/privatekey-wallet.ts +58 -0
  107. package/src/transaction/index.ts +20 -0
  108. package/src/transaction/sign-verify.test.ts +50 -0
  109. package/src/transaction/sign-verify.ts +39 -0
  110. package/src/transaction/status.ts +58 -0
  111. package/src/utils/address.test.ts +47 -0
  112. package/src/utils/address.ts +39 -0
  113. package/src/utils/bs58.ts +26 -0
  114. package/src/utils/djb2.test.ts +35 -0
  115. package/src/utils/djb2.ts +25 -0
  116. package/src/utils/index.ts +24 -0
  117. package/src/utils/password-crypto.test.ts +27 -0
  118. package/src/utils/password-crypto.ts +77 -0
  119. package/src/utils/subscription.ts +72 -0
  120. package/src/utils/utils.test.ts +160 -0
  121. package/src/utils/utils.ts +209 -0
  122. package/templates/base/README.md +34 -0
  123. package/templates/base/package.json +35 -0
  124. package/templates/base/src/greeter.ts +41 -0
  125. package/templates/base/tsconfig.json +19 -0
  126. package/templates/react/README.md +34 -0
  127. package/templates/react/config-overrides.js +18 -0
  128. package/templates/react/package.json +66 -0
  129. package/templates/react/src/App.tsx +42 -0
  130. package/templates/react/src/artifacts/greeter.ral.json +26 -0
  131. package/templates/react/src/artifacts/greeter_main.ral.json +22 -0
  132. package/templates/shared/.eslintrc.json +12 -0
  133. package/templates/shared/scripts/header.js +0 -0
  134. package/test/contract.test.ts +161 -0
  135. package/test/events.test.ts +138 -0
  136. package/test/transaction.test.ts +72 -0
  137. package/webpack.config.js +57 -0
@@ -0,0 +1,760 @@
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 __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.toApiVal = exports.extractArray = exports.Script = exports.Contract = exports.Common = void 0;
43
+ const buffer_1 = require("buffer/");
44
+ const cryptojs = __importStar(require("crypto-js"));
45
+ const crypto = __importStar(require("crypto"));
46
+ const fs_1 = __importDefault(require("fs"));
47
+ const fs_2 = require("fs");
48
+ const ralph = __importStar(require("./ralph"));
49
+ const utils_1 = require("../utils");
50
+ class Common {
51
+ constructor(sourceCodeSha256, functions) {
52
+ this.sourceCodeSha256 = sourceCodeSha256;
53
+ this.functions = functions;
54
+ }
55
+ static _getArtifactFromCache(codeHash) {
56
+ return this._artifactCache.get(codeHash);
57
+ }
58
+ static _putArtifactToCache(contract) {
59
+ if (!this._artifactCache.has(contract.codeHash)) {
60
+ if (this._artifactCache.size >= this.artifactCacheCapacity) {
61
+ const keyToDelete = this._artifactCache.keys().next().value;
62
+ this._artifactCache.delete(keyToDelete);
63
+ }
64
+ this._artifactCache.set(contract.codeHash, contract);
65
+ }
66
+ }
67
+ static _contractPath(fileName) {
68
+ if (fileName.endsWith('.json')) {
69
+ return `./contracts/${fileName.slice(0, -5)}`;
70
+ }
71
+ else {
72
+ return `./contracts/${fileName}`;
73
+ }
74
+ }
75
+ static _artifactPath(fileName) {
76
+ if (fileName.endsWith('.json')) {
77
+ return `./artifacts/${fileName}`;
78
+ }
79
+ else {
80
+ return `./artifacts/${fileName}.json`;
81
+ }
82
+ }
83
+ static _artifactsFolder() {
84
+ return './artifacts/';
85
+ }
86
+ static async _handleImports(contractStr, importsCache) {
87
+ const localImportsCache = [];
88
+ let result = contractStr.replace(Common.importRegex, (match) => {
89
+ localImportsCache.push(match);
90
+ return '';
91
+ });
92
+ for (const myImport of localImportsCache) {
93
+ const fileName = myImport.slice(8, -1);
94
+ if (!importsCache.includes(fileName)) {
95
+ importsCache.push(fileName);
96
+ const importContractStr = await Common._loadContractStr(fileName, importsCache, (code) => Contract.checkCodeType(fileName, code));
97
+ result = result.concat('\n', importContractStr);
98
+ }
99
+ }
100
+ return result;
101
+ }
102
+ static async _loadContractStr(fileName, importsCache, validate) {
103
+ const contractPath = this._contractPath(fileName);
104
+ const contractBuffer = await fs_2.promises.readFile(contractPath);
105
+ const contractStr = contractBuffer.toString();
106
+ validate(contractStr);
107
+ return Common._handleImports(contractStr, importsCache);
108
+ }
109
+ static checkFileNameExtension(fileName) {
110
+ if (!fileName.endsWith('.ral')) {
111
+ throw new Error('Smart contract file name should end with ".ral"');
112
+ }
113
+ }
114
+ static async _from(provider, fileName, loadContractStr, compile) {
115
+ Common.checkFileNameExtension(fileName);
116
+ const contractStr = await loadContractStr(fileName, []);
117
+ const contractHash = cryptojs.SHA256(contractStr).toString();
118
+ const existingContract = this._getArtifactFromCache(contractHash);
119
+ if (typeof existingContract !== 'undefined') {
120
+ return existingContract;
121
+ }
122
+ else {
123
+ return compile(provider, fileName, contractStr, contractHash);
124
+ }
125
+ }
126
+ _saveToFile(fileName) {
127
+ const artifactPath = Common._artifactPath(fileName);
128
+ return fs_2.promises.writeFile(artifactPath, this.toString());
129
+ }
130
+ }
131
+ exports.Common = Common;
132
+ Common.importRegex = new RegExp('^import "[a-z][a-z_0-9]*.ral"', 'mg');
133
+ Common.contractRegex = new RegExp('^TxContract [A-Z][a-zA-Z0-9]*', 'mg');
134
+ Common.interfaceRegex = new RegExp('^Interface [A-Z][a-zA-Z0-9]* \\{', 'mg');
135
+ Common.scriptRegex = new RegExp('^TxScript [A-Z][a-zA-Z0-9]*', 'mg');
136
+ Common._artifactCache = new Map();
137
+ Common.artifactCacheCapacity = 20;
138
+ class Contract extends Common {
139
+ constructor(sourceCodeSha256, bytecode, codeHash, fieldsSig, eventsSig, functions) {
140
+ super(sourceCodeSha256, functions);
141
+ this.bytecode = bytecode;
142
+ this.codeHash = codeHash;
143
+ this.fieldsSig = fieldsSig;
144
+ this.eventsSig = eventsSig;
145
+ }
146
+ static checkCodeType(fileName, contractStr) {
147
+ const interfaceMatches = contractStr.match(Contract.interfaceRegex);
148
+ if (interfaceMatches) {
149
+ return;
150
+ }
151
+ const contractMatches = contractStr.match(Contract.contractRegex);
152
+ if (contractMatches === null) {
153
+ throw new Error(`No contract found in: ${fileName}`);
154
+ }
155
+ else if (contractMatches.length > 1) {
156
+ throw new Error(`Multiple contracts in: ${fileName}`);
157
+ }
158
+ else {
159
+ return;
160
+ }
161
+ }
162
+ static async loadContractStr(fileName, importsCache) {
163
+ return Common._loadContractStr(fileName, importsCache, (code) => Contract.checkCodeType(fileName, code));
164
+ }
165
+ static async fromSource(provider, fileName) {
166
+ if (!fs_1.default.existsSync(Common._artifactsFolder())) {
167
+ fs_1.default.mkdirSync(Common._artifactsFolder(), { recursive: true });
168
+ }
169
+ const contract = await Common._from(provider, fileName, (fileName, importCaches) => Contract.loadContractStr(fileName, importCaches), Contract.compile);
170
+ this._putArtifactToCache(contract);
171
+ return contract;
172
+ }
173
+ static async compile(provider, fileName, contractStr, contractHash) {
174
+ const compiled = await provider.contracts.postContractsCompileContract({ code: contractStr });
175
+ const artifact = new Contract(contractHash, compiled.bytecode, compiled.codeHash, compiled.fields, compiled.events, compiled.functions);
176
+ await artifact._saveToFile(fileName);
177
+ return artifact;
178
+ }
179
+ // TODO: safely parse json
180
+ static fromJson(artifact) {
181
+ if (artifact.sourceCodeSha256 == null ||
182
+ artifact.bytecode == null ||
183
+ artifact.codeHash == null ||
184
+ artifact.fieldsSig == null ||
185
+ artifact.eventsSig == null ||
186
+ artifact.functions == null) {
187
+ throw Error('The artifact JSON for contract is incomplete');
188
+ }
189
+ const contract = new Contract(artifact.sourceCodeSha256, artifact.bytecode, artifact.codeHash, artifact.fieldsSig, artifact.eventsSig, artifact.functions);
190
+ this._putArtifactToCache(contract);
191
+ return contract;
192
+ }
193
+ // support both 'code.ral' and 'code.ral.json'
194
+ static async fromArtifactFile(fileName) {
195
+ const artifactPath = Contract._artifactPath(fileName);
196
+ const content = await fs_2.promises.readFile(artifactPath);
197
+ const artifact = JSON.parse(content.toString());
198
+ return Contract.fromJson(artifact);
199
+ }
200
+ toString() {
201
+ return JSON.stringify({
202
+ sourceCodeSha256: this.sourceCodeSha256,
203
+ bytecode: this.bytecode,
204
+ codeHash: this.codeHash,
205
+ fieldsSig: this.fieldsSig,
206
+ eventsSig: this.eventsSig,
207
+ functions: this.functions
208
+ }, null, 2);
209
+ }
210
+ toState(fields, asset, address) {
211
+ const addressDef = typeof address !== 'undefined' ? address : Contract.randomAddress();
212
+ return {
213
+ address: addressDef,
214
+ contractId: (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(addressDef)),
215
+ bytecode: this.bytecode,
216
+ codeHash: this.codeHash,
217
+ fields: fields,
218
+ fieldsSig: this.fieldsSig,
219
+ asset: asset
220
+ };
221
+ }
222
+ static randomAddress() {
223
+ const bytes = crypto.randomBytes(33);
224
+ bytes[0] = 3;
225
+ return utils_1.bs58.encode(bytes);
226
+ }
227
+ async _test(provider, funcName, params, expectPublic, accessType) {
228
+ const apiParams = this.toTestContract(funcName, params);
229
+ const apiResult = await provider.contracts.postContractsTestContract(apiParams);
230
+ const methodIndex = typeof params.testMethodIndex !== 'undefined' ? params.testMethodIndex : this.getMethodIndex(funcName);
231
+ const isPublic = this.functions[`${methodIndex}`].signature.indexOf('pub ') !== -1;
232
+ if (isPublic === expectPublic) {
233
+ const result = await this.fromTestContractResult(methodIndex, apiResult);
234
+ return result;
235
+ }
236
+ else {
237
+ throw new Error(`The test method ${funcName} is not ${accessType}`);
238
+ }
239
+ }
240
+ async testPublicMethod(provider, funcName, params) {
241
+ return this._test(provider, funcName, params, true, 'public');
242
+ }
243
+ async testPrivateMethod(provider, funcName, params) {
244
+ return this._test(provider, funcName, params, false, 'private');
245
+ }
246
+ toApiFields(fields) {
247
+ if (typeof fields === 'undefined') {
248
+ return [];
249
+ }
250
+ else {
251
+ return toApiFields(fields, this.fieldsSig);
252
+ }
253
+ }
254
+ toApiArgs(funcName, args) {
255
+ if (args) {
256
+ const func = this.functions.find((func) => func.name == funcName);
257
+ if (func == null) {
258
+ throw new Error(`Invalid function name: ${funcName}`);
259
+ }
260
+ return toApiArgs(args, func);
261
+ }
262
+ else {
263
+ return [];
264
+ }
265
+ }
266
+ getMethodIndex(funcName) {
267
+ return this.functions.findIndex((func) => func.name === funcName);
268
+ }
269
+ toApiContractStates(states) {
270
+ return typeof states != 'undefined' ? states.map((state) => toApiContractState(state)) : undefined;
271
+ }
272
+ toTestContract(funcName, params) {
273
+ return {
274
+ group: params.group,
275
+ address: params.address,
276
+ bytecode: this.bytecode,
277
+ initialFields: this.toApiFields(params.initialFields),
278
+ initialAsset: typeof params.initialAsset !== 'undefined' ? toApiAsset(params.initialAsset) : undefined,
279
+ methodIndex: this.getMethodIndex(funcName),
280
+ args: this.toApiArgs(funcName, params.testArgs),
281
+ existingContracts: this.toApiContractStates(params.existingContracts),
282
+ inputAssets: toApiInputAssets(params.inputAssets)
283
+ };
284
+ }
285
+ static async fromCodeHash(codeHash) {
286
+ const cached = this._getArtifactFromCache(codeHash);
287
+ if (typeof cached !== 'undefined') {
288
+ return cached;
289
+ }
290
+ const files = await fs_2.promises.readdir(Common._artifactsFolder());
291
+ for (const file of files) {
292
+ if (file.endsWith('.ral.json')) {
293
+ try {
294
+ const contract = await Contract.fromArtifactFile(file);
295
+ if (contract.codeHash === codeHash) {
296
+ return contract;
297
+ }
298
+ }
299
+ catch (_) { }
300
+ }
301
+ }
302
+ throw new Error(`Unknown code with code hash: ${codeHash}`);
303
+ }
304
+ static async getFieldsSig(state) {
305
+ return Contract.fromCodeHash(state.codeHash).then((contract) => contract.fieldsSig);
306
+ }
307
+ async fromApiContractState(state) {
308
+ const contract = await Contract.fromCodeHash(state.codeHash);
309
+ return {
310
+ address: state.address,
311
+ contractId: (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(state.address)),
312
+ bytecode: state.bytecode,
313
+ initialStateHash: state.initialStateHash,
314
+ codeHash: state.codeHash,
315
+ fields: fromApiFields(state.fields, contract.fieldsSig),
316
+ fieldsSig: await Contract.getFieldsSig(state),
317
+ asset: fromApiAsset(state.asset)
318
+ };
319
+ }
320
+ static async fromApiEvent(event, codeHash) {
321
+ let eventSig;
322
+ if (event.eventIndex == -1) {
323
+ eventSig = this.ContractCreatedEvent;
324
+ }
325
+ else if (event.eventIndex == -2) {
326
+ eventSig = this.ContractDestroyedEvent;
327
+ }
328
+ else {
329
+ const contract = await Contract.fromCodeHash(codeHash);
330
+ eventSig = contract.eventsSig[event.eventIndex];
331
+ }
332
+ return {
333
+ blockHash: event.blockHash,
334
+ contractAddress: event.contractAddress,
335
+ name: eventSig.name,
336
+ fields: fromApiEventFields(event.fields, eventSig)
337
+ };
338
+ }
339
+ async fromTestContractResult(methodIndex, result) {
340
+ const addressToCodeHash = new Map();
341
+ addressToCodeHash.set(result.address, result.codeHash);
342
+ result.contracts.forEach((contract) => addressToCodeHash.set(contract.address, contract.codeHash));
343
+ return {
344
+ address: result.address,
345
+ contractId: (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(result.address)),
346
+ returns: fromApiArray(result.returns, this.functions[`${methodIndex}`].returnTypes),
347
+ gasUsed: result.gasUsed,
348
+ contracts: await Promise.all(result.contracts.map((contract) => this.fromApiContractState(contract))),
349
+ txOutputs: result.txOutputs.map(fromApiOutput),
350
+ events: await Promise.all(result.events.map((event) => {
351
+ const contractAddress = event.contractAddress;
352
+ const codeHash = addressToCodeHash.get(contractAddress);
353
+ if (typeof codeHash !== 'undefined' || event.eventIndex < 0) {
354
+ return Contract.fromApiEvent(event, codeHash);
355
+ }
356
+ else {
357
+ throw Error(`Cannot find codeHash for the contract address: ${contractAddress}`);
358
+ }
359
+ }))
360
+ };
361
+ }
362
+ async paramsForDeployment(params) {
363
+ const bytecode = this.buildByteCodeToDeploy(params.initialFields ? params.initialFields : {});
364
+ const signerParams = {
365
+ signerAddress: params.signerAddress,
366
+ bytecode: bytecode,
367
+ initialAttoAlphAmount: extractOptionalNumber256(params.initialAttoAlphAmount),
368
+ issueTokenAmount: extractOptionalNumber256(params.issueTokenAmount),
369
+ initialTokenAmounts: params.initialTokenAmounts?.map(toApiToken),
370
+ gasAmount: params.gasAmount,
371
+ gasPrice: extractOptionalNumber256(params.gasPrice)
372
+ };
373
+ return signerParams;
374
+ }
375
+ async transactionForDeployment(signer, params) {
376
+ const signerParams = await this.paramsForDeployment({
377
+ ...params,
378
+ signerAddress: (await signer.getAccounts())[0].address
379
+ });
380
+ const response = await signer.buildContractCreationTx(signerParams);
381
+ return fromApiDeployContractUnsignedTx(response);
382
+ }
383
+ buildByteCodeToDeploy(initialFields) {
384
+ return ralph.buildContractByteCode(this.bytecode, initialFields, this.fieldsSig);
385
+ }
386
+ }
387
+ exports.Contract = Contract;
388
+ Contract.ContractCreatedEvent = {
389
+ name: 'ContractCreated',
390
+ signature: 'event ContractCreated(address:Address)',
391
+ fieldNames: ['address'],
392
+ fieldTypes: ['Address']
393
+ };
394
+ Contract.ContractDestroyedEvent = {
395
+ name: 'ContractDestroyed',
396
+ signature: 'event ContractDestroyed(address:Address)',
397
+ fieldNames: ['address'],
398
+ fieldTypes: ['Address']
399
+ };
400
+ class Script extends Common {
401
+ constructor(sourceCodeSha256, bytecodeTemplate, fieldsSig, functions) {
402
+ super(sourceCodeSha256, functions);
403
+ this.bytecodeTemplate = bytecodeTemplate;
404
+ this.fieldsSig = fieldsSig;
405
+ }
406
+ static checkCodeType(fileName, contractStr) {
407
+ const scriptMatches = contractStr.match(this.scriptRegex);
408
+ if (scriptMatches === null) {
409
+ throw new Error(`No script found in: ${fileName}`);
410
+ }
411
+ else if (scriptMatches.length > 1) {
412
+ throw new Error(`Multiple scripts in: ${fileName}`);
413
+ }
414
+ else {
415
+ return;
416
+ }
417
+ }
418
+ static async loadContractStr(fileName, importsCache) {
419
+ return Common._loadContractStr(fileName, importsCache, (code) => Script.checkCodeType(fileName, code));
420
+ }
421
+ static async fromSource(provider, fileName) {
422
+ return Common._from(provider, fileName, (fileName, importsCache) => Script.loadContractStr(fileName, importsCache), Script.compile);
423
+ }
424
+ static async compile(provider, fileName, scriptStr, contractHash) {
425
+ const compiled = await provider.contracts.postContractsCompileScript({ code: scriptStr });
426
+ const artifact = new Script(contractHash, compiled.bytecodeTemplate, compiled.fields, compiled.functions);
427
+ await artifact._saveToFile(fileName);
428
+ return artifact;
429
+ }
430
+ // TODO: safely parse json
431
+ static fromJson(artifact) {
432
+ if (artifact.sourceCodeSha256 == null ||
433
+ artifact.bytecodeTemplate == null ||
434
+ artifact.fieldsSig == null ||
435
+ artifact.functions == null) {
436
+ throw Error('The artifact JSON for script is incomplete');
437
+ }
438
+ return new Script(artifact.sourceCodeSha256, artifact.bytecodeTemplate, artifact.fieldsSig, artifact.functions);
439
+ }
440
+ static async fromArtifactFile(fileName) {
441
+ const artifactPath = Common._artifactPath(fileName);
442
+ const content = await fs_2.promises.readFile(artifactPath);
443
+ const artifact = JSON.parse(content.toString());
444
+ return this.fromJson(artifact);
445
+ }
446
+ toString() {
447
+ return JSON.stringify({
448
+ sourceCodeSha256: this.sourceCodeSha256,
449
+ bytecodeTemplate: this.bytecodeTemplate,
450
+ fieldsSig: this.fieldsSig,
451
+ functions: this.functions
452
+ }, null, 2);
453
+ }
454
+ async paramsForDeployment(params) {
455
+ const signerParams = {
456
+ signerAddress: params.signerAddress,
457
+ bytecode: this.buildByteCodeToDeploy(params.initialFields ? params.initialFields : {}),
458
+ attoAlphAmount: extractOptionalNumber256(params.attoAlphAmount),
459
+ tokens: typeof params.tokens !== 'undefined' ? params.tokens.map(toApiToken) : undefined,
460
+ gasAmount: params.gasAmount,
461
+ gasPrice: extractOptionalNumber256(params.gasPrice)
462
+ };
463
+ return signerParams;
464
+ }
465
+ async transactionForDeployment(signer, params) {
466
+ const signerParams = await this.paramsForDeployment({
467
+ ...params,
468
+ signerAddress: (await signer.getAccounts())[0].address
469
+ });
470
+ return await signer.buildScriptTx(signerParams);
471
+ }
472
+ buildByteCodeToDeploy(initialFields) {
473
+ return ralph.buildScriptByteCode(this.bytecodeTemplate, initialFields, this.fieldsSig);
474
+ }
475
+ }
476
+ exports.Script = Script;
477
+ function extractBoolean(v) {
478
+ if (typeof v === 'boolean') {
479
+ return v;
480
+ }
481
+ else {
482
+ throw new Error(`Invalid boolean value: ${v}`);
483
+ }
484
+ }
485
+ // TODO: check integer bounds
486
+ function extractNumber256(v) {
487
+ if ((typeof v === 'number' && Number.isInteger(v)) || typeof v === 'bigint') {
488
+ return v.toString();
489
+ }
490
+ else if (typeof v === 'string') {
491
+ return v;
492
+ }
493
+ else {
494
+ throw new Error(`Invalid 256 bit number: ${v}`);
495
+ }
496
+ }
497
+ function extractOptionalNumber256(v) {
498
+ return typeof v !== 'undefined' ? extractNumber256(v) : undefined;
499
+ }
500
+ // TODO: check hex string
501
+ function extractByteVec(v) {
502
+ if (typeof v === 'string') {
503
+ // try to convert from address to contract id
504
+ try {
505
+ const address = utils_1.bs58.decode(v);
506
+ if (address.length == 33 && address[0] == 3) {
507
+ return buffer_1.Buffer.from(address.slice(1)).toString('hex');
508
+ }
509
+ }
510
+ catch (_) {
511
+ return v;
512
+ }
513
+ return v;
514
+ }
515
+ else {
516
+ throw new Error(`Invalid string: ${v}`);
517
+ }
518
+ }
519
+ function extractBs58(v) {
520
+ if (typeof v === 'string') {
521
+ try {
522
+ utils_1.bs58.decode(v);
523
+ return v;
524
+ }
525
+ catch (error) {
526
+ throw new Error(`Invalid base58 string: ${v}`);
527
+ }
528
+ }
529
+ else {
530
+ throw new Error(`Invalid string: ${v}`);
531
+ }
532
+ }
533
+ function decodeNumber256(n) {
534
+ if (Number.isSafeInteger(Number.parseInt(n))) {
535
+ return Number(n);
536
+ }
537
+ else {
538
+ return BigInt(n);
539
+ }
540
+ }
541
+ function extractArray(tpe, v) {
542
+ if (!Array.isArray(v)) {
543
+ throw new Error(`Expected array, got ${v}`);
544
+ }
545
+ const semiColonIndex = tpe.lastIndexOf(';');
546
+ if (semiColonIndex == -1) {
547
+ throw new Error(`Invalid Val type: ${tpe}`);
548
+ }
549
+ const subType = tpe.slice(1, semiColonIndex);
550
+ const dim = parseInt(tpe.slice(semiColonIndex + 1, -1));
551
+ if (v.length != dim) {
552
+ throw new Error(`Invalid val dimension: ${v}`);
553
+ }
554
+ else {
555
+ return { value: v.map((v) => toApiVal(v, subType)), type: 'Array' };
556
+ }
557
+ }
558
+ exports.extractArray = extractArray;
559
+ function toApiVal(v, tpe) {
560
+ if (tpe === 'Bool') {
561
+ return { value: extractBoolean(v), type: tpe };
562
+ }
563
+ else if (tpe === 'U256' || tpe === 'I256') {
564
+ return { value: extractNumber256(v), type: tpe };
565
+ }
566
+ else if (tpe === 'ByteVec') {
567
+ return { value: extractByteVec(v), type: tpe };
568
+ }
569
+ else if (tpe === 'Address') {
570
+ return { value: extractBs58(v), type: tpe };
571
+ }
572
+ else {
573
+ return extractArray(tpe, v);
574
+ }
575
+ }
576
+ exports.toApiVal = toApiVal;
577
+ function decodeArrayType(tpe) {
578
+ const semiColonIndex = tpe.lastIndexOf(';');
579
+ if (semiColonIndex === -1) {
580
+ throw new Error(`Invalid Val type: ${tpe}`);
581
+ }
582
+ const subType = tpe.slice(1, semiColonIndex);
583
+ const dim = parseInt(tpe.slice(semiColonIndex + 1, -1));
584
+ if (subType[0] == '[') {
585
+ const [baseType, subDim] = decodeArrayType(subType);
586
+ return [baseType, (subDim.unshift(dim), subDim)];
587
+ }
588
+ else {
589
+ return [subType, [dim]];
590
+ }
591
+ }
592
+ function foldVals(vals, dims) {
593
+ if (dims.length == 1) {
594
+ return vals;
595
+ }
596
+ else {
597
+ const result = [];
598
+ const chunkSize = vals.length / dims[0];
599
+ const chunkDims = dims.slice(1);
600
+ for (let i = 0; i < vals.length; i += chunkSize) {
601
+ const chunk = vals.slice(i, i + chunkSize);
602
+ result.push(foldVals(chunk, chunkDims));
603
+ }
604
+ return result;
605
+ }
606
+ }
607
+ function _fromApiVal(vals, valIndex, tpe) {
608
+ if (vals.length === 0) {
609
+ throw new Error('Not enough Vals');
610
+ }
611
+ const firstVal = vals[`${valIndex}`];
612
+ if (tpe === 'Bool' && firstVal.type === tpe) {
613
+ return [firstVal.value, valIndex + 1];
614
+ }
615
+ else if ((tpe === 'U256' || tpe === 'I256') && firstVal.type === tpe) {
616
+ return [decodeNumber256(firstVal.value), valIndex + 1];
617
+ }
618
+ else if ((tpe === 'ByteVec' || tpe === 'Address') && firstVal.type === tpe) {
619
+ return [firstVal.value, valIndex + 1];
620
+ }
621
+ else {
622
+ const [baseType, dims] = decodeArrayType(tpe);
623
+ const arraySize = dims.reduce((a, b) => a * b);
624
+ const nextIndex = valIndex + arraySize;
625
+ const valsToUse = vals.slice(valIndex, nextIndex);
626
+ if (valsToUse.length == arraySize && valsToUse.every((val) => val.type === baseType)) {
627
+ const localVals = valsToUse.map((val) => fromApiVal(val, baseType));
628
+ return [foldVals(localVals, dims), nextIndex];
629
+ }
630
+ else {
631
+ throw new Error(`Invalid array Val type: ${valsToUse}, ${tpe}`);
632
+ }
633
+ }
634
+ }
635
+ function fromApiFields(vals, fieldsSig) {
636
+ return fromApiVals(vals, fieldsSig.names, fieldsSig.types);
637
+ }
638
+ function fromApiEventFields(vals, eventSig) {
639
+ return fromApiVals(vals, eventSig.fieldNames, eventSig.fieldTypes);
640
+ }
641
+ function fromApiVals(vals, names, types) {
642
+ let valIndex = 0;
643
+ const result = {};
644
+ types.forEach((currentType, index) => {
645
+ const currentName = names[`${index}`];
646
+ const [val, nextIndex] = _fromApiVal(vals, valIndex, currentType);
647
+ valIndex = nextIndex;
648
+ result[`${currentName}`] = val;
649
+ });
650
+ return result;
651
+ }
652
+ function fromApiArray(vals, types) {
653
+ let valIndex = 0;
654
+ const result = [];
655
+ for (const currentType of types) {
656
+ const [val, nextIndex] = _fromApiVal(vals, valIndex, currentType);
657
+ result.push(val);
658
+ valIndex = nextIndex;
659
+ }
660
+ return result;
661
+ }
662
+ function fromApiVal(v, tpe) {
663
+ if (v.type === 'Bool' && v.type === tpe) {
664
+ return v.value;
665
+ }
666
+ else if ((v.type === 'U256' || v.type === 'I256') && v.type === tpe) {
667
+ return decodeNumber256(v.value);
668
+ }
669
+ else if ((v.type === 'ByteVec' || v.type === 'Address') && v.type === tpe) {
670
+ return v.value;
671
+ }
672
+ else {
673
+ throw new Error(`Invalid node.Val type: ${v}`);
674
+ }
675
+ }
676
+ function toApiToken(token) {
677
+ return { id: token.id, amount: extractNumber256(token.amount) };
678
+ }
679
+ function fromApiToken(token) {
680
+ return { id: token.id, amount: decodeNumber256(token.amount) };
681
+ }
682
+ function toApiAsset(asset) {
683
+ return {
684
+ attoAlphAmount: extractNumber256(asset.alphAmount),
685
+ tokens: typeof asset.tokens !== 'undefined' ? asset.tokens.map(toApiToken) : []
686
+ };
687
+ }
688
+ function fromApiAsset(asset) {
689
+ return {
690
+ alphAmount: decodeNumber256(asset.attoAlphAmount),
691
+ tokens: typeof asset.tokens !== 'undefined' ? asset.tokens.map(fromApiToken) : undefined
692
+ };
693
+ }
694
+ function getVal(vals, name) {
695
+ if (name in vals) {
696
+ return vals[`${name}`];
697
+ }
698
+ else {
699
+ throw Error(`No Val exists for ${name}`);
700
+ }
701
+ }
702
+ function toApiContractState(state) {
703
+ return {
704
+ address: state.address,
705
+ bytecode: state.bytecode,
706
+ codeHash: state.codeHash,
707
+ initialStateHash: state.initialStateHash,
708
+ fields: toApiFields(state.fields, state.fieldsSig),
709
+ asset: toApiAsset(state.asset)
710
+ };
711
+ }
712
+ function toApiFields(fields, fieldsSig) {
713
+ return toApiVals(fields, fieldsSig.names, fieldsSig.types);
714
+ }
715
+ function toApiArgs(args, funcSig) {
716
+ return toApiVals(args, funcSig.argNames, funcSig.argTypes);
717
+ }
718
+ function toApiVals(fields, names, types) {
719
+ return names.map((name, index) => {
720
+ const val = getVal(fields, name);
721
+ const tpe = types[`${index}`];
722
+ return toApiVal(val, tpe);
723
+ });
724
+ }
725
+ function toApiInputAsset(inputAsset) {
726
+ return { address: inputAsset.address, asset: toApiAsset(inputAsset.asset) };
727
+ }
728
+ function toApiInputAssets(inputAssets) {
729
+ return typeof inputAssets !== 'undefined' ? inputAssets.map(toApiInputAsset) : undefined;
730
+ }
731
+ function fromApiOutput(output) {
732
+ if (output.type === 'AssetOutput') {
733
+ const asset = output;
734
+ return {
735
+ type: 'AssetOutput',
736
+ address: asset.address,
737
+ alphAmount: decodeNumber256(asset.attoAlphAmount),
738
+ tokens: asset.tokens.map(fromApiToken),
739
+ lockTime: asset.lockTime,
740
+ message: asset.message
741
+ };
742
+ }
743
+ else if (output.type === 'ContractOutput') {
744
+ const asset = output;
745
+ return {
746
+ type: 'ContractOutput',
747
+ address: asset.address,
748
+ alphAmount: decodeNumber256(asset.attoAlphAmount),
749
+ tokens: asset.tokens.map(fromApiToken)
750
+ };
751
+ }
752
+ else {
753
+ throw new Error(`Unknown output type: ${output}`);
754
+ }
755
+ }
756
+ function fromApiDeployContractUnsignedTx(result) {
757
+ return { ...result, contractId: (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(result.contractAddress)) };
758
+ }
759
+ (0, utils_1.assertType)();
760
+ (0, utils_1.assertType)();