@yerofey/cryptowallet-cli 1.9.0 → 1.11.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.
- package/README.md +1 -0
- package/cli.js +1 -41
- package/package.json +8 -8
- package/src/CW.js +9 -14
- package/src/Chain.js +30 -25
- package/src/Method.js +330 -318
- package/src/Wallet.js +10 -23
- package/src/options.js +43 -0
- package/src/utils.js +9 -19
package/README.md
CHANGED
package/cli.js
CHANGED
|
@@ -1,52 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
import { program } from 'commander';
|
|
5
4
|
import chalk from 'chalk';
|
|
5
|
+
import { options } from './src/options.js';
|
|
6
6
|
import { log, supportedChains } from './src/utils.js';
|
|
7
7
|
import Method from './src/Method.js';
|
|
8
8
|
|
|
9
|
-
program.option('-b, --chain <ticker>', 'Wallet for specific blockchain', 'ERC');
|
|
10
|
-
program.option('-c, --chain <ticker>', 'Wallet for specific blockchain', 'ERC');
|
|
11
|
-
program.option(
|
|
12
|
-
'-D, --csv [filename]',
|
|
13
|
-
'Save result into CSV file'
|
|
14
|
-
);
|
|
15
|
-
program.option(
|
|
16
|
-
'-f, --format <format>',
|
|
17
|
-
'Wallet format type (for cryptos with multiple wallet formats)'
|
|
18
|
-
);
|
|
19
|
-
program.option(
|
|
20
|
-
'-F, --filename <filename>',
|
|
21
|
-
'Filename to output the data (works with -o argument)'
|
|
22
|
-
);
|
|
23
|
-
program.option('-g, --geek', 'Display some more info (geeky)');
|
|
24
|
-
program.option('-l, --list', 'List all supported cryptos');
|
|
25
|
-
program.option(
|
|
26
|
-
'-m, --mnemonic [mnemonic]',
|
|
27
|
-
'Generate wallet from mnemonic string OR just a mnemonic string'
|
|
28
|
-
);
|
|
29
|
-
program.option(
|
|
30
|
-
'-n, --number <number>',
|
|
31
|
-
'Number of wallets to generate (if supported)'
|
|
32
|
-
);
|
|
33
|
-
program.option('-o, --output <format>', 'Return results into some file');
|
|
34
|
-
program.option('-p, --prefix <prefix>', 'Desired wallet prefix');
|
|
35
|
-
program.option(
|
|
36
|
-
'-P, --prefix-sensitive <prefix>',
|
|
37
|
-
'Desired wallet prefix (case-sensitive)'
|
|
38
|
-
);
|
|
39
|
-
program.option('-s, --suffix <suffix>', 'Desired wallet suffix');
|
|
40
|
-
program.option(
|
|
41
|
-
'-S, --suffix-sensitive <suffix>',
|
|
42
|
-
'Desired wallet suffix (case-sensitive)'
|
|
43
|
-
);
|
|
44
|
-
program.option('-v, --version', 'Display cryptowallet version');
|
|
45
|
-
program.parse();
|
|
46
|
-
|
|
47
9
|
(async () => {
|
|
48
|
-
const options = program.opts();
|
|
49
|
-
|
|
50
10
|
if (options.list !== undefined) {
|
|
51
11
|
return new Method('list').init();
|
|
52
12
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yerofey/cryptowallet-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "Crypto wallet generator CLI tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://github.com/yerofey/cryptowallet-cli",
|
|
@@ -66,26 +66,26 @@
|
|
|
66
66
|
"wallet generation"
|
|
67
67
|
],
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"@binance-chain/javascript-sdk": "^4.2.
|
|
69
|
+
"@binance-chain/javascript-sdk": "^4.2.1",
|
|
70
70
|
"@harmony-js/account": "^0.1.58",
|
|
71
71
|
"@yerofey/dogecoin-bip84": "^0.0.5",
|
|
72
72
|
"@yerofey/litecoin-bip84": "^0.0.5",
|
|
73
|
-
"bip39": "3.0
|
|
73
|
+
"bip39": "3.1.0",
|
|
74
74
|
"bip84": "0.2.7",
|
|
75
|
-
"chalk": "5.
|
|
75
|
+
"chalk": "5.3.0",
|
|
76
76
|
"coininfo": "5.2.1",
|
|
77
77
|
"coinkey": "3.0.0",
|
|
78
78
|
"columnify": "1.6.0",
|
|
79
|
-
"commander": "
|
|
79
|
+
"commander": "11.0.0",
|
|
80
80
|
"csv-writer": "^1.6.0",
|
|
81
81
|
"eth-lib": "0.1.29",
|
|
82
82
|
"ethereum-bip84": "0.0.3",
|
|
83
83
|
"ethereum-mnemonic-privatekey-utils": "1.0.5",
|
|
84
84
|
"tezos-sign": "1.4.1",
|
|
85
|
-
"tronweb": "5.
|
|
85
|
+
"tronweb": "5.3.0"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
|
-
"ava": "^5.
|
|
89
|
-
"eslint": "^8.
|
|
88
|
+
"ava": "^5.3.1",
|
|
89
|
+
"eslint": "^8.46.0"
|
|
90
90
|
}
|
|
91
91
|
}
|
package/src/CW.js
CHANGED
|
@@ -3,11 +3,17 @@ import { Wallet } from './Wallet.js';
|
|
|
3
3
|
|
|
4
4
|
class CW {
|
|
5
5
|
constructor(chain, options = {}) {
|
|
6
|
+
this.chain = chain;
|
|
7
|
+
this.options = this._prepareOptions(chain, options);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
_prepareOptions(chain, options) {
|
|
6
11
|
const csvFilename = 'cw-output';
|
|
12
|
+
|
|
7
13
|
if (options.csv !== undefined) {
|
|
8
14
|
options.output = 'csv';
|
|
9
15
|
|
|
10
|
-
if (typeof options.csv === 'string' &&
|
|
16
|
+
if (typeof options.csv === 'string' && options.csv.length > 0) {
|
|
11
17
|
options.filename = options.csv;
|
|
12
18
|
}
|
|
13
19
|
}
|
|
@@ -26,15 +32,7 @@ class CW {
|
|
|
26
32
|
suffixIsCaseSensitive: options.suffixSensitive !== undefined,
|
|
27
33
|
};
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
// eslint-disable-next-line no-prototype-builtins
|
|
31
|
-
if (!options.hasOwnProperty(key)) {
|
|
32
|
-
options[key] = defaultValues[key];
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
this.chain = chain;
|
|
37
|
-
this.options = options;
|
|
35
|
+
return { ...defaultValues, ...options };
|
|
38
36
|
}
|
|
39
37
|
|
|
40
38
|
async init() {
|
|
@@ -42,10 +40,7 @@ class CW {
|
|
|
42
40
|
this.row = chainData.row || {};
|
|
43
41
|
|
|
44
42
|
const w = await new Wallet(this).init();
|
|
45
|
-
|
|
46
|
-
for (const key of Object.keys(w)) {
|
|
47
|
-
this[key] = w[key];
|
|
48
|
-
}
|
|
43
|
+
Object.assign(this, w);
|
|
49
44
|
|
|
50
45
|
return this;
|
|
51
46
|
}
|
package/src/Chain.js
CHANGED
|
@@ -2,38 +2,43 @@ import path from 'node:path';
|
|
|
2
2
|
import { loadJson } from './utils.js';
|
|
3
3
|
|
|
4
4
|
class Chain {
|
|
5
|
-
constructor(chain, format) {
|
|
5
|
+
constructor(chain, format = '') {
|
|
6
6
|
this.chain = chain;
|
|
7
7
|
this.format = format;
|
|
8
|
+
this.row = null;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
async init() {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const data = (() => {
|
|
14
|
-
if (content.formats !== undefined) {
|
|
15
|
-
if (this.format != '' && this.format != content.defaultFormat) {
|
|
16
|
-
// case-insensitive format
|
|
17
|
-
for (const key of Object.keys(content.formats)) {
|
|
18
|
-
if (this.format.toLowerCase() == key.toLowerCase()) {
|
|
19
|
-
return content.formats[key];
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return content.formats[content.defaultFormat];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return content;
|
|
28
|
-
})();
|
|
29
|
-
|
|
30
|
-
this.row = {
|
|
31
|
-
...content,
|
|
32
|
-
...data,
|
|
33
|
-
};
|
|
34
|
-
|
|
12
|
+
const content = await this._loadChainJson();
|
|
13
|
+
this.row = this._parseContent(content);
|
|
35
14
|
return this;
|
|
36
15
|
}
|
|
16
|
+
|
|
17
|
+
async _loadChainJson() {
|
|
18
|
+
const filePath = `${path.dirname(import.meta.url)}/chains/${
|
|
19
|
+
this.chain
|
|
20
|
+
}.json`.replace('file://', '');
|
|
21
|
+
return await loadJson(filePath);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
_parseContent(content) {
|
|
25
|
+
if (!content.formats) return content;
|
|
26
|
+
|
|
27
|
+
const formatKey = this._findFormatKey(content);
|
|
28
|
+
return { ...content, ...content.formats[formatKey] };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_findFormatKey(content) {
|
|
32
|
+
if (!this.format || this.format === content.defaultFormat)
|
|
33
|
+
return content.defaultFormat;
|
|
34
|
+
|
|
35
|
+
const normalizedFormat = this.format.toLowerCase();
|
|
36
|
+
const matchingKey = Object.keys(content.formats).find(
|
|
37
|
+
(key) => key.toLowerCase() === normalizedFormat
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return matchingKey || content.defaultFormat;
|
|
41
|
+
}
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
export default Chain;
|
package/src/Method.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
+
import columnify from 'columnify';
|
|
4
|
+
import CsvWriter from 'csv-writer';
|
|
5
|
+
import { log, supportedChains, loadJson } from './utils.js';
|
|
6
|
+
import { generateMnemonicString } from './Wallet.js';
|
|
7
|
+
import CW from './CW.js';
|
|
8
|
+
|
|
3
9
|
const {
|
|
4
10
|
blue,
|
|
5
11
|
green,
|
|
@@ -10,366 +16,372 @@ const {
|
|
|
10
16
|
magenta,
|
|
11
17
|
white,
|
|
12
18
|
} = chalk;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
supportedChains,
|
|
18
|
-
loadJson,
|
|
19
|
-
} from './utils.js';
|
|
20
|
-
import { generateMnemonicString } from './Wallet.js';
|
|
21
|
-
import CW from './CW.js';
|
|
22
|
-
const pkg = await loadJson(`${path.dirname(import.meta.url)}/../package.json`.replace('file://', ''));
|
|
23
|
-
// eslint-disable-next-line no-undef
|
|
19
|
+
|
|
20
|
+
const pkg = await loadJson(
|
|
21
|
+
`${path.dirname(import.meta.url)}/../package.json`.replace('file://', '')
|
|
22
|
+
);
|
|
24
23
|
const _version = pkg['version'] || 0;
|
|
25
24
|
|
|
26
25
|
class Method {
|
|
27
26
|
constructor(name, params = {}) {
|
|
28
27
|
this.name = name;
|
|
29
28
|
this.params = params;
|
|
29
|
+
this.callMethods = this._initializeMethods();
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
_initializeMethods() {
|
|
33
|
+
return {
|
|
34
34
|
_: () => {},
|
|
35
|
-
list:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
list: this._list.bind(this),
|
|
36
|
+
mnemonic: this._mnemonic.bind(this),
|
|
37
|
+
version: this._version.bind(this),
|
|
38
|
+
wallet: this._wallet.bind(this),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
async _list() {
|
|
43
|
+
log(`🔠 All supported blockchains:\n`);
|
|
44
|
+
let cryptos = {};
|
|
45
|
+
for (const val of supportedChains) {
|
|
46
|
+
// eslint-disable-next-line no-undef
|
|
47
|
+
const data = await loadJson(
|
|
48
|
+
`${path.dirname(import.meta.url)}/chains/${val}.json`.replace(
|
|
49
|
+
'file://',
|
|
50
|
+
''
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
let title = data.title || '';
|
|
55
|
+
if (title == '' || val == 'ERC') {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
cryptos[blue(val)] = title;
|
|
59
|
+
}
|
|
60
|
+
log(
|
|
61
|
+
columnify(cryptos, {
|
|
62
|
+
showHeaders: false,
|
|
63
|
+
columnSplitter: ' - ',
|
|
64
|
+
})
|
|
65
|
+
);
|
|
66
|
+
log();
|
|
67
|
+
log(`ℹ️ Use flag "-c TICKER" to select specific blockchain`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
_mnemonic() {
|
|
71
|
+
log(
|
|
72
|
+
`✨ ${green('Done!')} ${blueBright(
|
|
73
|
+
'Here is your randomly generated 12 words mnemonic string:'
|
|
74
|
+
)}\n`
|
|
75
|
+
);
|
|
76
|
+
log(`📄 ${generateMnemonicString()}`);
|
|
77
|
+
log();
|
|
78
|
+
log(
|
|
79
|
+
greenBright(
|
|
80
|
+
'ℹ️ You can import this wallet into MetaMask, Trust Wallet and many other wallet apps'
|
|
81
|
+
)
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
_version() {
|
|
86
|
+
log(_version);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async _wallet() {
|
|
90
|
+
const chain = this.params.chain;
|
|
91
|
+
const options = this.params.options;
|
|
92
|
+
|
|
93
|
+
const cw = await new CW(chain, options).init();
|
|
94
|
+
|
|
95
|
+
let chainFullName =
|
|
96
|
+
(cw.row.name || chain) +
|
|
97
|
+
(cw.wallet.format !== undefined && cw.wallet.format != ''
|
|
98
|
+
? ' (' + cw.wallet.format + ')'
|
|
99
|
+
: '');
|
|
100
|
+
|
|
101
|
+
if (cw.options.prefix && !cw.prefixFound) {
|
|
102
|
+
log(
|
|
103
|
+
`😢 ${yellow(
|
|
104
|
+
'Sorry, ' + chainFullName + ' does not support prefix yet...'
|
|
105
|
+
)}`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (cw.options.suffix && !cw.suffixFound) {
|
|
110
|
+
log(
|
|
111
|
+
`😢 ${yellow(
|
|
112
|
+
'Sorry, ' + chainFullName + ' does not support suffix yet...'
|
|
113
|
+
)}`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (cw.options.mnemonic != '' && cw.wallet.mnemonic == undefined) {
|
|
118
|
+
log(
|
|
119
|
+
`😢 ${yellow(
|
|
120
|
+
'Sorry, ' + chainFullName + ' does not support mnemonic yet...'
|
|
121
|
+
)}`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (cw.wallet.error !== undefined) {
|
|
126
|
+
log(`⛔️ ${red(`Error: ${cw.wallet.error}`)}`);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let linesCount = 0;
|
|
131
|
+
const outputFormats = ['csv'];
|
|
132
|
+
const displayAsText =
|
|
133
|
+
cw.options.output === undefined ||
|
|
134
|
+
!outputFormats.includes(cw.options.output);
|
|
135
|
+
|
|
136
|
+
// prefix, suffix
|
|
137
|
+
if (displayAsText) {
|
|
138
|
+
if (cw.prefixFound && cw.suffixFound) {
|
|
48
139
|
log(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
140
|
+
`✨ ${green('Done!')} ${blueBright(
|
|
141
|
+
'Here is your brand new ' +
|
|
142
|
+
chainFullName +
|
|
143
|
+
' wallet with "' +
|
|
144
|
+
cw.options.prefix +
|
|
145
|
+
'" prefix and "' +
|
|
146
|
+
cw.options.suffix +
|
|
147
|
+
'" suffix:'
|
|
148
|
+
)}\n`
|
|
53
149
|
);
|
|
54
|
-
|
|
55
|
-
log(`ℹ️ Use flag "-c TICKER" to select specific blockchain`);
|
|
56
|
-
},
|
|
57
|
-
mnemonic: () => {
|
|
150
|
+
} else if (cw.prefixFound) {
|
|
58
151
|
log(
|
|
59
152
|
`✨ ${green('Done!')} ${blueBright(
|
|
60
|
-
'Here is your
|
|
153
|
+
'Here is your brand new ' +
|
|
154
|
+
chainFullName +
|
|
155
|
+
' wallet with "' +
|
|
156
|
+
cw.options.prefix +
|
|
157
|
+
'" prefix:'
|
|
61
158
|
)}\n`
|
|
62
159
|
);
|
|
63
|
-
|
|
64
|
-
log();
|
|
160
|
+
} else if (cw.suffixFound) {
|
|
65
161
|
log(
|
|
66
|
-
|
|
67
|
-
'
|
|
68
|
-
|
|
162
|
+
`✨ ${green('Done!')} ${blueBright(
|
|
163
|
+
'Here is your brand new ' +
|
|
164
|
+
chainFullName +
|
|
165
|
+
' wallet with "' +
|
|
166
|
+
cw.options.suffix +
|
|
167
|
+
'" suffix:'
|
|
168
|
+
)}\n`
|
|
69
169
|
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
let chainFullName =
|
|
81
|
-
(cw.row.name || chain) +
|
|
82
|
-
(cw.wallet.format !== undefined && cw.wallet.format != ''
|
|
83
|
-
? ' (' + cw.wallet.format + ')'
|
|
84
|
-
: '');
|
|
85
|
-
|
|
86
|
-
if (cw.options.prefix && !cw.prefixFound) {
|
|
87
|
-
log(
|
|
88
|
-
`😢 ${yellow(
|
|
89
|
-
'Sorry, ' + chainFullName + ' does not support prefix yet...'
|
|
90
|
-
)}`
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (cw.options.suffix && !cw.suffixFound) {
|
|
95
|
-
log(
|
|
96
|
-
`😢 ${yellow(
|
|
97
|
-
'Sorry, ' + chainFullName + ' does not support suffix yet...'
|
|
98
|
-
)}`
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (cw.options.mnemonic != '' && cw.wallet.mnemonic == undefined) {
|
|
103
|
-
log(
|
|
104
|
-
`😢 ${yellow(
|
|
105
|
-
'Sorry, ' + chainFullName + ' does not support mnemonic yet...'
|
|
106
|
-
)}`
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (cw.wallet.error !== undefined) {
|
|
111
|
-
log(`⛔️ ${red(`Error: ${cw.wallet.error}`)}`);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
170
|
+
} else {
|
|
171
|
+
log(
|
|
172
|
+
`✨ ${green('Done!')} ${blueBright(
|
|
173
|
+
'Here is your brand new ' + chainFullName + ' wallet:'
|
|
174
|
+
)}\n`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
linesCount += 1;
|
|
178
|
+
}
|
|
114
179
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
180
|
+
// result
|
|
181
|
+
let outputData = {};
|
|
182
|
+
if (cw.wallet.addresses !== undefined) {
|
|
183
|
+
// private key
|
|
184
|
+
if (cw.wallet.privateExtendedKey && cw.options.geek) {
|
|
185
|
+
log(`🔐 ${cw.wallet.privateExtendedKey}`);
|
|
186
|
+
linesCount += 1;
|
|
187
|
+
}
|
|
188
|
+
// mnemonic
|
|
189
|
+
if (cw.wallet.mnemonic) {
|
|
190
|
+
log(`📄 ${cw.wallet.mnemonic}`);
|
|
191
|
+
linesCount += 1;
|
|
192
|
+
}
|
|
193
|
+
// addresses
|
|
194
|
+
if (displayAsText) {
|
|
195
|
+
for (const item of cw.wallet.addresses) {
|
|
196
|
+
if (cw.wallet.addresses.length > 1) {
|
|
197
|
+
log();
|
|
198
|
+
log(`🆔 ${item.index}`);
|
|
199
|
+
}
|
|
120
200
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
201
|
+
if (
|
|
202
|
+
cw.prefixFound &&
|
|
203
|
+
cw.prefixFoundInWallets.includes(item.address) &&
|
|
204
|
+
cw.suffixFound &&
|
|
205
|
+
cw.suffixFoundInWallets.includes(item.address)
|
|
206
|
+
) {
|
|
207
|
+
// highlight found prefix
|
|
208
|
+
const addressCutPrefixLength =
|
|
209
|
+
cw.row.startsWith.length + cw.options.prefix.length;
|
|
210
|
+
const addressFirstPart = item.address.slice(
|
|
211
|
+
cw.row.startsWith.length,
|
|
212
|
+
addressCutPrefixLength
|
|
213
|
+
);
|
|
214
|
+
const addressLastPart = item.address.slice(
|
|
215
|
+
item.address.length - cw.options.suffix.length
|
|
134
216
|
);
|
|
135
|
-
} else if (cw.prefixFound) {
|
|
136
217
|
log(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
)}\n`
|
|
218
|
+
`👛 ${cw.row.startsWith}${magenta(
|
|
219
|
+
addressFirstPart
|
|
220
|
+
)}${item.address.substring(
|
|
221
|
+
cw.row.startsWith.length + addressFirstPart.length,
|
|
222
|
+
item.address.length - addressLastPart.length
|
|
223
|
+
)}${magenta(addressLastPart)}`
|
|
144
224
|
);
|
|
145
|
-
} else if (
|
|
225
|
+
} else if (
|
|
226
|
+
cw.prefixFound &&
|
|
227
|
+
cw.prefixFoundInWallets.includes(item.address)
|
|
228
|
+
) {
|
|
229
|
+
// highlight found prefix
|
|
230
|
+
const addressCutLength =
|
|
231
|
+
cw.row.startsWith.length + cw.options.prefix.length;
|
|
146
232
|
log(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
' wallet with "' +
|
|
151
|
-
cw.options.suffix +
|
|
152
|
-
'" suffix:'
|
|
153
|
-
)}\n`
|
|
233
|
+
`👛 ${cw.row.startsWith}${magenta(
|
|
234
|
+
item.address.slice(cw.row.startsWith.length, addressCutLength)
|
|
235
|
+
)}${item.address.slice(addressCutLength)}`
|
|
154
236
|
);
|
|
155
|
-
} else
|
|
237
|
+
} else if (
|
|
238
|
+
cw.suffixFound &&
|
|
239
|
+
cw.suffixFoundInWallets.includes(item.address)
|
|
240
|
+
) {
|
|
241
|
+
// highlight found suffix
|
|
156
242
|
log(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
243
|
+
`👛 ${item.address.slice(
|
|
244
|
+
0,
|
|
245
|
+
item.address.length - cw.options.suffix.length
|
|
246
|
+
)}${magenta(
|
|
247
|
+
item.address.slice(
|
|
248
|
+
item.address.length - cw.options.suffix.length
|
|
249
|
+
)
|
|
250
|
+
)}`
|
|
160
251
|
);
|
|
252
|
+
} else {
|
|
253
|
+
log(`👛 ${item.address}`);
|
|
161
254
|
}
|
|
162
|
-
|
|
255
|
+
log(`🔑 ${item.privateKey}`);
|
|
163
256
|
}
|
|
257
|
+
} else {
|
|
258
|
+
outputData.wallets = cw.wallet.addresses;
|
|
259
|
+
}
|
|
164
260
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
log(`🔐 ${cw.wallet.privateExtendedKey}`);
|
|
171
|
-
linesCount += 1;
|
|
172
|
-
}
|
|
173
|
-
// mnemonic
|
|
174
|
-
if (cw.wallet.mnemonic) {
|
|
175
|
-
log(`📄 ${cw.wallet.mnemonic}`);
|
|
176
|
-
linesCount += 1;
|
|
177
|
-
}
|
|
178
|
-
// addresses
|
|
179
|
-
if (displayAsText) {
|
|
180
|
-
for (const item of cw.wallet.addresses) {
|
|
181
|
-
if (cw.wallet.addresses.length > 1) {
|
|
182
|
-
log();
|
|
183
|
-
log(`🆔 ${item.index}`);
|
|
184
|
-
}
|
|
261
|
+
if (displayAsText && cw.row.path !== undefined && cw.options.geek) {
|
|
262
|
+
log();
|
|
263
|
+
log(`🗂 wallet address path: ${cw.row.path}'/0'/0/ID`);
|
|
264
|
+
linesCount += 1;
|
|
265
|
+
}
|
|
185
266
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
`👛 ${item.address.slice(
|
|
232
|
-
0,
|
|
233
|
-
item.address.length - cw.options.suffix.length
|
|
234
|
-
)}${magenta(
|
|
235
|
-
item.address.slice(
|
|
236
|
-
item.address.length - cw.options.suffix.length
|
|
237
|
-
)
|
|
238
|
-
)}`
|
|
239
|
-
);
|
|
240
|
-
} else {
|
|
241
|
-
log(`👛 ${item.address}`);
|
|
242
|
-
}
|
|
243
|
-
log(`🔑 ${item.privateKey}`);
|
|
267
|
+
// generate csv
|
|
268
|
+
if (!displayAsText) {
|
|
269
|
+
const filename =
|
|
270
|
+
cw.options.csvOutputFilename ||
|
|
271
|
+
cw.options.filename.split('.')[0] ||
|
|
272
|
+
'cw-output';
|
|
273
|
+
// eslint-disable-next-line no-undef
|
|
274
|
+
const createCsvWriter = CsvWriter.createObjectCsvWriter;
|
|
275
|
+
const csvWriter = createCsvWriter({
|
|
276
|
+
path: `${filename}.csv`,
|
|
277
|
+
header: [
|
|
278
|
+
{
|
|
279
|
+
id: 'index',
|
|
280
|
+
title: 'index',
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
id: 'address',
|
|
284
|
+
title: 'address',
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
id: 'privateKey',
|
|
288
|
+
title: 'privateKey',
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
});
|
|
292
|
+
csvWriter
|
|
293
|
+
.writeRecords(outputData.wallets)
|
|
294
|
+
.then(() =>
|
|
295
|
+
log(
|
|
296
|
+
`${linesCount > 0 ? '\n' : ''}🟠 ${yellow(
|
|
297
|
+
`Don't forget to save the data above manually, because it is not in the output file`
|
|
298
|
+
)} \n✨ ${green('Done!')} ${blueBright(
|
|
299
|
+
`The output successfully saved into "./${filename}.csv" file`
|
|
300
|
+
)}`
|
|
301
|
+
)
|
|
302
|
+
)
|
|
303
|
+
.catch(() =>
|
|
304
|
+
log(
|
|
305
|
+
`${linesCount > 0 ? '\n' : ''}⛔️ ${red(
|
|
306
|
+
`Error: failed to generate a file`
|
|
307
|
+
)}`
|
|
308
|
+
)
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
244
312
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
313
|
+
if (displayAsText) {
|
|
314
|
+
if (
|
|
315
|
+
cw.row.formats !== undefined ||
|
|
316
|
+
cw.row.network == 'EVM' ||
|
|
317
|
+
cw.row.apps ||
|
|
318
|
+
cw.wallet.tested !== undefined
|
|
319
|
+
) {
|
|
320
|
+
log();
|
|
321
|
+
}
|
|
249
322
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
323
|
+
if (cw.wallet.tested !== undefined) {
|
|
324
|
+
log(
|
|
325
|
+
red(
|
|
326
|
+
'‼️ This wallet generation format was not tested yet, do not use it!'
|
|
327
|
+
)
|
|
328
|
+
);
|
|
329
|
+
}
|
|
255
330
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
header: [
|
|
264
|
-
{
|
|
265
|
-
id: 'index',
|
|
266
|
-
title: 'index',
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
id: 'address',
|
|
270
|
-
title: 'address',
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
id: 'privateKey',
|
|
274
|
-
title: 'privateKey',
|
|
275
|
-
},
|
|
276
|
-
],
|
|
277
|
-
});
|
|
278
|
-
csvWriter
|
|
279
|
-
.writeRecords(outputData.wallets)
|
|
280
|
-
.then(() =>
|
|
281
|
-
log(
|
|
282
|
-
`${linesCount > 0 ? '\n' : ''}🟠 ${yellow(
|
|
283
|
-
`Don't forget to save the data above manually, because it is not in the output file`
|
|
284
|
-
)} \n✨ ${green('Done!')} ${blueBright(
|
|
285
|
-
`The output successfully saved into "./${filename}.csv" file`
|
|
286
|
-
)}`
|
|
287
|
-
)
|
|
288
|
-
)
|
|
289
|
-
.catch(() =>
|
|
290
|
-
log(
|
|
291
|
-
`${linesCount > 0 ? '\n' : ''}⛔️ ${red(
|
|
292
|
-
`Error: failed to generate a file`
|
|
293
|
-
)}`
|
|
294
|
-
)
|
|
295
|
-
);
|
|
296
|
-
}
|
|
331
|
+
if (
|
|
332
|
+
cw.row.formats !== undefined &&
|
|
333
|
+
Object.keys(cw.row.formats).length > 1
|
|
334
|
+
) {
|
|
335
|
+
let formatsString = '';
|
|
336
|
+
for (const val of Object.keys(cw.row.formats)) {
|
|
337
|
+
formatsString += blue(val) + ', ';
|
|
297
338
|
}
|
|
339
|
+
log(
|
|
340
|
+
yellow(
|
|
341
|
+
'*️⃣ You can create different wallet formats: ' +
|
|
342
|
+
formatsString.substring(0, formatsString.length - 2) +
|
|
343
|
+
' (use it with ' +
|
|
344
|
+
white('-f') +
|
|
345
|
+
' flag)'
|
|
346
|
+
)
|
|
347
|
+
);
|
|
348
|
+
}
|
|
298
349
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
log();
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
if (cw.wallet.tested !== undefined) {
|
|
310
|
-
log(
|
|
311
|
-
red(
|
|
312
|
-
'‼️ This wallet generation format was not tested yet, do not use it!'
|
|
313
|
-
)
|
|
314
|
-
);
|
|
315
|
-
}
|
|
350
|
+
if (cw.row.network == 'EVM' || false) {
|
|
351
|
+
log(
|
|
352
|
+
yellow(
|
|
353
|
+
'🆒 You can use this wallet in Ethereum, Binance Smart Chain, Polygon and few more networks (EVM compatible)'
|
|
354
|
+
)
|
|
355
|
+
);
|
|
356
|
+
}
|
|
316
357
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
yellow(
|
|
327
|
-
'*️⃣ You can create different wallet formats: ' +
|
|
328
|
-
formatsString.substring(0, formatsString.length - 2) +
|
|
329
|
-
' (use it with ' +
|
|
330
|
-
white('-f') +
|
|
331
|
-
' flag)'
|
|
332
|
-
)
|
|
333
|
-
);
|
|
334
|
-
}
|
|
358
|
+
if (cw.row.apps !== undefined) {
|
|
359
|
+
let apps = {
|
|
360
|
+
metamask: 'MetaMask',
|
|
361
|
+
tronlink: 'TronLink',
|
|
362
|
+
trustwallet: 'Trust Wallet',
|
|
363
|
+
'harmony-chrome-ext': 'Harmony Chrome Extension Wallet',
|
|
364
|
+
'binance-chain-wallet': 'Binance Chain Wallet',
|
|
365
|
+
};
|
|
366
|
+
let appsArray = [];
|
|
335
367
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
'🆒 You can use this wallet in Ethereum, Binance Smart Chain, Polygon and few more networks (EVM compatible)'
|
|
340
|
-
)
|
|
341
|
-
);
|
|
368
|
+
for (let key of Object.keys(apps)) {
|
|
369
|
+
if (cw.row.apps.includes(key)) {
|
|
370
|
+
appsArray.push(apps[key]);
|
|
342
371
|
}
|
|
372
|
+
}
|
|
343
373
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
tronlink: 'TronLink',
|
|
348
|
-
trustwallet: 'Trust Wallet',
|
|
349
|
-
'harmony-chrome-ext': 'Harmony Chrome Extension Wallet',
|
|
350
|
-
'binance-chain-wallet': 'Binance Chain Wallet',
|
|
351
|
-
};
|
|
352
|
-
let appsArray = [];
|
|
353
|
-
|
|
354
|
-
for (let key of Object.keys(apps)) {
|
|
355
|
-
if (cw.row.apps.includes(key)) {
|
|
356
|
-
appsArray.push(apps[key]);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
let appsString = appsArray.join(', ');
|
|
361
|
-
if (cw.row.apps || false) {
|
|
362
|
-
appsString += ' and many other wallet apps';
|
|
363
|
-
}
|
|
364
|
-
log(
|
|
365
|
-
greenBright('ℹ️ You can import this wallet into ' + appsString)
|
|
366
|
-
);
|
|
367
|
-
}
|
|
374
|
+
let appsString = appsArray.join(', ');
|
|
375
|
+
if (cw.row.apps || false) {
|
|
376
|
+
appsString += ' and many other wallet apps';
|
|
368
377
|
}
|
|
369
|
-
|
|
370
|
-
|
|
378
|
+
log(greenBright('ℹ️ You can import this wallet into ' + appsString));
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
371
382
|
|
|
372
|
-
|
|
383
|
+
async init() {
|
|
384
|
+
return (this.callMethods[this.name] || this.callMethods['_'])();
|
|
373
385
|
}
|
|
374
386
|
}
|
|
375
387
|
|
package/src/Wallet.js
CHANGED
|
@@ -1,35 +1,24 @@
|
|
|
1
1
|
import { log } from './utils.js';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
const { red } = chalk;
|
|
4
3
|
import CoinKey from 'coinkey';
|
|
5
4
|
import CoinInfo from 'coininfo';
|
|
6
5
|
import bip39 from 'bip39';
|
|
7
6
|
import bip84 from 'bip84';
|
|
8
|
-
const {
|
|
9
|
-
fromMnemonic,
|
|
10
|
-
fromZPrv,
|
|
11
|
-
} = bip84;
|
|
7
|
+
const { fromMnemonic, fromZPrv } = bip84;
|
|
12
8
|
import ethereumBip from 'ethereum-bip84';
|
|
13
|
-
const {
|
|
14
|
-
|
|
15
|
-
fromZPrv: fromZPrvEthereum,
|
|
16
|
-
} = ethereumBip;
|
|
9
|
+
const { fromMnemonic: fromMnemonicEthereum, fromZPrv: fromZPrvEthereum } =
|
|
10
|
+
ethereumBip;
|
|
17
11
|
import dogecoinBip from '@yerofey/dogecoin-bip84';
|
|
18
|
-
const {
|
|
19
|
-
fromMnemonic: fromMnemonicDoge,
|
|
20
|
-
fromZPrv: fromZPrvDoge
|
|
21
|
-
} = dogecoinBip;
|
|
12
|
+
const { fromMnemonic: fromMnemonicDoge, fromZPrv: fromZPrvDoge } = dogecoinBip;
|
|
22
13
|
import litecoinBip from '@yerofey/litecoin-bip84';
|
|
23
|
-
const {
|
|
24
|
-
fromMnemonic: fromMnemonicLite,
|
|
25
|
-
fromZPrv: fromZPrvLite,
|
|
26
|
-
} = litecoinBip;
|
|
14
|
+
const { fromMnemonic: fromMnemonicLite, fromZPrv: fromZPrvLite } = litecoinBip;
|
|
27
15
|
import { Account } from 'eth-lib/lib/index.js';
|
|
28
16
|
import { Wallet as HarmonyWallet } from '@harmony-js/account';
|
|
29
17
|
import pkutils from 'ethereum-mnemonic-privatekey-utils';
|
|
30
18
|
import bCrypto from '@binance-chain/javascript-sdk/lib/crypto/index.js';
|
|
31
19
|
import tronWeb from 'tronweb';
|
|
32
20
|
import tezos from 'tezos-sign';
|
|
21
|
+
const { red } = chalk;
|
|
33
22
|
|
|
34
23
|
class Wallet {
|
|
35
24
|
constructor(cw) {
|
|
@@ -312,8 +301,9 @@ class Wallet {
|
|
|
312
301
|
};
|
|
313
302
|
}
|
|
314
303
|
|
|
315
|
-
const _fromMnemonic =
|
|
316
|
-
|
|
304
|
+
const _fromMnemonic =
|
|
305
|
+
chain == 'DOGE' ? fromMnemonicDoge : fromMnemonicLite;
|
|
306
|
+
const _fromZPrv = chain == 'DOGE' ? fromZPrvDoge : fromZPrvLite;
|
|
317
307
|
const mnemonic = mnemonicString || bip39.generateMnemonic();
|
|
318
308
|
const root = new _fromMnemonic(mnemonic, '');
|
|
319
309
|
const child = root.deriveAccount(0);
|
|
@@ -487,7 +477,4 @@ function generateMnemonicString() {
|
|
|
487
477
|
return bip39.generateMnemonic();
|
|
488
478
|
}
|
|
489
479
|
|
|
490
|
-
|
|
491
|
-
export { _generateMnemonicString as generateMnemonicString };
|
|
492
|
-
const _Wallet = Wallet;
|
|
493
|
-
export { _Wallet as Wallet };
|
|
480
|
+
export { generateMnemonicString, Wallet };
|
package/src/options.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { program } from 'commander';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
program.option('-b, --chain <ticker>', 'Wallet for specific blockchain', 'ERC');
|
|
5
|
+
program.option('-c, --chain <ticker>', 'Wallet for specific blockchain', 'ERC');
|
|
6
|
+
program.option(
|
|
7
|
+
'-D, --csv [filename]',
|
|
8
|
+
'Save result into CSV file'
|
|
9
|
+
);
|
|
10
|
+
program.option(
|
|
11
|
+
'-f, --format <format>',
|
|
12
|
+
'Wallet format type (for cryptos with multiple wallet formats)'
|
|
13
|
+
);
|
|
14
|
+
program.option(
|
|
15
|
+
'-F, --filename <filename>',
|
|
16
|
+
'Filename to output the data (works with -o argument)'
|
|
17
|
+
);
|
|
18
|
+
program.option('-g, --geek', 'Display some more info (geeky)');
|
|
19
|
+
program.option('-l, --list', 'List all supported cryptos');
|
|
20
|
+
program.option(
|
|
21
|
+
'-m, --mnemonic [mnemonic]',
|
|
22
|
+
'Generate wallet from mnemonic string OR just a mnemonic string'
|
|
23
|
+
);
|
|
24
|
+
program.option(
|
|
25
|
+
'-n, --number <number>',
|
|
26
|
+
'Number of wallets to generate (if supported)'
|
|
27
|
+
);
|
|
28
|
+
program.option('-o, --output <format>', 'Return results into some file');
|
|
29
|
+
program.option('-p, --prefix <prefix>', 'Desired wallet prefix');
|
|
30
|
+
program.option(
|
|
31
|
+
'-P, --prefix-sensitive <prefix>',
|
|
32
|
+
'Desired wallet prefix (case-sensitive)'
|
|
33
|
+
);
|
|
34
|
+
program.option('-s, --suffix <suffix>', 'Desired wallet suffix');
|
|
35
|
+
program.option(
|
|
36
|
+
'-S, --suffix-sensitive <suffix>',
|
|
37
|
+
'Desired wallet suffix (case-sensitive)'
|
|
38
|
+
);
|
|
39
|
+
program.option('-v, --version', 'Display cryptowallet version');
|
|
40
|
+
program.parse();
|
|
41
|
+
|
|
42
|
+
export const options = program.opts();
|
|
43
|
+
export const zeroOptions = Object.keys(options).length === 0;
|
package/src/utils.js
CHANGED
|
@@ -21,12 +21,8 @@ const loadFile = async (filename, defaultValue = {}) => {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const loadJson = async (filename) => {
|
|
24
|
-
return JSON.parse(
|
|
25
|
-
|
|
26
|
-
new URL(filename, import.meta.url)
|
|
27
|
-
)
|
|
28
|
-
);
|
|
29
|
-
}
|
|
24
|
+
return JSON.parse(await readFile(new URL(filename, import.meta.url)));
|
|
25
|
+
};
|
|
30
26
|
|
|
31
27
|
const objectHasAllKeys = (obj, keysArray) =>
|
|
32
28
|
// eslint-disable-next-line no-prototype-builtins
|
|
@@ -34,17 +30,11 @@ const objectHasAllKeys = (obj, keysArray) =>
|
|
|
34
30
|
|
|
35
31
|
let supportedChains = [];
|
|
36
32
|
// eslint-disable-next-line no-undef
|
|
37
|
-
const chainsFolder = `${path.dirname(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
const chainsFolder = `${path.dirname(
|
|
34
|
+
decodeURIComponent(import.meta.url)
|
|
35
|
+
)}/chains/`.replace('file://', '');
|
|
36
|
+
supportedChains = filesList(chainsFolder).map((item) =>
|
|
37
|
+
item.replace(chainsFolder, '').replace('.json', '')
|
|
38
|
+
);
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
export { _log as log };
|
|
45
|
-
export { loadFile };
|
|
46
|
-
export { loadJson };
|
|
47
|
-
const _objectHasAllKeys = objectHasAllKeys;
|
|
48
|
-
export { _objectHasAllKeys as objectHasAllKeys };
|
|
49
|
-
const _supportedChains = supportedChains;
|
|
50
|
-
export { _supportedChains as supportedChains };
|
|
40
|
+
export { log, loadFile, loadJson, objectHasAllKeys, supportedChains };
|