seal-wallet-sdk
v0.1.1
Published
TypeScript SDK for the Seal smart wallet on Solana
Downloads
233
Maintainers
Readme
seal-wallet-sdk
TypeScript SDK for the Seal Smart Wallet on Solana.
Seal enables autonomous agent capabilities with on-chain spending limits and scoped permissions. Perfect for AI agents, trading bots, and automated workflows.
Installation
npm install seal-wallet-sdk @solana/web3.jsQuick Start
import { SealClient, solToLamports } from "seal-wallet-sdk";
import { Keypair } from "@solana/web3.js";
// Initialize client
const client = new SealClient({ network: "devnet" });
// Load your owner keypair
const owner = Keypair.fromSecretKey(/* your secret key */);
// Create a smart wallet with spending limits
const wallet = await client.createWallet(owner, {
dailyLimitSol: 10, // Max 10 SOL per day
perTxLimitSol: 1, // Max 1 SOL per transaction
});
console.log("Wallet created:", wallet.address.toBase58());Architecture Overview
flowchart TD
W["SmartWallet PDA<br/>owner + pda_authority<br/>wallet spending limits<br/>guardian set + recovery threshold"]
A["AgentConfig PDA<br/>agent identity<br/>program allowlist<br/>agent spending limits"]
S["SessionKey PDA<br/>ephemeral signer<br/>expiry + budget caps<br/>revocable by owner or agent"]
W -->|registers| A
A -->|creates| SFull Workflow Example
import {
SealClient,
solToLamports,
} from "seal-wallet-sdk";
import { Keypair, PublicKey } from "@solana/web3.js";
async function main() {
// 1. Initialize
const client = new SealClient({ network: "devnet" });
const owner = Keypair.generate();
const agent = Keypair.generate();
// 2. Create wallet with limits
const wallet = await client.createWallet(owner, {
dailyLimitSol: 10,
perTxLimitSol: 2,
});
console.log("Wallet:", wallet.address.toBase58());
// 3. Register an agent with scoped permissions
const agentConfig = await client.registerAgent(owner, agent.publicKey, {
name: "Trading Bot",
dailyLimitSol: 5, // Agent limited to 5 SOL/day (less than wallet)
perTxLimitSol: 0.5, // Agent limited to 0.5 SOL/tx
allowedPrograms: [ // Only allow specific programs
new PublicKey("JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"),
],
blockAllExceptAllowed: true, // Strict mode
});
console.log("Agent registered:", agentConfig.agent.toBase58());
// 4. Agent creates a time/amount-limited session
const { sessionKeypair, session } = await client.createSession(
agent,
owner.publicKey,
{
durationSecs: 3600, // 1 hour session
maxAmountLamports: solToLamports(1), // Max 1 SOL total
maxPerTxLamports: solToLamports(0.1), // Max 0.1 SOL per tx
}
);
console.log("Session created, expires:", new Date(Number(session.expiresAt) * 1000));
// 5. Agent executes a transaction via session
// (The session keypair signs, Seal validates and CPIs)
const MEMO_PROGRAM = new PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
const signature = await client.executeViaSession(
sessionKeypair,
owner.publicKey,
agent.publicKey,
MEMO_PROGRAM,
BigInt(0), // No SOL transfer, just a memo
Buffer.from("Hello from autonomous agent!"),
[], // No additional accounts needed for memo
);
console.log("Executed:", signature);
// 6. Owner can revoke session at any time
await client.revokeSession(
owner,
owner.publicKey,
agent.publicKey,
sessionKeypair.publicKey
);
console.log("Session revoked");
// 7. Owner can deregister agent (returns rent)
await client.deregisterAgent(owner, agent.publicKey);
console.log("Agent deregistered");
// 8. Owner can close wallet (after all agents removed)
await client.closeWallet(owner);
console.log("Wallet closed, rent returned");
}
main().catch(console.error);API Reference
SealClient
const client = new SealClient({
network?: "mainnet" | "devnet" | "localnet", // Default: "devnet"
rpcUrl?: string, // Custom RPC URL
programId?: PublicKey, // Custom program ID
commitment?: "processed" | "confirmed" | "finalized",
});Wallet Operations
// Create a new smart wallet
const wallet = await client.createWallet(owner: Keypair, options: {
dailyLimitSol: number,
perTxLimitSol: number,
}): Promise<SmartWallet>;
// Get wallet by PDA
const wallet = await client.getWallet(address: PublicKey): Promise<SmartWallet>;
// Update spending limits
const wallet = await client.updateSpendingLimits(
owner: Keypair,
newDailyLimitSol: number,
newPerTxLimitSol: number,
): Promise<SmartWallet>;
// Add a guardian for recovery
const wallet = await client.addGuardian(
owner: Keypair,
guardian: PublicKey,
): Promise<SmartWallet>;
// Close wallet (returns rent)
await client.closeWallet(owner: Keypair): Promise<void>;Agent Operations
// Register an agent
const agentConfig = await client.registerAgent(
owner: Keypair,
agent: PublicKey,
options: {
name: string,
dailyLimitSol: number,
perTxLimitSol: number,
allowedPrograms?: PublicKey[],
blockAllExceptAllowed?: boolean,
},
): Promise<AgentConfig>;
// Get agent config
const agentConfig = await client.getAgentConfig(address: PublicKey): Promise<AgentConfig>;
// Deregister agent (returns rent)
await client.deregisterAgent(owner: Keypair, agent: PublicKey): Promise<void>;Session Operations
// Create a session (agent creates)
const { sessionKeypair, session } = await client.createSession(
agent: Keypair,
walletOwner: PublicKey,
options: {
durationSecs?: number, // Default: 24 hours
maxAmountLamports?: bigint, // Total session budget
maxPerTxLamports?: bigint, // Per-transaction limit
},
): Promise<{ sessionKeypair: Keypair; session: SessionKey }>;
// Get session
const session = await client.getSession(address: PublicKey): Promise<SessionKey>;
// Revoke session (owner or agent)
await client.revokeSession(
authority: Keypair,
walletOwner: PublicKey,
agent: PublicKey,
sessionPubkey: PublicKey,
): Promise<void>;Execute Operations
// Execute via session (the core agent operation)
const signature = await client.executeViaSession(
sessionKeypair: Keypair,
walletOwner: PublicKey,
agent: PublicKey,
targetProgram: PublicKey,
amountLamports: bigint,
innerInstructionData: Buffer,
remainingAccounts: { pubkey: PublicKey; isSigner: boolean; isWritable: boolean }[],
): Promise<string>;Recovery Operations
// Recover wallet (guardian quorum rotates owner)
const wallet = await client.recoverWallet(
guardians: Keypair[],
walletOwner: PublicKey,
newOwner: PublicKey,
): Promise<SmartWallet>;Low-Level Instruction Builders
For advanced usage, you can build instructions directly:
import {
createWalletInstruction,
registerAgentInstruction,
createSessionInstruction,
executeViaSessionInstruction,
revokeSessionInstruction,
updateSpendingLimitInstruction,
addGuardianInstruction,
deregisterAgentInstruction,
recoverWalletInstruction,
closeWalletInstruction,
solToLamports,
} from "seal-wallet-sdk";PDA Derivation
import { deriveWalletPda, deriveAgentPda, deriveSessionPda } from "seal-wallet-sdk";
const [walletPda, walletBump] = deriveWalletPda(ownerPubkey);
const [agentPda, agentBump] = deriveAgentPda(walletPda, agentPubkey);
const [sessionPda, sessionBump] = deriveSessionPda(walletPda, agentPubkey, sessionPubkey);Types
interface SmartWallet {
address: PublicKey;
owner: PublicKey;
bump: number;
isLocked: boolean;
isClosed: boolean;
guardians: PublicKey[];
guardianCount: number;
dailyLimitLamports: bigint;
perTxLimitLamports: bigint;
todaySpentLamports: bigint;
lastResetTimestamp: bigint;
agentCount: number;
}
interface AgentConfig {
address: PublicKey;
wallet: PublicKey;
agent: PublicKey;
name: string;
bump: number;
isActive: boolean;
blockAllExceptAllowed: boolean;
allowedPrograms: PublicKey[];
dailyLimitLamports: bigint;
perTxLimitLamports: bigint;
txCount: bigint;
totalSpent: bigint;
createdAt: bigint;
}
interface SessionKey {
address: PublicKey;
wallet: PublicKey;
agent: PublicKey;
sessionPubkey: PublicKey;
bump: number;
isRevoked: boolean;
expiresAt: bigint;
maxAmountLamports: bigint;
maxPerTxLamports: bigint;
amountSpent: bigint;
}Security Considerations
Guardian Recovery
Seal supports guardian-based recovery with a configurable recovery_threshold.
New wallets start with recovery_threshold = 1, so if you add multiple guardians and want multi-party approval, set the threshold explicitly after setup.
See SECURITY.md for full details.
Spending Limits
Limits are enforced at three levels (most restrictive wins):
- Wallet-level: Set by owner
- Agent-level: Set by owner when registering agent
- Session-level: Set by agent when creating session
Session Security
- Sessions have an expiry timestamp
- Sessions have a total budget and per-tx limit
- Owner or agent can revoke sessions instantly
- Session keys are ephemeral keypairs
Testing
# Run SDK tests
npm test
# Run with coverage
npm run test:coverageLicense
Apache-2.0
