A Solana wallet powered by passkeys. Authenticate with biometrics, send transactions without gas fees, and swap tokens at the best prices.
FYt532fCsCuoHd9aaX5QN7pZLUTiSXwEjhBmZijgBAGS
Everything you need for a modern Solana wallet experience.
No seed phrases to write down. Use FaceID, TouchID, or fingerprint to secure your wallet.
Send SOL and tokens without holding any for fees. Kora paymaster sponsors all transactions.
Best-price token swaps via Jupiter aggregator. Completely gas-free.
Receive payments privately with one-time addresses. Generate Solana Pay QR codes.
Disposable identities with zero on-chain link to your main wallet.
Pay-per-view content with HTTP 402 standard. Instant crypto payments.
Learn how to build with Seedless Wallet.
Implement passkey-based wallet authentication using LazorKit SDK in React Native.
npm install @lazorkit/wallet-mobile-adapter @coral-xyz/anchor @solana/web3.js
npm install react-native-get-random-values react-native-url-polyfill buffer
npx expo install expo-crypto expo-web-browser expo-linking
Add polyfills at the top of your entry file:
// index.ts
import 'react-native-get-random-values';
import 'react-native-url-polyfill/auto';
import { Buffer } from 'buffer';
global.Buffer = global.Buffer || Buffer;
import { LazorKitProvider } from '@lazorkit/wallet-mobile-adapter';
function LazorProvider({ children }) {
return (
<LazorKitProvider
rpcUrl="https://api.devnet.solana.com"
portalUrl="https://portal.lazor.sh"
configPaymaster={{
paymasterUrl: "https://kora.devnet.lazorkit.com",
}}
>
{children}
</LazorKitProvider>
);
}
import { useWallet } from '@lazorkit/wallet-mobile-adapter';
import * as Linking from 'expo-linking';
const { connect, isConnecting } = useWallet();
const handleConnect = async () => {
const redirectUrl = Linking.createURL('callback');
await connect({
redirectUrl,
onSuccess: () => console.log('Connected'),
onFail: (error) => console.error(error),
});
};
Send SOL transfers without paying transaction fees. The Kora paymaster sponsors the fees.
Traditional flow: User pays fee in SOL, then transaction executes.
Gasless flow: User creates transaction, paymaster pays fee, transaction executes.
import { useWallet } from '@lazorkit/wallet-mobile-adapter';
import { PublicKey, SystemProgram, LAMPORTS_PER_SOL } from '@solana/web3.js';
import * as Linking from 'expo-linking';
const { smartWalletPubkey, signAndSendTransaction } = useWallet();
const handleSend = async (recipient, amount) => {
const recipientPubkey = new PublicKey(recipient);
const lamports = parseFloat(amount) * LAMPORTS_PER_SOL;
const transferInstruction = SystemProgram.transfer({
fromPubkey: smartWalletPubkey,
toPubkey: recipientPubkey,
lamports,
});
const redirectUrl = Linking.createURL('sign-callback');
const signature = await signAndSendTransaction(
{
instructions: [transferInstruction],
transactionOptions: {
clusterSimulation: 'mainnet',
// feeToken omitted = gasless
},
},
{
redirectUrl,
onSuccess: () => console.log('Sent'),
onFail: (error) => console.error(error),
}
);
};
const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
await signAndSendTransaction({
instructions: [transferInstruction],
transactionOptions: {
clusterSimulation: 'mainnet',
feeToken: USDC_MINT, // User pays in USDC
},
});
Integrate Jupiter swap aggregator with LazorKit's gasless infrastructure.
Use Jupiter's /swap-instructions endpoint to get raw instructions, then pass them
through LazorKit's gasless flow.
async function getQuote(inputMint, outputMint, amount) {
const params = new URLSearchParams({
inputMint,
outputMint,
amount,
slippageBps: '100',
});
const response = await fetch(
`https://api.jup.ag/swap/v1/quote?${params}`,
{ headers: { 'x-api-key': JUPITER_API_KEY } }
);
return response.json();
}
Critical for Kora compatibility. Remove Jupiter's compute budget instructions:
const COMPUTE_BUDGET_PROGRAM_ID = 'ComputeBudget111111111111111111111111111111';
function filterComputeBudget(instructions) {
return instructions.filter(
ix => !ix.programId.equals(new PublicKey(COMPUTE_BUDGET_PROGRAM_ID))
);
}
const { quote, instructions, addressLookupTableAccounts } =
await prepareSwap(SOL_MINT, USDC_MINT, amountInLamports, smartWalletPubkey);
await signAndSendTransaction({
instructions,
transactionOptions: {
addressLookupTableAccounts,
clusterSimulation: 'mainnet',
},
});
Implement stealth addresses and burner wallets for private transactions.
Generate one-time receiving addresses derived from a master seed.
import * as SecureStore from 'expo-secure-store';
import * as Crypto from 'expo-crypto';
import { Keypair } from '@solana/web3.js';
async function generateStealthAddress(index) {
const masterSeed = await getOrCreateMasterSeed();
const input = Buffer.concat([
Buffer.from(masterSeed, 'hex'),
Buffer.from('stealth'),
Buffer.from(index.toString()),
]);
const hash = await Crypto.digest(
Crypto.CryptoDigestAlgorithm.SHA256,
input
);
const keypair = Keypair.fromSeed(new Uint8Array(hash));
return keypair.publicKey.toBase58();
}
Completely isolated identities with no on-chain link.
async function createBurner(label) {
const keypair = Keypair.generate();
const id = await generateBurnerId();
// Store encrypted
await SecureStore.setItemAsync(
`burner_${id}`,
Buffer.from(keypair.secretKey).toString('base64')
);
return {
id,
label,
publicKey: keypair.publicKey.toBase58(),
};
}
async function destroyBurner(burnerId) {
await SecureStore.deleteItemAsync(`burner_${burnerId}`);
}
Implement pay-per-view content using HTTP 402 micropayments.
function parsePaymentRequired(body) {
if (body.payTo && body.maxAmountRequired) {
return {
scheme: body.scheme || 'exact',
network: 'solana',
maxAmountRequired: body.maxAmountRequired,
payTo: body.payTo,
};
}
return null;
}
async function payForContent(requirements) {
const paymentInstruction = SystemProgram.transfer({
fromPubkey: smartWalletPubkey,
toPubkey: new PublicKey(requirements.payTo),
lamports: Math.ceil(
parseFloat(requirements.maxAmountRequired) * LAMPORTS_PER_SOL
),
});
const signature = await signAndSendTransaction({
instructions: [paymentInstruction],
transactionOptions: { clusterSimulation: 'mainnet' },
});
return signature;
}
async function accessContent(url, signature) {
const proof = {
signature,
network: 'solana',
payload: {
timestamp: Date.now(),
},
};
const response = await fetch(url, {
headers: {
'X-PAYMENT': btoa(JSON.stringify(proof)),
},
});
return response.json();
}
Download the app or clone the source to build your own.