grindKeyPair

function grindKeyPair(config): Promise<CryptoKeyPair>;

Generates a single Ed25519 key pair whose base58-encoded public key satisfies the provided matches criterion. This is the main entry point for mining vanity Solana addresses: the function keeps generating fresh key pairs in parallel batches until one of them matches.

When matches is a RegExp, its literal characters (outside of escape sequences, character classes, quantifiers, and groups) are validated against the base58 alphabet up front. This catches common typos such as /^ab0/ (0 is not in the base58 alphabet) before any key is generated, preventing a guaranteed infinite loop.

When matches is a function, it is used as-is with no validation — use this form when you need arbitrary matching logic that cannot be expressed as a regex. Be mindful that if the function can never return true, the grind loop will never terminate unless you supply an AbortSignal.

Parameters

ParameterTypeDescription
configOmit<GrindKeyPairsConfig, "amount">See GrindKeyPairsConfig. The amount field is omitted because this function always returns a single key pair.

Returns

Promise<CryptoKeyPair>

A promise that resolves to a CryptoKeyPair whose base58-encoded public key satisfies the matcher.

Throws

SOLANA_ERROR__KEYS__INVALID_BASE58_IN_GRIND_REGEX when the provided regex contains a literal character that is not in the base58 alphabet.

Throws

The AbortSignal's reason when the supplied abortSignal is fired (either before the function is called or during the grind loop).

Examples

Mine a vanity address that starts with anza:

import { grindKeyPair } from '@solana/keys';
 
const keyPair = await grindKeyPair({ matches: /^anza/ });

Use the i flag for case-insensitive matching:

import { grindKeyPair } from '@solana/keys';
 
const keyPair = await grindKeyPair({ matches: /^anza/i });

Use a predicate function for arbitrary matching logic:

import { grindKeyPair } from '@solana/keys';
 
const keyPair = await grindKeyPair({
    matches: address => address.startsWith('anza') && address.length === 44,
});

Cap the grind at 60 seconds using AbortSignal.timeout():

import { grindKeyPair } from '@solana/keys';
 
const keyPair = await grindKeyPair({
    matches: /^anza/,
    abortSignal: AbortSignal.timeout(60_000),
});

Generate an extractable key pair so you can persist its private key bytes:

import { grindKeyPair } from '@solana/keys';
 
const keyPair = await grindKeyPair({ matches: /^anza/, extractable: true });
const privateKeyBytes = new Uint8Array(
    await crypto.subtle.exportKey('pkcs8', keyPair.privateKey),
);

See

On this page