@yerofey/cryptowallet-cli 1.5.3 → 1.6.2

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 CHANGED
@@ -11,8 +11,12 @@
11
11
  # via Yarn
12
12
  $ yarn global add @yerofey/cryptowallet-cli
13
13
 
14
- # or via NPM
14
+ # via NPM
15
15
  $ npm i -g @yerofey/cryptowallet-cli
16
+
17
+ # via Homebrew
18
+ $ brew tap yerofey/cryptowallet && brew install cryptowallet
19
+ # (it is building from scratch, so might took a while - like a minute or so)
16
20
  ```
17
21
 
18
22
  ## Usage
@@ -53,6 +57,9 @@ $ cw -c BNB -f BEP2 -m "radio bright pizza pluck family crawl palm flame forget
53
57
  # generate BNB (BEP20) wallet from mnemonic string
54
58
  $ cw -c BNB -f BEP20 -m "radio bright pizza pluck family crawl palm flame forget focus stock stadium"
55
59
 
60
+ # generate few wallets and save the output into a file
61
+ $ cw -c btc -n 10 -o csv -F out.csv
62
+
56
63
  # generate just a mnemonic string (12 words) to import in any wallet app
57
64
  $ cw -m
58
65
 
@@ -91,16 +98,26 @@ $ cw -l
91
98
  ## Options
92
99
  * `-b` or `-c` or `--chain`: Specify the blockchain ticker to generate a wallet for
93
100
  * `-f` or `--format`: Specify the blockchain wallet format (for BTC: legacy, segwit, bech32)
101
+ * `-F` or `--filename`: Specify a filename (without extension) to output the data (works only with `-o` argument)
94
102
  * `-g` or `--geek`: Display some additional "geeky" info
95
103
  * `-l` or `--list`: List all supported blockchains
96
104
  * `-m` or `--mnemonic`: Use a bip39 mnemonic phrase (if is set) to generate wallet, or leave it empty to generate new one
97
105
  * `-n` or `--number`: Specify number of wallets to display (works for HD wallets only, like BTC/LTC/DOGE)
106
+ * `-o` or `--output`: Specify a file format (currently only `csv` supported) to output the generated data
98
107
  * `-p` or `--prefix`: Specify desired prefix for the wallet address (**case-insensitive**)
99
108
  * `-P` or `--prefix-sensitive`: Specify desired prefix of the wallet address (**case-sensitive**)
100
109
  * `-s` or `--suffix`: Specify desired suffix for the wallet address (**case-insensitive**)
101
110
  * `-S` or `--suffix-sensitive`: Specify desired suffix for the wallet address (**case-sensitive**)
102
111
  * `-v` or `--version`: Display current version of CW tool
103
112
 
113
+ ## Tested setups
114
+ * Node
115
+ - [x] v16.12.0
116
+ * NPM
117
+ - [x] v8.1.0
118
+ * Yarn
119
+ - [x] v1.23.0
120
+
104
121
  ## Highlights
105
122
  - 24+ blockchains supported
106
123
  - Generate wallet with desired prefix/suffix
package/cli.js CHANGED
@@ -9,10 +9,12 @@ const Method = require('./src/Method');
9
9
  program.option('-b, --chain <ticker>', 'Wallet for specific blockchain', 'ERC');
10
10
  program.option('-c, --chain <ticker>', 'Wallet for specific blockchain', 'ERC');
11
11
  program.option('-f, --format <format>', 'Wallet format type (for cryptos with multiple wallet formats)');
12
+ program.option('-F, --filename <filename>', 'Filename to output the data (works with -o argument)');
12
13
  program.option('-g, --geek', 'Display some more info (geeky)');
13
14
  program.option('-l, --list', 'List all supported cryptos');
14
15
  program.option('-m, --mnemonic [mnemonic]', 'Generate wallet from mnemonic string OR just a mnemonic string');
15
16
  program.option('-n, --number <number>', 'Number of wallets to generate (if supported)');
17
+ program.option('-o, --output <format>', 'Return results into some file');
16
18
  program.option('-p, --prefix <prefix>', 'Desired wallet prefix');
17
19
  program.option('-P, --prefix-sensitive <prefix>', 'Desired wallet prefix (case-sensitive)');
18
20
  program.option('-s, --suffix <suffix>', 'Desired wallet suffix');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yerofey/cryptowallet-cli",
3
- "version": "1.5.3",
3
+ "version": "1.6.2",
4
4
  "homepage": "https://github.com/yerofey/cryptowallet-cli",
5
5
  "author": "Yerofey S. <pm@yerofey.dev> (https://github.com/yerofey)",
6
6
  "bin": {
@@ -11,6 +11,7 @@
11
11
  "node": ">=6"
12
12
  },
13
13
  "scripts": {
14
+ "build:release": "./bin/generate.sh",
14
15
  "test": "ava"
15
16
  },
16
17
  "files": [
@@ -67,6 +68,7 @@
67
68
  "coinkey": "3.0.0",
68
69
  "columnify": "1.5.4",
69
70
  "commander": "8.1.0",
71
+ "csv-writer": "^1.6.0",
70
72
  "eth-lib": "0.1.29",
71
73
  "ethereum-bip84": "0.0.3",
72
74
  "ethereum-mnemonic-privatekey-utils": "1.0.5",
package/src/CW.js CHANGED
@@ -5,10 +5,12 @@ class CW {
5
5
  constructor(chain, options = {}) {
6
6
  const defaultValues = {
7
7
  chain: chain || options.chain || '',
8
+ filename: 'output',
8
9
  format: '',
9
10
  geek: false,
10
11
  mnemonic: '',
11
12
  number: 1,
13
+ output: undefined,
12
14
  prefix: options.prefixSensitive || '',
13
15
  prefixIsCaseSensitive: options.prefixSensitive !== undefined,
14
16
  suffix: options.suffixSensitive || '',
package/src/Method.js CHANGED
@@ -66,98 +66,158 @@ class Method {
66
66
  return;
67
67
  }
68
68
 
69
+ let linesCount = 0;
70
+ const outputFormats = ['csv'];
71
+ const displayAsText = (cw.options.output === undefined || !outputFormats.includes(cw.options.output));
72
+
69
73
  // prefix, suffix
70
- if (cw.prefixFound && cw.suffixFound) {
71
- log(`✨ ${chalk.green('Done!')} ${chalk.blueBright('Here is your brand new ' + chainFullName + ' wallet with "' + cw.options.prefix + '" prefix and "' + cw.options.suffix + '" suffix:')}\n`);
72
- } else if (cw.prefixFound) {
73
- log(`✨ ${chalk.green('Done!')} ${chalk.blueBright('Here is your brand new ' + chainFullName + ' wallet with "' + cw.options.prefix + '" prefix:')}\n`);
74
- } else if (cw.suffixFound) {
75
- log(`✨ ${chalk.green('Done!')} ${chalk.blueBright('Here is your brand new ' + chainFullName + ' wallet with "' + cw.options.suffix + '" suffix:')}\n`);
76
- } else {
77
- log(`✨ ${chalk.green('Done!')} ${chalk.blueBright('Here is your brand new ' + chainFullName + ' wallet:')}\n`);
74
+ if (displayAsText) {
75
+ if (cw.prefixFound && cw.suffixFound) {
76
+ log(`✨ ${chalk.green('Done!')} ${chalk.blueBright('Here is your brand new ' + chainFullName + ' wallet with "' + cw.options.prefix + '" prefix and "' + cw.options.suffix + '" suffix:')}\n`);
77
+ } else if (cw.prefixFound) {
78
+ log(`✨ ${chalk.green('Done!')} ${chalk.blueBright('Here is your brand new ' + chainFullName + ' wallet with "' + cw.options.prefix + '" prefix:')}\n`);
79
+ } else if (cw.suffixFound) {
80
+ log(`✨ ${chalk.green('Done!')} ${chalk.blueBright('Here is your brand new ' + chainFullName + ' wallet with "' + cw.options.suffix + '" suffix:')}\n`);
81
+ } else {
82
+ log(`✨ ${chalk.green('Done!')} ${chalk.blueBright('Here is your brand new ' + chainFullName + ' wallet:')}\n`);
83
+ }
84
+ linesCount += 1;
78
85
  }
79
-
86
+
80
87
  // result
88
+ let outputData = {};
81
89
  if (cw.wallet.addresses !== undefined) {
90
+ // private key
82
91
  if (cw.wallet.privateExtendedKey) {
83
92
  log(`🔐 ${cw.wallet.privateExtendedKey}`);
93
+ linesCount += 1;
84
94
  }
95
+ // mnemonic
85
96
  if (cw.wallet.mnemonic) {
86
97
  log(`📄 ${cw.wallet.mnemonic}`);
98
+ linesCount += 1;
87
99
  }
88
-
100
+ // addresses
89
101
  for (const item of cw.wallet.addresses) {
90
- if (cw.wallet.addresses.length > 1) {
91
- log();
92
- log(`🆔 ${item.index}`);
93
- }
94
-
95
- if (cw.prefixFound && cw.prefixFoundInWallets.includes(item.address) && cw.suffixFound && cw.suffixFoundInWallets.includes(item.address)) {
96
- // highlight found prefix
97
- const addressCutPrefixLength = cw.row.startsWith.length + cw.options.prefix.length;
98
- const addressFirstPart = item.address.slice(cw.row.startsWith.length, addressCutPrefixLength);
99
- const addressLastPart = item.address.slice(item.address.length - cw.options.suffix.length);
100
- log(`👛 ${cw.row.startsWith}${chalk.magenta(addressFirstPart)}${item.address.substring(cw.row.startsWith.length + addressFirstPart.length, item.address.length - addressLastPart.length)}${chalk.magenta(addressLastPart)}`);
101
- } else if (cw.prefixFound && cw.prefixFoundInWallets.includes(item.address)) {
102
- // highlight found prefix
103
- const addressCutLength = cw.row.startsWith.length + cw.options.prefix.length;
104
- log(`👛 ${cw.row.startsWith}${chalk.magenta(item.address.slice(cw.row.startsWith.length, addressCutLength))}${item.address.slice(addressCutLength)}`);
105
- } else if (cw.suffixFound && cw.suffixFoundInWallets.includes(item.address)) {
106
- // highlight found suffix
107
- log(`👛 ${item.address.slice(0, item.address.length - cw.options.suffix.length)}${chalk.magenta(item.address.slice(item.address.length - cw.options.suffix.length))}`);
102
+ if (displayAsText) {
103
+ if (cw.wallet.addresses.length > 1) {
104
+ log();
105
+ log(`🆔 ${item.index}`);
106
+ }
107
+
108
+ if (cw.prefixFound && cw.prefixFoundInWallets.includes(item.address) && cw.suffixFound && cw.suffixFoundInWallets.includes(item.address)) {
109
+ // highlight found prefix
110
+ const addressCutPrefixLength = cw.row.startsWith.length + cw.options.prefix.length;
111
+ const addressFirstPart = item.address.slice(cw.row.startsWith.length, addressCutPrefixLength);
112
+ const addressLastPart = item.address.slice(item.address.length - cw.options.suffix.length);
113
+ log(`👛 ${cw.row.startsWith}${chalk.magenta(addressFirstPart)}${item.address.substring(cw.row.startsWith.length + addressFirstPart.length, item.address.length - addressLastPart.length)}${chalk.magenta(addressLastPart)}`);
114
+ } else if (cw.prefixFound && cw.prefixFoundInWallets.includes(item.address)) {
115
+ // highlight found prefix
116
+ const addressCutLength = cw.row.startsWith.length + cw.options.prefix.length;
117
+ log(`👛 ${cw.row.startsWith}${chalk.magenta(item.address.slice(cw.row.startsWith.length, addressCutLength))}${item.address.slice(addressCutLength)}`);
118
+ } else if (cw.suffixFound && cw.suffixFoundInWallets.includes(item.address)) {
119
+ // highlight found suffix
120
+ log(`👛 ${item.address.slice(0, item.address.length - cw.options.suffix.length)}${chalk.magenta(item.address.slice(item.address.length - cw.options.suffix.length))}`);
121
+ } else {
122
+ log(`👛 ${item.address}`);
123
+ }
124
+ log(`🔑 ${item.privateKey}`);
108
125
  } else {
109
- log(`👛 ${item.address}`);
126
+ // const createCsvWriter = csvWriter.createObjectCsvWriter;
127
+ // const csvWriter = createCsvWriter({
128
+ // path: 'out.csv',
129
+ // header: [
130
+ // {id: 'name', title: 'Name'},
131
+ // {id: 'surname', title: 'Surname'},
132
+ // {id: 'age', title: 'Age'},
133
+ // {id: 'gender', title: 'Gender'},
134
+ // ]
135
+ // });
136
+ // // TODO: build output into file
137
+ // log('TODO_BUILD_OUTPUT_INTO_FILE', item.address);
110
138
  }
111
- log(`🔑 ${item.privateKey}`);
139
+ }
140
+ if (!displayAsText) {
141
+ outputData.wallets = cw.wallet.addresses;
112
142
  }
113
143
 
114
- if (cw.row.path !== undefined && cw.options.geek) {
144
+ if (displayAsText && cw.row.path !== undefined && cw.options.geek) {
115
145
  log();
116
146
  log(`🗂 wallet address path: ${cw.row.path}'/0'/0/ID`);
147
+ linesCount += 1;
117
148
  }
118
- }
119
-
120
- if (cw.row.formats !== undefined || cw.row.network == 'EVM' || cw.row.apps || cw.wallet.tested !== undefined) {
121
- log();
122
- }
123
149
 
124
- if (cw.wallet.tested !== undefined) {
125
- log(chalk.red('‼️ This wallet generation format was not tested yet, do not use it!'));
126
- }
127
-
128
- if (cw.row.formats !== undefined && Object.keys(cw.row.formats).length > 1) {
129
- let formatsString = '';
130
- for (const val of Object.keys(cw.row.formats)) {
131
- formatsString += chalk.blue(val) + ', ';
150
+ // generate csv
151
+ if (!displayAsText) {
152
+ const filename = (cw.options.filename.split('.')[0]) ?? 'output';
153
+ const createCsvWriter = require('csv-writer').createObjectCsvWriter;
154
+ const csvWriter = createCsvWriter({
155
+ path: `${filename}.csv`,
156
+ header: [
157
+ {
158
+ id: 'index',
159
+ title: 'index',
160
+ },
161
+ {
162
+ id: 'address',
163
+ title: 'address',
164
+ },
165
+ {
166
+ id: 'privateKey',
167
+ title: 'privateKey',
168
+ },
169
+ ]
170
+ });
171
+ csvWriter
172
+ .writeRecords(outputData.wallets)
173
+ .then(()=> log(`${linesCount > 0 ? "\n" : ''}⚠️ ${chalk.yellow(`Don\'t forget to save the data above manually, because it is not in the output file`)} \n✨ ${chalk.green('Done!')} ${chalk.blueBright(`The output successfully saved into "${filename}.csv" file`)}`))
174
+ .catch(() => log(`${linesCount > 0 ? "\n" : ''}⛔️ ${chalk.red(`Error: failed to generate a file`)}`));
132
175
  }
133
- log(chalk.yellow('*️⃣ You can create different wallet formats: ' + formatsString.substring(0, formatsString.length - 2) + ' (use it with ' + chalk.white('-f') + ' flag)'));
134
176
  }
135
177
 
136
- if (cw.row.network == 'EVM' || false) {
137
- log(chalk.yellow('🆒 You can use this wallet in Ethereum, Binance Smart Chain, Polygon and few more networks (EVM compatible)'));
138
- }
178
+ if (displayAsText) {
179
+ if (cw.row.formats !== undefined || cw.row.network == 'EVM' || cw.row.apps || cw.wallet.tested !== undefined) {
180
+ log();
181
+ }
139
182
 
140
- if (cw.row.apps !== undefined) {
141
- let apps = {
142
- "metamask": "MetaMask",
143
- "tronlink": "TronLink",
144
- "trustwallet": "Trust Wallet",
145
- "harmony-chrome-ext": "Harmony Chrome Extension Wallet",
146
- "binance-chain-wallet": "Binance Chain Wallet"
183
+ if (cw.wallet.tested !== undefined) {
184
+ log(chalk.red('‼️ This wallet generation format was not tested yet, do not use it!'));
147
185
  }
148
- let appsArray = [];
149
186
 
150
- for (let key of Object.keys(apps)) {
151
- if (cw.row.apps.includes(key)) {
152
- appsArray.push(apps[key]);
187
+ if (cw.row.formats !== undefined && Object.keys(cw.row.formats).length > 1) {
188
+ let formatsString = '';
189
+ for (const val of Object.keys(cw.row.formats)) {
190
+ formatsString += chalk.blue(val) + ', ';
153
191
  }
192
+ log(chalk.yellow('*️⃣ You can create different wallet formats: ' + formatsString.substring(0, formatsString.length - 2) + ' (use it with ' + chalk.white('-f') + ' flag)'));
193
+ }
194
+
195
+ if (cw.row.network == 'EVM' || false) {
196
+ log(chalk.yellow('🆒 You can use this wallet in Ethereum, Binance Smart Chain, Polygon and few more networks (EVM compatible)'));
154
197
  }
155
198
 
156
- let appsString = appsArray.join(', ');
157
- if (cw.row.apps || false) {
158
- appsString += ' and many other wallet apps';
199
+ if (cw.row.apps !== undefined) {
200
+ let apps = {
201
+ "metamask": "MetaMask",
202
+ "tronlink": "TronLink",
203
+ "trustwallet": "Trust Wallet",
204
+ "harmony-chrome-ext": "Harmony Chrome Extension Wallet",
205
+ "binance-chain-wallet": "Binance Chain Wallet"
206
+ }
207
+ let appsArray = [];
208
+
209
+ for (let key of Object.keys(apps)) {
210
+ if (cw.row.apps.includes(key)) {
211
+ appsArray.push(apps[key]);
212
+ }
213
+ }
214
+
215
+ let appsString = appsArray.join(', ');
216
+ if (cw.row.apps || false) {
217
+ appsString += ' and many other wallet apps';
218
+ }
219
+ log(chalk.greenBright('ℹ️ You can import this wallet into ' + appsString));
159
220
  }
160
- log(chalk.greenBright('ℹ️ You can import this wallet into ' + appsString));
161
221
  }
162
222
  }
163
223
  }