Wallet Standard
Integrate LazorKit with @solana/wallet-adapter-react and other Wallet Standard clients.
LazorKit implements the Solana Wallet Standard, so you can drop it into any Wallet Adapter setup alongside Phantom, Solflare, Backpack, and friends.
When to use Wallet Standard
Pick this path if you already have a Wallet Adapter-powered app and want LazorKit to appear in the standard wallet picker. For a purpose-built integration, use the React SDK or React Native SDK directly — both expose session keys, deferred execution, and authority management that Wallet Standard doesn't cover.
Install
npm install @lazorkit/wallet \
@solana/wallet-adapter-react @solana/wallet-adapter-react-uiSetup
Register LazorKit as a standard wallet
Call registerLazorkitWallet once on the client. The Wallet Standard relies on the
global window object, so mount registration inside an effect:
'use client';
import { useEffect, useMemo } from 'react';
import {
ConnectionProvider,
WalletProvider,
} from '@solana/wallet-adapter-react';
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui';
import { registerLazorkitWallet } from '@lazorkit/wallet';
const CONFIG = {
RPC_URL: 'https://api.devnet.solana.com',
PORTAL_URL: 'https://portal.lazor.sh',
PAYMASTER: { paymasterUrl: 'https://kora.devnet.lazorkit.com' },
CLUSTER: 'devnet' as const,
};
export function Providers({ children }: { children: React.ReactNode }) {
useEffect(() => {
registerLazorkitWallet({
rpcUrl: CONFIG.RPC_URL,
portalUrl: CONFIG.PORTAL_URL,
paymasterConfig: CONFIG.PAYMASTER,
clusterSimulation: CONFIG.CLUSTER,
});
}, []);
const wallets = useMemo(() => [/* other adapters here */], []);
return (
<ConnectionProvider endpoint={CONFIG.RPC_URL}>
<WalletProvider wallets={wallets} autoConnect>
<WalletModalProvider>{children}</WalletModalProvider>
</WalletProvider>
</ConnectionProvider>
);
}Use the standard hook anywhere
Once registered, LazorKit appears in the standard wallet picker. Consume it with the
usual useWallet hook from @solana/wallet-adapter-react:
'use client';
import { useConnection, useWallet } from '@solana/wallet-adapter-react';
import {
LAMPORTS_PER_SOL,
PublicKey,
SystemProgram,
Transaction,
} from '@solana/web3.js';
export function TransferButton() {
const { connection } = useConnection();
const { publicKey, sendTransaction } = useWallet();
const send = async () => {
if (!publicKey) return;
const tx = new Transaction().add(
SystemProgram.transfer({
fromPubkey: publicKey, // vault PDA — where funds live
toPubkey: new PublicKey('RECIPIENT'),
lamports: 0.01 * LAMPORTS_PER_SOL,
}),
);
const sig = await sendTransaction(tx, connection);
console.log('tx', sig);
};
return <button onClick={send}>Send SOL</button>;
}LazorKit handles the paymaster relay internally — you don't need to set feePayer or
call signTransaction yourself.
Message signing (P256)
WebAuthn signs over derived WebAuthn payloads, not the raw challenge. signMessage
returns a JSON-encoded { signature, signedPayload } pair so consumers can verify both
pieces.
'use client';
import { useWallet } from '@solana/wallet-adapter-react';
export function SignAndVerify() {
const { signMessage } = useWallet();
const handle = async () => {
if (!signMessage) return;
const message = new TextEncoder().encode('Please verify ownership');
const result = await signMessage(message);
// result is a UTF-8 JSON blob — decode it:
const { signature, signedPayload } = JSON.parse(new TextDecoder().decode(result));
console.log('signature:', signature);
console.log('signed payload:', signedPayload);
// Verify with `crypto.subtle` against the wallet's P256 public key
};
return <button onClick={handle}>Sign Message</button>;
}Why two fields?
The authenticator doesn't sign the challenge directly — it signs
sha256(authenticatorData || sha256(clientDataJSON)). The verifier needs the exact
bytes that were signed. signedPayload gives you that byte sequence; signature is
the P256 signature over it.
See the React SDK's verifyMessage for an
in-browser verifier that wraps crypto.subtle.
What Wallet Standard supports
| Feature | Available |
|---|---|
connect / disconnect | yes |
signTransaction / signAllTransactions | yes (via paymaster) |
sendTransaction | yes |
signMessage | yes (P256 — see above) |
| Session keys | no — use React/RN SDK |
| Deferred execution | no — use React/RN SDK |
| Authority management | no — use React/RN SDK |
If you need advanced features, drop to the React SDK — it composes cleanly on top of the same wallet.
How it works
- Register —
registerLazorkitWalletpublishes the LazorKit adapter onwindow. - Discover — Wallet Adapter detects the new standard wallet and lists it in the picker.
- Transact — When the user sends a transaction, LazorKit handles passkey signing and paymaster relay under the hood, then returns the confirmed signature.