/** * Defensive “gas eats profit” floor for Base micropayments. * * When L2 gas spikes, $0.001–$0.01 charges can become uneconomic. With * `X402_DYNAMIC_MIN_ENABLED=true`, we estimate settle gas in USD from a * cached base-fee oracle and bump the minimum accept amount (and optionally * raise feeFreeBelow so FeeSplitter+release isn’t used until larger amounts). * * Default OFF — demo `$0.001` still works under normal Base fees. */ /** Subset of TollgateConfig needed by the gas floor (avoids circular imports). */ export interface GasFloorConfig { price: string; feeBps: number; feeFreeBelowUsdc: bigint; minPriceUsdc: bigint; dynamicMinEnabled: boolean; gasCostMaxFraction: number; gasOracleRpcUrl: string; gasOracleTtlMs: number; gasUsedEstimate: number; ethUsd: number; } /** Default gas units for a rough L2 EIP-3009 / ERC-20 settle estimate. */ export declare const DEFAULT_GAS_USED_ESTIMATE = 100000; /** Conservative ETH/USD floor when no live price feed (higher → more protective). */ export declare const DEFAULT_ETH_USD = 4000; /** Max fraction of payment that estimated gas may consume before bumping (50%). */ export declare const DEFAULT_GAS_COST_MAX_FRACTION = 0.5; /** Base-fee cache TTL (ms). Clamped to 15–60s. */ export declare const DEFAULT_GAS_ORACLE_TTL_MS = 30000; export declare const MIN_GAS_ORACLE_TTL_MS = 15000; export declare const MAX_GAS_ORACLE_TTL_MS = 60000; export type GasFloorReason = "disabled" | "static" | "min_floor" | "gas"; export interface GasFloorSnapshot { enabled: boolean; /** Configured PRICE as atomic USDC. */ configuredPriceAtomic: bigint; /** Static X402_MIN_PRICE_USDC (0 when unset). */ minPriceUsdc: bigint; /** Configured fee-free threshold. */ configuredFeeFreeBelowUsdc: bigint; /** Enforced / displayed minimum accept amount (atomic USDC). */ effectiveMinPriceAtomic: bigint; /** Effective fee-free threshold after optional gas-aware raise. */ effectiveFeeFreeBelowUsdc: bigint; /** Dollar form of effective min (e.g. `$0.001`). */ effectiveMinPrice: string; /** Last observed / injected base fee (wei), or null. */ baseFeeWei: string | null; /** Estimated L2 gas cost in USD, or null when unknown / disabled. */ estimatedGasCostUsd: number | null; gasCostMaxFraction: number; ethUsd: number; gasUsedEstimate: number; bumped: boolean; reason: GasFloorReason; oracleTtlMs: number; cachedAt: number | null; } export interface ComputeEffectiveMinsInput { priceAtomic: bigint; minPriceUsdc: bigint; feeFreeBelowUsdc: bigint; dynamicMinEnabled: boolean; /** null → skip gas bump (static floors only). */ gasCostUsd: number | null; gasCostMaxFraction: number; /** Operator fee bps — used to raise feeFreeBelow so 0.1% can cover release gas. */ feeBps: number; usdcDecimals?: number; } /** * Pure floor math (unit-testable with mocked gas USD). * * - effectiveMin = max(price, minPriceUsdc, gasDerivedMin when enabled) * - gasDerivedMin = ceil(gasCostUsd / maxFraction) in atomic USDC * - When gas forces a bump, also raise feeFreeBelow so FeeSplitter+release * is deferred until amounts where feeBps can cover estimated gas. */ export declare function computeEffectiveMins(input: ComputeEffectiveMinsInput): { effectiveMinPriceAtomic: bigint; effectiveFeeFreeBelowUsdc: bigint; bumped: boolean; reason: GasFloorReason; gasDerivedMinAtomic: bigint | null; }; /** gasUsed * baseFeeWei * ethUsd / 1e18 */ export declare function estimateGasCostUsd(baseFeeWei: bigint, gasUsedEstimate: number, ethUsd: number): number; export declare function usdToAtomicUsdc(usd: number, decimals?: number): bigint; export declare function dollarPriceToAtomic(price: string, decimals?: number): bigint; export declare function atomicUsdcToDollarPrice(atomic: bigint, decimals?: number): string; export type BaseFeeFetcher = () => Promise; export interface GasFloorOracleOptions { rpcUrl: string; ttlMs: number; /** Inject for tests. */ fetchBaseFee?: BaseFeeFetcher; /** Inject clock for tests. */ now?: () => number; fetchImpl?: typeof fetch; } /** Cached eth_getBlockByNumber baseFeePerGas reader (TTL 15–60s). */ export declare function createBaseFeeOracle(options: GasFloorOracleOptions): { getBaseFeeWei: () => Promise; peekCache: () => { baseFeeWei: bigint; fetchedAt: number; } | null; clearCache: () => void; }; export declare function clampTtl(ms: number): number; export declare function defaultRpcUrlForNetwork(network: string): string; export interface GasFloorService { getSnapshot: () => Promise; /** Sync view using last cached base fee (no RPC). Safe for middleware rewrites. */ getSnapshotSync: () => GasFloorSnapshot; /** Refresh cache (no-op when dynamic disabled). */ refresh: () => Promise; clearCache: () => void; } export declare function createGasFloorService(config: GasFloorConfig, options?: { fetchBaseFee?: BaseFeeFetcher; now?: () => number; fetchImpl?: typeof fetch; }): GasFloorService;