Wallet Standard
Integration with Solana Wallet Adapter and other frameworks.
Wallet Standard Support
The LazorKit SDK supports the Solana Wallet Standard, enabling compatibility with popular libraries like @solana/wallet-adapter-react.
Integration with @solana/wallet-adapter-react
Default Configuration
// Standard Devnet Configuration
export const DEFAULT_CONFIG = {
rpcUrl: 'https://api.devnet.solana.com',
portalUrl: 'https://portal.lazor.sh',
paymasterConfig: {
paymasterUrl: 'https://kora.devnet.lazorkit.com',
// apiKey: 'YOUR_API_KEY' // Optional
},
clusterSimulation: 'devnet'
};You can use LazorKit seamlessly alongside other standard wallets (like Phantom, Solflare) in your existing provider setup.
1. Installation
Install the necessary dependencies:
npm install @lazorkit/wallet @solana/wallet-adapter-react @solana/wallet-adapter-react-ui2. Register the Wallet
Call registerLazorkitWallet with your config. This adds LazorKit to the list of wallets so your adapter can find it.
For Next.js / SSR Apps (Recommended)
Use useEffect to ensure registration happens only on the client-side, as the Wallet Standard relies on the global window object.
For Create React App / Vite (SPA)
You can call this at the top level of your entry file if you don't need runtime configuration.
3. Setup Provider
Here is an example setup using ConnectionProvider and WalletProvider:
import { useMemo, useEffect } from 'react';
import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react';
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui';
import { registerLazorkitWallet } from '@lazorkit/wallet';
// Configuration
const CONFIG = {
RPC_URL: "https://api.devnet.solana.com",
PORTAL_URL: "https://portal.lazor.sh",
PAYMASTER: {
paymasterUrl: "https://kora.devnet.lazorkit.com",
apiKey: "YOUR_API_KEY"
},
CLUSTER: 'devnet'
};
export function AppProviders({ children }) {
// Register LazorKit once on mount
useEffect(() => {
registerLazorkitWallet({
rpcUrl: CONFIG.RPC_URL,
portalUrl: CONFIG.PORTAL_URL,
paymasterConfig: CONFIG.PAYMASTER,
clusterSimulation: CONFIG.CLUSTER,
});
}, []);
const wallets = useMemo(
() => [
// Standard wallets are automatically detected.
// LazorKit will appear here after registration.
],
[]
);
return (
<ConnectionProvider endpoint={CONFIG.RPC_URL}>
<WalletProvider wallets={wallets} autoConnect>
<WalletModalProvider>
{children}
</WalletModalProvider>
</WalletProvider>
</ConnectionProvider>
);
}Usage in Components
Once connected, you can use the standard useWallet hook from @solana/wallet-adapter-react:
import { useWallet } from '@solana/wallet-adapter-react';
import { SystemProgram, PublicKey } from '@solana/web3.js';
export function TransferButton() {
const { publicKey, sendTransaction } = useWallet();
const handleSend = async () => {
if (!publicKey) return;
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: publicKey,
toPubkey: new PublicKey("RECIPIENT"),
lamports: 1000,
})
);
// LazorKit abstracts the Paymaster logic internally here
const signature = await sendTransaction(transaction, connection);
console.log("Sig:", signature);
};
return <button onClick={handleSend}>Send SOL</button>;
}Message Signing & Verification (P256)
WebAuthn keys use the P256 curve (secp256r1), which works differently than standard Solana Ed25519 keys. The signMessage function returns a JSON object containing two critical pieces of data:
signature: The signature produced by the WebAuthn authenticator.signedPayload: The exact byte sequence that was signed by the authenticator, encoded as base64
Why two values?
In WebAuthn, the authenticator does not sign the challenge directly. Instead, the browser constructs clientDataJSON (which includes the challenge, origin, and operation type), and the authenticator signs a payload derived from both:
-
Browser data (clientDataJSON)
-
Authenticator data (authenticatorData)
Because this signed payload cannot be reconstructed from the challenge alone, the verifier must know the exact bytes that were signed in order to validate the signature.
For this reason, signedPayload is returned alongside the signature.
Here's how to decode and use them:
import { useWallet } from '@solana/wallet-adapter-react';
export function SignAndVerify() {
const { signMessage } = useWallet();
const handleSign = async () => {
if (!signMessage) return;
const message = new TextEncoder().encode("Please verify ownership");
// 1. Sign the message
const result = await signMessage(message);
// 2. Decode the result
const jsonString = new TextDecoder().decode(result);
const { signature, signedPayload } = JSON.parse(jsonString);
console.log("Signature:", signature);
console.log("Original Callenge:", signedPayload);
// 3. Verify (Conceptual)
// verify(publicKey, signedPayload, signature);
};
return <button onClick={handleSign}>Sign Message</button>;
}How It Works
- Register: The
registerfunction sets up the LazorKit adapter. - Discover: Your wallet provider sees the new adapter and adds it to the list.
- Transact: When you send a transaction, LazorKit handles the gas sponsorship (Paymaster) and signing logic automatically.
Note: LazorKit behaves like any other wallet to your app, but uses smart contracts and passkeys under the hood.