createLazyKeyPairSignerFromBytes
Creates a signer from a 64-bytes Uint8Array secret key (private key and public key) synchronously.
Unlike createKeyPairSignerFromBytes, this helper returns without awaiting. It derives the signer's MessagePartialSigner#address | address directly from the public key half of the secret key (the last 32 bytes) and defers the asynchronous CryptoKey import until the first time a message or transaction is signed. The imported key pair is memoised so the import only happens once, no matter how many times the signer is used.
This is useful when a signer must be created in a synchronous context — for instance, when registering signers up front — whilst the actual signing can remain asynchronous.
Type Parameters
| Type Parameter | Default type | Description |
|---|---|---|
TAddress extends string | string | Supply a string literal to define a signer having a particular address. |
Parameters
| Parameter | Type | Description |
|---|---|---|
bytes | ReadonlyUint8Array | A 64-bytes secret key, the first 32 of which represent the private key and the last 32 of which represent its associated public key. |
extractable? | boolean | Setting this to true makes it possible to extract the bytes of the private key using the crypto.subtle.exportKey() API. Defaults to false. Note that, because the import is deferred, this helper keeps a copy of the secret key bytes in memory until the first signing call completes, regardless of this setting. |
Returns
Readonly<{
address: Address<TAddress>;
signMessages: Promise<readonly Readonly<Record<Address, SignatureBytes>>[]>;
}> & Readonly<{
address: Address<TAddress>;
signTransactions: Promise<readonly Readonly<Record<Address, SignatureBytes>>[]>;
}>
A signer implementing both the MessagePartialSigner and TransactionPartialSigner
interfaces. Note that, because the CryptoKeyPair is imported lazily, this signer does not
expose a keyPair property and is therefore not a full KeyPairSigner.
Throws
SolanaError with code SOLANA_ERROR__KEYS__INVALID_KEY_PAIR_BYTE_LENGTH if the
provided bytes are not exactly 64 bytes long. This check is performed synchronously.
Example
Remarks
Because the CryptoKey import is deferred, the cryptographic check that the public key half of the secret key matches its private key half — which createKeyPairSignerFromBytes performs eagerly — is also deferred. A mismatched or corrupt secret key therefore throws on the first signing attempt rather than at creation time. Only the 64-bytes length is validated synchronously.
Since the import is deferred, the provided bytes are copied on creation so that the signer keeps
working even if the caller mutates or zeroes their buffer before the first signing attempt. This
internal copy is zeroed as soon as the import succeeds, so the plaintext secret key does not linger
in memory beyond the first signing call.
If the deferred import fails, the failure is not cached: the next signing call will attempt the import again. This means a transient failure can be retried, whilst a genuinely mismatched or corrupt secret key will fail on every attempt.
See
createKeyPairSignerFromBytes for the asynchronous variant that eagerly validates the
secret key and exposes the CryptoKeyPair via a keyPair property.