wative 1.0.9 → 1.0.10
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/index.esm.js +1 -1
- package/lib/index.umd.js +1 -1
- package/package.json +8 -3
- package/src/account.ts +255 -213
- package/src/assets.ts +163 -16
- package/src/home_page.ts +2 -2
- package/src/index.ts +2 -1
- package/src/network.ts +207 -17
- package/src/tools.ts +39 -10
- package/src/utils.ts +235 -5
- package/src/web3.ts +102 -2
- package/rollup.config.js +0 -30
package/src/utils.ts
CHANGED
|
@@ -3,10 +3,12 @@ const chalk = require('chalk')
|
|
|
3
3
|
import * as figlet from 'figlet'
|
|
4
4
|
import inquirer from 'inquirer'
|
|
5
5
|
import * as fs from 'fs'
|
|
6
|
+
import * as path from "path";
|
|
6
7
|
|
|
7
8
|
import { getChainIdByEvm } from "./web3";
|
|
8
9
|
import { MNEMONIC_WORDS } from './config';
|
|
9
10
|
import { getChainType } from './chain';
|
|
11
|
+
import { getBatchAccountBalance } from './assets';
|
|
10
12
|
|
|
11
13
|
const USER_HOME: any = process.env.HOME || process.env.USERPROFILE
|
|
12
14
|
const BASE_PATH = `${USER_HOME}/.wative`
|
|
@@ -100,6 +102,13 @@ export const tagValidator = (tag: string) => {
|
|
|
100
102
|
return true;
|
|
101
103
|
}
|
|
102
104
|
|
|
105
|
+
export const addrValidator = (tag: string) => {
|
|
106
|
+
if (tag.length < 6) {
|
|
107
|
+
return "Address length should be greater than 6";
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
|
|
103
112
|
export const numberValidator = (value: string) => {
|
|
104
113
|
if (isNaN(Number(value))) {
|
|
105
114
|
return "Value should be a number";
|
|
@@ -230,7 +239,7 @@ export const getRpcUrl = async (chain_id: string, text: string, update: boolean
|
|
|
230
239
|
return null
|
|
231
240
|
}
|
|
232
241
|
|
|
233
|
-
if (getChainType(chain_id) === "solana") {
|
|
242
|
+
if (getChainType(chain_id.toString()) === "solana") {
|
|
234
243
|
return rpc_url;
|
|
235
244
|
}
|
|
236
245
|
const new_chain_id = await getChainIdByEvm(rpc_url);
|
|
@@ -297,7 +306,7 @@ export const getColor = async (text: string) => {
|
|
|
297
306
|
}
|
|
298
307
|
|
|
299
308
|
export const getAccountLabel = async (text: string, account_label_list: string[]) => {
|
|
300
|
-
let reg = /^[a-zA-Z0-
|
|
309
|
+
let reg = /^(?![-_]).*?[a-zA-Z0-9_-]{4,20}(?<![-_])$/g;
|
|
301
310
|
for (let i = 0; i < 5; i++) {
|
|
302
311
|
let account_label = await inputSomething(text);
|
|
303
312
|
account_label = account_label.trim();
|
|
@@ -306,7 +315,7 @@ export const getAccountLabel = async (text: string, account_label_list: string[]
|
|
|
306
315
|
console.log(chalk.red("Account label already exists"));
|
|
307
316
|
continue;
|
|
308
317
|
} else {
|
|
309
|
-
return account_label
|
|
318
|
+
return account_label;
|
|
310
319
|
}
|
|
311
320
|
}
|
|
312
321
|
}
|
|
@@ -360,16 +369,29 @@ const passwordValidator = function (value: string) {
|
|
|
360
369
|
};
|
|
361
370
|
|
|
362
371
|
export const inputPassword = async (text: string) => {
|
|
372
|
+
let count = 0;
|
|
373
|
+
|
|
363
374
|
const questions = [
|
|
364
375
|
{
|
|
365
376
|
name: 'password',
|
|
366
377
|
type: 'password',
|
|
367
378
|
mask: '#',
|
|
368
379
|
message: `${text}:`,
|
|
369
|
-
validate:
|
|
380
|
+
validate: (fieldValue: string) => {
|
|
381
|
+
if (count >= 3) {
|
|
382
|
+
return true
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return passwordValidator(fieldValue);
|
|
386
|
+
}
|
|
370
387
|
}
|
|
371
388
|
]
|
|
372
|
-
|
|
389
|
+
|
|
390
|
+
let { password } = await inquirer.prompt(questions);
|
|
391
|
+
if (count >= 3) {
|
|
392
|
+
password = null;
|
|
393
|
+
}
|
|
394
|
+
|
|
373
395
|
return password;
|
|
374
396
|
}
|
|
375
397
|
|
|
@@ -443,4 +465,212 @@ export const getAccountChainType = (account_address: string) => {
|
|
|
443
465
|
export const checkFileExistence = (file_path: string): boolean => {
|
|
444
466
|
file_path = file_path.trim()
|
|
445
467
|
return fs.existsSync(file_path);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
export const chunkArray = (array: any, size: number) => {
|
|
471
|
+
let result: any = [];
|
|
472
|
+
for (let i = 0; i < array.length; i += size) {
|
|
473
|
+
result.push(array.slice(i, i + size));
|
|
474
|
+
}
|
|
475
|
+
return result;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
export const sleep = (ms: number) => {
|
|
479
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export const formatAddr = (addr: string, force_full_addr: boolean = true) => {
|
|
483
|
+
if (force_full_addr) {
|
|
484
|
+
return addr;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
if (addr.startsWith("0x")) {
|
|
488
|
+
return addr.slice(0, 8) + "..." + addr.slice(-6);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return addr.slice(0, 6) + "..." + addr.slice(-6);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
export const listWithLazyBalanceLoading = async (
|
|
495
|
+
options: string[],
|
|
496
|
+
is_evm: boolean,
|
|
497
|
+
keystore_path: string,
|
|
498
|
+
asset_info_list: any,
|
|
499
|
+
network_info: any,
|
|
500
|
+
show_gas_token: boolean,
|
|
501
|
+
show_extended_token: boolean,
|
|
502
|
+
message?: string,
|
|
503
|
+
default_account?: any
|
|
504
|
+
) => {
|
|
505
|
+
const questions = [
|
|
506
|
+
{
|
|
507
|
+
type: 'list',
|
|
508
|
+
name: 'inputText',
|
|
509
|
+
message: message || 'Choose an option',
|
|
510
|
+
choices: options,
|
|
511
|
+
pageSize: 30,
|
|
512
|
+
default: default_account,
|
|
513
|
+
filter: (val: string) => {
|
|
514
|
+
return val;
|
|
515
|
+
},
|
|
516
|
+
},
|
|
517
|
+
];
|
|
518
|
+
|
|
519
|
+
const promise: any = inquirer.prompt(questions);
|
|
520
|
+
|
|
521
|
+
let selected = 0;
|
|
522
|
+
let round = 0;
|
|
523
|
+
let pre_selected: any;
|
|
524
|
+
while (!promise.ui.activePrompt.answers[promise.ui.activePrompt.opt.name]) {
|
|
525
|
+
await sleep(2000);
|
|
526
|
+
if (pre_selected === promise.ui.activePrompt.selected) {
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (selected === promise.ui.activePrompt.selected) {
|
|
531
|
+
round = round + 1;
|
|
532
|
+
} else {
|
|
533
|
+
round = 0;
|
|
534
|
+
selected = promise.ui.activePrompt.selected;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
if (round < 5) {
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
round = 0;
|
|
541
|
+
const pageSize = promise.ui.activePrompt.opt.pageSize;
|
|
542
|
+
|
|
543
|
+
let accounts: any = [];
|
|
544
|
+
for (let i = 0; i < promise.ui.activePrompt.opt.choices.choices.length; i++) {
|
|
545
|
+
if (!promise.ui.activePrompt.opt.choices.choices[i].name) {
|
|
546
|
+
accounts.push(null);
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
let account: any = null;
|
|
551
|
+
|
|
552
|
+
if (is_evm) {
|
|
553
|
+
account = /0x[0-9a-fA-f]{40}/.exec(promise.ui.activePrompt.opt.choices.choices[i].name);
|
|
554
|
+
account = account ? account[0] : null;
|
|
555
|
+
} else {
|
|
556
|
+
let re_result = account = /\s+([0-9a-zA-Z]*)/.exec(promise.ui.activePrompt.opt.choices.choices[i].name);
|
|
557
|
+
account = re_result ? re_result[1] : null;
|
|
558
|
+
|
|
559
|
+
if (account === "Back") {
|
|
560
|
+
account = null;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (account) {
|
|
565
|
+
accounts.push(account)
|
|
566
|
+
} else {
|
|
567
|
+
accounts.push(null);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
accounts = accounts.concat(accounts);
|
|
571
|
+
let fromIndex: number, toIndex: number;
|
|
572
|
+
if (selected < pageSize / 2) {
|
|
573
|
+
if (accounts.length / 2 <= pageSize) {
|
|
574
|
+
fromIndex = 0;
|
|
575
|
+
toIndex = accounts.length / 2;
|
|
576
|
+
} else {
|
|
577
|
+
fromIndex = 0;
|
|
578
|
+
toIndex = pageSize;
|
|
579
|
+
}
|
|
580
|
+
} else {
|
|
581
|
+
if (accounts.length / 2 <= pageSize) {
|
|
582
|
+
fromIndex = 0;
|
|
583
|
+
toIndex = accounts.length / 2;
|
|
584
|
+
} else {
|
|
585
|
+
fromIndex = selected - pageSize / 2 + 1;
|
|
586
|
+
toIndex = selected + pageSize / 2 + 1;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
let active_account: any = accounts.slice(fromIndex, toIndex);
|
|
591
|
+
let batchBalanceOf = await getBatchAccountBalance(
|
|
592
|
+
keystore_path,
|
|
593
|
+
active_account,
|
|
594
|
+
asset_info_list,
|
|
595
|
+
network_info.rpcUrl,
|
|
596
|
+
network_info.name,
|
|
597
|
+
show_gas_token,
|
|
598
|
+
show_extended_token
|
|
599
|
+
);
|
|
600
|
+
|
|
601
|
+
let gas_token_name = network_info.nativeCurrency.symbol;
|
|
602
|
+
for (let i = fromIndex; i < toIndex; i++) {
|
|
603
|
+
let _index = i >= accounts.length / 2 ? i - accounts.length / 2 : i;
|
|
604
|
+
let _choice = promise.ui.activePrompt.opt.choices.choices[_index];
|
|
605
|
+
if (!_choice.name) {
|
|
606
|
+
continue;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
let name = _choice.name;
|
|
610
|
+
let account_address = accounts[i];
|
|
611
|
+
let token_message = '';
|
|
612
|
+
|
|
613
|
+
for (let token_name in batchBalanceOf[account_address]) {
|
|
614
|
+
if (!show_gas_token && token_name === gas_token_name) {
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
if (!show_extended_token && token_name !== gas_token_name) {
|
|
618
|
+
continue;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
if (name.includes(token_name)) {
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
token_message += `${token_name}: ${batchBalanceOf[account_address][token_name]} `;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
let nameList = name.split('(');
|
|
629
|
+
if (nameList.length > 1) {
|
|
630
|
+
let tag = nameList[1];
|
|
631
|
+
promise.ui.activePrompt.opt.choices.choices[_index].name = nameList[0] + ` ${token_message}` + `(${tag}`;
|
|
632
|
+
} else {
|
|
633
|
+
promise.ui.activePrompt.opt.choices.choices[_index].name = nameList[0] + ` ${token_message}`;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
promise.ui.activePrompt.screen.render('');
|
|
637
|
+
promise.ui.activePrompt.render();
|
|
638
|
+
pre_selected = selected;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
return promise.ui.activePrompt.answers[promise.ui.activePrompt.opt.name];
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
export const updateStorage = (keystore_path: string) => {
|
|
645
|
+
const network_path = path.resolve(keystore_path, 'network.json');
|
|
646
|
+
const networks = JSON.parse(fs.readFileSync(network_path, 'utf8'));
|
|
647
|
+
|
|
648
|
+
if (!networks.status) {
|
|
649
|
+
networks.status = {
|
|
650
|
+
fullAddr: true,
|
|
651
|
+
gasToken: false,
|
|
652
|
+
extendedToken: false
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
fs.writeFileSync(network_path, JSON.stringify(networks, null, 4));
|
|
657
|
+
let account_label_list = networks.accounts;
|
|
658
|
+
|
|
659
|
+
for (let i = 0; i < account_label_list.length; i++) {
|
|
660
|
+
let account_label_path = path.resolve(keystore_path, `accounts/${account_label_list[i]}.json`);
|
|
661
|
+
let account_info = JSON.parse(fs.readFileSync(account_label_path, 'utf8'));
|
|
662
|
+
if (account_info.account_type === "PP") {
|
|
663
|
+
continue;
|
|
664
|
+
}
|
|
665
|
+
if ("data" in account_info) {
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
668
|
+
account_info.data = [
|
|
669
|
+
{
|
|
670
|
+
ciphertexts: account_info.ciphertexts
|
|
671
|
+
}
|
|
672
|
+
];
|
|
673
|
+
delete account_info.ciphertexts;
|
|
674
|
+
fs.writeFileSync(account_label_path, JSON.stringify(account_info, null, 4));
|
|
675
|
+
}
|
|
446
676
|
}
|
package/src/web3.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import Web3 from 'web3';
|
|
2
|
-
import { excutePromiseFunction } from './utils';
|
|
2
|
+
import { chunkArray, excutePromiseFunction, sleep } from './utils';
|
|
3
3
|
import { Connection, PublicKey } from "@solana/web3.js";
|
|
4
4
|
import { getMint, getAssociatedTokenAddressSync } from "@solana/spl-token"
|
|
5
|
-
import { Metaplex } from "@metaplex-foundation/js";
|
|
5
|
+
import { Metaplex, token } from "@metaplex-foundation/js";
|
|
6
|
+
import { BigNumber } from "bignumber.js";
|
|
7
|
+
|
|
8
|
+
const chainIdAccountBalanceMap: any = {};
|
|
6
9
|
|
|
7
10
|
export const getChainIdByEvm = async (rpc_url: string) => {
|
|
8
11
|
let web3 = new Web3(rpc_url);
|
|
@@ -265,4 +268,101 @@ export const getAccountInfoInSolana = async (account: string, rpc_url: string) =
|
|
|
265
268
|
status: true,
|
|
266
269
|
output: result.output
|
|
267
270
|
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export const updateBalance = async (account_address_list: string[], token_address: string, chain_id: string, rpc_url: string, is_evm: boolean) => {
|
|
274
|
+
let accountBalanceMap: any;
|
|
275
|
+
if (chain_id in chainIdAccountBalanceMap) {
|
|
276
|
+
accountBalanceMap = chainIdAccountBalanceMap[chain_id][token_address] || {};
|
|
277
|
+
} else {
|
|
278
|
+
chainIdAccountBalanceMap[chain_id] = {};
|
|
279
|
+
accountBalanceMap = {};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
for (const account of account_address_list) {
|
|
283
|
+
if (!account) {
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (!(account in accountBalanceMap)) {
|
|
288
|
+
let result: any;
|
|
289
|
+
if (token_address === "0") {
|
|
290
|
+
if (is_evm) {
|
|
291
|
+
result = await getAccountBalanceInEvm(account, rpc_url);
|
|
292
|
+
} else {
|
|
293
|
+
result = await getAccountBalanceInSolana(account, rpc_url);
|
|
294
|
+
}
|
|
295
|
+
} else {
|
|
296
|
+
if (is_evm) {
|
|
297
|
+
result = await getTokenBalanceInEvm(account, token_address, rpc_url);
|
|
298
|
+
|
|
299
|
+
} else {
|
|
300
|
+
result = await getTokenBalanceInSolana(account, token_address, rpc_url);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (result.status) {
|
|
305
|
+
accountBalanceMap[account] = result.output;
|
|
306
|
+
}
|
|
307
|
+
await sleep(200);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
chainIdAccountBalanceMap[chain_id][token_address] = accountBalanceMap;
|
|
312
|
+
|
|
313
|
+
return chainIdAccountBalanceMap;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export const getTokenBalance = (
|
|
317
|
+
chain_id: string,
|
|
318
|
+
account_address_list: any,
|
|
319
|
+
asset_info_list: any,
|
|
320
|
+
network_info: any
|
|
321
|
+
) => {
|
|
322
|
+
let batchAccountBalanceOf: any = {};
|
|
323
|
+
|
|
324
|
+
if (!(chain_id in chainIdAccountBalanceMap)) {
|
|
325
|
+
return batchAccountBalanceOf;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
asset_info_list.unshift({
|
|
329
|
+
address: "0",
|
|
330
|
+
name: network_info.nativeCurrency.name,
|
|
331
|
+
symbol: network_info.nativeCurrency.symbol,
|
|
332
|
+
decimals: network_info.nativeCurrency.decimals,
|
|
333
|
+
display_decimals: 4
|
|
334
|
+
});
|
|
335
|
+
let account_address_list_len = account_address_list.length;
|
|
336
|
+
for (let i = 0; i < account_address_list_len; i++) {
|
|
337
|
+
let account_address = account_address_list[i];
|
|
338
|
+
|
|
339
|
+
if (!account_address) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
for (let j = 0; j < asset_info_list.length; j++) {
|
|
344
|
+
let asset_info = asset_info_list[j];
|
|
345
|
+
let token_balance = "0";
|
|
346
|
+
if (!chainIdAccountBalanceMap[chain_id][asset_info.address]) {
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (account_address in chainIdAccountBalanceMap[chain_id][asset_info.address]) {
|
|
351
|
+
let balance = new BigNumber(chainIdAccountBalanceMap[chain_id][asset_info.address][account_address]);
|
|
352
|
+
token_balance = balance.dividedBy(10 ** asset_info.decimals).toFixed(asset_info.display_decimals || 4, BigNumber.ROUND_FLOOR);
|
|
353
|
+
}
|
|
354
|
+
if (!batchAccountBalanceOf[account_address]) {
|
|
355
|
+
batchAccountBalanceOf[account_address] = {};
|
|
356
|
+
}
|
|
357
|
+
batchAccountBalanceOf[account_address][asset_info.symbol] = token_balance;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return batchAccountBalanceOf;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export const deleteTokenBalance = (chain_id: string, account_address: string, token_address: string) => {
|
|
365
|
+
try {
|
|
366
|
+
delete chainIdAccountBalanceMap[chain_id][token_address][account_address];
|
|
367
|
+
} catch (error) { }
|
|
268
368
|
}
|
package/rollup.config.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { terser } from 'rollup-plugin-terser';
|
|
2
|
-
import commonjs from '@rollup/plugin-commonjs';
|
|
3
|
-
import typescript from 'rollup-plugin-typescript2';
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
input: 'src/index.ts',
|
|
7
|
-
output: [
|
|
8
|
-
{
|
|
9
|
-
file: 'lib/index.esm.js',
|
|
10
|
-
format: 'es',
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
file: 'lib/index.umd.js',
|
|
14
|
-
format: 'umd',
|
|
15
|
-
name: 'demo',
|
|
16
|
-
},
|
|
17
|
-
],
|
|
18
|
-
plugins: [
|
|
19
|
-
terser(),
|
|
20
|
-
commonjs(),
|
|
21
|
-
typescript({
|
|
22
|
-
tsconfigOverride: {
|
|
23
|
-
compilerOptions: {
|
|
24
|
-
module: "ESNext"
|
|
25
|
-
},
|
|
26
|
-
include: ['src/**/*'],
|
|
27
|
-
},
|
|
28
|
-
})
|
|
29
|
-
]
|
|
30
|
-
};
|