@lumiapassport/core
v1.15.4
Published
Framework-agnostic core SDK for Lumia Passport smart accounts
Maintainers
Readme
@lumiapassport/core
Framework-agnostic core SDK for Lumia Passport smart accounts.
Features
- ✅ Zero React dependencies - Works in Node.js, browser, and edge functions
- ✅ TypeScript-first - Full type safety
- ✅ Modular - Import only what you need
- ✅ Storage abstraction - Works with file storage, memory, or custom storage
- ✅ Account Abstraction - Full ERC-4337 support
- ✅ MPC/TSS - Secure key management
- ✅ Server-side wallets - Backend wallet management with API keys
- ✅ Zero configuration - Works out of the box with Lumia Beam testnet
Installation
npm install @lumiapassport/core viem dkls23-wasm
# or
pnpm add @lumiapassport/core viem dkls23-wasm
# or
yarn add @lumiapassport/core viem dkls23-wasmQuick Start
The SDK works out of the box with Lumia Beam testnet. No additional configuration required:
import { createServerWalletManager, MemoryKeyshareStorage } from '@lumiapassport/core';
// Create manager with just API key
const manager = createServerWalletManager({
apiKey: process.env.LUMIA_PASSPORT_API_KEY!, // Get from dashboard.lumiapassport.com
storage: new MemoryKeyshareStorage(),
});
// Create a wallet
const wallet = await manager.createWallet('my-wallet');
console.log('Smart Account address:', wallet.smartAccountAddress);Usage
Server-Side Wallets (Recommended)
Create and manage backend wallets with a simple high-level API:
import { createServerWalletManager, MemoryKeyshareStorage } from '@lumiapassport/core';
// Create manager
const manager = createServerWalletManager({
apiKey: process.env.LUMIA_PASSPORT_API_KEY!, // Get from dashboard.lumiapassport.com
storage: new MemoryKeyshareStorage(), // Use FileKeyshareStorage or custom storage in production
});
// Create a wallet (handles all TSS protocol complexity)
const wallet = await manager.createWallet('treasury_main');
console.log('Owner address (EOA):', wallet.ownerAddress);
console.log('Smart Account address:', wallet.smartAccountAddress);
// Send a transaction (Account Abstraction with ERC-4337)
const userOpHash = await wallet.sendUserOperation(
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', // recipient
'1000000000000000000', // 1 ETH in wei
'0x', // optional contract call data
'standard' // fee type: 'economy' | 'standard' | 'fast'
);
console.log('UserOp hash:', userOpHash);
// Wait for transaction confirmation
const receipt = await manager.waitForUserOperationReceipt(userOpHash);
console.log('Transaction hash:', receipt.transactionHash);
// Sign a message
const signature = await wallet.signDigest(messageHash);
// List all wallets
const wallets = await manager.listWallets();
wallets.forEach(w => {
console.log(`${w.userId}: ${w.smartAccountAddress}`);
});Storage Options
MemoryKeyshareStorage (Development only)
Simple in-memory storage. Keyshares are lost on restart!
import { MemoryKeyshareStorage } from '@lumiapassport/core';
const storage = new MemoryKeyshareStorage();FileKeyshareStorage (Production-ready)
Encrypted file-based storage using AES-256-CBC. Available in Node.js only:
import { FileKeyshareStorage } from '@lumiapassport/core/clients/node';
const storage = new FileKeyshareStorage({
storageDir: './data/keyshares',
encryptionPassword: process.env.LUMIA_PASSPORT_KEYSHARE_ENCRYPTION_PASSWORD!,
});
// Initialize storage directory
await storage.init();
const manager = createServerWalletManager({
apiKey: process.env.LUMIA_PASSPORT_API_KEY!,
storage,
});Custom Storage
Implement the KeyshareStorage interface for custom backends (AWS KMS, Vault, etc.):
interface KeyshareStorage {
set(userId: string, keyshare: string): Promise<void> | void;
get(userId: string): Promise<string | null> | string | null;
has(userId: string): Promise<boolean> | boolean;
list(): Promise<string[]> | string[];
}Keyshare Backup and Restore
Backup keyshares to Lumia ShareVault for recovery:
// Check if wallet exists on TSS service
const exists = await manager.walletExists('my-wallet');
// Check if we have keyshare locally
const hasKeyshare = await manager.hasKeyshare('my-wallet');
if (!hasKeyshare) {
// Check if backup exists in vault
const { hasBackup } = await manager.checkBackupExists('my-wallet');
if (hasBackup) {
// Restore from vault
await manager.restoreFromVault('my-wallet', process.env.BACKUP_PASSWORD!);
console.log('Keyshare restored from vault');
}
}
// Backup keyshare to vault
await manager.backupToVault('my-wallet', process.env.BACKUP_PASSWORD!);Using Paymaster (Sponsored Transactions)
Configure paymaster for gasless transactions:
const manager = createServerWalletManager({
apiKey: process.env.LUMIA_PASSPORT_API_KEY!,
storage,
paymasterAddress: '0x...' as `0x${string}`, // Your paymaster contract
});See Server Wallets Documentation for complete guide.
Smart Contract Interactions
The SDK provides utilities for encoding smart contract calls for use with sendUserOperation().
ERC20 Token Transfer
import {
createServerWalletManager,
MemoryKeyshareStorage,
encodeERC20Transfer,
} from '@lumiapassport/core';
const manager = createServerWalletManager({
apiKey: process.env.LUMIA_PASSPORT_API_KEY!,
storage: new MemoryKeyshareStorage(),
});
const wallet = await manager.getWallet('treasury_main');
// Encode ERC20 transfer call
const callData = await encodeERC20Transfer(
'0xRecipientAddress...',
1000n * 10n ** 18n // 1000 tokens (18 decimals)
);
// Send the transaction
const userOpHash = await wallet.sendUserOperation(
'0xTokenContractAddress...', // to = token contract
'0', // value = 0 (no native token)
callData, // encoded transfer call
'standard'
);
// Wait for confirmation
const receipt = await manager.waitForUserOperationReceipt(userOpHash);
console.log('Transaction hash:', receipt.transactionHash);ERC20 Approve + TransferFrom Pattern
import { encodeERC20Approve } from '@lumiapassport/core';
// Step 1: Approve DEX router to spend tokens
const approveData = await encodeERC20Approve(
'0xDEXRouterAddress...',
2n ** 256n - 1n // MaxUint256 for unlimited approval
);
await wallet.sendUserOperation(
'0xTokenContractAddress...',
'0',
approveData,
'standard'
);Arbitrary Contract Call
For any smart contract method, use encodeContractCall():
import { encodeContractCall } from '@lumiapassport/core';
// Define ABI for the function you want to call
const stakingAbi = [
{
type: 'function',
name: 'stake',
stateMutability: 'nonpayable',
inputs: [
{ name: 'amount', type: 'uint256' },
{ name: 'lockPeriod', type: 'uint256' },
],
outputs: [],
},
] as const;
// Encode the call
const callData = await encodeContractCall(
stakingAbi,
'stake',
[1000n * 10n ** 18n, 30n * 24n * 60n * 60n] // amount, lock period in seconds
);
// Send transaction
await wallet.sendUserOperation(
'0xStakingContractAddress...',
'0',
callData,
'standard'
);Payable Functions (Sending Native Token + Data)
import { encodeContractCall } from '@lumiapassport/core';
// Example: Wrap ETH to WETH
const wethAbi = [
{
type: 'function',
name: 'deposit',
stateMutability: 'payable',
inputs: [],
outputs: [],
},
] as const;
const callData = await encodeContractCall(wethAbi, 'deposit', []);
await wallet.sendUserOperation(
'0xWETHContractAddress...',
'1000000000000000000', // 1 ETH in wei
callData,
'standard'
);NFT Transfers (ERC721 / ERC1155)
import {
encodeERC721TransferFrom,
encodeERC721SafeTransferFrom,
encodeERC1155SafeTransferFrom,
} from '@lumiapassport/core';
// ERC721 transfer
const nftData = await encodeERC721TransferFrom(
wallet.smartAccountAddress, // from
'0xRecipientAddress...', // to
123n // tokenId
);
await wallet.sendUserOperation('0xNFTContract...', '0', nftData, 'standard');
// ERC1155 transfer
const multiTokenData = await encodeERC1155SafeTransferFrom(
wallet.smartAccountAddress,
'0xRecipientAddress...',
1n, // tokenId
100n, // amount
'0x' // data
);
await wallet.sendUserOperation('0xERC1155Contract...', '0', multiTokenData, 'standard');Available Encoding Helpers
| Function | Description |
|----------|-------------|
| encodeContractCall(abi, functionName, args) | Generic encoder for any contract |
| encodeERC20Transfer(to, amount) | ERC20 transfer |
| encodeERC20Approve(spender, amount) | ERC20 approve |
| encodeERC20TransferFrom(from, to, amount) | ERC20 transferFrom |
| encodeERC721TransferFrom(from, to, tokenId) | ERC721 transfer |
| encodeERC721SafeTransferFrom(from, to, tokenId, data?) | ERC721 safe transfer |
| encodeERC721Approve(to, tokenId) | ERC721 approve |
| encodeERC721SetApprovalForAll(operator, approved) | ERC721 approval for all |
| encodeERC1155SafeTransferFrom(from, to, id, amount, data) | ERC1155 transfer |
| encodeERC1155SafeBatchTransferFrom(from, to, ids, amounts, data) | ERC1155 batch transfer |
| encodeERC1155SetApprovalForAll(operator, approved) | ERC1155 approval for all |
Standard ABIs
The SDK exports standard ABIs for common token standards:
import { ERC20_ABI, ERC721_ABI, ERC1155_ABI } from '@lumiapassport/core';
// Use with viem directly or with encodeContractCallBlockchain Read Layer
Read blockchain data without wallet connection:
import { getPublicClient } from '@lumiapassport/core/read';
import { erc20Abi } from 'viem';
// Create client for Lumia mainnet (uses built-in defaults)
const client = getPublicClient({ chainId: 994873017 });
// Read contract data
const balance = await client.readContract({
address: '0x...tokenAddress',
abi: erc20Abi,
functionName: 'balanceOf',
args: ['0x...userAddress'],
});
// Batch multiple reads into single RPC call
const results = await client.multicall({
contracts: [
{ address: '0x...token1', abi: erc20Abi, functionName: 'balanceOf', args: ['0x...user'] },
{ address: '0x...token2', abi: erc20Abi, functionName: 'symbol' },
],
});
// Query event logs
const logs = await client.getLogs({
address: '0x...tokenAddress',
event: { type: 'event', name: 'Transfer', inputs: [...] },
fromBlock: 1000000n,
toBlock: 'latest',
});
// Get transaction receipt (returns null if pending)
const receipt = await client.getTransactionReceipt({
hash: '0x...transactionHash',
});
// Wait for transaction to be mined
const receipt = await client.waitForTransactionReceipt({
hash: '0x...transactionHash',
confirmations: 1, // optional, default: 1
pollingInterval: 4000, // optional, default: 4000ms
timeout: 60000, // optional, default: 60000ms
onReplaced: (response) => {
console.log('Transaction replaced:', response.reason);
},
});Features:
- LRU Caching - 12s TTL with 1000 max entries
- RPC Fallback - Automatic failover to backup RPCs
- Multicall Batching - Batch reads for better performance
- Log Pagination - Automatic chunking for large block ranges
- Transaction Receipts - Get receipt or wait with polling/timeout
API
Modules
- read - Blockchain read operations (import from
@lumiapassport/core/read) - bundler - UserOperation management
- auth - JWT token management and verification
- clients - HTTP clients and account management
- mpc - MPC/TSS operations
- utils - Helper utilities
Storage Adapters
MemoryStorage- In-memory storage (server)LocalStorageAdapter- Browser localStorage- Custom adapters via
TokenStorageinterface
Examples
See USAGE_EXAMPLES.md for comprehensive examples.
License
MIT
