├── package.json ├── banner.js ├── README.md └── index.js /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sui-wallet-generator-fixed", 3 | "version": "1.1.0", 4 | "description": "A script to generate multiple Sui wallets (Address, Base64 PrivateKey, Mnemonic) with console output and file saving.", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "start": "node index.js", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [ 12 | "sui", 13 | "wallet", 14 | "generator", 15 | "crypto", 16 | "blockchain", 17 | "mnemonic", 18 | "private key", 19 | "mysten" 20 | ], 21 | "author": "Shashi (Updated by AI)", 22 | "license": "MIT", 23 | "dependencies": { 24 | "@mysten/sui.js": "^0.54.1", 25 | "bip39": "^3.1.0", 26 | "chalk": "^5.3.0", 27 | "moment": "^2.30.1", 28 | "readline-sync": "^1.4.10", 29 | "buffer": "^6.0.3" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /banner.js: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | 3 | // ASCII Art Banner for the EVM Wallet Generator 4 | export const banner = ` 5 | 6 | 7 | ██████╗ ██╗ ██╗ ███████╗ 8 | ██╔════╝ ██║ ██║ ██╔════╝ 9 | ██║ ██║ █╗ ██║ ███████╗ 10 | ██║ ██║███╗██║ ╚════██║ 11 | ╚██████╗ ╚███╔███╔╝ ███████║ 12 | ╚═════╝ ╚══╝╚══╝ ╚══════╝ 13 | 14 | -___________________________________________________________________________- 15 | 16 | ✦ ${chalk.magentaBright('--- SUI WALLET GENERATOR ---')} ✦ 17 | ➥ ${chalk.cyan('Telegram Channel:')} ${chalk.underline.blue('https://t.me/crypto_with_shashi')} 18 | ➥ ${chalk.cyan('Twitter Handle:')} ${chalk.underline.blue('https://x.com/SHASHI522004')} 19 | ➥ ${chalk.cyan('Github:')} ${chalk.underline.blue('https://github.com/cryptowithshashi')} 20 | `; 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # SUI WALLET GENERATOR GUIDE 3 | 4 | A simple and user-friendly Node.js script designed to generate multiple sui wallets. 5 | 6 | It generates and displays the Public Key (Address), the Private Key, and the Mnemonic Recovery Phrase for each wallet in a clean box format in your console. Credentials are also saved locally to a text file. 7 | 8 | # Features 9 | 10 | - Instantly create multiple crypto wallets in one go. 11 | 12 | - Neatly organized wallet details (Address, Private Key, and Secret Phrase). 13 | 14 | - Automatically saves all wallet details in a file for easy access. 15 | 16 | # Pre Requisites 17 | 18 | - Ensure Git, Node.js, and npm are installed. If not, install them using your VPS distribution's package manager. 19 | 20 | ```bash 21 | sudo apt update 22 | ``` 23 | ```bash 24 | sudo apt install git nodejs npm -y 25 | ``` 26 | # INSTALLATION GUIDE 27 | 28 | Install Dependencies 29 | 30 | ```bash 31 | sudo apt update && sudo apt upgrade -y 32 | sudo apt install -y git nodejs npm 33 | ``` 34 | 35 | Clone Repository 36 | 37 | ```bash 38 | git clone https://github.com/cryptowithshashi/SUI-WALLET-GENERATOR.git 39 | ``` 40 | 41 | ```bash 42 | cd SUI-WALLET-GENERATOR 43 | ``` 44 | 45 | Install Packages 46 | 47 | ```bash 48 | npm install 49 | ``` 50 | Execute the code 51 | 52 | ```bash 53 | node index.js 54 | ``` 55 | 56 | Use this command to check your wallet's info 57 | 58 | ```bash 59 | nano sui_wallets_output.txt 60 | ``` 61 | 62 | If you found error in your terminal is due to PowerShell's execution policy restricting script execution. You can enable script execution by running the following command in PowerShell as an administrator 63 | 64 | ```bash 65 | Set-ExecutionPolicy Unrestricted -Scope CurrentUser 66 | ``` 67 | 68 | If prompted, type A (for Yes to All) and press Enter. Now, try running your npm install command again. 69 | 70 | Enter number of wallets when prompted 71 | find saved wallets in solana_wallet_outputs.txt 72 | DELETE solana_wallet_outputs.txt from VPS after download. Store mnemonics in encrypted storage 73 | Never expose private keys online 74 | Maintain offline backups 75 | 76 | DISCLAIMER -- This tool is provided "as-is" for educational purposes. The developers assume no responsibility for lost funds or security breaches. Always audit generated wallets before mainnet use. 77 | 78 | ABOUT ME 79 | 80 | Twitter -- https://x.com/SHASHI522004 81 | 82 | Github -- https://github.com/cryptowithshashi 83 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | // Import necessary classes from Sui SDK and bip39 3 | import { Ed25519Keypair } from '@mysten/sui.js/keypairs/ed25519'; 4 | import { generateMnemonic } from 'bip39'; // Import bip39 for mnemonic generation 5 | import { appendFileSync } from 'fs'; 6 | import moment from 'moment'; 7 | import readlineSync from 'readline-sync'; 8 | import { Buffer } from 'buffer'; 9 | import { banner } from './banner.js'; // Assuming banner.js exists 10 | 11 | // --- Configuration --- 12 | const WALLET_FILE = './sui_wallets_output.txt'; // Output filename 13 | const BOX_WIDTH = 110; // Adjust if needed 14 | 15 | // --- Helper Functions --- 16 | 17 | /** 18 | * Creates a new random Sui Ed25519 keypair and extracts details. 19 | * Generates mnemonic first, then derives the keypair. 20 | * @returns {{publicKey: string, privateKey: string, mnemonic: string}} Wallet details. 21 | * publicKey is the Sui Address. 22 | * privateKey is the Base64 encoded secret key bytes. 23 | */ 24 | function generateNewSuiWallet() { 25 | try { 26 | // 1. Generate a new mnemonic phrase 27 | const mnemonicPhrase = generateMnemonic(); 28 | 29 | // 2. Derive the Ed25519 keypair from the mnemonic 30 | // Using the default derivation path for Sui (m/44'/784'/0'/0'/0') 31 | const keypair = Ed25519Keypair.deriveKeypair(mnemonicPhrase); 32 | 33 | // 3. Get the Sui address (derived from the public key) 34 | const suiAddress = keypair.getPublicKey().toSuiAddress(); 35 | 36 | // 4. Get the raw secret key bytes 37 | const secretKeyBytes = keypair.getSecretKey(); 38 | 39 | // 5. Encode the raw secret key bytes to Base64 string 40 | const privateKeyBase64 = Buffer.from(secretKeyBytes).toString('base64'); 41 | 42 | return { 43 | publicKey: suiAddress, 44 | privateKey: privateKeyBase64, // Base64 encoded secret key 45 | mnemonic: mnemonicPhrase, // The recovery phrase 46 | }; 47 | } catch (error) { 48 | console.error(chalk.red('Error during keypair generation:'), error); 49 | // Return null or throw error to indicate failure 50 | return null; 51 | } 52 | } 53 | 54 | 55 | /** 56 | * Displays wallet details in a formatted box to the console. 57 | * @param {object} walletData - Wallet data {publicKey, privateKey, mnemonic}. 58 | * @param {number} walletNumber - The sequential number of the wallet generated. 59 | */ 60 | function displayWalletInfoBox(walletData, walletNumber) { 61 | const topBorder = '┌' + '─'.repeat(BOX_WIDTH - 2) + '┐'; 62 | const bottomBorder = '└' + '─'.repeat(BOX_WIDTH - 2) + '┘'; 63 | const separator = '├' + '─'.repeat(BOX_WIDTH - 2) + '┤'; 64 | 65 | const formatLine = (label, value, color = chalk.white) => { 66 | const prefix = `│ ${label}: `; 67 | const maxContentLength = BOX_WIDTH - 4; // Account for borders and spaces 68 | const availableValueWidth = maxContentLength - (label.length + 2); // Width available for the value itself 69 | 70 | // Handle potential undefined/null values gracefully before accessing length 71 | let displayValue = (typeof value === 'string' || typeof value === 'number') ? String(value) : 'ERROR: MISSING VALUE'; 72 | 73 | // Truncate if necessary (less likely with adjusted width calculation) 74 | if (displayValue.length > availableValueWidth) { 75 | displayValue = displayValue.substring(0, availableValueWidth - 3) + '...'; 76 | } 77 | 78 | const lineContent = prefix + displayValue; 79 | // Calculate padding based on the actual length of the displayed content 80 | const paddingCount = Math.max(0, BOX_WIDTH - (lineContent.length - prefix.length + label.length + 4)); // Adjust padding calculation 81 | const padding = ' '.repeat(paddingCount); 82 | 83 | return color(`│ ${label}: ${displayValue}` + padding + ' │'); // Reconstruct line 84 | }; 85 | 86 | 87 | console.log(chalk.cyan(topBorder)); 88 | console.log(formatLine(`Wallet #${walletNumber}`, `(${moment().format('YYYY-MM-DD HH:mm:ss')})`, chalk.cyan.bold)); 89 | console.log(chalk.cyan(separator)); 90 | // Ensure labels have consistent padding for alignment 91 | console.log(formatLine('Sui Address ', walletData.publicKey, chalk.green)); 92 | console.log(formatLine('Private Key (B64) ', walletData.privateKey, chalk.red)); 93 | console.log(formatLine('Mnemonic Phrase ', walletData.mnemonic, chalk.magenta)); 94 | console.log(chalk.cyan(bottomBorder)); 95 | console.log(''); 96 | } 97 | 98 | /** 99 | * Saves wallet details (Sui Address, Base64 PrivKey, Mnemonic) to a file. 100 | * @param {object} walletData - {publicKey, privateKey, mnemonic}. 101 | */ 102 | function saveWalletToFile(walletData) { 103 | // Updated file content format for Sui 104 | const fileContent = `SuiAddress: ${walletData.publicKey} | PrivateKey(Base64): ${walletData.privateKey} | Mnemonic: ${walletData.mnemonic}\n`; 105 | try { 106 | appendFileSync(WALLET_FILE, fileContent); 107 | } catch (writeError) { 108 | console.error(chalk.red(`Error writing to file ${WALLET_FILE}:`), writeError); 109 | } 110 | } 111 | 112 | // --- Main Execution Logic (Async IIFE) --- 113 | (async () => { 114 | // 1. Display Banner 115 | console.log(banner); // Make sure banner.js provides the 'banner' export 116 | 117 | try { 118 | // 2. Get User Input 119 | const numberOfWalletsInput = readlineSync.question( 120 | chalk.yellow('Number of Sui wallets to generate: ') 121 | ); 122 | const requestedCount = parseInt(numberOfWalletsInput, 10); 123 | 124 | if (isNaN(requestedCount) || requestedCount <= 0) { 125 | console.log(chalk.red('Invalid input. Please enter a positive number.')); 126 | return; 127 | } 128 | 129 | console.log(chalk.cyan(`\nGenerating ${requestedCount} Sui wallet(s)...`)); 130 | 131 | // 3. Generate Wallets in a Loop 132 | let successCount = 0; 133 | for (let i = 1; i <= requestedCount; i++) { 134 | const newWallet = generateNewSuiWallet(); // Use updated function 135 | 136 | if (newWallet && newWallet.publicKey && newWallet.privateKey && newWallet.mnemonic) { 137 | displayWalletInfoBox(newWallet, i); 138 | saveWalletToFile(newWallet); 139 | successCount++; 140 | } else { 141 | console.log(chalk.red(`[${moment().format('HH:mm:ss')}] ERROR: Failed to generate Sui wallet #${i}. Check console for details.`)); 142 | // Optional: Stop execution if one fails, or continue 143 | // return; 144 | } 145 | } 146 | 147 | // 4. Final Confirmation Message 148 | if (successCount > 0) { 149 | console.log( 150 | chalk.greenBright( 151 | `\n✅ Success! ${successCount} Sui wallet(s) generated.` 152 | ) 153 | ); 154 | console.log( 155 | chalk.green( 156 | `Wallet details (Sui Address, PrivateKey Base64, Mnemonic) saved to ${chalk.bold(WALLET_FILE)}.` 157 | ) 158 | ); 159 | console.log(chalk.yellow.bold("\n⚠️ IMPORTANT: Secure BOTH your Mnemonic Phrase and your Base64 Private Key.")) 160 | console.log(chalk.yellow.bold(" The Mnemonic Phrase is essential for recovery in most Sui wallets.")) 161 | console.log(chalk.yellow.bold(" Treat these credentials as extremely sensitive! Do NOT share them!")) 162 | } else { 163 | console.log(chalk.red(`\n❌ Failed to generate any wallets. Please check errors above.`)); 164 | } 165 | 166 | } catch (error) { 167 | console.error(chalk.red('\n❌ An unexpected error occurred during script execution:')); 168 | console.error(chalk.red(error.message || error)); 169 | if (error.stack) { 170 | console.error(chalk.gray(error.stack)); 171 | } 172 | } 173 | })(); // End of IIFE 174 | --------------------------------------------------------------------------------