import { TransactionReceipt, Signer, Eip1193Provider, BrowserProvider, ContractRunner } from 'ethers'; declare const ERC20Abi: readonly ["function approve(address spender, uint256 amount) returns (bool)", "function allowance(address owner, address spender) view returns (uint256)", "function balanceOf(address owner) view returns (uint256)", "function decimals() view returns (uint8)"]; declare const FactoryAbi: ({ type: string; name: string; inputs: { name: string; type: string; }[]; outputs: { name: string; type: string; }[]; stateMutability: string; } | { type: string; name: string; inputs: { name: string; type: string; indexed: boolean; }[]; outputs?: never; stateMutability?: never; })[]; declare const VaultAbi: ({ type: string; name: string; inputs: { name: string; type: string; }[]; outputs: { name: string; type: string; }[]; stateMutability: string; } | { type: string; name: string; inputs: { name: string; type: string; indexed: boolean; }[]; outputs?: never; stateMutability?: never; })[]; declare const WETHAbi: readonly ["function deposit() payable", "function withdraw(uint256 amount)", "function balanceOf(address owner) view returns (uint256)"]; type Address = `0x${string}`; type ChainId = number; type Environment = "mainnet" | "testnet"; type LogLevel = "debug" | "info" | "warn" | "error" | "none"; type WalletName = "metamask" | "trust" | "coinbase" | "rabby" | "phantom" | "walletconnect" | "injected"; interface TransactionResult { hash: string; wait(): Promise; } interface UserProfile { morphoVault: string | null; isInitialDeposit: boolean; isWhitelisted: boolean; vaultVersion: string; walletAddress?: Address; isActive?: boolean; activeStrategies?: string[]; twitterAccount?: string; } interface AuthState { token: string | null; address: Address | null; authenticated: boolean; user: UserProfile | null; } interface NonceResponse { message: string; walletAddress?: Address; timestamp?: number; } interface LoginResponse { /** * Deprecated: the session token is now delivered as an httpOnly cookie and is * no longer returned in the login response body. Retained as optional for * backwards compatibility; it will be undefined under cookie-based auth. */ token?: string; expiresAt?: string; user?: UserProfile; } interface RefreshResult { /** ISO 8601 expiry of the freshly issued session token (set as an httpOnly cookie). */ expiresAt: string; } interface WalletState { address: Address; chainId: ChainId; connected: boolean; } interface IWalletAdapter { readonly name: string; readonly installed: boolean; connect(chainId: number): Promise; disconnect(): Promise; switchChain(chainId: number): Promise; getSigner(): Promise; getProvider(): Promise; getBrowserProvider(): Promise; signMessage(message: string): Promise; onAccountsChanged(cb: (accounts: string[]) => void): void; onChainChanged(cb: (chainId: number) => void): void; onDisconnect(cb: () => void): void; removeAllListeners(): void; } interface TokenConfig { symbol: string; address: Address; decimals: number; vaultAddresses: Address[]; } interface ChainConfig { environment: Environment; chainId: ChainId; name: string; rpcUrl: string; factoryAddress: Address; wethAddress: Address; tokens: TokenConfig[]; blockExplorerUrl?: string; } interface SurfConfig { projectName: string; projectId?: string; appId?: string; environment?: Environment; chainId?: ChainId; rpcUrl?: string; apiBaseUrl?: string; factoryAddress?: Address; autoApprove?: boolean; logger?: LogLevel; } interface ResolvedSurfConfig { projectName: string; projectId: string; appId: string; environment: Environment; chainId: ChainId; rpcUrl: string; apiBaseUrl: string; factoryAddress: Address; autoApprove: boolean; logger: LogLevel; } interface SurfClientOptions { config: ResolvedSurfConfig; registries: Record>; walletAdapters: Map; } interface VaultEarned { nativeEarningsUSD: number; merklRewardsUSD: number; leagueEarnedUSD: number; totalEarningsUSD: number; } interface VaultApyBreakdown { nativeAPY: number; merklAPY: number; leagueAPY: number; currentAPY: number; /** Alias some responses use for the blended current APY. */ totalAPY?: number; /** Trailing-window APYs (portfolio-weighted). Null until enough history exists. */ apy7d?: number | null; apy14d?: number | null; apy30d?: number | null; } interface VaultLeague { totalXP: number; rank: number; estimatedSURF: number; estimatedSURFUSD: number; joinDate: string; } interface VaultAsset { assetAddress: string; assetSymbol: string; assetDecimals: number; chainId: number; chainStatus: string; morphoVaultAddress: string; balance: number; currentValueUSD: number; depositedAmountUSD: number; totalEarnings: number; totalEarningsUSD: number; currentAPY: number; nativeAPY: number; merklAPY: number; leagueAPY: number; /** Trailing-window APYs for this asset. Null until enough history exists. */ apy7d?: number | null; apy14d?: number | null; apy30d?: number | null; leagueEarnedUSD: number; cumulativeReturn: number; vaultAddress: string; vaultVersion: string; } /** A vault's address on a specific chain. The vault may be deployed at different addresses on different chains. */ interface VaultChainAddress { chainId: number; vaultAddress: string; } interface VaultInfo { userVaultAddress: string | null; deploymentSalt: string | null; exists: boolean; walletAddress?: string | null; homeChainId?: number | null; vaultVersion?: string | null; isActive?: boolean; totalValueUSD?: number | null; totalDepositedUSD?: number | null; earned?: VaultEarned | null; apyBreakdown?: VaultApyBreakdown | null; league?: VaultLeague | null; assets?: VaultAsset[]; /** Per-chain vault addresses for chains where the address differs from `userVaultAddress` (e.g. Ethereum). */ chainAddresses?: VaultChainAddress[]; } interface DeployVaultResult { vaultAddress: string; transactionHash: string; salt: string; } interface PortfolioSummary { assets: string[]; deposited: bigint[]; currentValues: bigint[]; profits: bigint[]; activeCount: number; } interface FeeInfo { revenueAddress: string; feePercentage: bigint; rebalanceFeePercentage: bigint; merklClaimFeePercentage: bigint; } interface DepositParams { asset: Address; amount: string; vaultAddress?: string; bestVault?: string; wrapEth?: boolean; } interface WithdrawParams { asset: Address; amount?: string; vaultAddress?: string; } interface SupportedAsset { assetAddress: string; assetSymbol: string; assetDecimals: number; chainId: number; chainStatus: string; currentAPY: number; nativeAPY: number; merklAPY: number; leagueAPY: number; /** Trailing-window APYs. Null/absent when the position has no history. */ apy7d?: number | null; apy14d?: number | null; apy30d?: number | null; } /** Reference to a source/destination vault on a rebalance, migration, or cross-chain move. */ interface VaultRef { name: string; address: string; apy: number; } interface AgentMessage { message: string; txHash: string; timestamp: string; transactionType: "INITIAL_DEPOSIT" | "DEPOSIT" | "USER_DEPOSIT" | "WITHDRAWAL" | "USER_WITHDRAWAL" | "REBALANCE" | "REBALANCE_COMPLETED" | "REBALANCE_CANCELLED" | "CROSS_CHAIN_REBALANCE" | "MERKL_CLAIM" | "ASSET_ADDED" | "ASSET_REMOVED" | "ASSET_SWAPPED" | "MIGRATE" | string; executedBy: "USER" | "AGENT"; vaultVersion: string; chainId: number; signal?: string | null; /** Structured fields derived from the transaction. Omitted when not applicable. */ amount?: number | null; token?: string | null; fromVault?: VaultRef | null; toVault?: VaultRef | null; apyBefore?: number | null; apyAfter?: number | null; } interface AgentMessagesResult { page: number; limit: number; total: number; pages: number; messages: AgentMessage[]; } interface BestVaultOption { chainId: number; vaultAddress: Address; } interface VaultDeploymentPrediction { chainId: number; factoryAddress: Address; predictedVaultAddress: Address; } type SurfEventMap = { "wallet:connected": WalletState; "wallet:disconnected": void; "wallet:accountChanged": { oldAddress: string; newAddress: string; }; "wallet:chainChanged": { chainId: number; }; "auth:authenticated": AuthState; "auth:logout": void; "vault:deployed": DeployVaultResult; "deposit:started": { asset: string; amount: string; }; "deposit:approved": { asset: string; txHash: string; }; "deposit:completed": { asset: string; amount: string; txHash: string; }; "withdraw:started": { asset: string; amount: string; }; "withdraw:completed": { asset: string; amount: string; txHash: string; }; error: { code: string; message: string; }; }; declare const DEFAULT_CHAIN_IDS: Record; declare const CHAIN_REGISTRIES: Record>; declare function getFactoryAddress(environment: Environment, chainId: number): Address; declare function getWethAddress(environment: Environment, chainId: number): Address; declare function cloneRegistries(): Record>; declare function getDefaultChainId(environment: Environment): number; declare const ETHEREUM_MAINNET_TOKENS: TokenConfig[]; declare const POLYGON_MAINNET_TOKENS: TokenConfig[]; declare const BASE_MAINNET_TOKENS: TokenConfig[]; declare class SurfClientBuilder { private config; private readonly registries; private readonly walletAdapters; constructor(); setProject(name: string, id: string): this; setAppId(id: string): this; setEnvironment(environment: Environment): this; setChain(chainId: number): this; setRpcUrl(url: string): this; setApiBaseUrl(url: string): this; setFactoryAddress(address: `0x${string}`): this; setAutoApprove(enabled: boolean): this; setLogLevel(level: SurfConfig["logger"]): this; registerWalletAdapter(name: string, adapter: IWalletAdapter): this; registerChain(environment: Environment, config: ChainConfig): this; registerToken(environment: Environment, chainId: number, token: TokenConfig): this; build(): SurfClient; } declare class SurfClient { static create(config: SurfConfig): SurfClient; static builder(): SurfClientBuilder; private readonly events; private readonly authState; private readonly config; private readonly registries; private readonly walletAdapters; private readonly httpClient; private readonly authService; private readonly vaultApiService; private readonly tokenService; private readonly factoryService; private readonly vaultService; private readProvider; private activeWalletAdapter; private walletState; constructor(options: SurfClientOptions); on(event: K, handler: (data: SurfEventMap[K]) => void): void; off(event: K, handler: (data: SurfEventMap[K]) => void): void; /** * Validates the configured `appId` against the backend by calling * `GET /api/sdk/public/overview` with the `x-app-id` header. A 2xx response means * the appId is valid and returns the overview payload. Call this during client * setup (appId is required). Throws `SurfError(INVALID_APP_ID)` if the appId is * missing or rejected by the backend. */ verifyApp(): Promise; connectWallet(walletName: WalletName | string): Promise; disconnectWallet(): Promise; getWalletState(): WalletState | null; /** * Switches the SDK's active chain (and the connected wallet, if any). After this, * all reads/writes target `chainId`: `config.chainId`, the read provider, the * factory address, and the token list are updated from the chain registry. * * The chain must be registered for the active environment, else `UNSUPPORTED_CHAIN`. * Auth is unaffected (the cookie session is per-wallet, not per-chain). Note: any * custom `rpcUrl`/`factoryAddress` set at creation is replaced by the target chain's * registry values (a single override can't serve multiple chains). */ switchChain(chainId: number): Promise; registerWalletAdapter(name: string, adapter: IWalletAdapter): void; authenticate(): Promise; getAuthState(): AuthState; logout(): Promise; /** * Extends the session using the existing httpOnly auth cookie — no wallet * signature required. Requires a currently-valid session cookie; throws * `API_ERROR` (401) if the cookie is missing, expired, or already revoked. * The backend rotates the cookie; the old token is invalidated immediately. */ refreshSession(): Promise; getVault(walletAddress?: Address): Promise; getSupportedAssets(chainId?: number): Promise; getAgentMessages(walletAddress?: Address, page?: number, limit?: number, from?: string, to?: string): Promise; deployVault(): Promise; getOwnerVaults(owner?: Address): Promise; getOwnerVaultCount(owner?: Address): Promise; isVaultFromFactory(vaultAddress: string): Promise; deposit(params: DepositParams): Promise; getBestVault(assetSymbol: string): Promise; hasInitialDeposit(asset: string, vaultAddress?: string): Promise; withdraw(params: WithdrawParams): Promise; getWithdrawableAmount(asset: string, vaultAddress?: string): Promise; getPortfolioSummary(vaultAddress?: string): Promise; getAssetProfit(asset: string, vaultAddress?: string): Promise; getAssetProfitPercentage(asset: string, vaultAddress?: string): Promise; getTokenBalance(token: string, owner?: string): Promise; getAllowedAssets(vaultAddress?: string): Promise; getFeeInfo(vaultAddress?: string): Promise; getConfig(): Readonly; getSupportedTokens(): TokenConfig[]; private getChainConfig; private resolveToken; private resolveBestVault; private resolveVaultAddress; private requireWallet; private getSignerRunner; private getReadRunner; private getGasOverrides; private getEthLowFees; private waitForAllowance; private estimateWriteGas; private isContractRevert; private toTransactionResult; } declare class EventEmitter> { private readonly listeners; on(event: K, handler: (payload: EventMap[K]) => void): void; off(event: K, handler: (payload: EventMap[K]) => void): void; emit(event: K, payload: EventMap[K]): void; } interface HttpClientOptions { baseUrl: string; projectName: string; projectId: string; appId: string; } declare class HttpClient { private readonly options; constructor(options: HttpClientOptions); getAppId(): string; get(path: string, headers?: HeadersInit): Promise; post(path: string, body?: unknown, headers?: HeadersInit): Promise; private request; private resolveUrl; } declare class AuthService { private readonly http; constructor(http: HttpClient); getNonce(address: string): Promise; login(address: string, message: string, signature: string): Promise; refresh(): Promise; getMe(): Promise; } declare class FactoryService { contract(factoryAddress: string, runner: ContractRunner): any; deployVault(factoryAddress: string, owner: string, salt: string, runner: ContractRunner, overrides?: Record): Promise; computeVaultAddress(factoryAddress: string, owner: string, salt: string, runner: ContractRunner): Promise; getOwnerVaults(factoryAddress: string, owner: string, runner: ContractRunner): Promise; getOwnerVaultCount(factoryAddress: string, owner: string, runner: ContractRunner): Promise; isVaultFromFactory(factoryAddress: string, vaultAddress: string, runner: ContractRunner): Promise; } declare class TokenService { allowance(tokenAddress: string, owner: string, spender: string, runner: ContractRunner): Promise; approve(tokenAddress: string, spender: string, amount: bigint, runner: ContractRunner, overrides?: Record): Promise; balanceOf(tokenAddress: string, owner: string, runner: ContractRunner): Promise; decimals(tokenAddress: string, runner: ContractRunner): Promise; wrapNative(amount: bigint, wethAddress: string, runner: ContractRunner, overrides?: Record): Promise; } interface PrepareVaultResponse { salt: string; homeChainId: number; predictions: VaultDeploymentPrediction[]; } declare class VaultApiService { private readonly http; constructor(http: HttpClient); getVault(walletAddress: string): Promise; prepare(homeChainId: number): Promise; confirm(input: { userVaultAddress: string; homeChainId: number; deploymentSalt: string; initialAssets: Array>; }): Promise; getPending(): Promise<{ deploymentSalt: string | null; chainId?: number; factoryAddress?: string; predictedVaultAddress?: string; } | null>; getSupportedAssets(chainId?: number): Promise; getAgentMessages(walletAddress: string, page?: number, limit?: number, from?: string, to?: string): Promise; getBestVault(assetSymbol: string): Promise; } declare class VaultService { contract(vaultAddress: string, runner: ContractRunner): any; assetHasInitialDeposit(vaultAddress: string, asset: string, runner: ContractRunner): Promise; initialDeposit(vaultAddress: string, asset: string, bestVault: string, amount: bigint, runner: ContractRunner, overrides?: Record): Promise; userDeposit(vaultAddress: string, asset: string, amount: bigint, runner: ContractRunner, overrides?: Record): Promise; withdraw(vaultAddress: string, asset: string, amount: bigint, runner: ContractRunner, overrides?: Record): Promise; getAssetAvailableVaults(vaultAddress: string, asset: string, runner: ContractRunner): Promise; getAssetVaultAssets(vaultAddress: string, asset: string, runner: ContractRunner): Promise; getPortfolioSummary(vaultAddress: string, runner: ContractRunner): Promise; getAssetProfit(vaultAddress: string, asset: string, runner: ContractRunner): Promise; getAssetProfitPercentage(vaultAddress: string, asset: string, runner: ContractRunner): Promise; getTokenBalance(vaultAddress: string, token: string, runner: ContractRunner): Promise; getAllowedAssets(vaultAddress: string, runner: ContractRunner): Promise; getFeeInfo(vaultAddress: string, runner: ContractRunner): Promise; } declare function parseTokenAmount(amount: string, decimals: number): bigint; declare function formatTokenAmount(amount: bigint, decimals: number): string; declare function addApprovalBuffer(amount: bigint, basisPoints?: bigint): bigint; declare enum SurfErrorCode { INVALID_CONFIG = "INVALID_CONFIG", MISSING_PROJECT_ID = "MISSING_PROJECT_ID", INVALID_APP_ID = "INVALID_APP_ID", INVALID_ENVIRONMENT = "INVALID_ENVIRONMENT", UNSUPPORTED_CHAIN = "UNSUPPORTED_CHAIN", ENVIRONMENT_CHAIN_MISMATCH = "ENVIRONMENT_CHAIN_MISMATCH", WALLET_NOT_INSTALLED = "WALLET_NOT_INSTALLED", WALLET_NOT_CONNECTED = "WALLET_NOT_CONNECTED", WALLET_REJECTED = "WALLET_REJECTED", WRONG_CHAIN = "WRONG_CHAIN", AUTH_FAILED = "AUTH_FAILED", SIGNATURE_REJECTED = "SIGNATURE_REJECTED", VAULT_NOT_FOUND = "VAULT_NOT_FOUND", VAULT_ALREADY_EXISTS = "VAULT_ALREADY_EXISTS", VAULT_DEPLOY_FAILED = "VAULT_DEPLOY_FAILED", INSUFFICIENT_BALANCE = "INSUFFICIENT_BALANCE", APPROVE_FAILED = "APPROVE_FAILED", DEPOSIT_FAILED = "DEPOSIT_FAILED", WITHDRAW_FAILED = "WITHDRAW_FAILED", NO_BEST_VAULT = "NO_BEST_VAULT", API_ERROR = "API_ERROR", RPC_ERROR = "RPC_ERROR", TRANSACTION_FAILED = "TRANSACTION_FAILED" } declare class SurfError extends Error { readonly code: SurfErrorCode; readonly cause?: unknown | undefined; constructor(code: SurfErrorCode, message: string, cause?: unknown | undefined); } declare function assertAddress(value: string, fieldName: string): void; declare function validateTokenConfig(token: TokenConfig): void; declare function validateChainConfig(chain: ChainConfig): void; declare function validateEnvironment(value: string): asserts value is Environment; declare function validateConfig(config: SurfConfig, chainExists: (environment: Environment, chainId: number) => boolean, defaultChainIdForEnvironment: (environment: Environment) => number): ResolvedSurfConfig; declare abstract class BaseWalletAdapter { protected provider: Eip1193Provider | undefined; private readonly listeners; abstract readonly name: string; abstract get installed(): boolean; protected abstract resolveProvider(): Eip1193Provider | undefined; connect(chainId: number): Promise; disconnect(): Promise; switchChain(chainId: number): Promise; getSigner(): Promise; getProvider(): Promise; getBrowserProvider(): Promise; signMessage(message: string): Promise; onAccountsChanged(cb: (accounts: string[]) => void): void; onChainChanged(cb: (chainId: number) => void): void; onDisconnect(cb: () => void): void; removeAllListeners(): void; protected requireProvider(): Eip1193Provider; protected bindListeners(provider: Eip1193Provider): void; } declare class CoinbaseAdapter extends BaseWalletAdapter { readonly name = "coinbase"; get installed(): boolean; protected resolveProvider(): Eip1193Provider | undefined; } declare class InjectedAdapter extends BaseWalletAdapter { readonly name = "injected"; get installed(): boolean; protected resolveProvider(): Eip1193Provider | undefined; } declare class MetaMaskAdapter extends BaseWalletAdapter { readonly name = "metamask"; get installed(): boolean; protected resolveProvider(): Eip1193Provider | undefined; } declare class PhantomAdapter extends BaseWalletAdapter { readonly name = "phantom"; get installed(): boolean; protected resolveProvider(): Eip1193Provider | undefined; } declare class RabbyAdapter extends BaseWalletAdapter { readonly name = "rabby"; get installed(): boolean; protected resolveProvider(): Eip1193Provider | undefined; } declare class TrustWalletAdapter extends BaseWalletAdapter { readonly name = "trust"; get installed(): boolean; protected resolveProvider(): Eip1193Provider | undefined; } declare class WalletConnectAdapter extends BaseWalletAdapter { private readonly providerFactory?; readonly name = "walletconnect"; constructor(providerFactory?: (() => Eip1193Provider | undefined) | undefined); get installed(): boolean; protected resolveProvider(): Eip1193Provider | undefined; connect(chainId: number): Promise; } export { type Address, type AgentMessage, type AgentMessagesResult, AuthService, type AuthState, BASE_MAINNET_TOKENS, BaseWalletAdapter, type BestVaultOption, CHAIN_REGISTRIES, type ChainConfig, type ChainId, CoinbaseAdapter, DEFAULT_CHAIN_IDS, type DeployVaultResult, type DepositParams, ERC20Abi, ETHEREUM_MAINNET_TOKENS, type Environment, EventEmitter, FactoryAbi, FactoryService, type FeeInfo, HttpClient, type HttpClientOptions, type IWalletAdapter, InjectedAdapter, type LogLevel, type LoginResponse, MetaMaskAdapter, type NonceResponse, POLYGON_MAINNET_TOKENS, PhantomAdapter, type PortfolioSummary, type PrepareVaultResponse, RabbyAdapter, type RefreshResult, type ResolvedSurfConfig, type SupportedAsset, SurfClient, SurfClientBuilder, type SurfClientOptions, type SurfConfig, SurfError, SurfErrorCode, type SurfEventMap, type TokenConfig, TokenService, type TransactionResult, TrustWalletAdapter, type UserProfile, VaultAbi, VaultApiService, type VaultApyBreakdown, type VaultAsset, type VaultChainAddress, type VaultDeploymentPrediction, type VaultEarned, type VaultInfo, type VaultLeague, type VaultRef, VaultService, WETHAbi, WalletConnectAdapter, type WalletName, type WalletState, type WithdrawParams, addApprovalBuffer, assertAddress, cloneRegistries, formatTokenAmount, getDefaultChainId, getFactoryAddress, getWethAddress, parseTokenAmount, validateChainConfig, validateConfig, validateEnvironment, validateTokenConfig };