A comprehensive Solana-based smart wallet management system that provides secure passkey authentication, customizable policy engines, and flexible transaction execution capabilities.
LazorKit is a sophisticated smart wallet system built on Solana that enables users to create and manage smart wallets with advanced security features:
- Passkey Authentication: Secure authentication using secp256r1 WebAuthn credentials
- Policy Engine System: Customizable transaction policies with a default policy implementation
- Smart Wallet Management: Create, configure, and manage smart wallets with multiple wallet_devices
- Transaction Session Support: Execute complex transactions with session-based state management
- Policy Registry Management: Control which policy programs can be used
The system consists of two main Solana programs:
The core smart wallet program that handles:
- Smart wallet creation and initialization
- Passkey authentication management
- Policy program integration
- Transaction execution and session handling
- Configuration management
Key Instructions:
initialize- Initialize the programcreate_smart_wallet- Create a new smart wallet with passkeyupdate_policy- Update wallet policies directlyinvoke_policy- Execute policy program callsexecute_transaction- Execute transactions directlycreate_transaction_session- Create session for complex transactionsexecute_session_transaction- Execute session-based transactionsadd_policy_program- Add programs to the policy registryupdate_config- Update program configuration
A reference implementation of transaction policies that provides:
- Policy initialization and validation
- Device management for multi-device wallets
- Transaction checking and approval logic
Key Instructions:
init_policy- Initialize policy for a smart walletcheck_policy- Validate transaction against policiesadd_device- Add new wallet_device
The contract-integration folder provides a comprehensive TypeScript SDK for interacting with the LazorKit system:
contract-integration/
├── anchor/ # Generated Anchor types and IDL
├── client/ # Main client classes
├── pda/ # PDA derivation functions
├── webauthn/ # WebAuthn/Passkey utilities
├── auth.ts # Authentication utilities
├── transaction.ts # Transaction building utilities
├── utils.ts # General utilities
├── messages.ts # Message building utilities
├── constants.ts # Program constants
├── types.ts # TypeScript type definitions
├── index.ts # Main exports
└── README.md # This file
- Node.js (v16 or higher)
- Solana CLI
- Anchor Framework (v0.31.0)
- Rust (for program development)
- Clone the repository:
git clone <repository-url>
cd wallet-management-contract- Install dependencies:
npm install- Build the programs:
anchor build# Deploy LazorKit program
anchor deploy --provider.cluster devnet
# Deploy Default Policy program
anchor deploy --provider.cluster devnet --program-name default_policy# Initialize IDL for LazorKit
anchor idl init -f ./target/idl/lazorkit.json Gsuz7YcA5sbMGVRXT3xSYhJBessW4xFC4xYsihNCqMFh
# Initialize IDL for Default Policy
anchor idl init -f ./target/idl/default_policy.json BiE9vSdz9MidUiyjVYsu3PG4C1fbPZ8CVPADA9jRfXw7# Initialize IDL for LazorKit
anchor idl upgrade Gsuz7YcA5sbMGVRXT3xSYhJBessW4xFC4xYsihNCqMFh -f ./target/idl/lazorkit.json
# Initialize IDL for Default Policy
anchor idl upgrade BiE9vSdz9MidUiyjVYsu3PG4C1fbPZ8CVPADA9jRfXw7 -f ./target/idl/default_policy.jsonimport { LazorkitClient, DefaultPolicyClient } from './contract-integration';
import { Connection } from '@solana/web3.js';
// Initialize connection
const connection = new Connection('YOUR_RPC_URL');
// Create clients
const lazorkitClient = new LazorkitClient(connection);
const defaultPolicyClient = new DefaultPolicyClient(connection);import { BN } from '@coral-xyz/anchor';
// Generate wallet ID
const walletId = lazorkitClient.generateWalletId();
// Create smart wallet with passkey
const { transaction, smartWalletId, smartWallet } =
await lazorkitClient.createSmartWalletTxn({
payer: payer.publicKey,
passkeyPubkey: [
/* 33 bytes */
],
credentialIdBase64: 'base64-credential',
isPayForUser: true,
});// Execute transaction with authentication
const transaction = await lazorkitClient.executeTransactionWithAuth({
payer: payer.publicKey,
smartWallet: smartWallet.publicKey,
passkeySignature: {
passkeyPubkey: [
/* 33 bytes */
],
signature64: 'base64-signature',
clientDataJsonRaw64: 'base64-client-data',
authenticatorDataRaw64: 'base64-auth-data',
},
policyInstruction: null,
cpiInstruction: transferInstruction,
});// Update wallet policies
const updateTx = await lazorkitClient.updatePolicyWithAuth({
payer: payer.publicKey,
smartWallet: smartWallet.publicKey,
passkeySignature: {
passkeyPubkey: [
/* 33 bytes */
],
signature64: 'base64-signature',
clientDataJsonRaw64: 'base64-client-data',
authenticatorDataRaw64: 'base64-auth-data',
},
destroyPolicyInstruction: destroyInstruction,
initPolicyInstruction: initInstruction,
newWalletDevice: {
passkeyPubkey: [
/* 33 bytes */
],
credentialIdBase64: 'base64-credential',
},
});
// Invoke policy program
const invokeTx = await lazorkitClient.invokePolicyWithAuth({
payer: payer.publicKey,
smartWallet: smartWallet.publicKey,
passkeySignature: {
passkeyPubkey: [
/* 33 bytes */
],
signature64: 'base64-signature',
clientDataJsonRaw64: 'base64-client-data',
authenticatorDataRaw64: 'base64-auth-data',
},
policyInstruction: policyInstruction,
newWalletDevice: null,
});// Create transaction session
const sessionTx = await lazorkitClient.createChunkWithAuth({
payer: payer.publicKey,
smartWallet: smartWallet.publicKey,
passkeySignature: {
passkeyPubkey: [
/* 33 bytes */
],
signature64: 'base64-signature',
clientDataJsonRaw64: 'base64-client-data',
authenticatorDataRaw64: 'base64-auth-data',
},
policyInstruction: null,
expiresAt: Math.floor(Date.now() / 1000) + 3600, // 1 hour
});
// Execute session transaction (no authentication needed)
const executeTx = await lazorkitClient.executeSessionTransaction({
payer: payer.publicKey,
smartWallet: smartWallet.publicKey,
cpiInstruction: complexInstruction,
});// Build policy initialization instruction
const initPolicyIx = await defaultPolicyClient.buildInitPolicyIx(
payer.publicKey,
smartWallet.publicKey,
walletDevice.publicKey
);
// Build policy check instruction
const checkPolicyIx = await defaultPolicyClient.buildCheckPolicyIx(
walletDevice.publicKey
);
// Build add device instruction
const addDeviceIx = await defaultPolicyClient.buildAddDeviceIx(
payer.publicKey,
walletDevice.publicKey,
newWalletDevice.publicKey
);Run the test suite:
anchor testThe test suite includes:
- Smart wallet creation and initialization
- Default policy implementation
- Transaction execution
- Policy management
- Session functionality
- Passkey Authentication: Uses secp256r1 WebAuthn for secure authentication
- Multi-Device Support: Add multiple wallet_devices to a single wallet
- Policy-Based Validation: Customizable transaction validation policies
- Custom Policy Programs: Implement your own policy programs or use the default
- Session Support: Execute complex multi-step transactions with session management
- Policy Registry Management: Control which policy programs can be used
- TypeScript SDK: Full TypeScript support with generated types
- Anchor Integration: Built with Anchor framework for easy development
- Comprehensive Testing: Extensive test coverage
- Clean API: Well-organized, intuitive API with clear separation of concerns
| Program | Devnet | Mainnet |
|---|---|---|
| LazorKit | Gsuz7YcA5sbMGVRXT3xSYhJBessW4xFC4xYsihNCqMFh |
Gsuz7YcA5sbMGVRXT3xSYhJBessW4xFC4xYsihNCqMFh |
| Default Policy | BiE9vSdz9MidUiyjVYsu3PG4C1fbPZ8CVPADA9jRfXw7 |
BiE9vSdz9MidUiyjVYsu3PG4C1fbPZ8CVPADA9jRfXw7 |
The system uses an address lookup table to optimize transaction size:
- Address:
7Pr3DG7tRPAjVb44gqbxTj1KstikAuVZY7YmXdotVjLA
The SDK has been completely refactored with:
- Better Naming: More descriptive and consistent method names
- Improved Organization: Clear separation of concerns with dedicated utility modules
- Enhanced Type Safety: Comprehensive TypeScript interfaces and type definitions
- Cleaner Architecture: Modular design with authentication, transaction building, and message utilities
executeTxnDirectTx→executeTransactionWithAuthcallRuleDirectTx→invokePolicyWithAuthchangeRuleDirectTx→updatePolicyWithAuthcommitCpiTx→createChunkWithAuthexecuteCommitedTx→executeSessionTransactionMessageArgs→SmartWalletActionArgsDefaultRuleClient→DefaultPolicyClient- All "rule" terminology changed to "policy" for consistency
See the contract-integration README for detailed migration guide and examples.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
[Add your license information here]
For questions and support, please open an issue on GitHub or contact the development team.