JSPM

@solana/keys

0.0.0-experimental.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1421183
  • Score
    100M100P100Q179489F
  • License MIT

Helpers for generating and transforming key material

Package Exports

  • @solana/keys

Readme

npm npm-downloads
code-style-prettier

@solana/keys

This package contains utilities for validating, generating, and manipulating addresses and key material. It can be used standalone, but it is also exported as part of Kit @solana/kit.

Types

Signature

This type represents a 64-byte Ed25519 signature as a base58-encoded string.

SignatureBytes

This type represents a 64-byte Ed25519 signature.

Whenever you need to verify that a particular signature is, in fact, the one that would have been produced by signing some known bytes using the private key associated with some known public key, use the verifySignature() function in this package.

Functions

assertIsSignature()

From time to time you might acquire a string that you expect to be a base58-encoded signature (eg. of a transaction) from an untrusted network API or user input. To assert that such an arbitrary string is in fact an Ed25519 signature, use the assertIsSignature function.

import { assertIsSignature } from '@solana/keys';

// Imagine a function that asserts whether a user-supplied signature is valid or not.
function handleSubmit() {
    // We know only that what the user typed conforms to the `string` type.
    const signature: string = signatureInput.value;
    try {
        // If this type assertion function doesn't throw, then
        // Typescript will upcast `signature` to `Signature`.
        assertIsSignature(signature);
        // At this point, `signature` is a `Signature` that can be used with the RPC.
        const {
            value: [status],
        } = await rpc.getSignatureStatuses([signature]).send();
    } catch (e) {
        // `signature` turned out not to be a base58-encoded signature
    }
}

generateKeyPair()

Generates an Ed25519 public/private key pair for use with other methods in this package that accept CryptoKey objects.

import { generateKeyPair } from '@solana/keys';

const { privateKey, publicKey } = await generateKeyPair();

grindKeyPair()

Mines a vanity Ed25519 key pair whose base58-encoded public key satisfies the provided matches criterion. The matcher may be a RegExp or a predicate function that receives the candidate address as a string. Key pairs are generated in parallel batches until one matches, so the expected time to find a match grows exponentially with the length of the desired prefix.

import { grindKeyPair } from '@solana/keys';

const keyPair = await grindKeyPair({ matches: /^anza/ });

When matches is a RegExp, its literal characters are validated against the base58 alphabet up front to catch common typos (e.g. /^sol0/) before any key is generated. The config also accepts an extractable flag (forwarded to generateKeyPair), a concurrency setting for the batch size (defaulting to 32), and an abortSignal to cancel long-running grinds.

grindKeyPairs()

Mines multiple vanity Ed25519 key pairs whose base58-encoded public keys all satisfy the provided matches criterion. This is the batch variant of grindKeyPair() and accepts the same configuration plus an amount field.

import { grindKeyPairs } from '@solana/keys';

const keyPairs = await grindKeyPairs({ matches: /^anza/, amount: 4 });

createKeyPairFromBytes()

Given a 64-byte Uint8Array secret key, creates an Ed25519 public/private key pair for use with other methods in this package that accept CryptoKey objects.

import fs from 'fs';
import { createKeyPairFromBytes } from '@solana/keys';

// Get bytes from local keypair file.
const keypairFile = fs.readFileSync('~/.config/solana/id.json');
const keypairBytes = new Uint8Array(JSON.parse(keypairFile.toString()));

// Create a CryptoKeyPair from the bytes.
const { privateKey, publicKey } = await createKeyPairFromBytes(keypairBytes);

writeKeyPair()

Writes an extractable CryptoKeyPair to disk as a JSON array of 64 bytes, matching the format produced by solana-keygen. The first 32 bytes are the raw Ed25519 seed (private key) and the last 32 bytes are the raw public key. Missing parent directories are created automatically and the file is written with mode 0600 (owner read/write only). This helper requires a writable filesystem and will throw in environments that don't provide one (such as browsers or React Native).

import { generateKeyPair, writeKeyPair } from '@solana/keys';

// Generate an extractable key pair so its bytes can be persisted.
const keyPair = await generateKeyPair(true);
await writeKeyPair(keyPair, './my-keypair.json');

By default, writeKeyPair() refuses to overwrite an existing file and throws EEXIST. Callers can opt in by passing { unsafelyOverwriteExistingKeyPair: true }, but doing so permanently destroys the previous key and, with it, access to any funds or onchain state controlled by that address.

createKeyPairFromPrivateKeyBytes()

Given a private key represented as a 32-bytes Uint8Array, creates an Ed25519 public/private key pair for use with other methods in this package that accept CryptoKey objects.

import { createKeyPairFromPrivateKeyBytes } from '@solana/keys';

const { privateKey, publicKey } = await createKeyPairFromPrivateKeyBytes(new Uint8Array([...]));

This can be useful when you have a private key but not the corresponding public key or when you need to derive key pairs from seeds. For instance, the following code snippet derives a key pair from the hash of a message.

import { getUtf8Encoder } from '@solana/codecs-strings';
import { createKeyPairFromPrivateKeyBytes } from '@solana/keys';

const message = getUtf8Encoder().encode('Hello, World!');
const seed = new Uint8Array(await crypto.subtle.digest('SHA-256', message));

const derivedKeypair = await createKeyPairFromPrivateKeyBytes(seed);

createPrivateKeyFromBytes()

Given a private key represented as a 32-byte Uint8Array, creates an Ed25519 private key for use with other methods in this package that accept CryptoKey objects.

import { createPrivateKeyFromBytes } from '@solana/keys';

const privateKey = await createPrivateKeyFromBytes(new Uint8Array([...]));
const extractablePrivateKey = await createPrivateKeyFromBytes(new Uint8Array([...]), true);

getPublicKeyFromPrivateKey()

Given an extractable CryptoKey private key, gets the corresponding public key as a CryptoKey.

import { createPrivateKeyFromBytes, getPublicKeyFromPrivateKey } from '@solana/keys';

const privateKey = await createPrivateKeyFromBytes(new Uint8Array([...]), true);

const publicKey = await getPublicKeyFromPrivateKey(privateKey);
const extractablePublicKey = await getPublicKeyFromPrivateKey(privateKey, true);

isSignature()

This is a type guard that accepts a string as input. It will both return true if the string conforms to the Signature type and will refine the type for use in your program.

import { isSignature } from '@solana/keys';

if (isSignature(signature)) {
    // At this point, `signature` has been refined to a
    // `Signature` that can be used with the RPC.
    const {
        value: [status],
    } = await rpc.getSignatureStatuses([signature]).send();
    setSignatureStatus(status);
} else {
    setError(`${signature} is not a transaction signature`);
}

signBytes()

Given a private CryptoKey and a Uint8Array of bytes, this method will return the 64-byte Ed25519 signature of that data as a Uint8Array.

import { signBytes } from '@solana/keys';

const data = new Uint8Array([1, 2, 3]);
const signature = await signBytes(privateKey, data);

signature()

This helper combines asserting that a string is an Ed25519 signature with coercing it to the Signature type. It's best used with untrusted input.

import { signature } from '@solana/keys';

const signature = signature(userSuppliedSignature);
const {
    value: [status],
} = await rpc.getSignatureStatuses([signature]).send();

verifySignature()

Given a public CryptoKey, some SignatureBytes, and a Uint8Array of data, this method will return true if the signature was produced by signing the data using the private key associated with the public key, and false otherwise.

import { verifySignature } from '@solana/keys';

const data = new Uint8Array([1, 2, 3]);
if (!(await verifySignature(publicKey, signature, data))) {
    throw new Error('The data were *not* signed by the private key associated with `publicKey`');
}