evm-deployer 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/deployer ADDED
@@ -0,0 +1,602 @@
1
+ #!/usr/bin/env node
2
+
3
+ const
4
+ { ethers } =
5
+ require(
6
+ "ethers");
7
+ _ethers =
8
+ ethers;
9
+ _contract_factory =
10
+ _ethers.ContractFactory;
11
+ const
12
+ _libcrash =
13
+ require(
14
+ "crash-js");
15
+ _cmdline_check =
16
+ _libcrash._cmdline_check;
17
+ _dirname =
18
+ _libcrash._dirname;
19
+ _error_display =
20
+ _libcrash._error_display;
21
+ _file_read =
22
+ _libcrash._file_read;
23
+ _file_write =
24
+ _libcrash._file_write;
25
+ _json_read =
26
+ _libcrash._json_read;
27
+ _json_display =
28
+ _libcrash._json_display;
29
+ _msg_info =
30
+ _libcrash._msg_info;
31
+ _msg_error =
32
+ _libcrash._msg_error;
33
+ _path_join =
34
+ _libcrash._path_join;
35
+ const
36
+ _evm_wallet_module =
37
+ require(
38
+ "evm-wallet.js");
39
+ const
40
+ _wallet_get =
41
+ _evm_wallet_module._wallet_get;
42
+ const
43
+ _provider_get =
44
+ _evm_wallet_module._provider_get;
45
+
46
+ function
47
+ _global_variables() {
48
+ app_name =
49
+ "deployer";
50
+ retries_max =
51
+ "";
52
+ call_timeout =
53
+ "";
54
+ wallet_seed =
55
+ "";
56
+ contract_abi_path =
57
+ "";
58
+ contract_bytecode_path =
59
+ "";
60
+ contract_compiler_output_path =
61
+ "";
62
+ target_network =
63
+ "";
64
+ api_key_path =
65
+ "";
66
+ contract_output_file =
67
+ "";
68
+ tx_deployment_output_file =
69
+ "";
70
+ quiet =
71
+ "";
72
+ }
73
+
74
+ function
75
+ _msg_info_provider_generated(
76
+ _provider) {
77
+ let
78
+ _msg,
79
+ _template;
80
+ _template =
81
+ "Provider '{_provider}' generated.";
82
+ _msg =
83
+ _template.replaceAll(
84
+ "{_provider}",
85
+ _provider);
86
+ _msg_info(
87
+ _msg);
88
+ }
89
+
90
+ function
91
+ _msg_info_contract_deployed(
92
+ _contract) {
93
+ let
94
+ _msg,
95
+ _template;
96
+ _template =
97
+ "Deployed contract '{_contract}'.";
98
+ _msg =
99
+ _template.replaceAll(
100
+ "{_contract}",
101
+ _contract);
102
+ _msg_info(
103
+ _msg);
104
+ }
105
+
106
+ function
107
+ _msg_error_deployment_undefined(
108
+ _attempt) {
109
+ let
110
+ _msg,
111
+ _template;
112
+ _template =
113
+ "Deployment transaction undefined at attempt '{_attempt}'.";
114
+ _msg =
115
+ _template.replaceAll(
116
+ "{_attempt}",
117
+ _attempt);
118
+ _msg_info(
119
+ _msg);
120
+ _msg_error(
121
+ _msg,
122
+ 0);
123
+ }
124
+
125
+ async function
126
+ _contract_sanitize(
127
+ _contract) {
128
+ let
129
+ _contract_sanitized,
130
+ _field;
131
+ _contract_sanitized =
132
+ {};
133
+ for (_field in _contract) {
134
+ if ( _field != "runner" ) {
135
+ _contract_sanitized[
136
+ _field] =
137
+ _contract[
138
+ _field];
139
+ }
140
+ }
141
+ return _contract_sanitized;
142
+ }
143
+
144
+ function
145
+ _delay(
146
+ _time) {
147
+ return new Promise(resolve => setTimeout(resolve, _time));
148
+ }
149
+
150
+ async function
151
+ _evm_deployer(
152
+ _retries_max,
153
+ _call_timeout,
154
+ _wallet_seed,
155
+ _contract_abi_path,
156
+ _contract_bytecode_path,
157
+ _contract_compiler_output_path,
158
+ _target_network,
159
+ _api_key_path,
160
+ _contract_output_file,
161
+ _tx_deployment_output_file) {
162
+ let
163
+ _api_key,
164
+ _attempt,
165
+ _contract,
166
+ _contract_abi,
167
+ _contract_bytecode,
168
+ _contract_compiler_output,
169
+ _contract_json,
170
+ _contract_sanitized,
171
+ _factory,
172
+ _tx_deployment,
173
+ _tx_deployment_json,
174
+ _return,
175
+ _wallet,
176
+ _wallet_get_opts,
177
+ _wallet_password,
178
+ _wallet_path_list,
179
+ _wallet_path;
180
+ if ( _retries_max == "" ) {
181
+ _msg_info(
182
+ "Setting maximum call retries to '100'.");
183
+ _retries_max =
184
+ 100;
185
+ }
186
+ _retries_max =
187
+ Number(
188
+ _retries_max);
189
+ if ( _call_timeout == "" ) {
190
+ _msg_info(
191
+ "Setting timeout to '300' seconds.");
192
+ _call_timeout =
193
+ 300000;
194
+ }
195
+ _call_timeout =
196
+ Number(
197
+ _call_timeout);
198
+ _wallet_password =
199
+ "";
200
+ _wallet_path_list = [
201
+ _dirname(
202
+ _wallet_seed),
203
+ "wallet.dat"
204
+ ];
205
+ _wallet_path =
206
+ _path_join(
207
+ _wallet_path_list);
208
+ if ( _api_key_path != "" ) {
209
+ _api_key =
210
+ _file_read(
211
+ _api_key_path);
212
+ }
213
+ else if ( _api_key_path == "" ) {
214
+ _api_key =
215
+ "";
216
+ }
217
+ _provider =
218
+ _provider_get(
219
+ _target_network,
220
+ _api_key);
221
+ _msg_info_provider_generated(
222
+ _provider);
223
+ _wallet_get_opts = [
224
+ _wallet_path,
225
+ _wallet_password,
226
+ _wallet_seed,
227
+ _provider
228
+ ];
229
+ _wallet =
230
+ _wallet_get.apply(
231
+ null,
232
+ _wallet_get_opts);
233
+ if ( _contract_bytecode_path != "" ) {
234
+ if ( _contract_abi_path == "" ) {
235
+ _msg_error(
236
+ "Contract ABI is needed if deploying with bytecode.",
237
+ 1);
238
+ }
239
+ _contract_bytecode =
240
+ _file_read(
241
+ _contract_bytecode_path);
242
+ _contract_abi =
243
+ _json_read(
244
+ _contract_abi_path);
245
+ _factory = new
246
+ _contract_factory(
247
+ _contract_abi,
248
+ _contract_bytecode);
249
+ }
250
+ else if ( _contract_compiler_output_path != "" ) {
251
+ _contract_compiler_output =
252
+ _json_read(
253
+ _contract_compiler_output_path);
254
+ _factory =
255
+ _contract_factory.fromSolidity(
256
+ _contract_compiler_output);
257
+ }
258
+ _factory =
259
+ _factory.connect(
260
+ _wallet);
261
+ _attempt =
262
+ 1;
263
+ while ( _attempt <= _retries_max ) {
264
+ try {
265
+ _contract = await
266
+ _factory.deploy();
267
+ // It seems there is no
268
+ // timeout for the deployments.
269
+ // Probably there's a global one
270
+ // defined at provider's level
271
+ // which could be tweaked, but
272
+ // definitely not now.
273
+ _contract =
274
+ await _contract.waitForDeployment();
275
+ if ( _contract == undefined ) {
276
+ _msg_error_deployment_undefined(
277
+ _attempt);
278
+ throw { "error": {
279
+ "message":
280
+ "Contract undefined, error deploying." } };
281
+ }
282
+ else if ( _contract != undefined ) {
283
+ // _tx_deployment =
284
+ // await _factory.getDeployTransaction();
285
+ _tx_deployment =
286
+ _contract.deploymentTransaction();
287
+ _contract_sanitized =
288
+ await _contract_sanitize(
289
+ _contract);
290
+ _msg_info_contract_deployed(
291
+ _contract_sanitized);
292
+ if ( quiet == "n" ) {
293
+ console.log(
294
+ _contract_sanitized);
295
+ console.log(
296
+ _tx_deployment);
297
+ }
298
+ if ( _contract_output_file != "" ) {
299
+ _contract_json =
300
+ _json_display(
301
+ _contract_sanitized);
302
+ _file_write(
303
+ _contract_output_file,
304
+ _contract_json);
305
+ }
306
+ if ( _tx_deployment_output_file != "" ) {
307
+ _tx_deployment_json =
308
+ _json_display(
309
+ _tx_deployment);
310
+ _file_write(
311
+ _tx_deployment_output_file,
312
+ _tx_deployment_json);
313
+ }
314
+ _msg_info(
315
+ "Deployment transaction sent.");
316
+ break;
317
+ }
318
+ } catch (
319
+ _error) {
320
+ _error_display(
321
+ _error);
322
+ _msg_info(
323
+ "Waiting 3 seconds before retrying.");
324
+ await _delay(
325
+ 3000);
326
+ _attempt =
327
+ _attempt + 1;
328
+ }
329
+ }
330
+ if ( _attempt > _retries_max ) {
331
+ throw { "error": {
332
+ "message":
333
+ "Maximum number of retries reached." } };
334
+ }
335
+ _return = [
336
+ _contract_sanitized,
337
+ _tx_deployment
338
+ ];
339
+ return _return;
340
+ }
341
+
342
+ function
343
+ _config_show() {
344
+ let
345
+ _line,
346
+ _text;
347
+ _text =
348
+ [];
349
+ _text.push(
350
+ " Wallet seed: {wallet_seed}".replace(
351
+ "{wallet_seed}",
352
+ wallet_seed));
353
+ _text.push(
354
+ " Target network: {target_network}".replace(
355
+ "{target_network}",
356
+ target_network));
357
+ _text.push(
358
+ " API Key: {api_key}".replace(
359
+ "{api_key}",
360
+ api_key_path));
361
+ _text.push(
362
+ " Contract ABI: {contract_abi_path}".replace(
363
+ "{contract_abi_path}",
364
+ contract_abi_path));
365
+ _text.push(
366
+ " Contract bytecode: {contract_bytecode_path}".replace(
367
+ "{contract_bytecode_path}",
368
+ contract_bytecode_path));
369
+ _text.push(
370
+ " Contract compiler output: {contract_compiler_output_path}".replace(
371
+ "{contract_compiler_output_path}",
372
+ contract_compiler_output_path));
373
+ _text.push(
374
+ " Contract output file: {contract_output_file}".replace(
375
+ "{contract_output_file}",
376
+ contract_output_file));
377
+ _text.push(
378
+ "Deployment transaction output file: {tx_deployment_output_file}".replace(
379
+ "{tx_deployment_output_file}",
380
+ tx_deployment_output_file));
381
+ for ( _line of _text ) {
382
+ _msg_info(
383
+ _line);
384
+ }
385
+ }
386
+
387
+ function
388
+ _usage(
389
+ _exit) {
390
+ let
391
+ _line,
392
+ _text;
393
+ _text = [
394
+ "Usage:",
395
+ " deployer",
396
+ " <quiet>",
397
+ " <retries_max>",
398
+ " <call_timeout>",
399
+ " <seed_path>",
400
+ " <contract_abi_path>",
401
+ " <contract_bytecode_path>",
402
+ " <contract_compiler_output_path>",
403
+ " (<target_network>)",
404
+ " (<api_key>)",
405
+ " (<contract_output_file>)",
406
+ " (<tx_deployment_output_file>)",
407
+ "",
408
+ "Args:",
409
+ " <quiet> Can be 'y' or 'n'",
410
+ " Default: y",
411
+ " <retries_max> Maximum number of retries before",
412
+ " failing.",
413
+ " <call_timeout> How many milliseconds to wait for a return",
414
+ " before declaring the call failed.",
415
+ " <wallet_seed> Path of the file containing",
416
+ " the seed phrase.",
417
+ " <contract_abi_path> Contract ABI path.",
418
+ " <contract_bytecode_path> Path for the contract bytecode.",
419
+ " <contract_compiler_output_path> Path for the contract compiler",
420
+ " output path (the hardhat artifact).",
421
+ " <target_network> Network on which the contract",
422
+ " resides.",
423
+ " <api_key_path> Path of the API key for the",
424
+ " contract ABI provider service.",
425
+ " <contract_output_file> Path for an output file in which",
426
+ " to save the contract object generated",
427
+ " by the deployment call. Absolutely",
428
+ " not necessary.",
429
+ " <tx_deployment_output_file> Path for an output file in which",
430
+ " to save the transaction object generated",
431
+ " by the deployment call. Absolutely",
432
+ " necessary.",
433
+ "",
434
+ " Options:",
435
+ " -h (--help) This help."
436
+ ];
437
+ for ( _line of _text ) {
438
+ _msg_info(
439
+ _line);
440
+ }
441
+ process.exit(
442
+ _exit);
443
+ }
444
+
445
+
446
+ function _cmdline_parse() {
447
+ quiet =
448
+ "y";
449
+ process.argv.forEach(
450
+ function (
451
+ _value,
452
+ _index,
453
+ _array) {
454
+ if ( _index == 2 ) {
455
+ quiet =
456
+ _value;
457
+ }
458
+ if ( _index == 3 ) {
459
+ retries_max =
460
+ _value;
461
+ }
462
+ if ( _index == 4 ) {
463
+ call_timeout =
464
+ _value;
465
+ }
466
+ if ( _index == 5 ) {
467
+ wallet_seed =
468
+ _value;
469
+ }
470
+ if ( _index == 6 ) {
471
+ contract_abi_path =
472
+ _value;
473
+ }
474
+ if ( _index == 7 ) {
475
+ contract_bytecode_path =
476
+ _value;
477
+ }
478
+ if ( _index == 8 ) {
479
+ contract_compiler_output_path =
480
+ _value;
481
+ }
482
+ if ( _index == 9 ) {
483
+ target_network =
484
+ _value;
485
+ }
486
+ if ( _index == 10 ) {
487
+ api_key_path =
488
+ _value;
489
+ }
490
+ if ( _index == 11 ) {
491
+ contract_output_file =
492
+ _value;
493
+ }
494
+ if ( _index == 12 ) {
495
+ tx_deployment_output_file =
496
+ _value;
497
+ }
498
+ if ( _value == "-h" ||
499
+ _value == "--help" ) {
500
+ quiet =
501
+ "n";
502
+ _usage(
503
+ 0);
504
+ }
505
+ });
506
+ if ( contract_bytecode_path == "" &&
507
+ contract_compiler_output_path == "" ) {
508
+ quiet =
509
+ "n";
510
+ _usage(
511
+ 1);
512
+ }
513
+ }
514
+
515
+ function
516
+ _overrides_set() {
517
+ if ( retries_max == "" ) {
518
+ retries_max =
519
+ 100;
520
+ }
521
+ if ( call_timeout == "" ) {
522
+ call_timeout =
523
+ 300000;
524
+ }
525
+ if ( target_network == "" ) {
526
+ _msg_info(
527
+ "No network selected, setting Gnosis");
528
+ target_network =
529
+ "https://rpc.gnosischain.com";
530
+ }
531
+ }
532
+
533
+ async function
534
+ _evm_deployer_cmdline(
535
+ _app_opts) {
536
+ let
537
+ _contract,
538
+ _address,
539
+ _tx_deployment,
540
+ _tx_hash;
541
+ try {
542
+ [ _contract,
543
+ _tx_deployment ] =
544
+ await _evm_deployer.apply(
545
+ null,
546
+ app_opts);
547
+ if ( _contract != undefined ) {
548
+ _address =
549
+ _contract[
550
+ "target"];
551
+ _tx_hash =
552
+ _tx_deployment[
553
+ "hash"];
554
+ console.log(
555
+ "Address:",
556
+ _address);
557
+ console.log(
558
+ "Transaction:",
559
+ _tx_hash);
560
+ }
561
+ else if ( _contract == undefined ) {
562
+ throw { "error": {
563
+ "message":
564
+ "Error deploying the contract." } };
565
+ }
566
+ } catch (
567
+ _error) {
568
+ _error_display(
569
+ _error);
570
+ _msg_error(
571
+ "Contract deployment failed.",
572
+ 0);
573
+ throw _error;
574
+ };
575
+ }
576
+
577
+ if ( _cmdline_check(
578
+ "deployer") == true ) {
579
+ _global_variables();
580
+ _cmdline_parse();
581
+ _overrides_set();
582
+ _config_show();
583
+ app_opts = [
584
+ retries_max,
585
+ call_timeout,
586
+ wallet_seed,
587
+ contract_abi_path,
588
+ contract_bytecode_path,
589
+ contract_compiler_output_path,
590
+ target_network,
591
+ api_key_path,
592
+ contract_output_file,
593
+ tx_deployment_output_file
594
+ ];
595
+ _evm_deployer_cmdline(
596
+ app_opts);
597
+ }
598
+
599
+ module.exports = {
600
+ _evm_deployer:
601
+ _evm_deployer
602
+ };