/** * Smart Savings Manager * * Handles upgrading savings accounts to EIP-7702 smart accounts. * Enables advanced features like locked savings, spend & save, and periodic savings. * * Architecture: * 1. Take a basic SavingsAccount (BIP-44 derived) * 2. Create an EVMSmartWallet instance from its private key * 3. Initialize with EIP-7702 delegation * 4. Return a SmartSavingsAccount with full AA capabilities */ import { Chain } from "viem/chains"; import { EVMSmartWallet } from "../evm/smartWallet"; import { SmartWalletOptions } from "../evm/aa-service"; import { ChainWalletConfig } from "../types"; import { SavingsAccount, SmartSavingsAccount } from "./types"; // ============================================ // SmartSavingsManager Class // ============================================ /** * Manages EIP-7702 smart savings accounts * * This class provides: * 1. Upgrade from basic savings account to smart account * 2. Full Account Abstraction capabilities * 3. Access to Kernel modules (lock, hooks, session keys) * 4. Sponsored transactions via paymaster */ export class SmartSavingsManager { private chainConfig: ChainWalletConfig; constructor(chainConfig: ChainWalletConfig) { this.chainConfig = chainConfig; // Validate AA support if (!chainConfig.aaSupport?.enabled) { throw new Error( "Smart savings requires Account Abstraction (AA) support.\n" + "Your chain config must include aaSupport configuration with:\n" + "- bundlerUrl\n" + "- entryPoints\n" + "- kernelImplementations" ); } } /** * Upgrade a savings account to a smart account with EIP-7702 delegation * * This enables advanced features: * - Lock modules for time-locked savings * - Hooks for spend & save * - Session keys for periodic savings * - Sponsored transactions via paymaster * * @param savingsAccount - The basic savings account to upgrade * @param options - Optional smart wallet configuration * @returns SmartSavingsAccount with EVMSmartWallet instance * * @example * const basicSavings = wallet.deriveSavingsAccount(1); * const smartSavings = await smartSavingsManager.upgradeSavingsToSmartAccount(basicSavings); * await smartSavings.smartWallet.installModule({ ... }); */ async upgradeSavingsToSmartAccount( savingsAccount: SavingsAccount, options?: SmartWalletOptions ): Promise { // Merge options with chain config const mergedOptions: SmartWalletOptions = { ...options, aaConfig: this.chainConfig.aaSupport, bundlerUrl: options?.bundlerUrl || this.chainConfig.aaSupport?.bundlerUrl, paymasterUrl: options?.paymasterUrl || this.chainConfig.aaSupport?.paymasterUrl, entryPointVersion: options?.entryPointVersion || this.chainConfig.aaSupport?.entryPoints?.[0]?.version }; // Validate bundlerUrl if (!mergedOptions.bundlerUrl) { throw new Error( "bundlerUrl is required for smart savings.\n" + "Provide it via upgradeSavingsToSmartAccount options or chain config." ); } // Create viem chain object const chain: Chain = { id: this.chainConfig.chainId, name: this.chainConfig.name, nativeCurrency: { name: this.chainConfig.nativeToken.name, symbol: this.chainConfig.nativeToken.symbol, decimals: this.chainConfig.nativeToken.decimals }, rpcUrls: { default: { http: [this.chainConfig.rpcUrl] } }, blockExplorers: { default: { name: this.chainConfig.name + " Explorer", url: this.chainConfig.explorerUrl } }, testnet: this.chainConfig.testnet || false }; // Create EVMSmartWallet instance from savings account private key const smartWallet = new EVMSmartWallet( savingsAccount.privateKey, chain, mergedOptions ); // Note: Initialization (createAuthorization) is optional // User can call smartWallet.initialize() separately if needed // For now, we return uninitialized smart wallet const isInitialized = false; return { ...savingsAccount, smartWallet, isInitialized }; } /** * Upgrade and initialize a savings account in one step * * This is a convenience method that both upgrades and initializes. * * @param savingsAccount - The basic savings account to upgrade * @param options - Optional smart wallet configuration * @returns Initialized SmartSavingsAccount ready for transactions * * @example * const basicSavings = wallet.deriveSavingsAccount(1); * const smartSavings = await smartSavingsManager.upgradeSavingsAndInitialize(basicSavings); * // smartSavings is now ready for smart transactions */ async upgradeSavingsAndInitialize( savingsAccount: SavingsAccount, options?: SmartWalletOptions ): Promise { // First upgrade const smartSavings = await this.upgradeSavingsToSmartAccount(savingsAccount, options); // Then initialize await smartSavings.smartWallet.initialize(); // Update initialization status smartSavings.isInitialized = true; return smartSavings; } /** * Check if a savings account can be upgraded to smart account * * @returns true if chain supports AA and has required configuration */ canUpgradeToSmartAccount(): boolean { return !!( this.chainConfig.aaSupport?.enabled && this.chainConfig.aaSupport?.bundlerUrl && this.chainConfig.aaSupport?.entryPoints && this.chainConfig.aaSupport?.entryPoints.length > 0 ); } /** * Get the chain configuration * * @returns ChainWalletConfig */ getChainConfig(): ChainWalletConfig { return this.chainConfig; } }