Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.DS_Store
node_modules/
*.txt
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# Origin source
* [https://github.com/professorhantzen/ripple-vanity](https://github.com/professorhantzen/ripple-vanity)

# Update from origin
* Add cluster for multi core CPU usage
* Export result to file
* Support regex vanity string
* Default max attemps = Math.round(Number.MAX_VALUE/2);
* Some minor cleanup

# ripple-vanity
Simple node.js script to create Ripple "vanity" wallets. These are secp256k1 public/private key pairs, where the public key encodes to a base58 address containing a search string.

Expand All @@ -19,3 +29,4 @@ String format:
`123456789 ABCDEFGH JKLMN PQRSTUVWXYZabcdefghijk mnopqrstuvwxyz`

(Note: `0`, `I`, `O` and `l` are excluded, as per [base58](https://en.wikipedia.org/wiki/Base58) convention.)

13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "ripple-vanity",
"version": "1.1.0",
"private": true,
"dependencies": {
"ripple-keypairs": "^0.8.0"
},
"engines": {
"node": "6.*",
"npm": "3.*"
},
"main": "ripple-vanity.js"
}
81 changes: 47 additions & 34 deletions ripple-vanity.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,63 @@
// ripple vanity address finder
//
const l = console.log;
const s = process.stdout;
const log = console.log;
const stdout = process.stdout;
const cr = '\r\x1b[K';
const vanity_string = process.argv[2];
const attempts = process.argv[3];
const vanitystr = process.argv[2];
const attempts = process.argv[3] || Math.round(Number.MAX_VALUE / 2);
const cluster = require('cluster');
const numCPUs = process.argv[4] || Math.max(1, require('os').cpus().length - 1);
const xrpKeygen = require('ripple-keypairs');
const fs = require('fs');

var kp = require('ripple-keypairs');
var filename = 'VanityXRP_'+Math.round(new Date().getTime() / 1e3)+'.txt';
var start_time = Date.now();
var end_time = null;
var valid = false;
var found = 0;
var usage = 'Ripple Vanity Address Finder v1.0\n\n'+
'usage: node ripple-vanity.js <search-string> <number-of-attempts>\n'+
'example: node ripple-vanity.js xrp 100000\n\n'+
'<search-string> may be comprised of any of these characters:\n'+
'123456789 ABCDEFGH JKLMN PQRSTUVWXYZabcdefghijk mnopqrstuvwxyz\n'+
'(Note: \'0\', \'I\', \'O\' and \'l\' are excluded.)';
var valid = vanitystr && !~vanitystr.search('(0|O|I|l)');
var regex = new RegExp(vanitystr, 'i');
var found = 0;
var usage = 'Ripple Vanity Address Finder v1.1\n\n'+
'usage: node ripple-vanity.js <search-regex> <number-of-attempts> <number-of-CPUs>\n'+
'example: node ripple-vanity.js "mj(i|1)" 1000000 4\n\n'+
'<search-string> may be regex of comprised of any of these characters:\n'+
'123456789 ABCDEFGH JKLMN PQRSTUVWXYZabcdefghijk mnopqrstuvwxyz\n'+
'(Note: \'0\', \'I\', \'O\' and \'l\' are excluded.)\n---\n';

if(vanity_string &&
vanity_string.split('0').length === 1 &&
vanity_string.split('I').length === 1 &&
vanity_string.split('O').length === 1 &&
vanity_string.split('l').length === 1 ) valid = true;
if (cluster.isMaster || !valid || !attempts) {
log(usage);
log('Vanity is valid:', valid);
log('Searching', attempts, 'addresses for', regex, 'with', numCPUs, "CPUs\n");
stdout.write(cr + '0%');

if(attempts > 0 && valid) {
l('Searching', attempts, 'addresses for ' + '\"' + vanity_string +'\"...');
s.write(cr + '0%');
for (var i = numCPUs - 1; i >= 0; i--) {
cluster.fork();
}

// cluster.on('exit', function (deadWorker, code, signal) {
// for (var id in cluster.workers) cluster.workers[id].process.kill();
// return process.exit();
// });
} else {
var temp_wallet = null;
var prog = (attempts/100).toFixed(0) * 1; // for speed not accuracy
var step = prog;
var perc = 0;
for(var i = 0; i<attempts; i++){
if(i == prog) {
s.write(cr + ++perc + '%');

for (var i = 0; i<attempts; i++){
if (i == prog) {
stdout.write(cr + ++perc + '%');
prog += step;
}
temp_wallet = kp.generateWallet();
if(temp_wallet.accountID.indexOf(vanity_string)>-1) {
l(cr + i +', ' + temp_wallet.accountID + ', ' + temp_wallet.seed);
found++;
temp_wallet = xrpKeygen.generateWallet();

if (temp_wallet.accountID.search(regex) == 1) {
log('Found:', cr + i +', ' + temp_wallet.accountID + ', ' + temp_wallet.seed);
fs.appendFileSync(filename, temp_wallet.accountID+', '+temp_wallet.seed+'\n');
found++;
}
}

end_time = Date.now();
var pl = ''; if(found>1 || found === 0) pl = 'es' ;
l(cr + found + ' address'+pl+' found. Took ' + ((end_time-start_time)/60000).toFixed(1) + ' minutes.');
} else {
l(usage);
var pl = (found>1 || found === 0) ? 'es' : '';
log('Cluster', cluster.worker.id, ':', cr, found, 'address', pl, 'found. Took', ((end_time-start_time)/60e3).toFixed(1), 'minutes.');

return process.exit();
}