Create a working generator
This commit is contained in:
parent
328e7004b6
commit
1e57ee158d
8 changed files with 2858 additions and 0 deletions
27
README.md
Normal file
27
README.md
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Vanity ETH
|
||||
|
||||
Online ETH vanity address generator
|
||||
|
||||
## Local usage
|
||||
|
||||
Just clone the repo and open `index.html` with your web browser
|
||||
|
||||
## Local development
|
||||
|
||||
Install dependencies
|
||||
|
||||
```sh
|
||||
npm i
|
||||
```
|
||||
|
||||
Run the watcher to browserify JS as you code
|
||||
|
||||
```sh
|
||||
npm run-script watch
|
||||
```
|
||||
|
||||
Browserify / babelify /uglify before pushing to production
|
||||
|
||||
```sh
|
||||
npm run-script build
|
||||
```
|
31
gulpfile.js
Normal file
31
gulpfile.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
const gulp = require('gulp');
|
||||
const pump = require('pump');
|
||||
|
||||
const browserify = require('browserify');
|
||||
const babel = require('gulp-babel');
|
||||
const uglify = require('gulp-uglify');
|
||||
const source = require('vinyl-source-stream');
|
||||
|
||||
// Browserify
|
||||
gulp.task('browserify', cb => {
|
||||
pump([
|
||||
browserify('js/index.js').bundle(),
|
||||
source('bundle.js'),
|
||||
gulp.dest('js')
|
||||
], cb);
|
||||
});
|
||||
|
||||
// Browserify then babelify, then uglify
|
||||
gulp.task('build', ['browserify'], cb => {
|
||||
pump([
|
||||
gulp.src('js/bundle.js'),
|
||||
babel({presets: ['env']}),
|
||||
uglify(),
|
||||
gulp.dest('js')
|
||||
], cb);
|
||||
});
|
||||
|
||||
// Watch changes and browserify on the fly
|
||||
gulp.task('watch', () => {
|
||||
gulp.watch(['js/index.js', 'js/vanity.js'], ['browserify']);
|
||||
});
|
19
index.html
Normal file
19
index.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>Vanity ETH</title>
|
||||
</head>
|
||||
<body>
|
||||
<input type="text" value="ab" id="pattern">
|
||||
<input type="button" id="btn" value="Generate">
|
||||
<div id="counter-wrapper">
|
||||
<div id="counter"></div>
|
||||
</div>
|
||||
<div id="result"></div>
|
||||
<script src="js/bundle.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
1
js/bundle.js
Normal file
1
js/bundle.js
Normal file
File diff suppressed because one or more lines are too long
45
js/index.js
Normal file
45
js/index.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* eslint-env node, browser */
|
||||
|
||||
const vanity = require('./vanity');
|
||||
|
||||
let count = 0;
|
||||
const step = 100;
|
||||
const counter = document.getElementById('counter');
|
||||
|
||||
const parseInput = () => {
|
||||
return {
|
||||
pattern: document.getElementById('pattern').value,
|
||||
checksum: true
|
||||
};
|
||||
};
|
||||
|
||||
const incrementCounter = incr => {
|
||||
count += incr;
|
||||
counter.innerHTML = count.toString() + ' addresses generated';
|
||||
};
|
||||
|
||||
const displayResult = result => {
|
||||
incrementCounter(result.attempts);
|
||||
document.getElementById('result').innerHTML = 'address: ' + result.address + '<br>key: ' + result.privKey;
|
||||
};
|
||||
|
||||
const generate = input => {
|
||||
const add = vanity.getVanityWallet(input.pattern, input.checksum, step);
|
||||
if (add !== null) {
|
||||
return displayResult(add);
|
||||
}
|
||||
|
||||
incrementCounter(step);
|
||||
|
||||
// Use setTimeout to let the browser render
|
||||
setTimeout(() => {
|
||||
generate(input);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
// Add event listener on button
|
||||
document.getElementById('btn').addEventListener('click', () => {
|
||||
incrementCounter(-count);
|
||||
const input = parseInput();
|
||||
generate(input);
|
||||
});
|
73
js/vanity.js
Normal file
73
js/vanity.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
const ethUtils = require('ethereumjs-util');
|
||||
const randomBytes = require('randombytes');
|
||||
|
||||
const ERRORS = {
|
||||
invalidHex: 'Invalid hex input'
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a random wallet from a random private key
|
||||
* @returns {{address: string, privKey: string}}
|
||||
*/
|
||||
const getRandomWallet = () => {
|
||||
const randbytes = randomBytes(32);
|
||||
return {
|
||||
address: '0x' + ethUtils.privateToAddress(randbytes).toString('hex'),
|
||||
privKey: randbytes.toString('hex')
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a string is valid hexadecimal
|
||||
* @param hex
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isValidHex = hex => hex.length ? /^[0-9A-F]+$/g.test(hex.toUpperCase()) : true;
|
||||
|
||||
/**
|
||||
* Check if a wallet respects the input constraints
|
||||
* @param wallet
|
||||
* @param input
|
||||
* @param isChecksum
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isValidVanityWallet = (wallet, input, isChecksum) => {
|
||||
let address = wallet.address;
|
||||
address = isChecksum ? ethUtils.toChecksumAddress(address) : address;
|
||||
return address.substr(2, input.length) === input;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a lot of wallets until one satisfies the input constraints
|
||||
* @param input
|
||||
* @param isChecksum
|
||||
* @param max - Stop the generation after <max> attempts. Set to 0 for unlimited
|
||||
* @returns
|
||||
*/
|
||||
const getVanityWallet = (input, isChecksum, max) => {
|
||||
input = input || '';
|
||||
if (!isValidHex(input)) {
|
||||
throw new Error(ERRORS.invalidHex);
|
||||
}
|
||||
input = isChecksum ? input : input.toLowerCase();
|
||||
let _wallet = getRandomWallet();
|
||||
let attempts = 1;
|
||||
|
||||
while (!isValidVanityWallet(_wallet, input, isChecksum)) {
|
||||
_wallet = getRandomWallet();
|
||||
attempts++;
|
||||
if (max && attempts >= max) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (isChecksum) {
|
||||
_wallet.address = ethUtils.toChecksumAddress(_wallet.address);
|
||||
}
|
||||
|
||||
_wallet.attempts = attempts;
|
||||
return _wallet;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getVanityWallet
|
||||
};
|
2639
package-lock.json
generated
Normal file
2639
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
23
package.json
Normal file
23
package.json
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "vanity-eth",
|
||||
"description": "Online ETH vanity address generator",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"browserify": "^14.5.0",
|
||||
"ethereumjs-util": "^5.1.2",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-babel": "^7.0.0",
|
||||
"gulp-uglify": "^3.0.0",
|
||||
"pump": "^2.0.0",
|
||||
"randombytes": "^2.0.5",
|
||||
"vinyl-source-stream": "^1.1.0"
|
||||
},
|
||||
"license": "ISC",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "node ./node_modules/gulp/bin/gulp.js build",
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"watch": "node ./node_modules/gulp/bin/gulp.js watch"
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue