mirror of
https://github.com/pezkuwichain/pezkuwi-vanitygen.git
synced 2026-11-10 12:47:08 +00:00
Initial commit: Fork @polkadot/vanitygen to @pezkuwi/vanitygen
- Replace all @polkadot/* dependencies with @pezkuwi/* - Update package.json metadata for Pezkuwichain - Update CLI command from polkadot-js-vanitygen to pezkuwi-vanitygen - Update network options: bizinikiwi, pezkuwi, dicle, zagros - Set default network to pezkuwi (ss58Format: 42) - Update documentation and README - Build and test successful - Version 1.0.0
This commit is contained in:
commit
6a860cecfe
29 files changed
+1312
No files matched your search
@@ -0,0 +1,65 @@
|
||||
// Copyright 2017-2025 @pezkuwi/vanitygen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { GeneratorCalculation, GeneratorOptions } from './types.js';
|
||||
|
||||
const MAX_OFFSET = 5;
|
||||
|
||||
function calculateAtOne (atOffset: number, test: string[], address: string): GeneratorCalculation {
|
||||
return {
|
||||
count: test.reduce((count, c, index): number => {
|
||||
if (index === count) {
|
||||
count += (c === '?' || c === address.charAt(index + atOffset)) ? 1 : 0;
|
||||
}
|
||||
|
||||
return count;
|
||||
}, 0),
|
||||
offset: atOffset
|
||||
};
|
||||
}
|
||||
|
||||
function calculateAt (atOffset: number, test: string[][], address: string): GeneratorCalculation {
|
||||
let bestCount = 0;
|
||||
let bestOffset = 1;
|
||||
|
||||
for (let i = 0, count = test.length; i < count; i++) {
|
||||
const { count, offset } = calculateAtOne(atOffset, test[i], address);
|
||||
|
||||
if (count > bestCount) {
|
||||
bestCount = count;
|
||||
bestOffset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
count: bestCount,
|
||||
offset: bestOffset
|
||||
};
|
||||
}
|
||||
|
||||
export default function calculate (test: string[][], _address: string, { atOffset = -1, withCase = false }: GeneratorOptions): GeneratorCalculation {
|
||||
const address = withCase
|
||||
? _address
|
||||
: _address.toLowerCase();
|
||||
|
||||
if (atOffset > 0) {
|
||||
return calculateAt(atOffset, test, address);
|
||||
}
|
||||
|
||||
let bestCount = 0;
|
||||
let bestOffset = 1;
|
||||
|
||||
for (let i = 0; i < MAX_OFFSET; i++) {
|
||||
const { count, offset } = calculateAt(i, test, address);
|
||||
|
||||
if (count > bestCount) {
|
||||
bestCount = count;
|
||||
bestOffset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
count: bestCount,
|
||||
offset: bestOffset
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright 2017-2025 @pezkuwi/vanitygen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { GeneratorMatch, GeneratorOptions } from './types.js';
|
||||
|
||||
import { ed25519PairFromSeed, encodeAddress, mnemonicGenerate, mnemonicToMiniSecret, randomAsU8a, sr25519PairFromSeed } from '@pezkuwi/util-crypto';
|
||||
|
||||
import calculate from './calculate.js';
|
||||
|
||||
export default function generator (test: string[][], options: GeneratorOptions): GeneratorMatch {
|
||||
const mnemonic = options.withHex
|
||||
? undefined
|
||||
: mnemonicGenerate(12);
|
||||
const seed = mnemonic
|
||||
? mnemonicToMiniSecret(mnemonic)
|
||||
: randomAsU8a();
|
||||
const pair = options.type === 'sr25519'
|
||||
? sr25519PairFromSeed(seed)
|
||||
: ed25519PairFromSeed(seed);
|
||||
const address = encodeAddress(pair.publicKey, options.ss58Format);
|
||||
const { count, offset } = calculate(test, address, options);
|
||||
|
||||
return {
|
||||
address,
|
||||
count,
|
||||
mnemonic,
|
||||
offset,
|
||||
seed
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2017-2025 @pezkuwi/vanitygen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { GeneratorMatches, GeneratorOptions, GeneratorResult } from './types.js';
|
||||
|
||||
import generate from './generate.js';
|
||||
|
||||
export default function generator (options: GeneratorOptions): GeneratorResult {
|
||||
const { match, runs = 10, withCase = false } = options;
|
||||
const found: GeneratorMatches = [];
|
||||
const startAt = Date.now();
|
||||
const test = (withCase ? match : match.toLowerCase())
|
||||
.split(',')
|
||||
.map((c): string[] => c.split(''));
|
||||
|
||||
while (found.length !== runs) {
|
||||
found.push(generate(test, options));
|
||||
}
|
||||
|
||||
return {
|
||||
elapsed: Date.now() - startAt,
|
||||
found
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Copyright 2018-2025 @pezkuwi/api-cli authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import './cjs/index.js';
|
||||
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2025 @pezkuwi/vanitygen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Do not edit, auto-generated by @pezkuwi/dev
|
||||
// (packageInfo imports will be kept as-is, user-editable)
|
||||
|
||||
import { detectPackage } from '@pezkuwi/util';
|
||||
|
||||
import { packageInfo } from './packageInfo.js';
|
||||
|
||||
detectPackage(packageInfo, null, []);
|
||||
@@ -0,0 +1,6 @@
|
||||
// Copyright 2017-2025 @pezkuwi/vanitygen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Do not edit, auto-generated by @pezkuwi/dev
|
||||
|
||||
export const packageInfo = { name: '@pezkuwi/vanitygen', path: 'auto', type: 'auto', version: '1.0.0' };
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 2017-2025 @pezkuwi/vanitygen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// eslint-disable-next-line prefer-regex-literals
|
||||
const regex = new RegExp('^[1-9A-HJ-NP-Za-km-z]*$', '');
|
||||
|
||||
export default regex;
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
// Copyright 2017-2025 @pezkuwi/vanitygen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import './runcli.js';
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env node
|
||||
// Copyright 2017-2025 @pezkuwi/vanitygen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { KeypairType } from '@pezkuwi/util-crypto/types';
|
||||
import type { GeneratorMatch, GeneratorOptions } from './types.js';
|
||||
|
||||
import yargs from 'yargs';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
|
||||
import { u8aToHex } from '@pezkuwi/util';
|
||||
import { cryptoWaitReady } from '@pezkuwi/util-crypto';
|
||||
|
||||
import generator from './generator.js';
|
||||
import matchRegex from './regex.js';
|
||||
|
||||
interface Best extends GeneratorMatch {
|
||||
withCase?: boolean;
|
||||
}
|
||||
|
||||
interface ArgV {
|
||||
match: string;
|
||||
mnemonic: boolean;
|
||||
network: string;
|
||||
type: string;
|
||||
withCase: boolean;
|
||||
}
|
||||
|
||||
const { match, mnemonic, network, type, withCase } = yargs(hideBin(process.argv))
|
||||
.wrap(120)
|
||||
.option('match', {
|
||||
default: 'Test',
|
||||
type: 'string'
|
||||
})
|
||||
.option('mnemonic', {
|
||||
default: false,
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('network', {
|
||||
choices: ['bizinikiwi', 'pezkuwi', 'dicle', 'zagros'],
|
||||
default: 'pezkuwi'
|
||||
})
|
||||
.option('type', {
|
||||
choices: ['ed25519', 'sr25519'],
|
||||
default: 'sr25519'
|
||||
})
|
||||
.option('withCase', {
|
||||
default: false,
|
||||
type: 'boolean'
|
||||
})
|
||||
.argv as ArgV;
|
||||
|
||||
// eslint-disable-next-line prefer-regex-literals
|
||||
const NUMBER_REGEX = new RegExp('(\\d+?)(?=(\\d{3})+(?!\\d)|$)', 'g');
|
||||
const INDICATORS = ['|', '/', '-', '\\'];
|
||||
|
||||
const options: GeneratorOptions = {
|
||||
match,
|
||||
network,
|
||||
runs: 50,
|
||||
ss58Format: 42,
|
||||
type: type as KeypairType,
|
||||
withCase,
|
||||
withHex: !mnemonic
|
||||
};
|
||||
const startAt = Date.now();
|
||||
let best: Best = {
|
||||
address: '',
|
||||
count: -1,
|
||||
offset: 65536
|
||||
};
|
||||
let total = 0;
|
||||
let indicator = -1;
|
||||
const tests = options.match.split(',');
|
||||
|
||||
tests.forEach((test): void => {
|
||||
if (!matchRegex.test(test)) {
|
||||
console.error("Invalid character found in match string, allowed is '1-9' (no '0'), 'A-H, J-N & P-Z' (no 'I' or 'O'), 'a-k & m-z' (no 'l') and '?' (wildcard)");
|
||||
process.exit(-1);
|
||||
}
|
||||
});
|
||||
|
||||
switch (network) {
|
||||
case 'dicle':
|
||||
options.ss58Format = 2; // Dicle (formerly Kusama)
|
||||
break;
|
||||
|
||||
case 'pezkuwi':
|
||||
options.ss58Format = 42; // Pezkuwichain main relay
|
||||
break;
|
||||
|
||||
case 'zagros':
|
||||
options.ss58Format = 42; // Zagros canary network
|
||||
break;
|
||||
|
||||
case 'bizinikiwi':
|
||||
options.ss58Format = 42; // Generic substrate format
|
||||
break;
|
||||
|
||||
default:
|
||||
options.ss58Format = 42;
|
||||
break;
|
||||
}
|
||||
|
||||
console.log(options);
|
||||
|
||||
function showProgress (): void {
|
||||
const elapsed = (Date.now() - startAt) / 1000;
|
||||
|
||||
indicator++;
|
||||
|
||||
if (indicator === INDICATORS.length) {
|
||||
indicator = 0;
|
||||
}
|
||||
|
||||
process.stdout.write(`\r[${INDICATORS[indicator]}] ${(total.toString().match(NUMBER_REGEX) || []).join(',')} keys in ${(elapsed).toFixed(2)}s (${(total / elapsed).toFixed(0)} keys/s)`);
|
||||
}
|
||||
|
||||
function showBest (): void {
|
||||
const { address, count, mnemonic, offset, seed } = best;
|
||||
|
||||
console.log(`\r::: ${address.slice(0, offset)}[${address.slice(offset, count + offset)}]${address.slice(count + offset)} <= ${u8aToHex(seed)} (count=${count}, offset=${offset})${mnemonic ? '\n ' + mnemonic : ''}`);
|
||||
}
|
||||
|
||||
process.on('unhandledRejection', (error): void => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
cryptoWaitReady()
|
||||
.then((): void => {
|
||||
while (true) {
|
||||
const nextBest = generator(options).found.reduce((best, match): Best => {
|
||||
if ((match.count > best.count) || ((match.count === best.count) && (match.offset <= best.offset))) {
|
||||
return match;
|
||||
}
|
||||
|
||||
return best;
|
||||
}, best);
|
||||
|
||||
total += options.runs;
|
||||
|
||||
if (nextBest.address !== best.address) {
|
||||
best = nextBest;
|
||||
showBest();
|
||||
showProgress();
|
||||
} else if ((total % (options.withHex ? 1000 : 100)) === 0) {
|
||||
showProgress();
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error: Error): void => console.error(error));
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// Copyright 2017-2025 @pezkuwi/vanitygen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { GeneratorMatch } from './types.js';
|
||||
|
||||
function numberSort (a: number, b: number): number {
|
||||
if (a > b) {
|
||||
return -1;
|
||||
} else if (a < b) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
export default function sort (a: GeneratorMatch, b: GeneratorMatch): number {
|
||||
const countResult = numberSort(a.count, b.count);
|
||||
|
||||
if (countResult !== 0) {
|
||||
return countResult;
|
||||
}
|
||||
|
||||
const positionResult = numberSort(b.offset, a.offset);
|
||||
|
||||
if (positionResult !== 0) {
|
||||
return positionResult;
|
||||
}
|
||||
|
||||
return a.address.localeCompare(b.address);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2017-2025 @pezkuwi/vanitygen authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { KeypairType } from '@pezkuwi/util-crypto/types';
|
||||
|
||||
export interface GeneratorCalculation {
|
||||
count: number;
|
||||
offset: number;
|
||||
}
|
||||
|
||||
export interface GeneratorMatch extends GeneratorCalculation {
|
||||
address: string;
|
||||
mnemonic?: string;
|
||||
seed?: Uint8Array;
|
||||
}
|
||||
|
||||
export type GeneratorMatches = GeneratorMatch[];
|
||||
|
||||
export interface GeneratorOptions {
|
||||
atOffset?: number;
|
||||
match: string;
|
||||
network?: string;
|
||||
runs: number;
|
||||
ss58Format: number;
|
||||
type: KeypairType;
|
||||
withCase?: boolean;
|
||||
withHex?: boolean;
|
||||
}
|
||||
|
||||
export interface GeneratorResult {
|
||||
elapsed: number;
|
||||
found: GeneratorMatches;
|
||||
}
|
||||
Reference in new issue
Block a user