wative 1.2.8 → 1.2.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/package.json +21 -22
- package/src/account.ts +0 -864
- package/src/assets.ts +0 -399
- package/src/chain.ts +0 -28
- package/src/config.ts +0 -2074
- package/src/daemon-watcher.js +0 -181
- package/src/home_page.ts +0 -36
- package/src/index.d.ts +0 -12
- package/src/index.ts +0 -53
- package/src/network.ts +0 -819
- package/src/ssh/client.ts +0 -389
- package/src/ssh/config_manager.ts +0 -304
- package/src/ssh/index.ts +0 -66
- package/src/ssh/service_manager.ts +0 -685
- package/src/ssh/types.ts +0 -50
- package/src/ssh/utils.ts +0 -89
- package/src/ssh/wative_server.ts +0 -534
- package/src/tools.ts +0 -923
- package/src/tx_gas_utils.ts +0 -119
- package/src/utils.ts +0 -916
- package/src/wallet-cli.ts +0 -39
- package/src/wative.ts +0 -633
- package/src/web3.ts +0 -415
package/src/utils.ts
DELETED
|
@@ -1,916 +0,0 @@
|
|
|
1
|
-
/* tslint:disable no-var-requires */
|
|
2
|
-
const chalk = require('chalk')
|
|
3
|
-
import * as figlet from 'figlet'
|
|
4
|
-
import inquirer from 'inquirer'
|
|
5
|
-
import * as fs from 'fs'
|
|
6
|
-
import * as path from "path";
|
|
7
|
-
|
|
8
|
-
import { getChainIdByEvm, batchHasTokenBalance } from "./web3";
|
|
9
|
-
import { MNEMONIC_WORDS } from './config';
|
|
10
|
-
import { getChainType } from './chain';
|
|
11
|
-
import { getBatchAccountBalance } from './assets';
|
|
12
|
-
import { getNetworkInfo } from './account';
|
|
13
|
-
|
|
14
|
-
const USER_HOME: any = process.env.HOME || process.env.USERPROFILE
|
|
15
|
-
const BASE_PATH = `${USER_HOME}/.wative`
|
|
16
|
-
|
|
17
|
-
export const inputSomething = async (text: string, validate_func?: Function) => {
|
|
18
|
-
const questions = [
|
|
19
|
-
{
|
|
20
|
-
name: 'inputText',
|
|
21
|
-
type: 'input',
|
|
22
|
-
message: `${text}:`,
|
|
23
|
-
validate: validate_func
|
|
24
|
-
},
|
|
25
|
-
]
|
|
26
|
-
const { inputText } = await inquirer.prompt(questions)
|
|
27
|
-
return inputText.trim().toString()
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export const getAccountRange = async (account_info: any) => {
|
|
31
|
-
for (let i = 0; i < 5; i++) {
|
|
32
|
-
let start_address_index = await getAccountIndex(account_info, "Input start address or index");
|
|
33
|
-
if (!start_address_index) {
|
|
34
|
-
console.log(chalk.red("Invalid start account index"));
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
let end_address_index = await getAccountIndex(account_info, "Input end address or index");
|
|
38
|
-
if (!end_address_index) {
|
|
39
|
-
console.log(chalk.red("Invalid end account index"));
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
if (start_address_index > end_address_index) {
|
|
43
|
-
console.log(chalk.red("Invalid address range"));
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
return {
|
|
47
|
-
from: start_address_index,
|
|
48
|
-
to: end_address_index
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export const getAccountIndexByKeystoreSlug = async (keystore_path: string, keystore_slug: string, account_address: string) => {
|
|
55
|
-
let account_info_path = path.join(keystore_path, `accounts/${keystore_slug}.json`);
|
|
56
|
-
if (!fs.existsSync(account_info_path)) {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
let account_info = JSON.parse(fs.readFileSync(account_info_path, 'utf8'));
|
|
61
|
-
let account_data = account_info.data;
|
|
62
|
-
let account_type = account_info.account_type;
|
|
63
|
-
let account_length = account_data.length;
|
|
64
|
-
if (account_length === 0) {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
for (let i = 0; i < account_length; i++) {
|
|
68
|
-
if (account_type === "PK" && account_data[i].ciphertexts.address.toLocaleLowerCase() === account_address.toLocaleLowerCase()) {
|
|
69
|
-
return i.toString();
|
|
70
|
-
}
|
|
71
|
-
if (account_type === "PP" && (
|
|
72
|
-
account_data[i].ciphertexts.evm.address.toLocaleLowerCase() === account_address.toLocaleLowerCase() ||
|
|
73
|
-
account_data[i].ciphertexts.solana.address.toLocaleLowerCase() === account_address.toLocaleLowerCase()
|
|
74
|
-
)) {
|
|
75
|
-
return i.toString();
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export const getAccountIndex = async (account_info: any, message: string) => {
|
|
83
|
-
let account_data = account_info.data;
|
|
84
|
-
let account_length = account_data.length;
|
|
85
|
-
if (account_length === 0) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
let evm_account_list: any = [];
|
|
90
|
-
let solana_account_list: any = [];
|
|
91
|
-
|
|
92
|
-
for (let i = 0; i < account_length; i++) {
|
|
93
|
-
evm_account_list.push(account_data[i].ciphertexts.evm.address.toLocaleLowerCase());
|
|
94
|
-
solana_account_list.push(account_data[i].ciphertexts.solana.address.toLocaleLowerCase());
|
|
95
|
-
}
|
|
96
|
-
let max_account_index = account_length - 1;
|
|
97
|
-
for (let i = 0; i < 5; i++) {
|
|
98
|
-
let account_index_or_address = await inputSomething(message, accountIndexOrAddressValidator);
|
|
99
|
-
let account_chain_type = getAccountChainType(account_index_or_address);
|
|
100
|
-
if (account_chain_type === "unknown") {
|
|
101
|
-
if (Number(account_index_or_address) > max_account_index) {
|
|
102
|
-
console.log(chalk.red("Invalid account index"));
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
return Number(account_index_or_address);
|
|
106
|
-
} else if (account_chain_type === "evm" && evm_account_list.indexOf(account_index_or_address.toLocaleLowerCase()) !== -1) {
|
|
107
|
-
return evm_account_list.indexOf(account_index_or_address.toLocaleLowerCase());
|
|
108
|
-
} else if (account_chain_type === "solana" && solana_account_list.indexOf(account_index_or_address.toLocaleLowerCase()) !== -1) {
|
|
109
|
-
return solana_account_list.indexOf(account_index_or_address.toLocaleLowerCase());
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export const tagValidator = (tag: string) => {
|
|
117
|
-
if (tag === "") {
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
tag = tag.replace(/\s+/g, " ").trim();
|
|
122
|
-
|
|
123
|
-
if (tag.length > 40) {
|
|
124
|
-
return "Tag length should be less than 10";
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (/^[0-9a-zA-Z\s]*$/g.test(tag) === false) {
|
|
128
|
-
return "Tag should be alphanumeric";
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return true;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export const addrValidator = (tag: string) => {
|
|
135
|
-
if (tag.length < 6) {
|
|
136
|
-
return "Address length should be greater than 6";
|
|
137
|
-
}
|
|
138
|
-
return true;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export const numberValidator = (value: string) => {
|
|
142
|
-
if (isNaN(Number(value))) {
|
|
143
|
-
return "Value should be a number";
|
|
144
|
-
}
|
|
145
|
-
return true;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export const gasValidator = (value: string) => {
|
|
149
|
-
if (isNaN(Number(value)) || Number(value) > 1000) {
|
|
150
|
-
return "Value should be a number";
|
|
151
|
-
}
|
|
152
|
-
return true;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export const passphraseValidator = (passphrase: string) => {
|
|
156
|
-
passphrase = passphrase.replace(/\s+/g, " ");
|
|
157
|
-
const mnemonic_word_list = passphrase.split(/\s+/g);
|
|
158
|
-
if (mnemonic_word_list.length !== 12 && mnemonic_word_list.length !== 24) {
|
|
159
|
-
return "Passphrase should be equal to 12 or 24 words";
|
|
160
|
-
}
|
|
161
|
-
for (let i = 0; i < mnemonic_word_list.length; i++) {
|
|
162
|
-
if (MNEMONIC_WORDS.includes(mnemonic_word_list[i]) === false) {
|
|
163
|
-
return "Passphrase word should be valid";
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
return true;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export const expandAmountValidator = (amount: string) => {
|
|
170
|
-
let amount_number = Number(amount);
|
|
171
|
-
|
|
172
|
-
if (isNaN(amount_number)) {
|
|
173
|
-
return "Amount should be a number";
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
if (amount_number > 2000) {
|
|
177
|
-
return "Amount should be less than 2000";
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export const lastAccountNoValidator = (last_account_no: string) => {
|
|
184
|
-
let last_account_no_number = Number(last_account_no);
|
|
185
|
-
|
|
186
|
-
if (isNaN(last_account_no_number)) {
|
|
187
|
-
return "Last account no should be a number";
|
|
188
|
-
}
|
|
189
|
-
return true;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export const accountIndexOrAddressValidator = (account_index_or_address: string) => {
|
|
193
|
-
if (isNaN(Number(account_index_or_address)) === false) {
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
return chainAddressValidator(account_index_or_address);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
export const chainAddressValidator = (chain_address: string) => {
|
|
200
|
-
let account_chain_type = getAccountChainType(chain_address);
|
|
201
|
-
|
|
202
|
-
if (account_chain_type == "unknown") {
|
|
203
|
-
return "Address should be valid";
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return true;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export const selectSomething = async (options: any[], message?: string, _default?: any) => {
|
|
210
|
-
const questions = [
|
|
211
|
-
{
|
|
212
|
-
type: 'list',
|
|
213
|
-
name: 'inputText',
|
|
214
|
-
message: message || 'Choose an option',
|
|
215
|
-
default: _default,
|
|
216
|
-
choices: options,
|
|
217
|
-
pageSize: 30,
|
|
218
|
-
filter: (val: string) => {
|
|
219
|
-
return val;
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
]
|
|
223
|
-
const { inputText } = await inquirer.prompt(questions)
|
|
224
|
-
return inputText.toString()
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export const selectCheckboxSomething = async (options: any[], message?: string, _default?: any) => {
|
|
228
|
-
const questions = [
|
|
229
|
-
{
|
|
230
|
-
type: 'checkbox',
|
|
231
|
-
name: 'inputText',
|
|
232
|
-
message: message || 'Choose an option',
|
|
233
|
-
default: _default,
|
|
234
|
-
choices: options,
|
|
235
|
-
pageSize: 30,
|
|
236
|
-
filter: (val: string) => {
|
|
237
|
-
return val;
|
|
238
|
-
},
|
|
239
|
-
},
|
|
240
|
-
]
|
|
241
|
-
|
|
242
|
-
const { inputText } = await inquirer.prompt(questions)
|
|
243
|
-
return inputText
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
export const showIntroduction = () => {
|
|
247
|
-
console.log(
|
|
248
|
-
chalk.green(
|
|
249
|
-
figlet.textSync('Wative', {
|
|
250
|
-
font: 'ANSI Shadow',
|
|
251
|
-
horizontalLayout: 'default',
|
|
252
|
-
verticalLayout: 'default',
|
|
253
|
-
})
|
|
254
|
-
)
|
|
255
|
-
)
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
export const getKeystorePath = async () => {
|
|
259
|
-
let keystore_path: string = await inputSomething(`Keystore storage located in (default: ${BASE_PATH})`);
|
|
260
|
-
if (!keystore_path) {
|
|
261
|
-
keystore_path = BASE_PATH
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
keystore_path = keystore_path.trim();
|
|
265
|
-
keystore_path = keystore_path.replace("~", USER_HOME);
|
|
266
|
-
|
|
267
|
-
if (!fs.existsSync(keystore_path)) {
|
|
268
|
-
fs.mkdirSync(keystore_path, { recursive: true });
|
|
269
|
-
}
|
|
270
|
-
return keystore_path;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
export const getChainId = async (text: string, update: boolean = false) => {
|
|
274
|
-
for (let i = 0; i < 5; i++) {
|
|
275
|
-
const chain_id = await inputSomething(text);
|
|
276
|
-
if (chain_id === "" && update) {
|
|
277
|
-
return null
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
let reg = /^[0-9]*$/g;
|
|
281
|
-
if (reg.test(chain_id)) {
|
|
282
|
-
return chain_id;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
return null;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
export const getRpcUrl = async (chain_id: string, text: string, update: boolean = false) => {
|
|
290
|
-
for (let i = 0; i < 5; i++) {
|
|
291
|
-
let rpc_url = await inputSomething(text);
|
|
292
|
-
try {
|
|
293
|
-
if (rpc_url === "" && update) {
|
|
294
|
-
return null
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (getChainType(chain_id.toString()) === "solana") {
|
|
298
|
-
return rpc_url;
|
|
299
|
-
}
|
|
300
|
-
const new_chain_id = await getChainIdByEvm(rpc_url);
|
|
301
|
-
if (!new_chain_id.status) {
|
|
302
|
-
console.log(chalk.red(new_chain_id.output));
|
|
303
|
-
continue;
|
|
304
|
-
}
|
|
305
|
-
if (new_chain_id.output.toString() === chain_id.toString()) {
|
|
306
|
-
return rpc_url;
|
|
307
|
-
} else {
|
|
308
|
-
console.log(chalk.red("Rpc url not match chain id"));
|
|
309
|
-
}
|
|
310
|
-
} catch (err: any) {
|
|
311
|
-
console.log(chalk.red(err.message));
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return null;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
export const getMulticallAddress = async (text: string) => {
|
|
319
|
-
for (let i = 0; i < 5; i++) {
|
|
320
|
-
let multicall_address = await inputSomething(text);
|
|
321
|
-
if (multicall_address === "") {
|
|
322
|
-
return null
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (multicall_address !== "" && multicall_address.length !== 42) {
|
|
326
|
-
console.log(chalk.red("Multicall address length must be 42"));
|
|
327
|
-
continue;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
return multicall_address;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
return null;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
export const getSymbol = async (text: string) => {
|
|
337
|
-
let reg = /^[A-Za-z][0-9a-zA-Z]*$/g;
|
|
338
|
-
for (let i = 0; i < 5; i++) {
|
|
339
|
-
let symbol = await inputSomething(text);
|
|
340
|
-
if (symbol === "") {
|
|
341
|
-
return null
|
|
342
|
-
}
|
|
343
|
-
if (reg.test(symbol)) {
|
|
344
|
-
return symbol
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
return null;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
export const getColor = async (text: string) => {
|
|
351
|
-
let reg = /^#[0-9A-Fa-f]{6}$/g;
|
|
352
|
-
for (let i = 0; i < 5; i++) {
|
|
353
|
-
let color = await inputSomething(text);
|
|
354
|
-
if (color === "") {
|
|
355
|
-
return null
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
if (reg.test(color)) {
|
|
359
|
-
return color
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return null;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
export const getAccountNameByKeystoreSlug = (keystore_path: string, keystore_slug: string) => {
|
|
366
|
-
const networks = getNetworkInfo(keystore_path);
|
|
367
|
-
const account_name_list = networks.accounts;
|
|
368
|
-
const keystore_slug_list = batchGetKeystoreSlugByAccountName(account_name_list);
|
|
369
|
-
const index = keystore_slug_list.indexOf(keystore_slug);
|
|
370
|
-
if (index !== -1) {
|
|
371
|
-
return account_name_list[index];
|
|
372
|
-
}
|
|
373
|
-
return keystore_slug;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
export const getKeystoreSlugByAccountName = (account_name: string) => {
|
|
377
|
-
account_name = account_name.trim();
|
|
378
|
-
account_name = account_name.toLocaleLowerCase();
|
|
379
|
-
account_name = account_name.replace(/\s+/g, "-").trim();
|
|
380
|
-
account_name = account_name.replace(/\-+/g, "-").trim();
|
|
381
|
-
return account_name;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
export const batchGetKeystoreSlugByAccountName = (account_name_list: string[]) => {
|
|
385
|
-
let keystore_slug_list: string[] = [];
|
|
386
|
-
for (let i = 0; i < account_name_list.length; i++) {
|
|
387
|
-
keystore_slug_list.push(
|
|
388
|
-
getKeystoreSlugByAccountName(account_name_list[i])
|
|
389
|
-
);
|
|
390
|
-
}
|
|
391
|
-
return keystore_slug_list;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
export const getAccountName = async (text: string, account_name_list: string[]) => {
|
|
396
|
-
let keystore_slug_list = batchGetKeystoreSlugByAccountName(account_name_list);
|
|
397
|
-
let reg = /^(?![-_])[a-zA-Z0-9_-]{4,40}(?<![-_])$/g;
|
|
398
|
-
for (let i = 0; i < 5; i++) {
|
|
399
|
-
let account_name = await inputSomething(text);
|
|
400
|
-
account_name = account_name.trim();
|
|
401
|
-
let keystore_slug = getKeystoreSlugByAccountName(account_name);
|
|
402
|
-
|
|
403
|
-
if (reg.test(keystore_slug)) {
|
|
404
|
-
if (keystore_slug_list.includes(keystore_slug)) {
|
|
405
|
-
console.log(chalk.red("Account name already exists"));
|
|
406
|
-
continue;
|
|
407
|
-
} else {
|
|
408
|
-
return account_name;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
return null;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
const passwordValidator = function (value: string) {
|
|
416
|
-
let validatorInfo = "Password must contain at least: \n";
|
|
417
|
-
let myReg;
|
|
418
|
-
let access = true;
|
|
419
|
-
let tabspace = " ";
|
|
420
|
-
let green_string = chalk.green('\u2714');
|
|
421
|
-
let red_string = chalk.red('\u2716');
|
|
422
|
-
|
|
423
|
-
if (value.length >= 8) {
|
|
424
|
-
validatorInfo += tabspace + green_string + " 8 characters\n";
|
|
425
|
-
} else {
|
|
426
|
-
validatorInfo += tabspace + red_string + " 8 characters\n";
|
|
427
|
-
access = false;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
myReg = /[0-9]/;
|
|
431
|
-
if (myReg.test(value)) {
|
|
432
|
-
validatorInfo += tabspace + green_string + " One numerical character\n";
|
|
433
|
-
} else {
|
|
434
|
-
validatorInfo += tabspace + red_string + " One numerical character\n";
|
|
435
|
-
access = false;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
myReg = /[A-Z]/;
|
|
439
|
-
if (myReg.test(value)) {
|
|
440
|
-
validatorInfo += tabspace + green_string + " One uppercase letter\n";
|
|
441
|
-
} else {
|
|
442
|
-
validatorInfo += tabspace + red_string + " One uppercase letter\n";
|
|
443
|
-
access = false;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
myReg = /[!@#$%]/;
|
|
447
|
-
if (myReg.test(value)) {
|
|
448
|
-
validatorInfo += tabspace + green_string + " One sepcial character (i.e. !@#$%)\n";
|
|
449
|
-
} else {
|
|
450
|
-
validatorInfo += tabspace + red_string + " One sepcial character (i.e. !@#$%)\n";
|
|
451
|
-
access = false;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
if (access) {
|
|
455
|
-
return true;
|
|
456
|
-
} else {
|
|
457
|
-
return validatorInfo;
|
|
458
|
-
}
|
|
459
|
-
};
|
|
460
|
-
|
|
461
|
-
export const inputMaskedPassword = async (text: string, validate_func?: Function) => {
|
|
462
|
-
const questions = [
|
|
463
|
-
{
|
|
464
|
-
name: 'inputText',
|
|
465
|
-
type: 'password',
|
|
466
|
-
mask: '#',
|
|
467
|
-
message: `${text}:`,
|
|
468
|
-
validate: validate_func
|
|
469
|
-
},
|
|
470
|
-
]
|
|
471
|
-
const { inputText } = await inquirer.prompt(questions)
|
|
472
|
-
return inputText.trim().toString()
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
export const inputPasswordWithoutValidator = async (text: string) => {
|
|
476
|
-
const questions = [
|
|
477
|
-
{
|
|
478
|
-
name: 'password',
|
|
479
|
-
type: 'password',
|
|
480
|
-
mask: '#',
|
|
481
|
-
message: `${text}:`
|
|
482
|
-
}
|
|
483
|
-
]
|
|
484
|
-
|
|
485
|
-
let { password } = await inquirer.prompt(questions);
|
|
486
|
-
return password;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
export const importMaskedPassphrase = async (text: string, validate_func?: Function) => {
|
|
490
|
-
const questions = [
|
|
491
|
-
{
|
|
492
|
-
name: 'inputText',
|
|
493
|
-
type: 'input',
|
|
494
|
-
message: `${text}:`,
|
|
495
|
-
validate: validate_func,
|
|
496
|
-
transformer: (input: any) => {
|
|
497
|
-
const parts = input.split(' ');
|
|
498
|
-
const transformed = parts.map((part: any, index: any) => {
|
|
499
|
-
if (index < parts.length - 1) {
|
|
500
|
-
return '#'.repeat(part.length);
|
|
501
|
-
}
|
|
502
|
-
return part;
|
|
503
|
-
});
|
|
504
|
-
return transformed.join(' ');
|
|
505
|
-
}
|
|
506
|
-
},
|
|
507
|
-
]
|
|
508
|
-
const { inputText } = await inquirer.prompt(questions)
|
|
509
|
-
return inputText.trim().toString()
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
export const inputPassword = async (text: string) => {
|
|
514
|
-
let count = 0;
|
|
515
|
-
|
|
516
|
-
const questions = [
|
|
517
|
-
{
|
|
518
|
-
name: 'password',
|
|
519
|
-
type: 'password',
|
|
520
|
-
mask: '#',
|
|
521
|
-
message: `${text}:`,
|
|
522
|
-
validate: (fieldValue: string) => {
|
|
523
|
-
if (count >= 3) {
|
|
524
|
-
return true
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
return passwordValidator(fieldValue);
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
]
|
|
531
|
-
|
|
532
|
-
let { password } = await inquirer.prompt(questions);
|
|
533
|
-
if (count >= 3) {
|
|
534
|
-
password = null;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
return password;
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
export const confirmSomething = async (text: string, _default = true) => {
|
|
541
|
-
const questions = [
|
|
542
|
-
{
|
|
543
|
-
name: 'confirm',
|
|
544
|
-
type: 'confirm',
|
|
545
|
-
message: `${text}`,
|
|
546
|
-
default: _default
|
|
547
|
-
}
|
|
548
|
-
]
|
|
549
|
-
const { confirm } = await inquirer.prompt(questions);
|
|
550
|
-
return confirm;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
export const editorSomething = async (text: string, validate_func?: Function) => {
|
|
554
|
-
const questions = [
|
|
555
|
-
{
|
|
556
|
-
name: 'editor',
|
|
557
|
-
type: 'editor',
|
|
558
|
-
message: `${text}`,
|
|
559
|
-
validate: validate_func
|
|
560
|
-
}
|
|
561
|
-
]
|
|
562
|
-
const { editor } = await inquirer.prompt(questions);
|
|
563
|
-
return editor.trim().toString()
|
|
564
|
-
};
|
|
565
|
-
|
|
566
|
-
export const hexValidator = function (value: string) {
|
|
567
|
-
let reg = /^0x[0-9a-fA-F]*$/g;
|
|
568
|
-
if (reg.test(value.trim())) {
|
|
569
|
-
return true;
|
|
570
|
-
} else {
|
|
571
|
-
return false;
|
|
572
|
-
}
|
|
573
|
-
};
|
|
574
|
-
|
|
575
|
-
export interface Result {
|
|
576
|
-
status: boolean;
|
|
577
|
-
output: any;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
export const excutePromiseFunction = async (fn: Function, params: any): Promise<Result> => {
|
|
581
|
-
let result: Result;
|
|
582
|
-
try {
|
|
583
|
-
let output = await fn(...params);
|
|
584
|
-
result = {
|
|
585
|
-
status: true,
|
|
586
|
-
output
|
|
587
|
-
};
|
|
588
|
-
} catch (err: any) {
|
|
589
|
-
result = {
|
|
590
|
-
status: false,
|
|
591
|
-
output: err.toString()
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
return result;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
export const getAccountChainType = (account_address: string) => {
|
|
598
|
-
if (account_address.startsWith("0x") && account_address.length === 42) {
|
|
599
|
-
return "evm";
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
if (/^[A-HJ-NP-Za-km-z1-9]*$/.test(account_address) && account_address.length <= 44 && account_address.length >= 32) {
|
|
603
|
-
return "solana";
|
|
604
|
-
}
|
|
605
|
-
return "unknown";
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
export const checkFileExistence = (file_path: string): boolean => {
|
|
609
|
-
file_path = file_path.trim()
|
|
610
|
-
return fs.existsSync(file_path);
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
export const chunkArray = (array: any, size: number) => {
|
|
614
|
-
let result: any = [];
|
|
615
|
-
for (let i = 0; i < array.length; i += size) {
|
|
616
|
-
result.push(array.slice(i, i + size));
|
|
617
|
-
}
|
|
618
|
-
return result;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
export const sleep = (ms: number) => {
|
|
622
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
export const formatAddr = (addr: string, force_full_addr: boolean = true) => {
|
|
626
|
-
if (force_full_addr) {
|
|
627
|
-
return addr;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
if (addr.startsWith("0x")) {
|
|
631
|
-
return addr.slice(0, 8) + "..." + addr.slice(-6);
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
return addr.slice(0, 6) + "..." + addr.slice(-6);
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
// 提取账户地址的辅助函数
|
|
638
|
-
const extractAccountFromChoice = (choice: any, is_evm: boolean): string | null => {
|
|
639
|
-
if (!choice.name) {
|
|
640
|
-
return null;
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
let account: any = null;
|
|
644
|
-
|
|
645
|
-
if (is_evm) {
|
|
646
|
-
account = /0x[0-9a-fA-f]{40}/.exec(choice.name);
|
|
647
|
-
account = account ? account[0] : null;
|
|
648
|
-
} else {
|
|
649
|
-
let re_result = /\s+([0-9a-zA-Z]*)/.exec(choice.name);
|
|
650
|
-
account = re_result ? re_result[1] : null;
|
|
651
|
-
|
|
652
|
-
if (account === "Back") {
|
|
653
|
-
account = null;
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
return account;
|
|
658
|
-
};
|
|
659
|
-
|
|
660
|
-
// 计算分页索引的辅助函数
|
|
661
|
-
const calculatePageIndices = (selected: number, pageSize: number, accountsLength: number): { fromIndex: number, toIndex: number } => {
|
|
662
|
-
let fromIndex: number, toIndex: number;
|
|
663
|
-
|
|
664
|
-
if (selected < pageSize / 2) {
|
|
665
|
-
if (accountsLength / 2 <= pageSize) {
|
|
666
|
-
fromIndex = 0;
|
|
667
|
-
toIndex = accountsLength / 2;
|
|
668
|
-
} else {
|
|
669
|
-
fromIndex = 0;
|
|
670
|
-
toIndex = pageSize;
|
|
671
|
-
}
|
|
672
|
-
} else {
|
|
673
|
-
if (accountsLength / 2 <= pageSize) {
|
|
674
|
-
fromIndex = 0;
|
|
675
|
-
toIndex = accountsLength / 2;
|
|
676
|
-
} else {
|
|
677
|
-
fromIndex = selected - pageSize / 2 + 1;
|
|
678
|
-
toIndex = selected + pageSize / 2 + 1;
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
return { fromIndex, toIndex };
|
|
683
|
-
};
|
|
684
|
-
|
|
685
|
-
// 提取账户列表的辅助函数
|
|
686
|
-
const extractAccountsList = (choices: any[], is_evm: boolean): (string | null)[] => {
|
|
687
|
-
const accounts: (string | null)[] = [];
|
|
688
|
-
|
|
689
|
-
for (let i = 0; i < choices.length; i++) {
|
|
690
|
-
const account = extractAccountFromChoice(choices[i], is_evm);
|
|
691
|
-
accounts.push(account);
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
return accounts.concat(accounts);
|
|
695
|
-
};
|
|
696
|
-
|
|
697
|
-
// 处理账户余额显示的辅助函数
|
|
698
|
-
const processAccountBalanceDisplay = (
|
|
699
|
-
choices: any[],
|
|
700
|
-
accounts: (string | null)[],
|
|
701
|
-
batchBalanceOf: any,
|
|
702
|
-
pad_index_map: any,
|
|
703
|
-
gas_token_name: string,
|
|
704
|
-
show_gas_token: boolean,
|
|
705
|
-
show_extended_token: boolean,
|
|
706
|
-
fromIndex: number,
|
|
707
|
-
toIndex: number
|
|
708
|
-
) => {
|
|
709
|
-
for (let i = fromIndex; i < toIndex; i++) {
|
|
710
|
-
let _index = i >= accounts.length / 2 ? i - accounts.length / 2 : i;
|
|
711
|
-
let _choice = choices[_index];
|
|
712
|
-
if (!_choice.name) {
|
|
713
|
-
continue;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
let name = _choice.name;
|
|
717
|
-
let account_address = accounts[i];
|
|
718
|
-
let token_message = '';
|
|
719
|
-
if (!account_address) {
|
|
720
|
-
continue;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
for (let token_name in batchBalanceOf[account_address]) {
|
|
724
|
-
if (!show_gas_token && token_name === gas_token_name) {
|
|
725
|
-
continue;
|
|
726
|
-
}
|
|
727
|
-
if (!show_extended_token && token_name !== gas_token_name) {
|
|
728
|
-
continue;
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
if (name.includes(token_name)) {
|
|
732
|
-
continue;
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
token_message += `${token_name}:${batchBalanceOf[account_address][token_name].padEnd(pad_index_map[token_name])} `;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
let nameList = name.split('(');
|
|
739
|
-
if (nameList.length > 1) {
|
|
740
|
-
let tag = nameList[1];
|
|
741
|
-
choices[_index].name = nameList[0] + ` ${token_message}` + `(${tag}`;
|
|
742
|
-
} else {
|
|
743
|
-
choices[_index].name = nameList[0] + ` ${token_message}`;
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
};
|
|
747
|
-
|
|
748
|
-
export const listWithLazyBalanceLoading = async (
|
|
749
|
-
options: string[],
|
|
750
|
-
is_evm: boolean,
|
|
751
|
-
keystore_path: string,
|
|
752
|
-
asset_info_list: any,
|
|
753
|
-
network_info: any,
|
|
754
|
-
show_gas_token: boolean,
|
|
755
|
-
show_extended_token: boolean,
|
|
756
|
-
direct_display: boolean,
|
|
757
|
-
message?: string,
|
|
758
|
-
default_account?: any
|
|
759
|
-
) => {
|
|
760
|
-
const questions = [
|
|
761
|
-
{
|
|
762
|
-
type: 'list',
|
|
763
|
-
name: 'inputText',
|
|
764
|
-
message: message || 'Choose an option',
|
|
765
|
-
choices: options,
|
|
766
|
-
pageSize: 30,
|
|
767
|
-
default: default_account,
|
|
768
|
-
loop: true,
|
|
769
|
-
filter: (val: string) => {
|
|
770
|
-
return val;
|
|
771
|
-
},
|
|
772
|
-
},
|
|
773
|
-
];
|
|
774
|
-
|
|
775
|
-
const promise: any = inquirer.prompt(questions);
|
|
776
|
-
|
|
777
|
-
let selected = 0;
|
|
778
|
-
let round = 0;
|
|
779
|
-
let pre_selected: any;
|
|
780
|
-
|
|
781
|
-
while (!promise.ui.activePrompt.answers[promise.ui.activePrompt.opt.name]) {
|
|
782
|
-
if (!direct_display) {
|
|
783
|
-
await sleep(1000);
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
if (pre_selected === promise.ui.activePrompt.selected) {
|
|
787
|
-
continue;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
if (selected === promise.ui.activePrompt.selected) {
|
|
791
|
-
round = round + 1;
|
|
792
|
-
} else {
|
|
793
|
-
round = 0;
|
|
794
|
-
selected = promise.ui.activePrompt.selected;
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
if (direct_display) {
|
|
798
|
-
round = 6;
|
|
799
|
-
direct_display = false;
|
|
800
|
-
|
|
801
|
-
const pageSize = promise.ui.activePrompt.opt.pageSize;
|
|
802
|
-
const accounts = extractAccountsList(promise.ui.activePrompt.opt.choices.choices, is_evm);
|
|
803
|
-
const { fromIndex, toIndex } = calculatePageIndices(selected, pageSize, accounts.length);
|
|
804
|
-
const active_account: any = accounts.slice(fromIndex, toIndex);
|
|
805
|
-
|
|
806
|
-
let has_balance = batchHasTokenBalance(network_info.chainId.toString(), active_account);
|
|
807
|
-
if (!has_balance) {
|
|
808
|
-
round = 0;
|
|
809
|
-
continue;
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
if (round < 5) {
|
|
814
|
-
continue;
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
round = 0;
|
|
818
|
-
const pageSize = promise.ui.activePrompt.opt.pageSize;
|
|
819
|
-
const accounts = extractAccountsList(promise.ui.activePrompt.opt.choices.choices, is_evm);
|
|
820
|
-
const { fromIndex, toIndex } = calculatePageIndices(selected, pageSize, accounts.length);
|
|
821
|
-
const active_account: any = accounts.slice(fromIndex, toIndex);
|
|
822
|
-
|
|
823
|
-
let batchBalanceOf = await getBatchAccountBalance(
|
|
824
|
-
keystore_path,
|
|
825
|
-
active_account,
|
|
826
|
-
asset_info_list,
|
|
827
|
-
network_info.rpcUrl,
|
|
828
|
-
network_info.name,
|
|
829
|
-
show_gas_token,
|
|
830
|
-
show_extended_token
|
|
831
|
-
);
|
|
832
|
-
|
|
833
|
-
let pad_index_map: any = {};
|
|
834
|
-
|
|
835
|
-
for (let account_address in batchBalanceOf) {
|
|
836
|
-
for (let token_name in batchBalanceOf[account_address]) {
|
|
837
|
-
let balance = batchBalanceOf[account_address][token_name];
|
|
838
|
-
let new_pad_index = balance.length + 1;
|
|
839
|
-
if (!pad_index_map[token_name]) {
|
|
840
|
-
pad_index_map[token_name] = new_pad_index;
|
|
841
|
-
} else if (pad_index_map[token_name] < new_pad_index) {
|
|
842
|
-
pad_index_map[token_name] = new_pad_index;
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
const gas_token_name = network_info.nativeCurrency.symbol;
|
|
848
|
-
processAccountBalanceDisplay(
|
|
849
|
-
promise.ui.activePrompt.opt.choices.choices,
|
|
850
|
-
accounts,
|
|
851
|
-
batchBalanceOf,
|
|
852
|
-
pad_index_map,
|
|
853
|
-
gas_token_name,
|
|
854
|
-
show_gas_token,
|
|
855
|
-
show_extended_token,
|
|
856
|
-
fromIndex,
|
|
857
|
-
toIndex
|
|
858
|
-
);
|
|
859
|
-
|
|
860
|
-
promise.ui.activePrompt.screen.render('');
|
|
861
|
-
promise.ui.activePrompt.render();
|
|
862
|
-
pre_selected = selected;
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
return promise.ui.activePrompt.answers[promise.ui.activePrompt.opt.name];
|
|
866
|
-
};
|
|
867
|
-
|
|
868
|
-
export const updateStorage = (keystore_path: string) => {
|
|
869
|
-
const network_path = path.resolve(keystore_path, 'network.json');
|
|
870
|
-
const networks = JSON.parse(fs.readFileSync(network_path, 'utf8'));
|
|
871
|
-
|
|
872
|
-
if (!networks.status) {
|
|
873
|
-
networks.status = {
|
|
874
|
-
fullAddr: true,
|
|
875
|
-
gasToken: false,
|
|
876
|
-
extendedToken: false
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
if (!networks.showTokens) {
|
|
881
|
-
networks.showTokens = {};
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
let account_list_len = networks.accounts.length;
|
|
885
|
-
for (let i = 0; i < account_list_len; i++) {
|
|
886
|
-
let account_name = networks.accounts[account_list_len - 1 - i];
|
|
887
|
-
let keystore_slug = getKeystoreSlugByAccountName(account_name);
|
|
888
|
-
let keystore_slug_path = path.resolve(keystore_path, `accounts/${keystore_slug}.json`);
|
|
889
|
-
|
|
890
|
-
if (!fs.existsSync(keystore_slug_path)) {
|
|
891
|
-
networks.accounts.splice(account_list_len - 1 - i, 1);
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
fs.writeFileSync(network_path, JSON.stringify(networks, null, 4));
|
|
896
|
-
let account_name_list = networks.accounts;
|
|
897
|
-
let keystore_slug_list = batchGetKeystoreSlugByAccountName(account_name_list);
|
|
898
|
-
|
|
899
|
-
for (let i = 0; i < keystore_slug_list.length; i++) {
|
|
900
|
-
let keystore_slug_path = path.resolve(keystore_path, `accounts/${keystore_slug_list[i]}.json`);
|
|
901
|
-
let account_info = JSON.parse(fs.readFileSync(keystore_slug_path, 'utf8'));
|
|
902
|
-
if (account_info.account_type === "PP") {
|
|
903
|
-
continue;
|
|
904
|
-
}
|
|
905
|
-
if ("data" in account_info) {
|
|
906
|
-
continue;
|
|
907
|
-
}
|
|
908
|
-
account_info.data = [
|
|
909
|
-
{
|
|
910
|
-
ciphertexts: account_info.ciphertexts
|
|
911
|
-
}
|
|
912
|
-
];
|
|
913
|
-
delete account_info.ciphertexts;
|
|
914
|
-
fs.writeFileSync(keystore_slug_path, JSON.stringify(account_info, null, 4));
|
|
915
|
-
}
|
|
916
|
-
}
|