UNPKG

@funkit/connect

Version:

Funkit Connect SDK elevates DeFi apps via web2 sign-ins and one-click checkouts.

183 lines (182 loc) 8.09 kB
/** * Lighter.xyz withdrawal. * * Lighter supports two withdrawal types — the SDK exposes them as a * multi-method config so the user is shown a selection screen first: * * 1. **Fast** — routed through Fun + Relay. USDC Perps only. Multiple * destination chains/tokens supported. Completes in seconds. * 2. **Secure** — Lighter's native bridge to Ethereum mainnet. Supports all * Lighter assets. Destination chain is locked to Ethereum and the * destination token matches the source. Completion ~60+ minutes. * * Both callbacks conform to CustomWithdrawalConfig.withdrawCallback; the * caller provides the actual on-chain implementation. */ import { type Address } from 'viem'; import type { CustomWithdrawalConfig, LighterRouteType, MultiMethodWithdrawalConfig } from '../providers/FunkitCheckoutContext/types'; export { LIGHTER_ROUTE_TYPE } from '../modals/WithdrawalModal/LighterWithdrawal'; export type { LighterRouteType } from '../providers/FunkitCheckoutContext/types'; export type LighterTransferParams = { toAccountIndex: number; assetIndex: number; fromRouteType: number; toRouteType: number; amount: number; usdcFee: number; memo: string; ethSigner?: { signMessage: (message: string) => Promise<string>; }; nonce?: number; }; export type LighterTransaction = { hash: string; status: number | 'pending' | 'confirmed' | 'failed'; block_height?: number; message?: string; }; export type LighterSigner = { transfer: (params: LighterTransferParams) => Promise<[unknown, string, string | null]>; }; export interface LighterWithdrawalConfig { /** * The connected user's L1 address. The hook resolves the Lighter account * index from this internally — get it from `useFunkitUserInfo` (or your * own wallet hook) in the caller and pass it through. */ l1Address: Address; /** Title shown on the selection screen. Defaults to "Withdraw". */ modalTitle?: string; disableConnectedWallet?: boolean; fastIconSrc?: string; secureIconSrc?: string; /** Pre-built Lighter signer. */ signerClient: LighterSigner; sendLighterSecureWithdrawal: LighterSecureWithdrawalExec; /** * Returns the minimum Secure withdrawal amount in token units for the given symbol. * Spot USDC is passed as `USDC (Spot)` (perps collateral is plain `USDC`); * return `undefined` to fall back to the per-base-symbol defaults. * * ```ts * getSecureMinWithdrawalAmount: (symbol) => ({ USDC: 1, ETH: 0.001 }[symbol] ?? 0) * ``` */ getSecureMinWithdrawalAmount?: (symbol: string) => number | undefined; /** * Awaited hook fired after the user taps "Withdraw" but before either method * (Fast or Secure) fetches a nonce, prompts the wallet, or submits the L2 tx. * * Lighter strategies and withdrawals share the same L2 signing account, so a * strategy that's still placing/cancelling orders will bump the nonce out * from under the withdrawal and the signed tx is rejected. Cancel in-flight * strategies here (awaited) so the withdrawal signs against a stable nonce. * * Throw to abort the withdrawal — the message is shown to the user verbatim * and no nonce is consumed. Applies to both Fast and Secure. */ onBeforeSign?: () => Promise<void> | void; } /** * Default minimum Secure-withdrawal amounts (token units) for known Lighter * assets. Used as a fallback when `LighterWithdrawalConfig.getSecureMinWithdrawalAmount` * is omitted or returns `undefined` for a symbol. */ export declare const LIGHTER_DEFAULT_SECURE_MIN_WITHDRAWAL_AMOUNTS: Record<string, number>; export interface LighterSecureWithdrawalCallbackParams { /** Withdrawal amount in token units (e.g. "1.5" for 1.5 ETH). */ amountTokenUnits: string; /** The Lighter asset index (e.g. 1 for ETH, 3 for USDC). */ assetIndex: number; /** * Lighter L2 route type ({@link LIGHTER_ROUTE_TYPE}: 0 = perps / USDC * collateral, 1 = spot). Pass it through to `client.withdraw({ routeType })` * — USDC shares asset index 3 across both routes, so the route type is what * selects Perps vs Spot. */ routeType: LighterRouteType; } type LighterSecureWithdrawalExec = (params: LighterSecureWithdrawalCallbackParams) => Promise<string>; export interface LighterSecureWithdrawalConfig { accountIndex: string; modalTitle?: string; disableConnectedWallet?: boolean; iconSrc?: string; /** * Submit the Secure withdrawal on Lighter's L2. Funds bridge directly to * Ethereum mainnet. No relay/swap — the token withdrawn is the token received. */ sendLighterSecureWithdrawal: LighterSecureWithdrawalExec; /** * Returns the minimum withdrawal amount in token units for the given symbol. * * ```ts * getMinWithdrawalAmount: (symbol) => ({ USDC: 1, ETH: 0.001 }[symbol] ?? 0) * ``` */ getMinWithdrawalAmount?: (symbol: string) => number; /** * Awaited hook fired before the Secure withdrawal fetches a nonce, prompts * the wallet, or submits the L2 tx. See {@link LighterWithdrawalConfig['onBeforeSign']}. */ onBeforeSign?: () => Promise<void> | void; } /** * Records a Lighter Secure withdrawal in Fun's direct-execution table as * `EXTERNALLY_FULFILLED` — tracking-only, since Fun is not in the execution * path. The row is keyed off the L2 tx hash and exists purely for attribution * and support tooling; the backend writes a one-time terminal `listenerInfo` * and never polls for L1 settlement (see EXTERNALLY_FULFILLED design doc). * * Fire-and-forget: callers should not await this, and any failure here must * not block the withdrawal success UI. Failures log at warn/error and return. */ export declare function trackLighterSecureWithdrawal({ apiKey, userId, txHash, recipientAddr, assetIndex, mainnetTokenAddress, amountTokenUnits, withdrawalUSD, }: { apiKey: string; userId: string; txHash: string; recipientAddr: Address; /** * Lighter L2 asset index. Used as `fromTokenAddress` * (`pad(toHex(assetIndex))`) and to resolve symbol + mainnet decimals from * {@link LIGHTER_SECURE_ASSETS_BY_INDEX}. */ assetIndex: number; /** Mainnet ERC-20 address the L2 asset bridges to (resolved by the modal). */ mainnetTokenAddress: Address; /** User-input amount in token units (e.g. "1.5" for 1.5 ETH). */ amountTokenUnits: string; /** * USD value of the withdrawal as computed by the modal (token amount × live * spot price). Avoids a separate spot-price round-trip from this helper. */ withdrawalUSD: string; }): Promise<void>; /** Single-method config for Lighter's Secure withdrawal (bridge to Ethereum). */ export declare function createLighterSecureWithdrawalConfig(config: LighterSecureWithdrawalConfig): CustomWithdrawalConfig; /** * The single React entry point for Lighter withdrawals. Returns a * `MultiMethodWithdrawalConfig` ready to hand to the withdrawal modal, or * `null` while the inputs aren't ready yet. * * The hook owns every Lighter-specific concern that requires React context: * - the user's Lighter account index (resolved from `config.l1Address`) * - the live Secure-withdrawal delay (`/api/v1/withdrawalDelay`) * - the active locale (so the disclaimer renders correctly) * * Pass `null` while prerequisites (wallet, signer, etc.) aren't ready — the * hook always invokes its inner hooks (Rules of Hooks) and returns `null` * until you supply a real config and the account resolves: * * ```tsx * const { address: l1Address } = useFunkitUserInfo() * const lighter = useLighterWithdrawalConfig( * l1Address && walletClient * ? { l1Address, signerClient, sendLighterSecureWithdrawal, ... } * : null, * ) * if (!lighter) return { ready: false, disabledReason: '...' } * ``` */ export declare function useLighterWithdrawalConfig(config: LighterWithdrawalConfig | null): MultiMethodWithdrawalConfig | null;