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:
Kurdistan Tech Ministry committed 2026-01-11 23:22:39 +03:00
commit 6a860cecfe
29 files changed
+1312

No files matched your search

+65
View File
@@ -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
};
}
+30
View File
@@ -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
};
}
+24
View File
@@ -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
};
}
+4
View File
@@ -0,0 +1,4 @@
// Copyright 2018-2025 @pezkuwi/api-cli authors & contributors
// SPDX-License-Identifier: Apache-2.0
import './cjs/index.js';
+11
View File
@@ -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, []);
+6
View File
@@ -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' };
+7
View File
@@ -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;
+5
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+33
View File
@@ -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;
}