A TypeScript implementation of a Solana vanity address generator using the official @solana/web3.js library. This educational tool generates cryptographically secure Solana keypairs where the public address matches your desired prefix and/or suffix pattern.
This tool generates private keys for cryptocurrency wallets. Please understand:
- Never share your generated keypair files with anyone
- Store backups in secure locations
- Never commit keypair files to version control
- The keypair file contains your private key - losing it means losing access to your funds
- 🔐 Secure Generation: Uses
@solana/web3.jsKeypair.generate() with cryptographically secure randomness - 🎯 Prefix & Suffix Matching: Find addresses that start and/or end with your pattern
- 🔠 Case Insensitive: Optional case-insensitive matching
- 📁 Solana CLI Compatible: Output format works with
solana config set --keypair - 🔒 Secure File Permissions: Keypair files created with 0600 permissions
- ✅ File Verification: Verifies written files for integrity
- 📊 Progress Reporting: Real-time feedback on generation progress
# Clone the repository
git clone https://github.com/hippopotomonstrosesquippedaliophobi/solana-vanity-address.git
cd solana-vanity-address/typescript
# Install dependencies
npm install
# Build the project
npm run build# Generate an address starting with "So"
npm start -- --prefix So
# Generate an address ending with "na"
npm start -- --suffix na
# Case-insensitive matching
npm start -- --prefix sol --ignore-case
# Both prefix and suffix
npm start -- --prefix So --suffix na
# Specify output file
npm start -- --prefix So --output my-keypair.json
# Show all options
npm start -- --helpimport { VanityGenerator, saveKeypair } from 'solana-vanity-ts';
async function main() {
// Create a generator
const generator = new VanityGenerator({
prefix: 'So',
onProgress: (attempts, rate) => {
console.log(`${attempts} attempts, ${rate}/sec`);
},
});
// Generate the address
const result = await generator.generate();
console.log(`Found: ${result.publicKey}`);
console.log(`Attempts: ${result.attempts}`);
// Save securely
await saveKeypair(result.secretKey, `${result.publicKey}.json`);
}
main();| Option | Short | Description |
|---|---|---|
--prefix <string> |
-p |
Address prefix to search for (Base58 characters) |
--suffix <string> |
-s |
Address suffix to search for (Base58 characters) |
--ignore-case |
-i |
Enable case-insensitive matching |
--output <file> |
-o |
Output file path (default: <address>.json) |
--max-attempts <n> |
-m |
Maximum attempts before giving up |
--verbose |
-v |
Show detailed progress |
--overwrite |
Overwrite existing output file | |
--security-check |
Run security checks before generation | |
--help |
-h |
Show help |
--version |
-V |
Show version |
# Show information about vanity addresses
npm start -- info
# Validate a pattern
npm start -- validate "Sol"Solana addresses use Base58 encoding. Valid characters are:
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
Excluded characters (to avoid confusion):
0(zero)O(uppercase O)I(uppercase I)l(lowercase L)
Finding a vanity address becomes exponentially harder with each additional character:
| Characters | Expected Attempts | Est. Time (~15K/sec) |
|---|---|---|
| 1 | 58 | < 1 second |
| 2 | 3,364 | < 1 second |
| 3 | 195,112 | ~13 seconds |
| 4 | 11,316,496 | ~12 minutes |
| 5 | 656,356,768 | ~12 hours |
| 6 | 38,068,692,544 | ~29 days |
Note: These are statistical averages. Actual time may vary.
import { VanityGenerator } from 'solana-vanity-ts';
const generator = new VanityGenerator({
prefix?: string; // Address prefix to match
suffix?: string; // Address suffix to match
ignoreCase?: boolean; // Case-insensitive matching (default: false)
maxAttempts?: number; // Maximum attempts before giving up
onProgress?: (attempts: number, rate: number) => void;
});
// Generate an address
const result = await generator.generate();
// result.publicKey - The matching address (string)
// result.secretKey - The secret key (Uint8Array)
// result.attempts - Number of attempts made
// result.duration - Time taken in millisecondsimport { saveKeypair } from 'solana-vanity-ts';
await saveKeypair(secretKey, outputPath, {
overwrite?: boolean; // Overwrite existing file (default: false)
verify?: boolean; // Verify file after writing (default: true)
});import {
validatePrefix,
validateSuffix,
isValidBase58Char,
estimateAttempts,
} from 'solana-vanity-ts';
// Validate a prefix
const result = validatePrefix('Sol');
if (!result.valid) {
console.log(result.errors);
}
// Check a single character
const isValid = isValidBase58Char('S'); // true
const isInvalid = isValidBase58Char('0'); // false
// Estimate difficulty
const attempts = estimateAttempts('Sol'); // 195112See the examples/ directory:
- basic-usage.ts - Simple generation example
- with-worker-threads.ts - Parallel generation using worker threads
- batch-generation.ts - Generate multiple addresses
Run examples with:
npx ts-node examples/basic-usage.ts# Run all tests
npm test
# Run with coverage
npm run test:coverage
# Watch mode
npm run test:watch# Lint code
npm run lint
# Fix lint issues
npm run lint:fix
# Check formatting
npm run format:check
# Format code
npm run format
# Type check
npm run typecheck# Build TypeScript
npm run build
# Clean build artifacts
npm run cleanThe TypeScript implementation achieves approximately 15,000-20,000 attempts per second on modern hardware.
For faster generation, consider:
- Using the Rust CLI implementation (100,000+ attempts/sec)
- Using worker threads for parallel generation (see examples)
- Reducing pattern length
- Run on trusted hardware - Don't generate keys on shared or public computers
- Verify integrity - Check that saved files match generated keys
- Secure storage - Use encrypted storage for keypair files
- Minimal permissions - Files are created with 0600 (owner read/write only)
- Clear memory - Use
clearSensitiveData()to zero out secret keys after use
import { clearSensitiveData } from 'solana-vanity-ts';
// After using the secret key
clearSensitiveData(result.secretKey);Your pattern contains characters not in the Base58 alphabet. Check for:
- Zero (
0) - useoinstead - Uppercase O (
O) - useoinstead - Uppercase I (
I) - useiinstead - Lowercase L (
l) - useLinstead
The output file already exists. Either:
- Choose a different output path with
--output - Use
--overwriteto replace the existing file
Longer patterns take exponentially longer. Consider:
- Shortening your pattern
- Using case-insensitive matching (
--ignore-case) - Using the Rust implementation for better performance
MIT License - see LICENSE for details.
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
- Solana Web3.js - Official Solana JavaScript API
- Commander.js - CLI framework
- Chalk - Terminal string styling