diff --git a/README.md b/README.md index 9dacb7d..6a6ffd7 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,7 @@ $ cw -l ## Options - `-b` or `-c` or `--chain`: Specify the blockchain ticker to generate a wallet for +- `-C` or `--copy`: Copy the generated mnemonic to the clipboard - `-D` or `--csv`: Save output into CSV file with custom or default name ("`cw-output.csv`") - this is a shorthand for `-o csv -F filename` - `-f` or `--format`: Specify the blockchain wallet format (for BTC: legacy, segwit, bech32) - `-g` or `--geek`: Display some additional "geeky" info diff --git a/cli.js b/cli.js index 9be8297..c9df005 100644 --- a/cli.js +++ b/cli.js @@ -18,7 +18,7 @@ import Method from './src/Method.js'; options.mnemonic === '' || options.mnemonic.split(' ').length === 1) ) { - return new Method('mnemonic').init({ mnemonic: options.mnemonic }); + return new Method('mnemonic').init({ mnemonic: options.mnemonic, copy: options?.copy || false }); } if (options.version) { @@ -29,7 +29,7 @@ import Method from './src/Method.js'; return new Method('donate').init(); } - const chain = options.chain.toUpperCase() || 'ETH'; + const chain = options.chain.toUpperCase() || 'ERC'; if (supportedChains.includes(chain)) { return new Method('wallet', { chain, diff --git a/package.json b/package.json index 9385038..0c0dbde 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@yerofey/cryptowallet-cli", - "version": "1.20.0", + "version": "1.21.0", "description": "Crypto wallet generator CLI tool", "type": "module", "homepage": "https://github.com/yerofey/cryptowallet-cli", @@ -114,6 +114,7 @@ "bs58": "^5.0.0", "buffer": "^6.0.3", "chalk": "5.3.0", + "clipboardy": "^4.0.0", "coininfo": "5.2.1", "coinkey": "3.0.0", "columnify": "1.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aa67970..f1acc79 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ dependencies: chalk: specifier: 5.3.0 version: 5.3.0 + clipboardy: + specifier: ^4.0.0 + version: 4.0.0 coininfo: specifier: 5.2.1 version: 5.2.1 @@ -4755,6 +4758,15 @@ packages: string-width: 5.1.2 dev: true + /clipboardy@4.0.0: + resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} + engines: {node: '>=18'} + dependencies: + execa: 8.0.1 + is-wsl: 3.1.0 + is64bit: 2.0.0 + dev: false + /cliui@6.0.0: resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} dependencies: @@ -5911,6 +5923,21 @@ packages: dev: false optional: true + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.2.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: false + /expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} @@ -6487,6 +6514,11 @@ packages: dev: false optional: true + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: false + /getenv@1.0.0: resolution: {integrity: sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg==} engines: {node: '>=6'} @@ -6790,6 +6822,11 @@ packages: dev: false optional: true + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: false + /humanize-ms@1.2.1: resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} dependencies: @@ -6956,6 +6993,12 @@ packages: dev: false optional: true + /is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + dev: false + /is-error@2.2.2: resolution: {integrity: sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==} dev: true @@ -7017,6 +7060,14 @@ packages: engines: {node: '>=6.5.0', npm: '>=3'} dev: false + /is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + dependencies: + is-docker: 3.0.0 + dev: false + /is-interactive@1.0.0: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} @@ -7074,6 +7125,11 @@ packages: dev: false optional: true + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false + /is-typedarray@1.0.0: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} dev: false @@ -7111,6 +7167,20 @@ packages: dev: false optional: true + /is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + dependencies: + is-inside-container: 1.0.0 + dev: false + + /is64bit@2.0.0: + resolution: {integrity: sha512-jv+8jaWCl0g2lSBkNSVXdzfBA0npK1HGC2KtWM9FumFRoGS94g3NbCCLVnCYHLjp4GrW2KZeeSTMo5ddtznmGw==} + engines: {node: '>=18'} + dependencies: + system-architecture: 0.1.0 + dev: false + /is_js@0.9.0: resolution: {integrity: sha512-8Y5EHSH+TonfUHX2g3pMJljdbGavg55q4jmHzghJCdqYDbdNROC8uw/YFQwIRCRqRJT1EY3pJefz+kglw+o7sg==} dev: false @@ -7854,7 +7924,6 @@ packages: /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: false - optional: true /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} @@ -8149,7 +8218,6 @@ packages: /mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - dev: true /mimic-response@1.0.1: resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} @@ -8499,6 +8567,13 @@ packages: dev: false optional: true + /npm-run-path@5.2.0: + resolution: {integrity: sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: false + /npmlog@4.1.2: resolution: {integrity: sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==} requiresBuild: true @@ -8591,6 +8666,13 @@ packages: dev: false optional: true + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: false + /open@6.4.0: resolution: {integrity: sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==} engines: {node: '>=8'} @@ -8858,6 +8940,11 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: false + /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: false @@ -9939,7 +10026,6 @@ packages: /signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - dev: true /signed-varint@2.0.1: resolution: {integrity: sha512-abgDPg1106vuZZOvw7cFwdCABddfJRz5akcCcchzTbhyhYnsG31y4AlZEgp315T7W3nQq5P4xeOm186ZiPVFzw==} @@ -10225,6 +10311,11 @@ packages: dev: false optional: true + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: false + /strip-hex-prefix@1.0.0: resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} engines: {node: '>=6.5.0', npm: '>=3'} @@ -10339,6 +10430,11 @@ packages: resolution: {integrity: sha512-YQSL4duoHmLhsTD1Pw8RW6TZ5MaTX5rXJnqacJottr2P2LZBF/Yvrc3ku4NUpMOm8aM0KOCqM+UAkMA5HWQCzQ==} dev: false + /system-architecture@0.1.0: + resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} + engines: {node: '>=18'} + dev: false + /tar-fs@2.1.1: resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} requiresBuild: true diff --git a/src/Method.js b/src/Method.js index 2eb04df..b65be14 100644 --- a/src/Method.js +++ b/src/Method.js @@ -1,6 +1,7 @@ import { config } from 'dotenv'; import path from 'node:path'; import chalk from 'chalk'; +import clipboardy from 'clipboardy'; import columnify from 'columnify'; import CsvWriter from 'csv-writer'; import { log, supportedChains, loadJson } from './utils.js'; @@ -69,6 +70,7 @@ class Method { const mnemonicLength = ['12', '18', '24'].includes(mnemonic) ? parseInt(mnemonic, 10) : 12; + const mnemonicString = generateMnemonicString(mnemonicLength); log( `✨ ${green('Done!')} ${blueBright( @@ -77,13 +79,26 @@ class Method { } words mnemonic string:` )}\n` ); - log(`📄 ${generateMnemonicString(mnemonicLength)}`); + log(`📄 ${mnemonicString}`); + // copy to clipboard if flag is set + if (this.inputOptions.copy) { + clipboardy.writeSync(mnemonicString); + log(`📋 ${green('Mnemonic copied to your clipboard!')}`); + } log(); log( greenBright( 'ℹī¸ You can import it into your favorite wallet app or use it to generate a wallet with "-m" flag' ) ); + + // donation + log(); + log( + blueBright( + '🙏 Consider supporting this project - check donations options with: cw --donate' + ) + ); } _version() { @@ -199,6 +214,7 @@ class Method { if (displayAsText) { // display addresses + let index = 0; for (const item of cw.wallet.addresses) { if (cw.wallet.addresses.length > 1) { log(); @@ -350,6 +366,13 @@ class Method { if (item.privateKey !== undefined) { log(`🔑 ${item.privateKey}`); } + // copy to clipboard if flag is set + if (cw.options.copy && cw.wallet.mnemonic !== undefined && index == 0) { + clipboardy.writeSync(cw.wallet.mnemonic); + log(`📋 ${green('Mnemonic copied to your clipboard!')}`); + } + + index += 1; } // tested @@ -418,7 +441,7 @@ class Method { } } - // formats, network, apps + // formats, network, apps, attempts, donation if (displayAsText) { if ( cw.row.formats !== undefined || @@ -468,6 +491,7 @@ class Method { ); } + // apps if (cw.row.apps !== undefined) { let apps = { metamask: 'MetaMask', diff --git a/src/options.js b/src/options.js index 19fb1ba..740e67a 100644 --- a/src/options.js +++ b/src/options.js @@ -3,6 +3,7 @@ import { program } from 'commander'; program.option('-b, --chain ', 'Wallet for specific blockchain', 'ERC'); program.option('-c, --chain ', 'Wallet for specific blockchain', 'ERC'); +program.option('-C, --copy', 'Copy the result to the clipboard'); program.option( '-D, --csv [filename]', 'Save result into CSV file'