import { type CheckoutQuoteResponse } from '@funkit/utils'; import { type Address, type Hex, type PublicClient } from 'viem'; import type { SwappedSellOrderData } from '../interfaces/swappedTransport'; import type { WithdrawalClient } from '../interfaces/withdrawalClient'; import type { FunLogger } from '../utils/funLogger'; /** Swapped's minimum sell amount, in EUR (its internal unit). */ export declare const SWAPPED_MIN_SELL_EUR = 7; /** * Balance-derived EUR cap for a Swapped sell: floor the USD balance converted * at `eurRate` so the sell never exceeds what the user holds and the /fops * query key stays stable against sub-unit balance jitter. Undefined when there * is no positive balance or the rate hasn't resolved (→ no cap). */ export declare function getSwappedSellCapEur(usdBalance: number, eurRate: number | undefined): number | undefined; /** * USD equivalent of Swapped's EUR sell minimum, for the "balance too low for * cash" gate. Undefined while the EUR rate is unresolved (gate stays open). */ export declare function getSwappedCashMinUsd(eurRate: number | undefined): number | undefined; export interface SwappedSellLimits { defaultMinAmount: number; defaultMaxAmount?: number; } /** * The `checkoutLimitsCriteria` for a Swapped sell: always the fixed EUR * minimum, plus the balance-derived cap only when it clears the minimum (a max * at/below the min is a contradictory range for Swapped's iframe). */ export declare function buildSwappedSellLimits(eurMax: number | null | undefined): SwappedSellLimits; /** * Operator override (Statsig `swappedwithdrawalsourceoverrides`) pinning a * Swapped withdrawal to a known-good accepted asset, keyed on the source asset, * for when the config's requested target isn't supported by Swapped. `when` * matches the source; `use` is the target the Relay quote delivers. */ export interface SwappedSourceRouteOverride { when: { chainId: string; tokenAddress: string; }; use: { chainId: string; tokenAddress: Address; symbol: string; }; } /** * First well-formed override whose `when` matches the source asset, or * `undefined`. First match wins so ops can order more specific rules ahead of * broader ones. */ export declare function findSwappedSourceOverride(overrides: readonly SwappedSourceRouteOverride[] | undefined, source: { chainId: string; tokenAddress: string; }): SwappedSourceRouteOverride | undefined; /** The token the user holds/sells (the on-chain source leg). */ export interface SwappedWithdrawalSourceToken { /** Numeric chain id as a string, matching api-base's token shapes. */ chainId: string; address: string; symbol: string; } /** The token Swapped accepts (the on-chain target leg), when ≠ source. */ export interface SwappedWithdrawalTargetToken { chainId: string; address: string; symbol: string; } /** * On-chain legs of a Swapped order (source the user holds, target the provider * accepts). Target precedence: Statsig override `use` > configured target > * source (same-asset). Single source of truth for the FOP fetch and the quote — * they must agree or the `/fops` rail and the delivered asset diverge. */ export declare function resolveSwappedWithdrawalLegs({ source, target, override, }: { source: SwappedWithdrawalSourceToken; target?: SwappedWithdrawalTargetToken; override?: SwappedSourceRouteOverride; }): { sourceChainId: number; sourceTokenAddress: Address; sourceTokenSymbol: string; targetTokenAddress: Address; targetChainId: string; targetTokenSymbol: string; overrideApplied: boolean; }; export type SwappedWithdrawalLegs = ReturnType; /** * Provider-agnostic fiat off-ramp order: deliver `amount` of the accepted * token to `destinationAddress`. Mirrors @funkit/connect's `FiatWithdrawalOrder` * (useFiatWithdrawal.ts) — keep the shapes in sync until web migrates here. */ export interface FiatWithdrawalOrder { orderId: string; destinationAddress: Address; /** Amount (human units) of the target/accepted token the provider expects. */ amount: string; /** * Provider-reported accepted asset, by name (e.g. `'USDC'` / `'base'`). * Informational only — surfaced in the route-decision log for reconciliation, * never used to determine routing (routing comes from the resolved legs). */ providerCrypto?: string; providerNetwork?: string; } /** * Guard for the embed's SWAPPED_ORDER_DATA payload. Rejected payloads take the * recoverable embed-error path rather than failing mid-execution: * - `address` must be a valid EVM address — it becomes the relay quote * `recipientAddress` / DirectExecution `recipientAddr`, which this pipeline * never validates downstream (the flow is EVM-only by construction). * - `amount` drives the EXACT_OUT transaction, so it must be a positive plain * decimal `parseUnits` can parse — no sign / exponent / whitespace / hex. */ export declare function isValidOrderData(data: SwappedSellOrderData | undefined): data is SwappedSellOrderData; /** Map a validated embed payload onto the provider-agnostic order shape. */ export declare function toFiatWithdrawalOrder(data: SwappedSellOrderData): FiatWithdrawalOrder; /** * Full-precision human-amount → base-unit conversion for the EXACT_OUT quote. * * Precision is preserved by passing the original amount string straight to * `parseUnits` — never coerced through a JS Number first. Fractional digits * beyond the token's precision are trimmed. Malformed input is left to throw: * for an EXACT_OUT order, silently sending a wrong amount is worse than * surfacing an error (the embed shows its error state). Callers gate on * {@link isValidOrderData} first, so valid orders never reach the throw. */ export declare function toWithdrawalAmountBaseUnit(amount: string, decimals: number): bigint; export type FiatWithdrawalErrorCode = 'MISSING_DECIMALS_READER' | 'MISSING_RELAY_QUOTE' | 'MISSING_TX_HASH'; /** Typed pre-execution failure so callers can branch without string matching. */ export declare class FiatWithdrawalError extends Error { readonly code: FiatWithdrawalErrorCode; constructor(code: FiatWithdrawalErrorCode, message: string); } export interface ProcessFiatWithdrawalOrderParams { order: FiatWithdrawalOrder; wallet: WithdrawalClient; legs: SwappedWithdrawalLegs; apiKey: string; userId: string; logger: FunLogger; /** * Read-only client on the TARGET chain for the erc20 `decimals()` read. * Unused (and optional) when `targetDecimals` is provided. */ publicClient?: Pick; /** Known target-token decimals — skips the on-chain read. */ targetDecimals?: number; /** Relay step progress (raw step action text), for optional host display. */ onStepMessage?: (message: string) => void; } /** * The headless order → quote → execute → record pipeline for a Swapped fiat * off-ramp withdrawal (port of @funkit/connect's `useFiatWithdrawal` + * `confirmCheckout` direct-execution path, framework-free). * * Quoting is delegated to ./quote (EXACT_OUT) — the provider credits fiat on * the exact deposited amount, so we deliver exactly what it expects; the wallet * pays whatever source amount the quote requires. Callers own re-entrancy/dedupe * guards and user-rejection handling (see `isUserRejectedError`); pre-record * steps throw on failure. A failed reconciliation record after the tx settles * does NOT throw (see below), so the caller can't misread it as an execution * failure. * * Requires the process-global relay client to be initialized first * (`ensureRelayClientInitialized`). */ export declare function processFiatWithdrawalOrder({ order, wallet, legs, apiKey, userId, logger, publicClient, targetDecimals, onStepMessage, }: ProcessFiatWithdrawalOrderParams): Promise<{ txHash: Hex; quote: CheckoutQuoteResponse; }>; //# sourceMappingURL=swappedWithdrawal.d.ts.map