@latchprotocol/widgets 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -3
- package/dist/chunks/{SwapWidget-DgyHAVc8.js → SwapWidget-B0oDyBNK.js} +58 -66
- package/dist/chunks/SwapWidget-B0oDyBNK.js.map +1 -0
- package/dist/chunks/{scan-Dhu7f4Nl.js → scan-Cdm3p_wF.js} +2 -2
- package/dist/chunks/scan-Cdm3p_wF.js.map +1 -0
- package/dist/chunks/{useLocker-D1c_NTk-.js → useLocker-m3WH-bQm.js} +641 -641
- package/dist/chunks/{useLocker-D1c_NTk-.js.map → useLocker-m3WH-bQm.js.map} +1 -1
- package/dist/components/LaunchWidget.d.ts.map +1 -1
- package/dist/embed/lockBadge.d.ts +1 -1
- package/dist/embed.js +16 -16
- package/dist/embed.js.map +1 -1
- package/dist/headless.js +2 -2
- package/dist/index.js +90 -90
- package/dist/index.js.map +1 -1
- package/dist/latch-embed.js +1 -1
- package/dist/latch-embed.js.map +1 -1
- package/dist/latch-embed.mjs +5 -6
- package/dist/latch-embed.mjs.map +1 -1
- package/dist/trust/model.d.ts +4 -3
- package/dist/trust/model.d.ts.map +1 -1
- package/package.json +1 -5
- package/dist/chunks/SwapWidget-DgyHAVc8.js.map +0 -1
- package/dist/chunks/scan-Dhu7f4Nl.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scan-Dhu7f4Nl.js","sources":["../../src/config/chain.ts","../../src/config/integrator.ts","../../src/core/math.ts","../../src/context/WidgetProvider.tsx","../../src/core/format.ts","../../src/callpath/constants.ts","../../src/callpath/plan.ts","../../src/callpath/swap.ts","../../src/callpath/launch.ts","../../src/hooks/useAsyncResource.ts","../../src/adapters/protocol.ts","../../src/core/errors.ts","../../src/hooks/useSwapExecute.ts","../../src/hooks/useSwapQuote.ts","../../src/hooks/useLaunch.ts","../../src/hooks/useTokens.ts","../../src/core/clMath.ts","../../src/core/liquidityGuards.ts","../../src/core/pool.ts","../../src/hooks/useLiquidity.ts","../../src/core/liquidityRefresh.ts","../../src/core/tokenLists.ts","../../src/hooks/useTokenLists.ts","../../src/components/swap/state.ts","../../src/locks/fetch.ts","../../src/locks/model.ts","../../src/locks/embedModel.ts","../../src/locks/scan.ts"],"sourcesContent":["// SPDX-License-Identifier: MIT\n/**\n * Chain and deployment configuration.\n *\n * LatchProtocol targets many chains, and nothing in this package knows which one\n * you are on. There are no bundled RPC URLs and no address book: every address\n * and every transport arrives from the embedder through a {@link ChainConfig}.\n * That is deliberate - a hardcoded address is a bug that ships to every host.\n */\n\nimport { getAddress, isAddress, type Address, type Transport } from \"viem\";\n\n/** Native asset metadata for a chain. */\nexport interface NativeCurrencyConfig {\n readonly name: string;\n readonly symbol: string;\n readonly decimals: number;\n}\n\n/**\n * Deployed contract addresses.\n *\n * Only `vault` and at least one pool manager are structurally required. The\n * rest are required by the operations that use them, and the widgets fail with\n * a named error rather than a decoding failure when one is missing.\n */\nexport interface ContractAddresses {\n /** The singleton that custodies every token in the protocol. */\n readonly vault: Address;\n /** Concentrated-liquidity pool manager. */\n readonly clPoolManager?: Address;\n /** Liquidity-book (bin) pool manager. */\n readonly binPoolManager?: Address;\n /** Universal router - the entry point for swaps and integrator fees. */\n readonly universalRouter?: Address;\n /** Position manager for concentrated-liquidity positions. */\n readonly clPositionManager?: Address;\n /** Position manager for liquidity-book positions. */\n readonly binPositionManager?: Address;\n /** Permit2, used by the router to pull the input currency. */\n readonly permit2?: Address;\n /** Off-path CL quoter (`CLQuoter`), if one is deployed. Quotes concentrated-liquidity hops. */\n readonly quoter?: Address;\n /** Off-path `BinQuoter`, if one is deployed. Quotes liquidity-book hops. */\n readonly binQuoter?: Address;\n /**\n * `LaunchGuardHook`, the hook that backs the launch widget.\n *\n * Not a launchpad and not a sale contract: it is the hook a launch pool names\n * in its `PoolKey`, and the launch widget reads its per-pool schedule. Leave\n * it unset on a chain where no `LaunchGuardHook` is deployed — the widget\n * renders a \"not configured on this chain\" state, which is the truth. Setting\n * it to an address that is not a `LaunchGuardHook` produces read failures,\n * not a fallback.\n */\n readonly launchGuardHook?: Address;\n /**\n * How `launchGuardHook` measures time: `\"timestamp\"` for the current build,\n * `\"contract-block\"` for the block-numbered one still deployed on Robinhood.\n * Take it from `LatchDeployment.durationClocks.launchGuardHook` in the SDK.\n * When omitted, the live adapter uses the SDK record if the address matches it,\n * and otherwise asks the hook (`CLOCK_MODE()`), never guessing.\n */\n readonly launchGuardHookClock?: \"timestamp\" | \"contract-block\";\n /**\n * `BinLaunchGuardHook`: the launch guard a Bin (liquidity-book) launch pool\n * names in its `PoolKey`. Same schedule, same gates, same `getLaunch` shape\n * as the CL guard; only ever built on `block.timestamp`. Leave it unset where\n * none is deployed.\n */\n readonly binLaunchGuardHook?: Address;\n /**\n * `LaunchpadKitV2`, the locked-launch kit. With it set, a launch can be\n * looked up by its TOKEN (`legsOf(token)` names every pool the launch\n * opened) instead of by one pool id. The pools themselves must still be in\n * the host's pool list: the singleton enumerates nothing.\n */\n readonly launchpadKitV2?: Address;\n}\n\n/** Everything the widgets need to know about the chain they are pointed at. */\nexport interface ChainConfig {\n readonly chainId: number;\n readonly name: string;\n readonly nativeCurrency: NativeCurrencyConfig;\n readonly contracts: ContractAddresses;\n /**\n * viem transport for reads. Omitted when the host drives reads itself (for\n * example through wagmi).\n */\n readonly transport?: Transport;\n readonly blockExplorerUrl?: string;\n /** Seconds added to `block.timestamp` for transaction deadlines. */\n readonly defaultDeadlineSeconds?: number;\n}\n\n/** Names of the addresses a caller can require. */\nexport type ContractName = keyof ContractAddresses;\n\n/** Raised when the chain config cannot support a requested operation. */\nexport class ChainConfigError extends Error {\n readonly chainId: number;\n readonly contract: ContractName | null;\n\n constructor(message: string, chainId: number, contract: ContractName | null = null) {\n super(`[@latchprotocol/widgets] ${message}`);\n this.name = \"ChainConfigError\";\n this.chainId = chainId;\n this.contract = contract;\n }\n}\n\nconst ZERO = \"0x0000000000000000000000000000000000000000\";\n\nfunction assertAddress(value: unknown, label: string, chainId: number, name: ContractName): Address {\n if (typeof value !== \"string\" || !isAddress(value)) {\n throw new ChainConfigError(\n `chain ${chainId}: ${label} is not a valid address: ${JSON.stringify(value)}`,\n chainId,\n name,\n );\n }\n const checksummed = getAddress(value);\n if (checksummed === ZERO) {\n throw new ChainConfigError(\n `chain ${chainId}: ${label} is the zero address. Pass the deployed address ` +\n \"from the address book.\",\n chainId,\n name,\n );\n }\n return checksummed;\n}\n\n/**\n * Structural validation of a chain config.\n *\n * Checks shape only. It cannot tell you an address is wrong, just that it is\n * well-formed and present.\n */\nexport function assertValidChainConfig(config: ChainConfig): void {\n if (!Number.isInteger(config.chainId) || config.chainId <= 0) {\n throw new ChainConfigError(\n `chainId must be a positive integer, received ${String(config.chainId)}`,\n Number(config.chainId) || 0,\n );\n }\n if (config.nativeCurrency.decimals < 0 || config.nativeCurrency.decimals > 36) {\n throw new ChainConfigError(\n `nativeCurrency.decimals is out of range: ${config.nativeCurrency.decimals}`,\n config.chainId,\n );\n }\n assertAddress(config.contracts.vault, \"contracts.vault\", config.chainId, \"vault\");\n if (!config.contracts.clPoolManager && !config.contracts.binPoolManager) {\n throw new ChainConfigError(\n `chain ${config.chainId}: at least one of contracts.clPoolManager or ` +\n \"contracts.binPoolManager must be set\",\n config.chainId,\n );\n }\n}\n\n/**\n * Reads a required address, failing with a message that names what is missing\n * and which operation needed it.\n */\nexport function requireContract(\n config: ChainConfig,\n name: ContractName,\n usedFor: string,\n): Address {\n const value = config.contracts[name];\n if (value === undefined) {\n throw new ChainConfigError(\n `chain ${config.chainId} (${config.name}): contracts.${name} is not configured, ` +\n `but it is required to ${usedFor}.`,\n config.chainId,\n name,\n );\n }\n return assertAddress(value, `contracts.${name}`, config.chainId, name);\n}\n\n/**\n * The best reading of the clock the NEXT block will carry: the later of the\n * pending block's timestamp and the latest block's, ignoring whichever could\n * not be read; `null` when neither was.\n *\n * WHY THE PENDING BLOCK. `max(latest.timestamp, localNow)` covers an idle\n * chain whose clock matches wall time, and a chain whose clock is AHEAD of\n * wall time (a devnet after `evm_increaseTime`) while it is busy. It does not\n * cover the two together: a chain running ahead of wall time whose last block\n * is older than the deadline window. Its next block is stamped about\n * `localNow + offset`, later than `latest + window`, and `localNow` is below\n * `latest`, so neither term reaches it and the transaction arrives expired.\n * Nothing on the client can know the offset without asking the node; the\n * pending block is that question (anvil and geth-style nodes stamp it with the\n * next block's time). Where the RPC has no pending block it refuses or echoes\n * the latest, and the bound falls back to the latest block's - the residual\n * case is then that one combination on such an RPC, which the window's size\n * (20 minutes by default) makes rare, and the user's wallet reports as the\n * router's deadline error rather than a loss.\n */\nexport function nextBlockClock(pending: bigint | null, latest: bigint | null): bigint | null {\n if (pending === null) return latest;\n if (latest === null) return pending;\n return pending > latest ? pending : latest;\n}\n\n/**\n * Default transaction deadline: base + configured window, as a unix timestamp,\n * where base = max(chain clock, local clock).\n *\n * `nowSeconds` should be the chain's clock (the next block's, see\n * {@link nextBlockClock} and {@link chainDeadline}); the local clock is only\n * the fallback. The later of the two is used, so an idle chain whose last block\n * is old does not produce a deadline that has passed by the time the next\n * block is mined, and a chain ahead of wall time is not given a deadline in\n * its past.\n */\nexport function defaultDeadline(config: ChainConfig, nowSeconds?: number | bigint): bigint {\n const window = BigInt(config.defaultDeadlineSeconds ?? 20 * 60);\n const local = BigInt(Math.floor(Date.now() / 1000));\n const chain = nowSeconds === undefined ? local : BigInt(nowSeconds);\n return (chain > local ? chain : local) + window;\n}\n\n/**\n * The deadline for a transaction about to be built: the chain's clock (the\n * adapter's `getBlockTimestamp`, which the viem adapter reads from the pending\n * block where the RPC serves one) or the local clock, whichever is later, +\n * the configured window. A failed\n * block read falls back to the local clock rather than blocking the trade.\n */\nexport async function chainDeadline(\n config: ChainConfig,\n adapter: { getBlockTimestamp?(): Promise<bigint> },\n): Promise<bigint> {\n if (adapter.getBlockTimestamp === undefined) return defaultDeadline(config);\n try {\n return defaultDeadline(config, await adapter.getBlockTimestamp());\n } catch {\n return defaultDeadline(config);\n }\n}\n\n/**\n * Explorer link for a transaction hash, or `null` when no explorer is set.\n *\n * The one place a widget builds an explorer link. An empty (or whitespace-only)\n * `blockExplorerUrl` is NO explorer: a host running against a local devnet\n * passes \"\" or leaves it out, and a link to \"/tx/0x…\" would open this page.\n * Callers render the bare hash instead.\n */\nexport function explorerTxUrl(config: Pick<ChainConfig, \"blockExplorerUrl\">, hash: string): string | null {\n const base = (config.blockExplorerUrl ?? \"\").trim().replace(/\\/+$/, \"\");\n if (base === \"\") return null;\n return `${base}/tx/${hash}`;\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Integrator fee attribution.\n *\n * This is the module that makes the widgets worth embedding. An integrator -\n * the team whose app hosts the widget - names a `referrer` address and a fee in\n * basis points, and that fee is taken out of the swap's **output** currency and\n * paid to the referrer inside the same transaction as the swap.\n *\n * The fee is not an accounting entry we settle later. It is an action in the\n * swap plan (`TAKE_PORTION`), or a command in the router plan (`PAY_PORTION`),\n * so it either happens atomically with the swap or the whole transaction\n * reverts. Nothing is trusted, escrowed or owed.\n *\n * ## Invariants enforced here\n *\n * 1. `feeBps` is an integer in `[0, MAX_INTEGRATOR_FEE_BPS]`.\n * 2. A non-zero `feeBps` requires a syntactically valid, non-zero `referrer`.\n * Configuring a fee with no destination is a loud failure, never a silent\n * zero: the alternative is a widget that quietly earns the embedder nothing.\n * 3. The predicted fee uses the same arithmetic as the contracts\n * (`amount * bps / 10_000`, truncating), so the number shown in the UI is\n * the number the chain pays out - not an estimate.\n */\n\nimport { getAddress, isAddress, type Address } from \"viem\";\n\n/** Basis-point denominator. 10_000 bps = 100%. */\nexport const BPS_DENOMINATOR = 10_000;\n\n/**\n * Largest integrator fee the widgets will encode, in basis points (1.00%).\n *\n * The on-chain `BipsLibrary.calculatePortion` only rejects values above\n * 10_000 bps, so this ceiling is a client-side policy, not a contract limit.\n * It exists so an embedder cannot ship a widget that quietly takes a third of\n * a user's output, which would poison the widget for every other integrator.\n * Anything above this is a configuration error, not a business decision.\n */\nexport const MAX_INTEGRATOR_FEE_BPS = 100;\n\n/** The zero address, rejected as a fee destination. */\nexport const ZERO_ADDRESS: Address = \"0x0000000000000000000000000000000000000000\";\n\n/**\n * Where the integrator fee is taken in the call path.\n *\n * - `take-portion` - a `TAKE_PORTION` action inside the swap plan. The vault\n * credit is split before anything leaves the singleton, so the router never\n * custodies the fee. This is the default.\n * - `pay-portion` - the swap takes its full output to the router, then a\n * router-level `PAY_PORTION` command forwards the fee and `SWEEP` returns the\n * remainder. Needed when the fee must be taken across a multi-command plan.\n */\nexport type IntegratorFeeMode = \"take-portion\" | \"pay-portion\";\n\n/** Integrator fee configuration, as an embedder writes it. */\nexport interface IntegratorConfig {\n /** Address that receives the fee. Required whenever `feeBps > 0`. */\n readonly referrer: Address;\n /** Fee in basis points of the swap output, `0 .. MAX_INTEGRATOR_FEE_BPS`. */\n readonly feeBps: number;\n /** Where in the call path the fee is taken. Defaults to `take-portion`. */\n readonly feeMode?: IntegratorFeeMode;\n /**\n * Free-form label recorded in widget analytics events. Never sent on-chain.\n */\n readonly label?: string;\n}\n\n/** Machine-readable reasons an integrator config can be rejected. */\nexport type IntegratorConfigErrorCode =\n | \"FEE_BPS_NOT_A_NUMBER\"\n | \"FEE_BPS_NOT_AN_INTEGER\"\n | \"FEE_BPS_NEGATIVE\"\n | \"FEE_BPS_ABOVE_MAX\"\n | \"REFERRER_MISSING\"\n | \"REFERRER_MALFORMED\"\n | \"REFERRER_ZERO_ADDRESS\"\n | \"FEE_MODE_UNKNOWN\";\n\n/** Thrown when an integrator config cannot be used to build a call path. */\nexport class IntegratorConfigError extends Error {\n readonly code: IntegratorConfigErrorCode;\n\n constructor(code: IntegratorConfigErrorCode, message: string) {\n super(`[@latchprotocol/widgets] integrator config rejected (${code}): ${message}`);\n this.name = \"IntegratorConfigError\";\n this.code = code;\n }\n}\n\n/**\n * A validated integrator config.\n *\n * Only this type reaches the call-path builders. There is no way to construct\n * one except through {@link validateIntegratorConfig}, so an unvalidated fee can\n * never be encoded into a transaction.\n */\nexport interface ResolvedIntegratorConfig {\n readonly referrer: Address;\n readonly feeBps: number;\n readonly feeMode: IntegratorFeeMode;\n readonly label: string | null;\n /** `true` when `feeBps > 0`, i.e. the call path gains a fee step. */\n readonly active: boolean;\n /** Non-fatal configuration remarks worth surfacing in a dev console. */\n readonly warnings: readonly string[];\n}\n\nconst FEE_MODES: readonly IntegratorFeeMode[] = [\"take-portion\", \"pay-portion\"];\n\nfunction isKnownFeeMode(value: string): value is IntegratorFeeMode {\n return (FEE_MODES as readonly string[]).includes(value);\n}\n\n/**\n * Validates and normalises an integrator config.\n *\n * @throws {IntegratorConfigError} on any violation of the documented rules.\n */\nexport function validateIntegratorConfig(config: IntegratorConfig): ResolvedIntegratorConfig {\n const { feeBps } = config;\n\n if (typeof feeBps !== \"number\" || Number.isNaN(feeBps)) {\n throw new IntegratorConfigError(\n \"FEE_BPS_NOT_A_NUMBER\",\n `feeBps must be a number, received ${JSON.stringify(feeBps)}`,\n );\n }\n if (!Number.isFinite(feeBps) || !Number.isInteger(feeBps)) {\n throw new IntegratorConfigError(\n \"FEE_BPS_NOT_AN_INTEGER\",\n `feeBps must be a whole number of basis points, received ${feeBps}. ` +\n \"There is no sub-basis-point precision on-chain.\",\n );\n }\n if (feeBps < 0) {\n throw new IntegratorConfigError(\n \"FEE_BPS_NEGATIVE\",\n `feeBps must not be negative, received ${feeBps}`,\n );\n }\n if (feeBps > MAX_INTEGRATOR_FEE_BPS) {\n throw new IntegratorConfigError(\n \"FEE_BPS_ABOVE_MAX\",\n `feeBps ${feeBps} exceeds MAX_INTEGRATOR_FEE_BPS (${MAX_INTEGRATOR_FEE_BPS} bps = ` +\n `${MAX_INTEGRATOR_FEE_BPS / 100}%). Raise it only by forking this package and ` +\n \"owning the consequences for your users.\",\n );\n }\n\n const feeMode = config.feeMode ?? \"take-portion\";\n if (!isKnownFeeMode(feeMode)) {\n throw new IntegratorConfigError(\n \"FEE_MODE_UNKNOWN\",\n `feeMode must be one of ${FEE_MODES.join(\" | \")}, received ${JSON.stringify(feeMode)}`,\n );\n }\n\n const warnings: string[] = [];\n const rawReferrer: unknown = config.referrer;\n const active = feeBps > 0;\n\n if (rawReferrer === undefined || rawReferrer === null || rawReferrer === \"\") {\n if (active) {\n throw new IntegratorConfigError(\n \"REFERRER_MISSING\",\n `feeBps is ${feeBps} but no referrer address was provided. A fee with no ` +\n \"destination would be silently forfeited; refusing to build the call path.\",\n );\n }\n return {\n referrer: ZERO_ADDRESS,\n feeBps: 0,\n feeMode,\n label: config.label ?? null,\n active: false,\n warnings,\n };\n }\n\n if (typeof rawReferrer !== \"string\" || !isAddress(rawReferrer)) {\n throw new IntegratorConfigError(\n \"REFERRER_MALFORMED\",\n `referrer is not a valid EVM address: ${JSON.stringify(rawReferrer)}`,\n );\n }\n\n const referrer = getAddress(rawReferrer);\n\n if (referrer === ZERO_ADDRESS) {\n if (active) {\n throw new IntegratorConfigError(\n \"REFERRER_ZERO_ADDRESS\",\n `feeBps is ${feeBps} but referrer is the zero address. The fee would be burned.`,\n );\n }\n return {\n referrer: ZERO_ADDRESS,\n feeBps: 0,\n feeMode,\n label: config.label ?? null,\n active: false,\n warnings,\n };\n }\n\n if (!active) {\n warnings.push(\n `referrer ${referrer} is configured but feeBps is 0, so this widget will earn ` +\n \"the integrator nothing. Set feeBps to start collecting.\",\n );\n }\n\n return {\n referrer,\n feeBps,\n feeMode,\n label: config.label ?? null,\n active,\n warnings,\n };\n}\n\n/** The resolved config used when an embedder configures no integrator at all. */\nexport const NO_INTEGRATOR_FEE: ResolvedIntegratorConfig = {\n referrer: ZERO_ADDRESS,\n feeBps: 0,\n feeMode: \"take-portion\",\n label: null,\n active: false,\n warnings: [],\n};\n\n/** Validates an optional config, falling back to {@link NO_INTEGRATOR_FEE}. */\nexport function resolveIntegratorConfig(\n config: IntegratorConfig | undefined | null,\n): ResolvedIntegratorConfig {\n if (config === undefined || config === null) return NO_INTEGRATOR_FEE;\n return validateIntegratorConfig(config);\n}\n\n/**\n * The integrator's cut of `grossAmount`, in the output currency's smallest unit.\n *\n * Mirrors `BipsLibrary.calculatePortion`: multiply first, then divide, so the\n * rounding matches the chain exactly. Integer division truncates, which favours\n * the user by at most one wei.\n */\nexport function calculateIntegratorFee(grossAmount: bigint, feeBps: number): bigint {\n if (grossAmount < 0n) {\n throw new RangeError(`calculateIntegratorFee: grossAmount must not be negative: ${grossAmount}`);\n }\n if (!Number.isInteger(feeBps) || feeBps < 0 || feeBps > BPS_DENOMINATOR) {\n throw new RangeError(\n `calculateIntegratorFee: feeBps must be an integer in [0, ${BPS_DENOMINATOR}]: ${feeBps}`,\n );\n }\n return (grossAmount * BigInt(feeBps)) / BigInt(BPS_DENOMINATOR);\n}\n\n/** A gross output amount split into the integrator's cut and the user's. */\nexport interface IntegratorFeeSplit {\n /** Output before the integrator fee. */\n readonly grossAmount: bigint;\n /** Amount routed to the referrer. Zero when no fee is active. */\n readonly integratorFee: bigint;\n /** Amount the user actually receives. */\n readonly netAmount: bigint;\n readonly feeBps: number;\n /** Fee destination, or `null` when no fee is active. */\n readonly referrer: Address | null;\n}\n\n/** Splits a gross output amount according to a validated integrator config. */\nexport function splitIntegratorFee(\n grossAmount: bigint,\n config: ResolvedIntegratorConfig,\n): IntegratorFeeSplit {\n if (!config.active) {\n return {\n grossAmount,\n integratorFee: 0n,\n netAmount: grossAmount,\n feeBps: 0,\n referrer: null,\n };\n }\n const integratorFee = calculateIntegratorFee(grossAmount, config.feeBps);\n return {\n grossAmount,\n integratorFee,\n netAmount: grossAmount - integratorFee,\n feeBps: config.feeBps,\n referrer: config.referrer,\n };\n}\n\n/** Human-readable percentage for a bps value, e.g. `25 -> \"0.25%\"`. */\nexport function formatBps(bps: number): string {\n const percent = bps / 100;\n return `${Number.isInteger(percent) ? percent.toString() : percent.toFixed(2)}%`;\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Quote arithmetic.\n *\n * Everything here is pure, integer-only and independent of any chain, adapter\n * or component, so it can be tested exhaustively. The rounding directions match\n * the contracts: fees and minimum-received amounts round **down**, maximum-spend\n * amounts round **up**. Every rounding error is therefore in the user's favour\n * or, at worst, causes a revert instead of a silent loss.\n */\n\nimport {\n calculateIntegratorFee,\n splitIntegratorFee,\n type ResolvedIntegratorConfig,\n} from \"../config/integrator.js\";\n\n/** Basis-point denominator as a bigint. */\nexport const BPS = 10_000n;\n\n/** Pips denominator, matching `ProtocolFeeLibrary.PIPS_DENOMINATOR`. */\nexport const PIPS = 1_000_000n;\n\n/**\n * Highest slippage tolerance the widgets accept, in bps (50%).\n *\n * Above this a \"swap\" is indistinguishable from a donation to whoever is\n * watching the mempool.\n */\nexport const MAX_SLIPPAGE_BPS = 5_000;\n\n/** Slippage used when the embedder sets none. */\nexport const DEFAULT_SLIPPAGE_BPS = 50;\n\n/** Price impact at or above which the UI demands explicit confirmation. */\nexport const HIGH_PRICE_IMPACT_BPS = 300;\n\n/** Price impact treated as certainly-a-mistake. */\nexport const SEVERE_PRICE_IMPACT_BPS = 1_000;\n\nfunction assertNonNegative(value: bigint, label: string): void {\n if (value < 0n) throw new RangeError(`${label} must not be negative: ${value}`);\n}\n\nfunction assertBps(value: number, label: string, max: number): void {\n if (!Number.isInteger(value) || value < 0 || value > max) {\n throw new RangeError(`${label} must be an integer in [0, ${max}]: ${value}`);\n }\n}\n\n/** `floor(amount * bps / 10_000)`. */\nexport function portionOf(amount: bigint, bps: number): bigint {\n assertNonNegative(amount, \"amount\");\n assertBps(bps, \"bps\", 10_000);\n return (amount * BigInt(bps)) / BPS;\n}\n\n/** `floor(amount * pips / 1_000_000)`. */\nexport function pipsOf(amount: bigint, pips: number): bigint {\n assertNonNegative(amount, \"amount\");\n assertBps(pips, \"pips\", 1_000_000);\n return (amount * BigInt(pips)) / PIPS;\n}\n\n/**\n * Minimum amount that must be received for the transaction to be acceptable.\n *\n * Rounds down, so the on-chain check is never tighter than the user's stated\n * tolerance.\n */\nexport function minimumReceived(expected: bigint, slippageBps: number): bigint {\n assertNonNegative(expected, \"expected\");\n assertBps(slippageBps, \"slippageBps\", MAX_SLIPPAGE_BPS);\n return (expected * (BPS - BigInt(slippageBps))) / BPS;\n}\n\n/**\n * Maximum amount the user is willing to spend.\n *\n * Rounds up, so a one-wei rounding difference on-chain does not revert an\n * otherwise valid exact-output swap.\n */\nexport function maximumSpent(expected: bigint, slippageBps: number): bigint {\n assertNonNegative(expected, \"expected\");\n assertBps(slippageBps, \"slippageBps\", MAX_SLIPPAGE_BPS);\n const numerator = expected * (BPS + BigInt(slippageBps));\n return numerator % BPS === 0n ? numerator / BPS : numerator / BPS + 1n;\n}\n\n/**\n * Price impact in basis points: how much worse the realised rate is than the\n * pool's rate for an infinitesimal trade.\n *\n * `spotAmountOut` is what the same input would return at the current price with\n * no impact and no LP fee. Returns `null` when that reference is unavailable or\n * zero, because a fabricated zero would read as \"no impact\" - the most\n * dangerous possible default.\n */\nexport function priceImpactBps(\n grossAmountOut: bigint,\n spotAmountOut: bigint | null | undefined,\n): number | null {\n if (spotAmountOut === null || spotAmountOut === undefined || spotAmountOut <= 0n) return null;\n assertNonNegative(grossAmountOut, \"grossAmountOut\");\n if (grossAmountOut >= spotAmountOut) return 0;\n const impact = ((spotAmountOut - grossAmountOut) * BPS) / spotAmountOut;\n return Number(impact);\n}\n\n/** Severity buckets for a price impact, used for presentation and gating. */\nexport type PriceImpactSeverity = \"unknown\" | \"low\" | \"elevated\" | \"high\" | \"severe\";\n\n/** Classifies a price impact in bps. */\nexport function priceImpactSeverity(bps: number | null): PriceImpactSeverity {\n if (bps === null) return \"unknown\";\n if (bps >= SEVERE_PRICE_IMPACT_BPS) return \"severe\";\n if (bps >= HIGH_PRICE_IMPACT_BPS) return \"high\";\n if (bps >= 100) return \"elevated\";\n return \"low\";\n}\n\n/** Inputs to {@link buildQuoteBreakdown}. */\nexport interface QuoteBreakdownInput {\n /** Input amount, in the input currency's smallest unit. */\n readonly amountIn: bigint;\n /** Output before any integrator fee, as returned by the adapter. */\n readonly grossAmountOut: bigint;\n /** Output at the current price with no impact, if the adapter can supply it. */\n readonly spotAmountOut?: bigint | null;\n /** LP fee already deducted by the pool, in the output currency. */\n readonly lpFeeAmount?: bigint;\n /** Pool's LP fee rate in pips. */\n readonly lpFeePips?: number;\n /** The rate is hook-set and was not readable; `lpFeePips` is a placeholder zero. */\n readonly lpFeeUnknown?: boolean;\n /** User's slippage tolerance. */\n readonly slippageBps: number;\n /** Validated integrator config. */\n readonly integrator: ResolvedIntegratorConfig;\n}\n\n/**\n * Everything a swap UI and a swap call path need, derived once.\n *\n * The two minimums matter and are not interchangeable:\n *\n * - `minAmountOutGross` is checked by the swap action, before the fee is split.\n * - `minAmountOutNet` is what the user is guaranteed to actually receive, and is\n * the value the final take/sweep enforces.\n */\nexport interface QuoteBreakdown {\n readonly amountIn: bigint;\n readonly grossAmountOut: bigint;\n readonly integratorFee: bigint;\n readonly integratorFeeBps: number;\n readonly netAmountOut: bigint;\n readonly minAmountOutGross: bigint;\n readonly minAmountOutNet: bigint;\n readonly lpFeeAmount: bigint;\n readonly lpFeePips: number;\n /** See {@link QuoteBreakdownInput.lpFeeUnknown}. Render as \"dynamic\", never as a percentage. */\n readonly lpFeeUnknown: boolean;\n readonly slippageBps: number;\n readonly priceImpactBps: number | null;\n readonly priceImpactSeverity: PriceImpactSeverity;\n}\n\n/**\n * Derives the full quote breakdown.\n *\n * `minAmountOutNet` is computed as `minGross - portion(minGross)` rather than\n * `portion(netAmountOut)`. That matters: the fee is taken on-chain from the\n * *realised* output, not the quoted one, and `x - floor(x * bps / 10_000)` is\n * monotonically non-decreasing in `x`. So this is a genuine floor on what the\n * user receives whenever the swap itself clears `minAmountOutGross`.\n */\nexport function buildQuoteBreakdown(input: QuoteBreakdownInput): QuoteBreakdown {\n const { amountIn, grossAmountOut, slippageBps, integrator } = input;\n assertNonNegative(amountIn, \"amountIn\");\n assertNonNegative(grossAmountOut, \"grossAmountOut\");\n assertBps(slippageBps, \"slippageBps\", MAX_SLIPPAGE_BPS);\n\n const split = splitIntegratorFee(grossAmountOut, integrator);\n const minAmountOutGross = minimumReceived(grossAmountOut, slippageBps);\n const minAmountOutNet = integrator.active\n ? minAmountOutGross - calculateIntegratorFee(minAmountOutGross, integrator.feeBps)\n : minAmountOutGross;\n\n const impact = priceImpactBps(grossAmountOut, input.spotAmountOut ?? null);\n\n return {\n amountIn,\n grossAmountOut,\n integratorFee: split.integratorFee,\n integratorFeeBps: split.feeBps,\n netAmountOut: split.netAmount,\n minAmountOutGross,\n minAmountOutNet,\n lpFeeAmount: input.lpFeeAmount ?? 0n,\n lpFeePips: input.lpFeePips ?? 0,\n lpFeeUnknown: input.lpFeeUnknown ?? false,\n slippageBps,\n priceImpactBps: impact,\n priceImpactSeverity: priceImpactSeverity(impact),\n };\n}\n\n/**\n * Exchange rate as a floating-point number of output units per input unit.\n *\n * Display only. Never feed this back into a call path - it loses precision by\n * construction.\n */\nexport function exchangeRate(\n amountIn: bigint,\n decimalsIn: number,\n amountOut: bigint,\n decimalsOut: number,\n): number | null {\n if (amountIn <= 0n || amountOut <= 0n) return null;\n const scaledIn = Number(amountIn) / 10 ** decimalsIn;\n const scaledOut = Number(amountOut) / 10 ** decimalsOut;\n if (!Number.isFinite(scaledIn) || scaledIn === 0) return null;\n return scaledOut / scaledIn;\n}\n\n/** Progress of a sale as a percentage in `[0, 100]`. */\nexport function progressPercent(sold: bigint, total: bigint): number {\n if (total <= 0n) return 0;\n const capped = sold > total ? total : sold;\n return Number((capped * 10_000n) / total) / 100;\n}\n\n/** Clamps `value` to `[min, max]`. */\nexport function clampBigInt(value: bigint, min: bigint, max: bigint): bigint {\n if (min > max) throw new RangeError(`clampBigInt: min ${min} exceeds max ${max}`);\n if (value < min) return min;\n if (value > max) return max;\n return value;\n}\n\n/** Rounds a tick down to the nearest usable multiple of `tickSpacing`. */\nexport function floorTickToSpacing(tick: number, tickSpacing: number): number {\n if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) {\n throw new RangeError(`tickSpacing must be a positive integer: ${tickSpacing}`);\n }\n return Math.floor(tick / tickSpacing) * tickSpacing;\n}\n\n/** Rounds a tick up to the nearest usable multiple of `tickSpacing`. */\nexport function ceilTickToSpacing(tick: number, tickSpacing: number): number {\n if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) {\n throw new RangeError(`tickSpacing must be a positive integer: ${tickSpacing}`);\n }\n return Math.ceil(tick / tickSpacing) * tickSpacing;\n}\n","// SPDX-License-Identifier: MIT\n/**\n * The one piece of shared state every widget reads.\n *\n * `WidgetProvider` holds the adapter, the chain config and - critically - the\n * *validated* integrator config. Validation happens once, here, at mount:\n * a bad `feeBps` or a missing `referrer` fails immediately and visibly rather\n * than at the moment a user presses Swap.\n */\n\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n type ReactNode,\n} from \"react\";\nimport type { ProtocolAdapter } from \"../adapters/protocol.js\";\nimport type { ChainConfig } from \"../config/chain.js\";\nimport { assertValidChainConfig } from \"../config/chain.js\";\nimport {\n resolveIntegratorConfig,\n type IntegratorConfig,\n type ResolvedIntegratorConfig,\n} from \"../config/integrator.js\";\nimport { DEFAULT_SLIPPAGE_BPS, MAX_SLIPPAGE_BPS } from \"../core/math.js\";\n\n/** Colour scheme applied to the styled widgets. */\nexport type WidgetTheme = \"light\" | \"dark\" | \"system\";\n\n/** Value exposed to every widget beneath the provider. */\nexport interface WidgetContextValue {\n readonly adapter: ProtocolAdapter;\n readonly chain: ChainConfig;\n /** Always validated. Never optional at this layer. */\n readonly integrator: ResolvedIntegratorConfig;\n readonly defaultSlippageBps: number;\n readonly theme: WidgetTheme;\n /** Locale used by number formatting; defaults to the browser's. */\n readonly locale: string | undefined;\n /**\n * What the \"Connect wallet\" call to action does when pressed, for every\n * widget under this provider. `undefined` leaves that CTA a disabled label.\n */\n readonly onConnectRequest: (() => void) | undefined;\n}\n\n/**\n * The context itself. Exported so a host can detect whether a provider is\n * mounted above it (`useContext(WidgetContext) === null`) instead of catching\n * the throw from {@link useWidgetContext}; {@link useOptionalWidgetContext}\n * is the same test as a hook.\n */\nexport const WidgetContext = createContext<WidgetContextValue | null>(null);\n\n/** Props accepted by {@link WidgetProvider}. */\nexport interface WidgetProviderProps {\n /** Where chain reads and writes go. Mock in dev, viem-backed in production. */\n readonly adapter: ProtocolAdapter;\n /**\n * Integrator fee attribution.\n *\n * Omit it and the widgets work, earning you nothing. Supplying it is the\n * entire commercial reason to embed them.\n */\n readonly integrator?: IntegratorConfig;\n readonly defaultSlippageBps?: number;\n readonly theme?: WidgetTheme;\n readonly locale?: string;\n /**\n * Opens the host's wallet-connect flow (RainbowKit's `openConnectModal`,\n * a custom modal, whatever the host has). While no account is connected the\n * widgets' primary button reads \"Connect wallet\"; with this set it is an\n * enabled button that calls it, without it the button stays a disabled label\n * and the visitor connects through the host's own control. A widget's own\n * `onConnectRequest` prop overrides this one.\n */\n readonly onConnectRequest?: () => void;\n readonly children: ReactNode;\n}\n\n/** Root provider. Wrap every widget in exactly one of these. */\nexport function WidgetProvider(props: WidgetProviderProps): JSX.Element {\n const {\n adapter,\n integrator,\n defaultSlippageBps = DEFAULT_SLIPPAGE_BPS,\n theme = \"system\",\n locale,\n onConnectRequest,\n children,\n } = props;\n\n // Throws synchronously during render on a bad config. That is intended: a\n // widget that silently drops the integrator's fee is worse than one that\n // refuses to mount and says why.\n const resolvedIntegrator = useMemo(\n () => resolveIntegratorConfig(integrator ?? null),\n [integrator],\n );\n\n const chain = adapter.chain;\n\n useMemo(() => {\n assertValidChainConfig(chain);\n return null;\n }, [chain]);\n\n if (!Number.isInteger(defaultSlippageBps) || defaultSlippageBps < 0) {\n throw new RangeError(\n `[@latchprotocol/widgets] defaultSlippageBps must be a non-negative integer: ${defaultSlippageBps}`,\n );\n }\n if (defaultSlippageBps > MAX_SLIPPAGE_BPS) {\n throw new RangeError(\n `[@latchprotocol/widgets] defaultSlippageBps ${defaultSlippageBps} exceeds ` +\n `MAX_SLIPPAGE_BPS (${MAX_SLIPPAGE_BPS})`,\n );\n }\n\n useEffect(() => {\n for (const warning of resolvedIntegrator.warnings) {\n // eslint-disable-next-line no-console\n console.warn(`[@latchprotocol/widgets] ${warning}`);\n }\n }, [resolvedIntegrator]);\n\n const value = useMemo<WidgetContextValue>(\n () => ({\n adapter,\n chain,\n integrator: resolvedIntegrator,\n defaultSlippageBps,\n theme,\n locale,\n onConnectRequest,\n }),\n [adapter, chain, resolvedIntegrator, defaultSlippageBps, theme, locale, onConnectRequest],\n );\n\n return <WidgetContext.Provider value={value}>{children}</WidgetContext.Provider>;\n}\n\n/** Reads the widget context. Throws when used outside a {@link WidgetProvider}. */\nexport function useWidgetContext(): WidgetContextValue {\n const value = useContext(WidgetContext);\n if (value === null) {\n throw new Error(\n \"[@latchprotocol/widgets] no WidgetProvider found. Wrap your app (or just the \" +\n \"widget) in <WidgetProvider adapter={...} integrator={...}>.\",\n );\n }\n return value;\n}\n\n/**\n * Reads the widget context, or `null` when no {@link WidgetProvider} is\n * mounted above. For hosts that mount the provider late (once a pool\n * directory is read, say) and want to render a waiting state in the\n * meantime without an error boundary.\n */\nexport function useOptionalWidgetContext(): WidgetContextValue | null {\n return useContext(WidgetContext);\n}\n\n/** Convenience accessor for the adapter. */\nexport function useProtocolAdapter(): ProtocolAdapter {\n return useWidgetContext().adapter;\n}\n\n/** Convenience accessor for the validated integrator config. */\nexport function useIntegrator(): ResolvedIntegratorConfig {\n return useWidgetContext().integrator;\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Display formatting and user-input parsing.\n *\n * Parsing is the security-relevant half: a mis-parsed decimal string becomes a\n * wrong `amountIn`, and `parseUnits` will happily truncate extra decimal places.\n * {@link parseAmount} refuses ambiguous input instead of guessing.\n */\n\nimport { formatUnits, parseUnits } from \"viem\";\n\n/** A rejected amount string, with a reason suitable for showing to a user. */\nexport interface AmountParseFailure {\n readonly ok: false;\n readonly reason:\n | \"empty\"\n | \"not-a-number\"\n | \"negative\"\n | \"too-many-decimals\"\n | \"zero\";\n readonly message: string;\n}\n\n/** A successfully parsed amount. */\nexport interface AmountParseSuccess {\n readonly ok: true;\n readonly value: bigint;\n}\n\nexport type AmountParseResult = AmountParseSuccess | AmountParseFailure;\n\nconst NUMERIC = /^\\d*(?:\\.\\d*)?$/;\n\n/**\n * Parses a user-entered decimal string into the token's smallest unit.\n *\n * @param allowZero when `false` (default) a zero amount is rejected, since a\n * zero-amount swap is never what the user meant.\n */\nexport function parseAmount(\n input: string,\n decimals: number,\n allowZero = false,\n): AmountParseResult {\n const trimmed = input.trim();\n if (trimmed === \"\" || trimmed === \".\") {\n return { ok: false, reason: \"empty\", message: \"Enter an amount\" };\n }\n if (trimmed.startsWith(\"-\")) {\n return { ok: false, reason: \"negative\", message: \"Amount must be positive\" };\n }\n if (!NUMERIC.test(trimmed)) {\n return { ok: false, reason: \"not-a-number\", message: \"Amount must be a number\" };\n }\n const [, fraction = \"\"] = trimmed.split(\".\");\n if (fraction.length > decimals) {\n return {\n ok: false,\n reason: \"too-many-decimals\",\n message: `This token has ${decimals} decimals; ${fraction.length} were entered`,\n };\n }\n const value = parseUnits(trimmed, decimals);\n if (value === 0n && !allowZero) {\n return { ok: false, reason: \"zero\", message: \"Enter an amount greater than zero\" };\n }\n return { ok: true, value };\n}\n\n/**\n * Formats a smallest-unit amount for display.\n *\n * Trims trailing zeros and caps the visible fraction, but never rounds a value\n * up to a non-zero display when it is zero, and never shows `0` for a non-zero\n * dust amount - it shows `<0.0001` instead.\n */\nexport function formatAmount(\n value: bigint,\n decimals: number,\n maxFractionDigits = 6,\n): string {\n if (value === 0n) return \"0\";\n const negative = value < 0n;\n const raw = formatUnits(negative ? -value : value, decimals);\n const [whole = \"0\", fraction = \"\"] = raw.split(\".\");\n const sign = negative ? \"-\" : \"\";\n\n if (fraction === \"\") return `${sign}${groupThousands(whole)}`;\n\n const trimmed = fraction.slice(0, maxFractionDigits).replace(/0+$/, \"\");\n if (trimmed === \"\") {\n // Non-zero, but smaller than the display precision.\n if (whole === \"0\") {\n const epsilon = `0.${\"0\".repeat(Math.max(0, maxFractionDigits - 1))}1`;\n return `${sign}<${epsilon}`;\n }\n return `${sign}${groupThousands(whole)}`;\n }\n return `${sign}${groupThousands(whole)}.${trimmed}`;\n}\n\nfunction groupThousands(whole: string): string {\n return whole.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\n}\n\n/** Formats a rate for display, e.g. `1 A = 1,234.5678 B`. */\nexport function formatRate(\n rate: number | null,\n symbolIn: string,\n symbolOut: string,\n): string {\n if (rate === null || !Number.isFinite(rate) || rate <= 0) return \"-\";\n const digits = rate >= 1000 ? 2 : rate >= 1 ? 4 : 6;\n return `1 ${symbolIn} = ${rate.toLocaleString(undefined, {\n maximumFractionDigits: digits,\n })} ${symbolOut}`;\n}\n\n/** Formats a bps value as a percentage string. */\nexport function formatPercentFromBps(bps: number | null): string {\n if (bps === null) return \"unknown\";\n const percent = bps / 100;\n if (percent > 0 && percent < 0.01) return \"<0.01%\";\n return `${percent.toFixed(2)}%`;\n}\n\n/** Formats a pips value (1e6 = 100%) as a percentage string. */\nexport function formatPercentFromPips(pips: number): string {\n const percent = pips / 10_000;\n if (percent > 0 && percent < 0.001) return \"<0.001%\";\n return `${trimTrailingZeros(percent.toFixed(3))}%`;\n}\n\nfunction trimTrailingZeros(value: string): string {\n return value.includes(\".\") ? value.replace(/\\.?0+$/, \"\") : value;\n}\n\n/** Shortens an address for display: `0x1234...cdef`. */\nexport function shortAddress(address: string): string {\n if (address.length <= 12) return address;\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\n/** Formats a remaining duration in seconds as a compact `1d 4h 3m` string. */\nexport function formatDuration(totalSeconds: number): string {\n if (!Number.isFinite(totalSeconds) || totalSeconds <= 0) return \"0s\";\n const seconds = Math.floor(totalSeconds);\n const days = Math.floor(seconds / 86_400);\n const hours = Math.floor((seconds % 86_400) / 3_600);\n const minutes = Math.floor((seconds % 3_600) / 60);\n const secs = seconds % 60;\n const parts: string[] = [];\n if (days > 0) parts.push(`${days}d`);\n if (hours > 0) parts.push(`${hours}h`);\n if (minutes > 0 && days === 0) parts.push(`${minutes}m`);\n if (parts.length === 0) parts.push(`${secs}s`);\n return parts.join(\" \");\n}\n\n/** Formats a unix timestamp for display in the viewer's locale. */\nexport function formatTimestamp(unixSeconds: bigint | number): string {\n const ms = Number(unixSeconds) * 1000;\n if (!Number.isFinite(ms)) return \"-\";\n return new Date(ms).toLocaleString();\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Command, action and sentinel constants for the LatchProtocol call path.\n *\n * These mirror the on-chain libraries and must be kept in step with them:\n *\n * - commands: `packages/router/src/libraries/Commands.sol`\n * - actions: `packages/periphery/src/libraries/Actions.sol`\n * - sentinels:`packages/periphery/src/libraries/ActionConstants.sol`\n *\n * They are transcribed rather than imported because the Solidity is GPL-2.0 and\n * this package is MIT. Constants carry no copyright; the encoding logic here is\n * written against the ABI, not derived from the sources.\n */\n\nimport type { Address } from \"viem\";\n\n/** Universal-router command ids. */\nexport const COMMANDS = {\n SWEEP: 0x04,\n TRANSFER: 0x05,\n /** Pays a bps portion of the router's balance of a token to a recipient. */\n PAY_PORTION: 0x06,\n WRAP_ETH: 0x0b,\n UNWRAP_WETH: 0x0c,\n /** Runs an encoded periphery action plan inside one vault lock. */\n INFI_SWAP: 0x10,\n} as const;\n\n/** Periphery action ids. */\nexport const ACTIONS = {\n CL_INCREASE_LIQUIDITY: 0x00,\n CL_DECREASE_LIQUIDITY: 0x01,\n CL_MINT_POSITION: 0x02,\n CL_BURN_POSITION: 0x03,\n CL_SWAP_EXACT_IN_SINGLE: 0x06,\n CL_SWAP_EXACT_IN: 0x07,\n CL_SWAP_EXACT_OUT_SINGLE: 0x08,\n CL_SWAP_EXACT_OUT: 0x09,\n SETTLE: 0x0b,\n SETTLE_ALL: 0x0c,\n SETTLE_PAIR: 0x0d,\n TAKE: 0x0e,\n TAKE_ALL: 0x0f,\n /** Takes a bps portion of the open credit straight to a recipient. */\n TAKE_PORTION: 0x10,\n TAKE_PAIR: 0x11,\n CLOSE_CURRENCY: 0x12,\n CLEAR_OR_TAKE: 0x13,\n SWEEP: 0x14,\n BIN_ADD_LIQUIDITY: 0x19,\n BIN_REMOVE_LIQUIDITY: 0x1a,\n BIN_SWAP_EXACT_IN_SINGLE: 0x1c,\n BIN_SWAP_EXACT_IN: 0x1d,\n BIN_SWAP_EXACT_OUT_SINGLE: 0x1e,\n BIN_SWAP_EXACT_OUT: 0x1f,\n} as const;\n\n/** Recipient sentinel: the account that called the router. */\nexport const MSG_SENDER: Address = \"0x0000000000000000000000000000000000000001\";\n\n/** Recipient sentinel: the router contract itself. */\nexport const ADDRESS_THIS: Address = \"0x0000000000000000000000000000000000000002\";\n\n/** Amount sentinel: use the whole open delta for this currency. */\nexport const OPEN_DELTA = 0n;\n\n/** Amount sentinel: use the contract's entire balance. */\nexport const CONTRACT_BALANCE = 1n << 255n;\n\n/** Address used by the router's payment helpers to mean native value. */\nexport const NATIVE_SENTINEL: Address = \"0x0000000000000000000000000000000000000000\";\n\n/** Scale used by liquidity-book distribution weights. */\nexport const BIN_DISTRIBUTION_SCALE = 10n ** 18n;\n\n/** Minimal ABI for `UniversalRouter.execute`. */\nexport const UNIVERSAL_ROUTER_ABI = [\n {\n type: \"function\",\n name: \"execute\",\n stateMutability: \"payable\",\n inputs: [\n { name: \"commands\", type: \"bytes\" },\n { name: \"inputs\", type: \"bytes[]\" },\n { name: \"deadline\", type: \"uint256\" },\n ],\n outputs: [],\n },\n] as const;\n\n/** Minimal ABI for the position managers' batched entry point. */\nexport const POSITION_MANAGER_ABI = [\n {\n type: \"function\",\n name: \"modifyLiquidities\",\n stateMutability: \"payable\",\n inputs: [\n { name: \"unlockData\", type: \"bytes\" },\n { name: \"deadline\", type: \"uint256\" },\n ],\n outputs: [],\n },\n] as const;\n\n/** Minimal ERC-20 surface the widgets need. */\nexport const ERC20_ABI = [\n {\n type: \"function\",\n name: \"approve\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"spender\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\" }],\n },\n {\n type: \"function\",\n name: \"allowance\",\n stateMutability: \"view\",\n inputs: [\n { name: \"owner\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n type: \"function\",\n name: \"balanceOf\",\n stateMutability: \"view\",\n inputs: [{ name: \"account\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n {\n type: \"function\",\n name: \"decimals\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint8\" }],\n },\n {\n type: \"function\",\n name: \"symbol\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n },\n {\n type: \"function\",\n name: \"name\",\n stateMutability: \"view\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n },\n] as const;\n\n/** Permit2's allowance surface, used for the second half of the approval flow. */\nexport const PERMIT2_ABI = [\n {\n type: \"function\",\n name: \"allowance\",\n stateMutability: \"view\",\n inputs: [\n { name: \"user\", type: \"address\" },\n { name: \"token\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n ],\n outputs: [\n { name: \"amount\", type: \"uint160\" },\n { name: \"expiration\", type: \"uint48\" },\n { name: \"nonce\", type: \"uint48\" },\n ],\n },\n {\n type: \"function\",\n name: \"approve\",\n stateMutability: \"nonpayable\",\n inputs: [\n { name: \"token\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n { name: \"amount\", type: \"uint160\" },\n { name: \"expiration\", type: \"uint48\" },\n ],\n outputs: [],\n },\n] as const;\n\n/** Largest value Permit2 will store as an allowance amount. */\nexport const MAX_UINT160 = (1n << 160n) - 1n;\n\n/** Largest value Permit2 will store as an expiration. */\nexport const MAX_UINT48 = (1n << 48n) - 1n;\n\n/** Largest ERC-20 allowance. */\nexport const MAX_UINT256 = (1n << 256n) - 1n;\n","// SPDX-License-Identifier: MIT\n/**\n * Action-plan encoding.\n *\n * A periphery call is a list of `(actionId, abi-encoded params)` pairs executed\n * inside one vault lock. The pairs are transported as `abi.encode(bytes actions,\n * bytes[] params)`, where `actions` is the raw concatenation of one-byte ids.\n *\n * `CalldataDecoder.decodeActionsRouterParams` requires *strict* encoding - the\n * first word must be exactly `0x40` - which is what a standard two-parameter ABI\n * encoding produces. Do not hand-roll this.\n */\n\nimport { concatHex, encodeAbiParameters, type Hex } from \"viem\";\n\n/** One step of a plan. */\nexport interface PlannedAction {\n readonly action: number;\n readonly params: Hex;\n /** Debug label, never encoded. */\n readonly label: string;\n}\n\n/** An ordered list of actions destined for one vault lock. */\nexport class ActionPlan {\n readonly #steps: PlannedAction[] = [];\n\n /** Appends an action. Order is the execution order. */\n add(action: number, params: Hex, label: string): this {\n if (!Number.isInteger(action) || action < 0 || action > 0xff) {\n throw new RangeError(`action id must fit in one byte: ${action}`);\n }\n this.#steps.push({ action, params, label });\n return this;\n }\n\n /** The planned steps, in order. */\n get steps(): readonly PlannedAction[] {\n return this.#steps;\n }\n\n /** Human-readable trace of the plan, used in dev tooling and error messages. */\n describe(): string {\n return this.#steps\n .map((step, index) => `${index}. ${step.label} (0x${step.action.toString(16).padStart(2, \"0\")})`)\n .join(\"\\n\");\n }\n\n /** `abi.encode(bytes actions, bytes[] params)`. */\n encode(): Hex {\n if (this.#steps.length === 0) {\n throw new Error(\"[@latchprotocol/widgets] cannot encode an empty action plan\");\n }\n const actions = concatHex(\n this.#steps.map((step) => `0x${step.action.toString(16).padStart(2, \"0\")}` as Hex),\n );\n const params = this.#steps.map((step) => step.params);\n return encodeAbiParameters(\n [\n { name: \"actions\", type: \"bytes\" },\n { name: \"params\", type: \"bytes[]\" },\n ],\n [actions, params],\n );\n }\n}\n\n/** Convenience constructor. */\nexport function plan(): ActionPlan {\n return new ActionPlan();\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Swap call-path construction - **including integrator fee attribution**.\n *\n * This is the file that turns `integrator: { referrer, feeBps }` into money.\n * The fee is not a post-hoc transfer and not an off-chain promise: it is a step\n * in the same plan as the swap, so it settles atomically with it.\n *\n * ## The two fee modes\n *\n * ### `take-portion` (default)\n *\n * ```text\n * UniversalRouter.execute([INFI_SWAP], [plan], deadline)\n * plan:\n * 0. CL_SWAP_EXACT_IN_SINGLE amountOutMinimum = minAmountOutGross\n * 1. SETTLE_ALL pay currencyIn from the caller (via Permit2)\n * 2. TAKE_PORTION feeBps of the output credit -> referrer\n * 3. TAKE_ALL the rest -> caller, floored at minAmountOutNet\n * ```\n *\n * The vault credit is split before anything leaves the singleton, so the router\n * never custodies the fee and there is no window in which it can be swept.\n *\n * ### `pay-portion`\n *\n * ```text\n * UniversalRouter.execute([INFI_SWAP, PAY_PORTION, SWEEP], [...], deadline)\n * ```\n *\n * The swap takes its whole output to the router, `PAY_PORTION` forwards the\n * fee, and `SWEEP` returns the remainder to the recipient. Use this when the\n * fee has to be taken across a plan the periphery cannot express alone.\n *\n * ## Two minimums, deliberately\n *\n * The swap action enforces `minAmountOutGross`; the final take/sweep enforces\n * `minAmountOutNet`. Because `x - floor(x * bps / 10_000)` is monotonically\n * non-decreasing in `x`, clearing the gross floor guarantees clearing the net\n * floor. Both are encoded so that neither the pool nor the fee step can quietly\n * erode the user's guarantee.\n */\n\nimport {\n encodeAbiParameters,\n encodeFunctionData,\n isAddressEqual,\n type Address,\n type Hex,\n} from \"viem\";\nimport { poolKeyToTuple, type PoolKey } from \"@latchprotocol/sdk\";\nimport {\n ACTIONS,\n ADDRESS_THIS,\n COMMANDS,\n MSG_SENDER,\n OPEN_DELTA,\n UNIVERSAL_ROUTER_ABI,\n} from \"./constants.js\";\nimport { ActionPlan, plan } from \"./plan.js\";\nimport type { ResolvedIntegratorConfig } from \"../config/integrator.js\";\nimport { MAX_INTEGRATOR_FEE_BPS, calculateIntegratorFee } from \"../config/integrator.js\";\n\n/** ABI shape of a `PoolKey` struct. */\nexport const POOL_KEY_COMPONENTS = [\n { name: \"currency0\", type: \"address\" },\n { name: \"currency1\", type: \"address\" },\n { name: \"hooks\", type: \"address\" },\n { name: \"poolManager\", type: \"address\" },\n { name: \"fee\", type: \"uint24\" },\n { name: \"parameters\", type: \"bytes32\" },\n] as const;\n\nconst SWAP_EXACT_IN_SINGLE_PARAMS = [\n {\n name: \"params\",\n type: \"tuple\",\n components: [\n { name: \"poolKey\", type: \"tuple\", components: POOL_KEY_COMPONENTS },\n { name: \"swapDirection\", type: \"bool\" },\n { name: \"amountIn\", type: \"uint128\" },\n { name: \"amountOutMinimum\", type: \"uint128\" },\n { name: \"hookData\", type: \"bytes\" },\n ],\n },\n] as const;\n\nconst PATH_KEY_COMPONENTS = [\n { name: \"intermediateCurrency\", type: \"address\" },\n { name: \"fee\", type: \"uint24\" },\n { name: \"hooks\", type: \"address\" },\n { name: \"poolManager\", type: \"address\" },\n { name: \"hookData\", type: \"bytes\" },\n { name: \"parameters\", type: \"bytes32\" },\n] as const;\n\nconst SWAP_EXACT_IN_PARAMS = [\n {\n name: \"params\",\n type: \"tuple\",\n components: [\n { name: \"currencyIn\", type: \"address\" },\n { name: \"path\", type: \"tuple[]\", components: PATH_KEY_COMPONENTS },\n { name: \"amountIn\", type: \"uint128\" },\n { name: \"amountOutMinimum\", type: \"uint128\" },\n ],\n },\n] as const;\n\nconst CURRENCY_AND_UINT256 = [\n { name: \"currency\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n] as const;\n\nconst CURRENCY_ADDRESS_AND_UINT256 = [\n { name: \"currency\", type: \"address\" },\n { name: \"recipient\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n] as const;\n\n/** One hop of a swap, resolved to the exact pool it will execute against. */\nexport interface SwapHop {\n readonly poolKey: PoolKey;\n readonly poolType: \"CL\" | \"BIN\";\n /** Input currency of this hop. */\n readonly currencyIn: Address;\n /** Output currency of this hop. */\n readonly currencyOut: Address;\n readonly hookData?: Hex;\n}\n\n/** Everything needed to encode a swap transaction. */\nexport interface BuildSwapCallArgs {\n readonly router: Address;\n readonly hops: readonly SwapHop[];\n readonly amountIn: bigint;\n readonly minAmountOutGross: bigint;\n readonly minAmountOutNet: bigint;\n /**\n * Quoted gross output, used only to report the expected fee back to the UI.\n * The chain always recomputes the fee from the realised output.\n */\n readonly expectedAmountOutGross?: bigint;\n readonly integrator: ResolvedIntegratorConfig;\n /** Who receives the output. Use the caller's own address for the normal case. */\n readonly recipient: Address;\n /** The account submitting the transaction, used to detect the sentinel case. */\n readonly sender: Address;\n readonly deadline: bigint;\n}\n\n/** A fully encoded swap transaction plus the trace used to explain it. */\nexport interface EncodedSwapCall {\n readonly to: Address;\n readonly data: Hex;\n readonly value: bigint;\n readonly commands: Hex;\n readonly inputs: readonly Hex[];\n /** Human-readable dump of the periphery plan. */\n readonly planTrace: string;\n /** Populated whenever a fee step was encoded. */\n readonly integratorFee: {\n readonly referrer: Address;\n readonly feeBps: number;\n readonly currency: Address;\n readonly mode: \"take-portion\" | \"pay-portion\";\n /** Fee implied by the quoted output. The chain recomputes it on the real one. */\n readonly expectedAmount: bigint;\n } | null;\n}\n\nfunction isNative(currency: Address): boolean {\n return isAddressEqual(currency, \"0x0000000000000000000000000000000000000000\");\n}\n\n/** `true` when `currency0` is the input, i.e. the swap runs zero-for-one. */\nfunction isZeroForOne(hop: SwapHop): boolean {\n return isAddressEqual(hop.poolKey.currency0, hop.currencyIn);\n}\n\nfunction assertHopsConnected(hops: readonly SwapHop[]): void {\n if (hops.length === 0) {\n throw new Error(\"[@latchprotocol/widgets] cannot encode a swap with no hops\");\n }\n for (let i = 1; i < hops.length; i += 1) {\n const previous = hops[i - 1];\n const current = hops[i];\n if (previous === undefined || current === undefined) continue;\n if (!isAddressEqual(previous.currencyOut, current.currencyIn)) {\n throw new Error(\n `[@latchprotocol/widgets] route is not contiguous: hop ${i - 1} outputs ` +\n `${previous.currencyOut} but hop ${i} takes ${current.currencyIn}`,\n );\n }\n }\n}\n\nfunction assertUniformPoolType(hops: readonly SwapHop[]): \"CL\" | \"BIN\" {\n const first = hops[0];\n if (first === undefined) {\n throw new Error(\"[@latchprotocol/widgets] cannot encode a swap with no hops\");\n }\n for (const hop of hops) {\n if (hop.poolType !== first.poolType) {\n throw new Error(\n \"[@latchprotocol/widgets] a single swap action cannot mix CL and BIN hops. \" +\n \"Split the route into one action per pool type, or route through a single type.\",\n );\n }\n }\n return first.poolType;\n}\n\n/** Encodes the single-hop swap action's parameters. */\nfunction encodeSingleHop(hop: SwapHop, amountIn: bigint, minOut: bigint): Hex {\n return encodeAbiParameters(SWAP_EXACT_IN_SINGLE_PARAMS, [\n {\n poolKey: {\n currency0: hop.poolKey.currency0,\n currency1: hop.poolKey.currency1,\n hooks: hop.poolKey.hooks,\n poolManager: hop.poolKey.poolManager,\n fee: hop.poolKey.fee,\n parameters: hop.poolKey.parameters,\n },\n // CL calls this `zeroForOne`, BIN calls it `swapForY`; same bit, same meaning.\n swapDirection: isZeroForOne(hop),\n amountIn,\n amountOutMinimum: minOut,\n hookData: hop.hookData ?? \"0x\",\n },\n ]);\n}\n\n/** Encodes the multi-hop swap action's parameters. */\nfunction encodeMultiHop(hops: readonly SwapHop[], amountIn: bigint, minOut: bigint): Hex {\n const first = hops[0];\n if (first === undefined) throw new Error(\"[@latchprotocol/widgets] empty route\");\n return encodeAbiParameters(SWAP_EXACT_IN_PARAMS, [\n {\n currencyIn: first.currencyIn,\n path: hops.map((hop) => ({\n intermediateCurrency: hop.currencyOut,\n fee: hop.poolKey.fee,\n hooks: hop.poolKey.hooks,\n poolManager: hop.poolKey.poolManager,\n hookData: hop.hookData ?? \"0x\",\n parameters: hop.poolKey.parameters,\n })),\n amountIn,\n amountOutMinimum: minOut,\n },\n ]);\n}\n\n/**\n * Builds the periphery action plan for a swap.\n *\n * Exported so integrators building their own router flows can reuse exactly the\n * plan the widgets use, fee step included.\n */\nexport function buildSwapPlan(args: BuildSwapCallArgs): {\n readonly plan: ActionPlan;\n readonly currencyIn: Address;\n readonly currencyOut: Address;\n} {\n assertHopsConnected(args.hops);\n const poolType = assertUniformPoolType(args.hops);\n const first = args.hops[0];\n const last = args.hops[args.hops.length - 1];\n if (first === undefined || last === undefined) {\n throw new Error(\"[@latchprotocol/widgets] empty route\");\n }\n const currencyIn = first.currencyIn;\n const currencyOut = last.currencyOut;\n\n assertFeeArgs(args);\n\n const single = args.hops.length === 1;\n const action = single\n ? poolType === \"CL\"\n ? ACTIONS.CL_SWAP_EXACT_IN_SINGLE\n : ACTIONS.BIN_SWAP_EXACT_IN_SINGLE\n : poolType === \"CL\"\n ? ACTIONS.CL_SWAP_EXACT_IN\n : ACTIONS.BIN_SWAP_EXACT_IN;\n\n const params = single\n ? encodeSingleHop(first, args.amountIn, args.minAmountOutGross)\n : encodeMultiHop(args.hops, args.amountIn, args.minAmountOutGross);\n\n const p = plan().add(\n action,\n params,\n `${poolType} swap exact-in${single ? \" (single hop)\" : ` (${args.hops.length} hops)`}`,\n );\n\n p.add(\n ACTIONS.SETTLE_ALL,\n encodeAbiParameters(CURRENCY_AND_UINT256, [currencyIn, args.amountIn]),\n \"settle input currency from the caller\",\n );\n\n const recipientIsSender = isAddressEqual(args.recipient, args.sender);\n const takeRecipient = recipientIsSender ? MSG_SENDER : args.recipient;\n\n if (args.integrator.feeMode === \"pay-portion\") {\n // The router needs custody of the output to run PAY_PORTION over its balance.\n p.add(\n ACTIONS.TAKE,\n encodeAbiParameters(CURRENCY_ADDRESS_AND_UINT256, [\n currencyOut,\n ADDRESS_THIS,\n OPEN_DELTA,\n ]),\n \"take output to the router for the fee split\",\n );\n return { plan: p, currencyIn, currencyOut };\n }\n\n if (args.integrator.active) {\n p.add(\n ACTIONS.TAKE_PORTION,\n encodeAbiParameters(CURRENCY_ADDRESS_AND_UINT256, [\n currencyOut,\n args.integrator.referrer,\n BigInt(args.integrator.feeBps),\n ]),\n `integrator fee: ${args.integrator.feeBps} bps of output to ${args.integrator.referrer}`,\n );\n }\n\n if (recipientIsSender) {\n p.add(\n ACTIONS.TAKE_ALL,\n encodeAbiParameters(CURRENCY_AND_UINT256, [currencyOut, args.minAmountOutNet]),\n \"take remaining output to the caller, floored at minAmountOutNet\",\n );\n } else {\n // TAKE cannot express a minimum; the swap action's amountOutMinimum\n // (minAmountOutGross) is what protects the user in this branch.\n p.add(\n ACTIONS.TAKE,\n encodeAbiParameters(CURRENCY_ADDRESS_AND_UINT256, [\n currencyOut,\n takeRecipient,\n OPEN_DELTA,\n ]),\n \"take remaining output to the configured recipient\",\n );\n }\n\n return { plan: p, currencyIn, currencyOut };\n}\n\nfunction assertFeeArgs(args: BuildSwapCallArgs): void {\n const { integrator } = args;\n if (integrator.active) {\n if (integrator.feeBps <= 0 || integrator.feeBps > MAX_INTEGRATOR_FEE_BPS) {\n throw new RangeError(\n `[@latchprotocol/widgets] refusing to encode integrator feeBps ${integrator.feeBps}; ` +\n `expected 1..${MAX_INTEGRATOR_FEE_BPS}. This config should have been rejected by ` +\n \"validateIntegratorConfig - do not construct ResolvedIntegratorConfig by hand.\",\n );\n }\n if (isNative(integrator.referrer)) {\n throw new Error(\n \"[@latchprotocol/widgets] refusing to encode an integrator fee to the zero address\",\n );\n }\n }\n if (args.minAmountOutNet > args.minAmountOutGross) {\n throw new RangeError(\n `[@latchprotocol/widgets] minAmountOutNet (${args.minAmountOutNet}) exceeds ` +\n `minAmountOutGross (${args.minAmountOutGross}); the fee step can only reduce the output`,\n );\n }\n if (args.amountIn <= 0n) {\n throw new RangeError(`[@latchprotocol/widgets] amountIn must be positive: ${args.amountIn}`);\n }\n}\n\n/** Encodes the full `UniversalRouter.execute` call for a swap. */\nexport function buildSwapCall(args: BuildSwapCallArgs): EncodedSwapCall {\n const { plan: actionPlan, currencyIn, currencyOut } = buildSwapPlan(args);\n\n const commandBytes: number[] = [COMMANDS.INFI_SWAP];\n const inputs: Hex[] = [actionPlan.encode()];\n\n const usePayPortion = args.integrator.feeMode === \"pay-portion\";\n const recipientIsSender = isAddressEqual(args.recipient, args.sender);\n const sweepRecipient = recipientIsSender ? MSG_SENDER : args.recipient;\n\n if (usePayPortion) {\n if (args.integrator.active) {\n commandBytes.push(COMMANDS.PAY_PORTION);\n inputs.push(\n encodeAbiParameters(CURRENCY_ADDRESS_AND_UINT256, [\n currencyOut,\n args.integrator.referrer,\n BigInt(args.integrator.feeBps),\n ]),\n );\n }\n commandBytes.push(COMMANDS.SWEEP);\n inputs.push(\n encodeAbiParameters(CURRENCY_ADDRESS_AND_UINT256, [\n currencyOut,\n sweepRecipient,\n args.minAmountOutNet,\n ]),\n );\n }\n\n const commands = `0x${commandBytes\n .map((command) => command.toString(16).padStart(2, \"0\"))\n .join(\"\")}` as Hex;\n\n const data = encodeFunctionData({\n abi: UNIVERSAL_ROUTER_ABI,\n functionName: \"execute\",\n args: [commands, inputs, args.deadline],\n });\n\n const expectedFee = args.integrator.active\n ? calculateIntegratorFee(\n args.expectedAmountOutGross ?? args.minAmountOutGross,\n args.integrator.feeBps,\n )\n : 0n;\n\n return {\n to: args.router,\n data,\n value: isNative(currencyIn) ? args.amountIn : 0n,\n commands,\n inputs,\n planTrace: actionPlan.describe(),\n integratorFee: args.integrator.active\n ? {\n referrer: args.integrator.referrer,\n feeBps: args.integrator.feeBps,\n currency: currencyOut,\n mode: args.integrator.feeMode,\n expectedAmount: expectedFee,\n }\n : null,\n };\n}\n\n/** Positional pool-key tuple, re-exported so callers do not reach into the SDK. */\nexport { poolKeyToTuple };\n","// SPDX-License-Identifier: MIT\n/**\n * Launch call path.\n *\n * ## A Latch launch is a pool, and buying into one is a swap\n *\n * There is no Latch sale contract. No `buy`, no soft cap, no hard cap, no\n * allocation, no claim, no per-wallet limit. A launch is an ordinary\n * concentrated-liquidity pool with `LaunchGuardHook` named in its `PoolKey`,\n * a **dynamic** LP fee, and a fee schedule that decays from `initialFeeBips`\n * to `finalFeeBips` over a window starting at the launch's start.\n *\n * ## Two clocks, two hook generations\n *\n * The `LaunchGuardHook` built from current source measures in `block.timestamp`\n * seconds (`startTime`, `decaySeconds`). The one still deployed on Robinhood\n * (0x8b4F…575c) measures in the EVM's `block.number` (`startBlock`,\n * `decayBlocks`), which on Arbitrum Nitro is Ethereum's block, not the RPC's.\n * Their structs line up word for word, so the wrong ABI returns plausible\n * numbers rather than an error. Every record here therefore carries its\n * `durationClock`, and every comparison takes \"now\" on that same clock: the\n * latest block's timestamp, or `readContractBlockNumber`.\n *\n * That single design decision is what shapes this file. From the hook's own\n * source (`packages/hooks/src/launch/LaunchGuardHook.sol`):\n *\n * > THE `sender` ARGUMENT OF EVERY HOOK CALLBACK IS THE LOCKER, NOT THE END\n * > USER. […] Consequence: NO identity-based protection is implementable at\n * > this layer. There are no per-wallet caps, no allowlists, and no \"one buy\n * > per address\" rules in this hook, because none of them could be enforced\n * > honestly.\n *\n * So there is nothing per-account to read and nothing per-account to display.\n * Everything the hook knows is keyed by `PoolId`, and the only write path is\n * a swap through the router — which this package already encodes correctly in\n * {@link ./swap.js}. {@link buildLaunchBuyCall} therefore does not invent a\n * second call path: it checks the gates the hook will check, and then delegates\n * to `buildSwapCall`.\n *\n * ## What this file reads\n *\n * `LAUNCH_GUARD_HOOK_ABI` comes from `@latchprotocol/sdk`, which generates it\n * from compiled artifacts rather than from the GPL Solidity sources, so nothing\n * here puts an MIT consumer inside the core contracts' licence.\n *\n * Three views on the hook matter to a UI, all keyed by pool id:\n *\n * ```solidity\n * function getLaunch(PoolId poolId) external view returns (Launch memory);\n * function currentFee(PoolId poolId) external view returns (uint24);\n * function feeAt(PoolId poolId, uint256 timestampOrBlock) external view returns (uint24);\n * ```\n *\n * ## A naming trap worth stating once\n *\n * The struct fields are called `initialFeeBips` and `finalFeeBips`, but the\n * hook's own denominator is\n *\n * ```solidity\n * uint24 public constant FEE_DENOMINATOR = LPFeeLibrary.ONE_HUNDRED_PERCENT_FEE; // 1_000_000\n * ```\n *\n * so the unit is **pips** (hundredths of a basis point), not bips: `3_000` is\n * 0.30%, not 30%. The ABI keeps the contract's spelling because that is the\n * ABI; the TypeScript below says `Pips`, because that is what the number means.\n * Rendering these with a bps formatter would overstate every launch fee 100x.\n */\n\nimport { isAddressEqual, type Address } from \"viem\";\nimport { LAUNCH_GUARD_HOOK_ABI, LAUNCH_GUARD_HOOK_BLOCK_ABI, type DurationClock } from \"@latchprotocol/sdk\";\nimport {\n buildSwapCall,\n type BuildSwapCallArgs,\n type EncodedSwapCall,\n type SwapHop,\n} from \"./swap.js\";\n\n/**\n * The hook's ABIs, re-exported so callers need not depend on the SDK directly.\n * `LAUNCH_GUARD_HOOK_ABI` is the timestamp generation; `LAUNCH_GUARD_HOOK_BLOCK_ABI`\n * the block-numbered one still deployed. Select with {@link launchGuardAbiFor}.\n */\nexport { LAUNCH_GUARD_HOOK_ABI, LAUNCH_GUARD_HOOK_BLOCK_ABI };\nexport type { DurationClock };\n\n/** The ABI that decodes a hook of this clock correctly. */\nexport function launchGuardAbiFor(clock: DurationClock) {\n return clock === \"timestamp\" ? LAUNCH_GUARD_HOOK_ABI : LAUNCH_GUARD_HOOK_BLOCK_ABI;\n}\n\n/**\n * `LaunchGuardHook.FEE_DENOMINATOR`. 1_000_000 == 100%.\n *\n * Identical to the protocol-wide pips denominator, which is why a launch fee\n * can be rendered with the same formatter as any other LP fee.\n */\nexport const LAUNCH_FEE_DENOMINATOR = 1_000_000;\n\nconst ZERO_ADDRESS: Address = \"0x0000000000000000000000000000000000000000\";\n\n/**\n * A decoded `LaunchGuardHook.Launch` record, from either hook generation.\n *\n * Field-for-field the struct, with three changes: the clock is recorded,\n * `start` / `window` are named for what they are on EITHER clock, and the fee\n * fields are renamed to the unit they are actually in.\n */\nexport interface LaunchGuard {\n /** `timestamp`: `start` and `window` are seconds. `contract-block`: contract blocks. */\n readonly durationClock: DurationClock;\n /** Launch owner. The zero address means the pool id has never been claimed. */\n readonly owner: Address;\n /** First point (`startTime` or `startBlock`) at which swaps are permitted. */\n readonly start: bigint;\n /** Length of the decay window from `start`, in the clock's unit (`decaySeconds` or `decayBlocks`). */\n readonly window: number;\n /**\n * When false the hook applies no gate and no tax: it overrides the fee with\n * `finalFeePips` and nothing else. It does NOT mean \"no hook\".\n */\n readonly enabled: boolean;\n /** Fee at `start`, in pips. */\n readonly initialFeePips: number;\n /** Fee at and after `start + window`, in pips. */\n readonly finalFeePips: number;\n /**\n * Per-TRANSACTION cap on the input amount of a buy, in the quote currency.\n * `0` disables it. This is not a per-wallet cap and cannot be made into one.\n */\n readonly maxBuyPerTx: bigint;\n /** Which side of the pool is the token being launched. */\n readonly launchTokenIsCurrency0: boolean;\n /** Set by the hook on the first swap at or after `start`. */\n readonly launched: boolean;\n}\n\n/** The tuple shape `getLaunch` returns, as viem decodes it, for either generation. */\nexport interface RawLaunchGuard {\n readonly owner: Address;\n /** Timestamp generation. */\n readonly startTime?: number | bigint;\n readonly decaySeconds?: number;\n /** Block-numbered generation. */\n readonly startBlock?: number | bigint;\n readonly decayBlocks?: number;\n readonly enabled: boolean;\n readonly initialFeeBips: number;\n readonly finalFeeBips: number;\n readonly maxBuyPerTx: bigint;\n readonly launchTokenIsCurrency0: boolean;\n readonly launched: boolean;\n}\n\n/**\n * Normalises a `getLaunch` result into a {@link LaunchGuard}.\n *\n * `clock` must be the clock of the ABI the result was decoded with. A record\n * whose fields do not match that generation throws rather than defaulting.\n */\nexport function decodeLaunchGuard(raw: RawLaunchGuard, clock: DurationClock): LaunchGuard {\n const start = clock === \"timestamp\" ? raw.startTime : raw.startBlock;\n const window = clock === \"timestamp\" ? raw.decaySeconds : raw.decayBlocks;\n if (start === undefined || window === undefined) {\n throw new Error(\n `[@latchprotocol/widgets] getLaunch result has no ${clock === \"timestamp\" ? \"startTime/decaySeconds\" : \"startBlock/decayBlocks\"}: ` +\n \"it was decoded with the other hook generation's ABI.\",\n );\n }\n return {\n durationClock: clock,\n owner: raw.owner,\n start: BigInt(start),\n window: Number(window),\n enabled: raw.enabled,\n initialFeePips: raw.initialFeeBips,\n finalFeePips: raw.finalFeeBips,\n maxBuyPerTx: raw.maxBuyPerTx,\n launchTokenIsCurrency0: raw.launchTokenIsCurrency0,\n launched: raw.launched,\n };\n}\n\n/** `false` when the pool id has never been claimed, i.e. there is no launch. */\nexport function isLaunchConfigured(guard: LaunchGuard): boolean {\n return !isAddressEqual(guard.owner, ZERO_ADDRESS);\n}\n\n/**\n * Where a launch is in its schedule.\n *\n * - `unclaimed` — no launch record. Every view on the hook reverts\n * `LaunchNotConfigured`, and the pool could not have been initialized.\n * - `disabled` — `enabled == false`. No gate, no tax; the hook only pins the\n * fee at `finalFeePips`. Trading is open.\n * - `pending` — now < `start`. Every swap reverts `TradingNotOpen`. The owner\n * may still move the start.\n * - `decaying` — inside `[start, start + window)`. The fee is\n * above `finalFeePips` and `maxBuyPerTx` is enforced if it is set.\n * - `settled` — at or past `start + window`. The fee is exactly\n * `finalFeePips` and the per-transaction cap no longer applies.\n */\nexport type LaunchPhase = \"unclaimed\" | \"disabled\" | \"pending\" | \"decaying\" | \"settled\";\n\n/** The schedule as of one point on the hook's clock. Pure; nothing here is interpolated. */\nexport interface LaunchSchedule {\n readonly phase: LaunchPhase;\n /** The unit of `now`, `start`, `end`, `untilOpen` and `remaining`. */\n readonly durationClock: DurationClock;\n /** The point this view was computed for: a timestamp or a contract block. */\n readonly now: bigint;\n readonly start: bigint | null;\n /** `start + window`, the first point at the final fee. */\n readonly end: bigint | null;\n /** Units until trading opens, or `null` when it already has. */\n readonly untilOpen: bigint | null;\n /** Units left in the decay window, or `null` outside it. */\n readonly remaining: bigint | null;\n /** Progress through the decay window in bps, or `null` outside it. */\n readonly decayProgressBps: number | null;\n /** Fee a swap at `now` pays, in pips. `null` when unclaimed. */\n readonly feePips: number | null;\n readonly initialFeePips: number | null;\n readonly finalFeePips: number | null;\n /** `true` when a swap at `now` would be accepted by the hook. */\n readonly tradingOpen: boolean;\n /** The configured cap, or `null` when none is set. */\n readonly maxBuyPerTx: bigint | null;\n /** `true` only while the hook would actually check that cap. */\n readonly maxBuyPerTxEnforced: boolean;\n}\n\n/**\n * The fee a swap at `now` pays, in pips — an exact mirror of\n * `LaunchGuardHook.feeAt` including its rounding. `now` is on the guard's own\n * clock: the latest block's timestamp, or the CONTRACT block number.\n *\n * The subtracted discount is floored, so the fee rounds **up**, toward the LPs\n * and away from the sniper. Reproducing that direction matters: a UI that\n * rounded the other way would quote a fee lower than the one charged.\n *\n * Returns `null` for an unclaimed pool, where the contract reverts. Before the\n * start it returns `initialFeePips`, matching the contract —\n * though such a swap would in fact revert, so read that value as \"the fee at\n * the open\" rather than as a fee anyone can pay.\n */\nexport function launchFeeAt(guard: LaunchGuard, now: bigint): number | null {\n if (!isLaunchConfigured(guard)) return null;\n if (!guard.enabled) return guard.finalFeePips;\n if (now < guard.start) return guard.initialFeePips;\n const window = BigInt(guard.window);\n const elapsed = now - guard.start;\n if (window <= 0n || elapsed >= window) return guard.finalFeePips;\n const spread = BigInt(guard.initialFeePips - guard.finalFeePips);\n const discount = (spread * elapsed) / window;\n return guard.initialFeePips - Number(discount);\n}\n\n/** Derives the whole schedule at one point on the guard's clock. Pure. */\nexport function launchScheduleAt(guard: LaunchGuard, now: bigint): LaunchSchedule {\n const durationClock = guard.durationClock;\n if (!isLaunchConfigured(guard)) {\n return {\n phase: \"unclaimed\",\n durationClock,\n now,\n start: null,\n end: null,\n untilOpen: null,\n remaining: null,\n decayProgressBps: null,\n feePips: null,\n initialFeePips: null,\n finalFeePips: null,\n tradingOpen: false,\n maxBuyPerTx: null,\n maxBuyPerTxEnforced: false,\n };\n }\n\n const window = BigInt(guard.window);\n const end = guard.start + window;\n const feePips = launchFeeAt(guard, now);\n const maxBuyPerTx = guard.maxBuyPerTx === 0n ? null : guard.maxBuyPerTx;\n\n // A disabled launch is not gated and not taxed. `beforeSwap` returns the\n // final fee and returns early, so neither the start block nor the cap is\n // consulted - reporting a countdown here would be describing a gate that\n // does not run.\n if (!guard.enabled) {\n return {\n phase: \"disabled\",\n durationClock,\n now,\n start: guard.start,\n end,\n untilOpen: null,\n remaining: null,\n decayProgressBps: null,\n feePips,\n initialFeePips: guard.initialFeePips,\n finalFeePips: guard.finalFeePips,\n tradingOpen: true,\n maxBuyPerTx,\n maxBuyPerTxEnforced: false,\n };\n }\n\n if (now < guard.start) {\n return {\n phase: \"pending\",\n durationClock,\n now,\n start: guard.start,\n end,\n untilOpen: guard.start - now,\n remaining: null,\n decayProgressBps: 0,\n feePips,\n initialFeePips: guard.initialFeePips,\n finalFeePips: guard.finalFeePips,\n tradingOpen: false,\n maxBuyPerTx,\n maxBuyPerTxEnforced: false,\n };\n }\n\n const elapsed = now - guard.start;\n if (window > 0n && elapsed < window) {\n return {\n phase: \"decaying\",\n durationClock,\n now,\n start: guard.start,\n end,\n untilOpen: null,\n remaining: window - elapsed,\n decayProgressBps: Number((elapsed * 10_000n) / window),\n feePips,\n initialFeePips: guard.initialFeePips,\n finalFeePips: guard.finalFeePips,\n tradingOpen: true,\n maxBuyPerTx,\n maxBuyPerTxEnforced: maxBuyPerTx !== null,\n };\n }\n\n return {\n phase: \"settled\",\n durationClock,\n now,\n start: guard.start,\n end,\n untilOpen: null,\n remaining: null,\n decayProgressBps: 10_000,\n feePips,\n initialFeePips: guard.initialFeePips,\n finalFeePips: guard.finalFeePips,\n tradingOpen: true,\n maxBuyPerTx,\n maxBuyPerTxEnforced: false,\n };\n}\n\n/**\n * Why the hook would reject this buy. `null` means it would not.\n *\n * Each value names an actual revert in `LaunchGuardHook`, so a blocked button\n * here corresponds to a transaction that would have failed rather than to a\n * rule the widget made up.\n */\nexport type LaunchBuyBlockReason =\n | \"not-configured\"\n | \"trading-not-open\"\n | \"exceeds-max-buy-per-tx\"\n | null;\n\n/** Result of {@link evaluateLaunchBuy}. */\nexport interface LaunchBuyGate {\n readonly reason: LaunchBuyBlockReason;\n /** A message suitable for a disabled button, or `null` when not blocked. */\n readonly message: string | null;\n /** The contract error this would surface as, or `null`. */\n readonly revert: string | null;\n}\n\n/**\n * Evaluates the gates `LaunchGuardHook._beforeSwap` will evaluate.\n *\n * `amountIn` is the input amount of the swap, denominated in the **quote**\n * currency, which is the denomination `maxBuyPerTx` uses. Pass `null` while the\n * amount field is empty: the schedule gates are still checked, the cap is not.\n *\n * This covers only the hook. Balance, allowance and slippage are the swap\n * path's business and are evaluated there.\n */\nexport function evaluateLaunchBuy(args: {\n readonly guard: LaunchGuard;\n /** Now, on the guard's own clock. */\n readonly now: bigint;\n readonly amountIn: bigint | null;\n}): LaunchBuyGate {\n const schedule = launchScheduleAt(args.guard, args.now);\n\n if (schedule.phase === \"unclaimed\") {\n return {\n reason: \"not-configured\",\n message: \"No launch is configured for this pool\",\n revert: \"LaunchNotConfigured\",\n };\n }\n if (!schedule.tradingOpen) {\n return {\n reason: \"trading-not-open\",\n message: \"Trading has not opened yet\",\n revert: \"TradingNotOpen\",\n };\n }\n if (\n schedule.maxBuyPerTxEnforced &&\n schedule.maxBuyPerTx !== null &&\n args.amountIn !== null &&\n args.amountIn > schedule.maxBuyPerTx\n ) {\n return {\n reason: \"exceeds-max-buy-per-tx\",\n message: \"Amount is over the per-transaction cap for this launch\",\n revert: \"BuyExceedsMaxPerTx\",\n };\n }\n return { reason: null, message: null, revert: null };\n}\n\n/**\n * `true` when this hop buys the launch token, i.e. its input is the quote\n * currency.\n *\n * Mirrors the hook: `isBuy = launchTokenIsCurrency0 ? !zeroForOne : zeroForOne`.\n * Only a buy is subject to `maxBuyPerTx`; a sell is uncapped by design.\n */\nexport function hopIsLaunchBuy(hop: SwapHop, guard: LaunchGuard): boolean {\n const zeroForOne = isAddressEqual(hop.poolKey.currency0, hop.currencyIn);\n return guard.launchTokenIsCurrency0 ? !zeroForOne : zeroForOne;\n}\n\n/** Arguments for {@link buildLaunchBuyCall}. */\nexport interface BuildLaunchBuyArgs extends Omit<BuildSwapCallArgs, \"hops\"> {\n /**\n * The launch pool. A single hop: the hook governs one pool, and routing a\n * launch buy through an intermediate pool would leave the guard un-consulted\n * on the leg that matters.\n */\n readonly hop: SwapHop;\n /** The launch record read from the hook, used to check the gates. */\n readonly guard: LaunchGuard;\n /** Now, on the guard's clock, that the gates are evaluated against — the latest read from chain. */\n readonly now: bigint;\n}\n\n/**\n * Encodes a launch buy.\n *\n * This is {@link buildSwapCall} with the hook's preconditions checked first. It\n * is not a different transaction and there is no launch-specific calldata: the\n * router, the action plan and the integrator fee step are all exactly the swap\n * path's, because buying into a launch is a swap.\n *\n * Throws rather than encoding when the hook would revert. A launch fails in\n * `beforeSwap`, which is inside the vault lock, so the user pays gas for the\n * whole plan before finding out — refusing here is strictly cheaper than\n * letting them send it.\n *\n * Exact-output is not encodable at all: `beforeSwap` cannot know the input\n * amount of an exact-output swap, so the hook rejects one outright while the\n * cap is live (`ExactOutputBuyBlockedDuringLaunch`). This package only encodes\n * exact-input swaps, so the case cannot arise here.\n */\nexport function buildLaunchBuyCall(args: BuildLaunchBuyArgs): EncodedSwapCall {\n /* A CL hop is guarded by `LaunchGuardHook`, a BIN hop by `BinLaunchGuardHook`.\n Same schedule, same gates, same `Launch` record, same buy direction rule;\n the router action differs (`CL_SWAP_EXACT_IN_SINGLE` vs\n `BIN_SWAP_EXACT_IN_SINGLE`) and `buildSwapCall` picks it from the hop. */\n if (isAddressEqual(args.hop.poolKey.hooks, ZERO_ADDRESS)) {\n // A pool key naming no hook has no guard to consult, so the whole schedule\n // this function just validated would apply to nothing.\n throw new Error(\n \"[@latchprotocol/widgets] the pool key names no hook, so it is not a launch pool\",\n );\n }\n if (!hopIsLaunchBuy(args.hop, args.guard)) {\n throw new Error(\n \"[@latchprotocol/widgets] this hop sells the launch token rather than buying it. \" +\n \"Sells are ordinary swaps: use buildSwapCall directly.\",\n );\n }\n\n const gate = evaluateLaunchBuy({\n guard: args.guard,\n now: args.now,\n amountIn: args.amountIn,\n });\n if (gate.reason !== null) {\n throw new Error(\n `[@latchprotocol/widgets] refusing to encode a launch buy: ${gate.message} ` +\n `(the hook would revert ${gate.revert})`,\n );\n }\n\n const { hop, guard, now, ...swapArgs } = args;\n void guard;\n void now;\n return buildSwapCall({ ...swapArgs, hops: [hop] });\n}\n","// SPDX-License-Identifier: MIT\n/**\n * A small async-resource hook.\n *\n * The widgets deliberately do not depend on a data-fetching library: an\n * embeddable widget that drags TanStack Query into a host's bundle - and its\n * provider into the host's tree - is a widget teams decline to embed. This is\n * the minimum that behaves correctly: it cancels stale results, exposes a real\n * status enum rather than a pile of booleans, and never resolves into a\n * component that has unmounted.\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\n/** Lifecycle of an async resource. */\nexport type AsyncStatus = \"idle\" | \"loading\" | \"success\" | \"error\";\n\n/** State of an async resource. */\nexport interface AsyncResource<T> {\n readonly status: AsyncStatus;\n readonly data: T | null;\n readonly error: Error | null;\n /** `Date.now()` of the last successful load. */\n readonly updatedAt: number | null;\n /** True while refreshing over previously loaded data. */\n readonly isRefreshing: boolean;\n refetch(): void;\n}\n\n/** Options for {@link useAsyncResource}. */\nexport interface UseAsyncResourceOptions {\n /** Skip fetching entirely. The resource stays `idle`. */\n readonly enabled?: boolean;\n /** Poll interval in milliseconds. Omit or set 0 to disable polling. */\n readonly refetchIntervalMs?: number;\n}\n\nfunction toError(cause: unknown): Error {\n if (cause instanceof Error) return cause;\n return new Error(String(cause));\n}\n\n/**\n * Runs `loader` whenever `deps` change, with cancellation of stale results.\n *\n * `loader` must be stable or memoised by the caller; `deps` is what actually\n * triggers a refetch.\n */\nexport function useAsyncResource<T>(\n loader: () => Promise<T>,\n deps: readonly unknown[],\n options: UseAsyncResourceOptions = {},\n): AsyncResource<T> {\n const { enabled = true, refetchIntervalMs = 0 } = options;\n\n const [status, setStatus] = useState<AsyncStatus>(\"idle\");\n const [data, setData] = useState<T | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const [updatedAt, setUpdatedAt] = useState<number | null>(null);\n const [isRefreshing, setIsRefreshing] = useState(false);\n const [reloadToken, setReloadToken] = useState(0);\n\n const mounted = useRef(true);\n const requestId = useRef(0);\n const loaderRef = useRef(loader);\n loaderRef.current = loader;\n\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n\n const refetch = useCallback(() => {\n setReloadToken((token) => token + 1);\n }, []);\n\n useEffect(() => {\n if (!enabled) {\n setStatus(\"idle\");\n setIsRefreshing(false);\n return;\n }\n\n requestId.current += 1;\n const id = requestId.current;\n const hadData = data !== null;\n\n if (hadData) setIsRefreshing(true);\n else setStatus(\"loading\");\n\n void loaderRef\n .current()\n .then((result) => {\n if (!mounted.current || id !== requestId.current) return;\n setData(result);\n setError(null);\n setStatus(\"success\");\n setUpdatedAt(Date.now());\n setIsRefreshing(false);\n })\n .catch((cause: unknown) => {\n if (!mounted.current || id !== requestId.current) return;\n setError(toError(cause));\n setStatus(\"error\");\n setIsRefreshing(false);\n });\n // `data` is intentionally excluded: including it would refetch on every\n // successful load. It is read only to decide between \"loading\" and\n // \"refreshing\", which is a presentation detail.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, reloadToken, ...deps]);\n\n useEffect(() => {\n if (!enabled || refetchIntervalMs <= 0) return;\n const handle = setInterval(refetch, refetchIntervalMs);\n return () => clearInterval(handle);\n }, [enabled, refetchIntervalMs, refetch]);\n\n return { status, data, error, updatedAt, isRefreshing, refetch };\n}\n","// SPDX-License-Identifier: MIT\n/**\n * The chain boundary.\n *\n * Every read and every write the widgets perform goes through\n * {@link ProtocolAdapter}. No component, hook or controller in this package\n * imports a viem client directly, which is what makes an implementation\n * swappable without touching a line of UI.\n *\n * One implementation ships: {@link ../adapters/viem.js | ViemProtocolAdapter},\n * real reads and writes through a viem transport. The package ships no mock\n * adapter (source of truth only); the unit suites keep a test-only one under\n * test/helpers/. A host can implement this interface itself, for example on\n * top of wagmi or its own backend quoter - and if such an adapter serves\n * anything not read from a chain, `isMock` must be `true` so the widgets say so.\n */\n\nimport type { Address, Hex } from \"viem\";\nimport type { PoolKey, PoolId } from \"@latchprotocol/sdk\";\nimport type { LaunchGuard } from \"../callpath/launch.js\";\nimport type { ChainConfig } from \"../config/chain.js\";\nimport type { ResolvedIntegratorConfig } from \"../config/integrator.js\";\nimport type { TokenSaleAdapter } from \"./sale.js\";\n\n/** Which flavour of pool a key addresses. */\nexport type PoolType = \"CL\" | \"BIN\";\n\n/** Where a piece of data came from. Rendered by the UI; never cosmetic. */\nexport type DataSource = \"live\" | \"mock\";\n\n/** ERC-20 (or native) token metadata. */\nexport interface TokenInfo {\n readonly address: Address;\n readonly symbol: string;\n readonly name: string;\n readonly decimals: number;\n /** `https://` or `ipfs://` (resolved through the SDK's allow-listed gateways). Anything else renders as a monogram. */\n readonly logoUrl?: string;\n /** True for the chain's native asset (the zero address). */\n readonly isNative?: boolean;\n /**\n * Provenance, once token lists are in play (`SwapWidget`'s `tokenLists` prop).\n * `name` is the list the entry's fields came from, or `null` for a token the\n * adapter itself offers (the pools this site routes through); `alsoIn` is\n * every other list that names the same address. Absent when no list was given.\n */\n readonly listSource?: { readonly name: string | null; readonly alsoIn: readonly string[] };\n /** A tokenised stock, from a list's `extensions.stock`. The picker badges it; `rebasing` is a warning. */\n readonly stock?: { readonly issuer: string; readonly ticker: string; readonly rebasing: boolean };\n /** The list's tag ids for this token (`native`, `stock`, `test`, `launch`, ...). */\n readonly tags?: readonly string[];\n}\n\n/** A pool the widgets can route through or provide liquidity to. */\nexport interface PoolInfo {\n readonly id: PoolId;\n readonly key: PoolKey;\n readonly poolType: PoolType;\n readonly token0: TokenInfo;\n readonly token1: TokenInfo;\n /** Static LP fee in pips, or the dynamic-fee marker. */\n readonly lpFeePips: number;\n /** Concentrated-liquidity pools only. */\n readonly tickSpacing?: number;\n /** Liquidity-book pools only. */\n readonly binStep?: number;\n /** Hook contract, or the zero address. */\n readonly hooks: Address;\n}\n\n/** Live-ish pool state needed to render ranges and prices. */\nexport interface PoolState {\n readonly poolId: PoolId;\n readonly poolType: PoolType;\n /** Concentrated liquidity: current tick and price. */\n readonly currentTick?: number;\n readonly sqrtPriceX96?: bigint;\n readonly liquidity?: bigint;\n /** Liquidity book: currently active bin. */\n readonly activeId?: number;\n readonly source: DataSource;\n}\n\n/** One hop of a route. */\nexport interface RouteStep {\n readonly poolId: PoolId;\n readonly poolType: PoolType;\n readonly tokenIn: TokenInfo;\n readonly tokenOut: TokenInfo;\n readonly lpFeePips: number;\n readonly hooks: Address;\n}\n\n/** A swap quote request. Only exact-input is supported by the swap widget UI. */\nexport interface SwapQuoteRequest {\n readonly tokenIn: TokenInfo;\n readonly tokenOut: TokenInfo;\n readonly amountIn: bigint;\n /**\n * Restrict the quote to ONE pool. A launch widget sets this: a token with\n * both a CL and a Bin leg has two direct pools, and the schedule, the gate\n * and the buy must all refer to the same one.\n */\n readonly poolId?: PoolId;\n}\n\n/**\n * A swap quote.\n *\n * `grossAmountOut` is the pool's output **before** any integrator fee. The fee\n * split is computed by {@link ../core/math.js | buildQuoteBreakdown}, never by\n * the adapter, so that no adapter can under-report what an embedder earns.\n */\nexport interface SwapQuoteResult {\n readonly route: readonly RouteStep[];\n readonly amountIn: bigint;\n readonly grossAmountOut: bigint;\n /** Output at the current price with no impact, if computable. */\n readonly spotAmountOut: bigint | null;\n /** LP fee paid, expressed in the input currency. */\n readonly lpFeeAmount: bigint;\n readonly lpFeePips: number;\n /**\n * `true` when the pool's fee is set per swap by its hook and the adapter\n * could not read the rate in force (it can for a launch guard). `lpFeePips`\n * is then `0` and must be rendered as \"dynamic\", never as \"0%\".\n */\n readonly lpFeeUnknown?: boolean;\n readonly estimatedGas: bigint | null;\n readonly source: DataSource;\n}\n\n/** A transaction the host is asked to sign, in adapter-neutral form. */\nexport interface WidgetTransactionRequest {\n readonly to: Address;\n readonly data: Hex;\n readonly value: bigint;\n /** Human-readable summary, used in confirmation UI and error messages. */\n readonly summary: string;\n /** Populated when the transaction includes an integrator fee step. */\n readonly integratorFee?: {\n readonly referrer: Address;\n readonly feeBps: number;\n readonly currency: Address;\n readonly expectedAmount: bigint;\n };\n readonly source: DataSource;\n}\n\n/** The two-step allowance the router needs before it can pull the input token. */\nexport type ApprovalKind = \"erc20-to-permit2\" | \"permit2-to-router\";\n\n/** An outstanding approval blocking a swap or liquidity action. */\nexport interface ApprovalRequirement {\n readonly kind: ApprovalKind;\n readonly token: TokenInfo;\n readonly spender: Address;\n readonly current: bigint;\n readonly required: bigint;\n}\n\n/** Parameters for building a swap transaction. */\nexport interface SwapExecutionRequest {\n readonly quote: SwapQuoteResult;\n readonly tokenIn: TokenInfo;\n readonly tokenOut: TokenInfo;\n readonly amountIn: bigint;\n /** Floor enforced by the swap action, before the integrator fee. */\n readonly minAmountOutGross: bigint;\n /** Floor on what the user receives, after the integrator fee. */\n readonly minAmountOutNet: bigint;\n /** Validated integrator config. Threaded straight into the call path. */\n readonly integrator: ResolvedIntegratorConfig;\n readonly recipient: Address;\n readonly deadline: bigint;\n /** Extra data forwarded to the pool's hook, if any. */\n readonly hookData?: Hex;\n}\n\n/** A price range, expressed in whichever units the pool type uses. */\nexport type LiquidityRange =\n | { readonly type: \"CL\"; readonly tickLower: number; readonly tickUpper: number }\n | {\n readonly type: \"BIN\";\n readonly activeIdDesired: number;\n readonly binIdLower: number;\n readonly binIdUpper: number;\n /** How many bins the active id may drift before the mint reverts. */\n readonly idSlippage: number;\n };\n\n/** Request to quote an add-liquidity operation. */\nexport interface AddLiquidityQuoteRequest {\n readonly pool: PoolInfo;\n readonly range: LiquidityRange;\n readonly amount0Desired: bigint;\n readonly amount1Desired: bigint;\n}\n\n/** Quoted result of adding liquidity. */\nexport interface AddLiquidityQuote {\n readonly pool: PoolInfo;\n readonly range: LiquidityRange;\n readonly amount0: bigint;\n readonly amount1: bigint;\n /** CL: liquidity units. BIN: total liquidity minted across the bins. */\n readonly liquidity: bigint;\n /** Share of the pool this position would represent, in bps. Null if unknown. */\n readonly shareBps: number | null;\n /** BIN only: the per-bin distribution the call path will encode. */\n readonly binDistribution?: readonly BinLiquidityShare[];\n readonly source: DataSource;\n}\n\n/** One bin's share of a liquidity-book mint. */\nexport interface BinLiquidityShare {\n readonly binId: number;\n /** Offset from the active bin. */\n readonly deltaId: number;\n /** Share of `amount0`, scaled to 1e18. */\n readonly distributionX: bigint;\n /** Share of `amount1`, scaled to 1e18. */\n readonly distributionY: bigint;\n}\n\n/** An existing liquidity position owned by the connected account. */\nexport interface PositionInfo {\n readonly id: string;\n /** CL positions are ERC-721 token ids; bin positions are ERC-6909-style. */\n readonly tokenId?: bigint;\n readonly pool: PoolInfo;\n readonly range: LiquidityRange;\n readonly liquidity: bigint;\n readonly amount0: bigint;\n readonly amount1: bigint;\n readonly feesOwed0: bigint;\n readonly feesOwed1: bigint;\n /** BIN positions: the bins actually held, with their share amounts. */\n readonly binAmounts?: readonly { readonly binId: number; readonly amount: bigint }[];\n readonly inRange: boolean;\n readonly source: DataSource;\n}\n\n/** Request to build an add-liquidity transaction. */\nexport interface AddLiquidityExecutionRequest {\n readonly quote: AddLiquidityQuote;\n readonly amount0Max: bigint;\n readonly amount1Max: bigint;\n readonly recipient: Address;\n readonly deadline: bigint;\n readonly integrator: ResolvedIntegratorConfig;\n readonly hookData?: Hex;\n /** Set to increase an existing CL position rather than mint a new one. */\n readonly tokenId?: bigint;\n}\n\n/** Request to build a remove-liquidity transaction. */\nexport interface RemoveLiquidityExecutionRequest {\n readonly position: PositionInfo;\n /** Fraction of the position to withdraw, in bps of its liquidity. */\n readonly percentBps: number;\n readonly amount0Min: bigint;\n readonly amount1Min: bigint;\n readonly recipient: Address;\n readonly deadline: bigint;\n readonly integrator: ResolvedIntegratorConfig;\n readonly hookData?: Hex;\n}\n\n/** Quote for removing liquidity. */\nexport interface RemoveLiquidityQuote {\n readonly position: PositionInfo;\n readonly percentBps: number;\n readonly amount0: bigint;\n readonly amount1: bigint;\n readonly source: DataSource;\n}\n\n/**\n * A Latch launch.\n *\n * Not a token sale. A launch is a concentrated-liquidity pool with\n * `LaunchGuardHook` named in its `PoolKey` and a fee that decays from\n * `initialFeePips` to `finalFeePips` over `guard.window`. Everything the\n * hook knows is keyed by `PoolId`, and every field below is read from it or\n * from the pool key — there is no sale record, no cap, no allocation and no\n * per-account state to read, because none of those exist.\n *\n * Buying into a launch is an ordinary swap, quoted with `quoteSwap` and\n * executed with `buildSwap`, which is why this interface adds no buy method.\n */\nexport interface LaunchInfo {\n readonly poolId: PoolId;\n /** The pool itself: key, tokens, tick spacing. */\n readonly pool: PoolInfo;\n /** The launch guard the pool key names: `LaunchGuardHook` for a CL pool, `BinLaunchGuardHook` for a Bin pool. */\n readonly hook: Address;\n /** The token being launched, resolved from `guard.launchTokenIsCurrency0`. */\n readonly launchToken: TokenInfo;\n /** The other side of the pool: what buyers pay with, and what caps are in. */\n readonly quoteToken: TokenInfo;\n /** The decoded `getLaunch(poolId)` record. */\n readonly guard: LaunchGuard;\n /**\n * `currentFee(poolId)` as the hook answered it, in pips.\n *\n * Read from chain rather than derived, so the number on screen is the number\n * the contract will charge. {@link ../callpath/launch.js | launchFeeAt}\n * reproduces the same maths locally for the projected schedule.\n */\n readonly currentFeePips: number;\n /**\n * \"Now\" on the hook's own clock when the reads above were taken\n * (`guard.durationClock`): the latest `block.timestamp` for the timestamp\n * build, or `block.number` as the hook sees it for the block-numbered one —\n * NOT `eth_blockNumber`, which on an Arbitrum chain is the L2 block.\n */\n readonly readAt: bigint;\n readonly source: DataSource;\n}\n\n/** Result of waiting on a transaction. */\nexport interface TransactionOutcome {\n readonly hash: Hex;\n readonly status: \"success\" | \"reverted\";\n readonly blockNumber: bigint | null;\n readonly source: DataSource;\n}\n\n/**\n * The single interface every chain read and write passes through.\n *\n * Methods that a given deployment cannot support must throw\n * {@link UnsupportedOperationError} rather than returning empty or zero data.\n * Silence is indistinguishable from \"there is no liquidity\", which is a lie the\n * UI would render as fact.\n */\nexport interface ProtocolAdapter {\n /** Identifies the implementation, e.g. `\"viem\"`. */\n readonly kind: string;\n /**\n * `true` when nothing this adapter returns came from a chain. The styled\n * widgets render a persistent banner when this is set, and it cannot be\n * suppressed by configuration.\n */\n readonly isMock: boolean;\n readonly chain: ChainConfig;\n\n /** Connected account, or `null` when no wallet is connected. */\n getAccount(): Promise<Address | null>;\n\n /** Tokens this deployment knows about, for the token picker. */\n listTokens(): Promise<readonly TokenInfo[]>;\n getToken(address: Address): Promise<TokenInfo | null>;\n getBalance(token: TokenInfo, owner: Address): Promise<bigint>;\n\n /** Pools available for routing and liquidity provision. */\n listPools(): Promise<readonly PoolInfo[]>;\n getPoolState(pool: PoolInfo): Promise<PoolState>;\n\n /**\n * Approvals still required before `spender` can pull `amount` of `token`\n * through Permit2. `spender` defaults to the universal router (a swap); a\n * liquidity add passes the position manager that settles the deposit.\n */\n getApprovalRequirements(\n token: TokenInfo,\n owner: Address,\n amount: bigint,\n spender?: Address,\n ): Promise<readonly ApprovalRequirement[]>;\n buildApproval(requirement: ApprovalRequirement): Promise<WidgetTransactionRequest>;\n\n quoteSwap(request: SwapQuoteRequest): Promise<SwapQuoteResult>;\n buildSwap(request: SwapExecutionRequest): Promise<WidgetTransactionRequest>;\n\n quoteAddLiquidity(request: AddLiquidityQuoteRequest): Promise<AddLiquidityQuote>;\n buildAddLiquidity(request: AddLiquidityExecutionRequest): Promise<WidgetTransactionRequest>;\n listPositions(owner: Address, pool?: PoolInfo): Promise<readonly PositionInfo[]>;\n quoteRemoveLiquidity(position: PositionInfo, percentBps: number): Promise<RemoveLiquidityQuote>;\n buildRemoveLiquidity(\n request: RemoveLiquidityExecutionRequest,\n ): Promise<WidgetTransactionRequest>;\n\n /**\n * Launch pools this deployment surfaces.\n *\n * Must throw — not return `[]` — when the chain config carries neither a\n * `launchGuardHook` nor a `binLaunchGuardHook` address. An empty array means\n * \"a guard is deployed and no pool uses it\"; a `ChainConfigError` means \"there is no guard here\". A UI\n * has to be able to tell those apart, and only one of them is a launchpad\n * that does not exist on this chain.\n */\n listLaunches(): Promise<readonly LaunchInfo[]>;\n /** One launch by pool id, or `null` when that pool has no launch record. */\n getLaunch(poolId: PoolId): Promise<LaunchInfo | null>;\n /**\n * Every pool a `LaunchpadKitV2` launch opened for `token`, as launches, in\n * the kit's leg order. Must throw `ChainConfigError` naming `launchpadKitV2`\n * when no kit is configured; returns `[]` for a token the kit never launched.\n */\n getLaunchesForToken(token: Address): Promise<readonly LaunchInfo[]>;\n\n /**\n * Optional. A third-party token sale contract, which Latch does not have.\n * Nothing in this package reads it; see {@link ./sale.js}.\n */\n readonly sale?: TokenSaleAdapter;\n\n sendTransaction(request: WidgetTransactionRequest): Promise<Hex>;\n waitForTransaction(hash: Hex): Promise<TransactionOutcome>;\n /**\n * The chain's clock, in seconds: the timestamp the next block will carry\n * where the RPC can say (the pending block), else the latest block's (see\n * `nextBlockClock` in config/chain). Transaction deadlines are\n * compared with `block.timestamp`, so they are built from this clock rather\n * than the browser's: a devnet whose time was advanced, or a visitor whose\n * clock is wrong, would otherwise sign a trade that is already expired.\n * Optional: without it the widgets fall back to the local clock.\n */\n getBlockTimestamp?(): Promise<bigint>;\n}\n\n/** Thrown when an adapter cannot perform an operation on this deployment. */\nexport class UnsupportedOperationError extends Error {\n readonly operation: string;\n\n constructor(operation: string, detail: string) {\n super(`[@latchprotocol/widgets] ${operation} is not available: ${detail}`);\n this.name = \"UnsupportedOperationError\";\n this.operation = operation;\n }\n}\n\n/** Thrown when a wallet action is required but no account is connected. */\nexport class WalletNotConnectedError extends Error {\n constructor(action: string) {\n super(`[@latchprotocol/widgets] connect a wallet before attempting to ${action}`);\n this.name = \"WalletNotConnectedError\";\n }\n}\n\n/** Thrown when the requested route does not exist in this deployment. */\nexport class NoRouteError extends Error {\n readonly tokenIn: Address;\n readonly tokenOut: Address;\n\n constructor(tokenIn: Address, tokenOut: Address) {\n super(`[@latchprotocol/widgets] no pool connects ${tokenIn} to ${tokenOut}`);\n this.name = \"NoRouteError\";\n this.tokenIn = tokenIn;\n this.tokenOut = tokenOut;\n }\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Turns whatever a quote, a wallet or a transaction threw into one sentence a\n * trader can read.\n *\n * The raw error stays on the hook results (`error`) for hosts and logs; this is\n * only what the styled widgets PRINT. Nothing here invents a cause: a revert is\n * decoded against the ABIs of the contracts the widgets actually call (router,\n * quoters, position managers, launch guards, core), wrappers are unwrapped\n * (core's `WrappedError`, the quoter's `UnexpectedRevertBytes`), and a known\n * error name gets a plain explanation. An unknown selector is reported as what\n * it is - an unrecognised refusal - never guessed at.\n */\n\nimport { BaseError, decodeErrorResult, parseAbi, type Abi, type Hex } from \"viem\";\nimport {\n BIN_LAUNCH_GUARD_HOOK_ABI,\n BIN_POSITION_MANAGER_ABI,\n BIN_QUOTER_ABI,\n CL_POSITION_MANAGER_ABI,\n CL_QUOTER_ABI,\n LAUNCH_GUARD_HOOK_ABI,\n UNIVERSAL_ROUTER_ABI,\n} from \"@latchprotocol/sdk\";\nimport { LATCH_POSITION_LOCK_ABI, LATCH_TOKEN_LOCK_ABI } from \"@latchprotocol/sdk/lock\";\nimport { NoRouteError, UnsupportedOperationError, WalletNotConnectedError } from \"../adapters/protocol.js\";\n\n/* Core errors that surface through the router and the quoters. Declared here\n because the SDK ships events for core, not its errors. */\nconst CORE_ERRORS_ABI = parseAbi([\n \"error WrappedError(address target, bytes4 selector, bytes reason, bytes details)\",\n \"error UnexpectedRevertBytes(bytes revertData)\",\n \"error PoolNotInitialized()\",\n \"error InvalidFeeForExactOut()\",\n \"error InvalidSqrtPriceLimit(uint160 sqrtPriceCurrentX96, uint160 sqrtPriceLimitX96)\",\n \"error NoLiquidityToReceiveFees()\",\n \"error BinPool__OutOfLiquidity()\",\n \"error BinPool__InsufficientAmountUnSpecified()\",\n \"error CurrencyNotSettled()\",\n \"error HookDeltaExceedsSwapAmount()\",\n \"error InvalidHookResponse()\",\n \"error HookCallFailed()\",\n \"error Error(string)\",\n]);\n\n/* One ABI of errors only; duplicates across ABIs decode identically. */\nconst ERROR_ABI: Abi = (() => {\n const seen = new Set<string>();\n const out: unknown[] = [];\n for (const abi of [\n CORE_ERRORS_ABI,\n UNIVERSAL_ROUTER_ABI,\n CL_QUOTER_ABI,\n BIN_QUOTER_ABI,\n CL_POSITION_MANAGER_ABI,\n BIN_POSITION_MANAGER_ABI,\n LAUNCH_GUARD_HOOK_ABI,\n BIN_LAUNCH_GUARD_HOOK_ABI,\n LATCH_POSITION_LOCK_ABI,\n LATCH_TOKEN_LOCK_ABI,\n ] as readonly (readonly { type: string; name?: string; inputs?: readonly { type: string }[] }[])[]) {\n for (const item of abi) {\n if (item.type !== \"error\" || item.name === undefined) continue;\n const key = `${item.name}(${(item.inputs ?? []).map((i) => i.type).join(\",\")})`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(item);\n }\n }\n return out as Abi;\n})();\n\n/** Plain explanations for the refusals a trader can actually meet. */\nconst EXPLANATIONS: Readonly<Record<string, string>> = {\n TransactionDeadlinePassed: \"The transaction's deadline passed before it was mined. Nothing was spent; try again.\",\n DeadlinePassed: \"The transaction's deadline passed before it was mined. Nothing was spent; try again.\",\n SignatureDeadlineExpired: \"The signature's deadline passed. Sign again.\",\n TooLittleReceived: \"The price moved past your slippage tolerance, so the trade was refused.\",\n V3TooLittleReceived: \"The price moved past your slippage tolerance, so the trade was refused.\",\n V2TooLittleReceived: \"The price moved past your slippage tolerance, so the trade was refused.\",\n TooMuchRequested: \"The price moved past your slippage tolerance, so the trade was refused.\",\n MinimumAmountInsufficient: \"The pool would return less than your minimum, so it was refused. Widen slippage or try again.\",\n MaximumAmountExceeded: \"The pool would take more than your maximum, so it was refused. Widen slippage or try again.\",\n LiquiditySlippageCaught: \"The pool price moved while you were adding liquidity, so it was refused.\",\n IdSlippageCaught: \"The active bin moved while you were adding liquidity, so it was refused.\",\n NotEnoughLiquidity: \"The pool does not hold enough liquidity to fill this amount.\",\n BinPool__OutOfLiquidity: \"The pool does not hold enough liquidity to fill this amount.\",\n InvalidSqrtPriceLimit: \"This amount would move the price past the pool's limit. Try a smaller amount.\",\n PoolNotInitialized: \"This pool has not been initialised yet.\",\n InsufficientBalance: \"Your balance is too low for this transaction.\",\n InsufficientETH: \"Not enough native currency was sent with this transaction.\",\n InsufficientToken: \"Your token balance is too low for this transaction.\",\n BalanceTooLow: \"Your balance is too low for this transaction.\",\n TradingNotOpen: \"Trading on this launch pool has not opened yet.\",\n BuyExceedsMaxPerTx: \"This buy is larger than the launch's per-transaction cap. Try a smaller amount.\",\n ExactOutputBuyBlockedDuringLaunch: \"Exact-output buys are blocked while the launch is decaying.\",\n TaxedActiveBinMintBlocked: \"Liquidity cannot be added to the active bin while the launch's creator tax is live.\",\n EnforcedPause: \"The router is paused.\",\n ContractLocked: \"The contract is busy with another call. Try again.\",\n /* LatchPositionLock / LatchTokenLock (the locker widget). */\n InsufficientFee: \"Less than the lock fee was sent. The fee may have risen since it was read; reload and try again.\",\n AlreadyLocked: \"This position is already locked.\",\n EmptyPosition: \"This position holds no liquidity, so there is nothing to lock.\",\n NotPositionOwner: \"The connected wallet does not own this position.\",\n InvalidUnlock: \"The unlock date must be in the future and at most 100 years away.\",\n InvalidOwner: \"The lock owner is not a valid address.\",\n NotLater: \"A lock can only be extended to a later date, never shortened.\",\n NotLockOwner: \"Only the lock owner can do this.\",\n NotPendingOwner: \"Only the address the lock was offered to can accept it.\",\n NotLocked: \"No lock exists for this position.\",\n StillLocked: \"The lock has not reached its unlock date yet.\",\n PositionIsLocked: \"This position is held by a lock.\",\n InvalidSchedule: \"The schedule is invalid: it needs start <= cliff <= end, an end in the future, at most 100 years away.\",\n InvalidBeneficiary: \"The beneficiary is not a valid address.\",\n NativeValueMismatch: \"The native amount sent does not match the amount plus the fee.\",\n NoSuchLock: \"No lock exists with this id.\",\n NotBeneficiary: \"Only the beneficiary can claim or move this lock.\",\n NotPendingBeneficiary: \"Only the address the lock was offered to can accept it.\",\n NothingToClaim: \"Nothing has vested beyond what was already claimed.\",\n ZeroAmount: \"Lock an amount above zero.\",\n SafeERC20FailedOperation: \"The token transfer failed. Check the balance and the approval.\",\n};\n\n/** The revert data a thrown error carries, if any. */\nfunction revertDataOf(error: unknown): Hex | null {\n let found: Hex | null = null;\n const visit = (value: unknown): void => {\n if (found !== null || value === null || typeof value !== \"object\") return;\n const record = value as Record<string, unknown>;\n for (const key of [\"raw\", \"data\"]) {\n const v = record[key];\n if (typeof v === \"string\" && /^0x[0-9a-fA-F]{8,}$/.test(v)) {\n found = v as Hex;\n return;\n }\n if (v !== null && typeof v === \"object\" && typeof (v as Record<string, unknown>).data === \"string\") {\n const inner = (v as Record<string, unknown>).data as string;\n if (/^0x[0-9a-fA-F]{8,}$/.test(inner)) {\n found = inner as Hex;\n return;\n }\n }\n }\n visit(record.cause);\n };\n visit(error);\n if (found !== null) return found;\n /* Anvil and some nodes only put it in the message: \"custom error 0x5bf6f916: …\". */\n const message = messageOf(error);\n const inMessage = /custom error (0x[0-9a-fA-F]{8})(?::\\s*(?:0x)?([0-9a-fA-F]*))?/.exec(message);\n if (inMessage !== null) return `${inMessage[1]}${inMessage[2] ?? \"\"}` as Hex;\n const signature = /signature:\\s*\\n?\\s*(0x[0-9a-fA-F]{8,})/.exec(message);\n if (signature !== null) return signature[1] as Hex;\n return null;\n}\n\nfunction messageOf(error: unknown): string {\n if (error instanceof BaseError) return `${error.message}`;\n if (error instanceof Error) return error.message;\n return String(error);\n}\n\n/** Decodes revert data to an error name, following wrappers. `null` when unknown. */\nexport function decodeRevertName(data: Hex, depth = 0): string | null {\n if (depth > 4 || data.length < 10) return null;\n try {\n const decoded = decodeErrorResult({ abi: ERROR_ABI, data });\n const args = (decoded.args ?? []) as readonly unknown[];\n if (decoded.errorName === \"WrappedError\") {\n const inner = args[2];\n if (typeof inner === \"string\" && inner.length >= 10) return decodeRevertName(inner as Hex, depth + 1) ?? \"WrappedError\";\n return \"WrappedError\";\n }\n if (decoded.errorName === \"UnexpectedRevertBytes\") {\n const inner = args[0];\n if (typeof inner === \"string\" && inner.length >= 10) return decodeRevertName(inner as Hex, depth + 1);\n return null;\n }\n if (decoded.errorName === \"Error\" && typeof args[0] === \"string\") return `Error: ${args[0]}`;\n return decoded.errorName;\n } catch {\n return null;\n }\n}\n\n/** A sentence for a decoded refusal. */\nfunction explainRevert(name: string): string {\n if (name.startsWith(\"Error: \")) return `The contract refused: ${name.slice(7)}`;\n return EXPLANATIONS[name] ?? `The contract refused the transaction (${name}).`;\n}\n\nfunction isUserRejection(error: unknown): boolean {\n let hit = false;\n const visit = (value: unknown, depth: number): void => {\n if (hit || depth > 6 || value === null || typeof value !== \"object\") return;\n const record = value as Record<string, unknown>;\n if (record.code === 4001 || record.name === \"UserRejectedRequestError\") {\n hit = true;\n return;\n }\n visit(record.cause, depth + 1);\n };\n visit(error, 0);\n return hit || /user rejected|user denied|rejected the request/i.test(messageOf(error));\n}\n\n/** The first human line of a message, without the package tag or viem's appendix. */\nfunction firstLine(message: string): string {\n const cleaned = message.replace(/^\\[@latchprotocol\\/widgets\\]\\s*/, \"\");\n const line = cleaned.split(\"\\n\")[0]?.trim() ?? \"\";\n return line.length > 180 ? `${line.slice(0, 177)}…` : line;\n}\n\n/** What went wrong, in one plain sentence. `context` names the action for the fallbacks. */\nexport function describeError(error: unknown, context: \"quote\" | \"swap\" | \"liquidity\" | \"transaction\" = \"transaction\"): string {\n if (error === null || error === undefined) return \"Something went wrong.\";\n if (isUserRejection(error)) return \"You rejected the request in your wallet. Nothing was sent.\";\n if (error instanceof WalletNotConnectedError) return \"Connect a wallet first.\";\n if (error instanceof NoRouteError) return \"No pool on this site connects these two tokens.\";\n\n const data = revertDataOf(error);\n const name = data === null ? null : decodeRevertName(data);\n if (name !== null) return explainRevert(name);\n\n if (error instanceof UnsupportedOperationError) {\n if (error.operation === \"quoteSwap\") {\n if (/every direct pool for this pair failed to quote/.test(error.message)) {\n return \"No pool could quote this trade. The amount may be more than the pool can fill, or trading may not be open yet.\";\n }\n if (/no configured pool holds both/.test(error.message)) return \"No pool on this site connects these two tokens.\";\n if (/no quoter is configured/.test(error.message)) return \"This site has no quoter for that pool type, so it will not price the trade.\";\n }\n if (error.operation === \"quoteAddLiquidity\") {\n if (/mint no liquidity/.test(error.message)) return \"These amounts add no liquidity to this range. Enter a larger amount of the token the range holds.\";\n if (/active bin is/.test(error.message)) return \"The active bin moved since the range was set. Reset the range and try again.\";\n if (/nothing to deposit/.test(error.message)) return \"The chosen bins take only the token whose amount is zero. Enter an amount of the other token.\";\n return \"This position cannot be priced on this pool. Check the range and the amounts.\";\n }\n return \"This action is not available on this deployment.\";\n }\n\n if (data !== null) return `The contract refused the transaction (unrecognised error ${data.slice(0, 10)}).`;\n if (error instanceof BaseError && typeof error.shortMessage === \"string\" && error.shortMessage !== \"\") {\n if (/reverted/i.test(error.shortMessage)) {\n return context === \"quote\" ? \"The pool refused to quote this trade.\" : \"The transaction would revert, so it was not sent.\";\n }\n return firstLine(error.shortMessage);\n }\n const line = firstLine(messageOf(error));\n return line === \"\" ? \"Something went wrong.\" : line;\n}\n","// SPDX-License-Identifier: MIT\r\n/**\r\n * Headless swap execution: approvals, signature, confirmation.\r\n *\r\n * The integrator fee is threaded in here, not chosen here. The hook reads the\r\n * validated config from context and passes it to `adapter.buildSwap`, which\r\n * hands it to `buildSwapCall`, which encodes the `TAKE_PORTION` (or\r\n * `PAY_PORTION`) step. There is no code path that executes a swap while\r\n * dropping the fee, and none that executes one with an unvalidated fee.\r\n */\r\n\r\nimport { useCallback, useMemo, useState } from \"react\";\r\nimport type { Hex } from \"viem\";\r\nimport type {\r\n ApprovalRequirement,\r\n SwapQuoteResult,\r\n TokenInfo,\r\n WidgetTransactionRequest,\r\n} from \"../adapters/protocol.js\";\r\nimport { WalletNotConnectedError } from \"../adapters/protocol.js\";\r\nimport { chainDeadline } from \"../config/chain.js\";\r\nimport { useWidgetContext } from \"../context/WidgetProvider.js\";\r\nimport { describeError } from \"../core/errors.js\";\r\nimport type { QuoteBreakdown } from \"../core/math.js\";\r\nimport { useAsyncResource } from \"./useAsyncResource.js\";\r\n\r\n/** Where a swap is in its lifecycle. */\r\nexport type SwapExecutionStep =\r\n | \"idle\"\r\n | \"needs-approval\"\r\n | \"approving\"\r\n | \"building\"\r\n | \"awaiting-signature\"\r\n | \"pending\"\r\n | \"success\"\r\n | \"error\";\r\n\r\n/** Parameters for {@link useSwapExecute}. */\r\nexport interface UseSwapExecuteParams {\r\n readonly tokenIn: TokenInfo | null;\r\n readonly tokenOut: TokenInfo | null;\r\n readonly amountIn: bigint | null;\r\n readonly quote: SwapQuoteResult | null;\r\n readonly breakdown: QuoteBreakdown | null;\r\n /** Defaults to the connected account. */\r\n readonly recipient?: `0x${string}`;\r\n /** Called once the swap transaction confirms. */\r\n readonly onSuccess?: (hash: Hex) => void;\r\n readonly onError?: (error: Error) => void;\r\n}\r\n\r\n/** Result of {@link useSwapExecute}. */\r\nexport interface UseSwapExecuteResult {\r\n readonly step: SwapExecutionStep;\r\n readonly error: Error | null;\r\n readonly txHash: Hex | null;\r\n readonly approvals: readonly ApprovalRequirement[];\r\n readonly needsApproval: boolean;\r\n readonly canExecute: boolean;\r\n /** One-line description of the current state, suitable for `aria-live`. */\r\n readonly statusMessage: string;\r\n /** The built transaction, exposed so a host can inspect or simulate it. */\r\n readonly preparedTransaction: WidgetTransactionRequest | null;\r\n approve(): Promise<void>;\r\n execute(): Promise<void>;\r\n reset(): void;\r\n}\r\n\r\nfunction toError(cause: unknown): Error {\r\n return cause instanceof Error ? cause : new Error(String(cause));\r\n}\r\n\r\n/** Drives the approve-then-swap flow. */\r\nexport function useSwapExecute(params: UseSwapExecuteParams): UseSwapExecuteResult {\r\n const { adapter, chain, integrator } = useWidgetContext();\r\n const { tokenIn, tokenOut, amountIn, quote, breakdown } = params;\r\n\r\n const [step, setStep] = useState<SwapExecutionStep>(\"idle\");\r\n const [error, setError] = useState<Error | null>(null);\r\n const [txHash, setTxHash] = useState<Hex | null>(null);\r\n const [prepared, setPrepared] = useState<WidgetTransactionRequest | null>(null);\r\n const [approvalToken, setApprovalToken] = useState(0);\r\n\r\n const accountResource = useAsyncResource(\r\n useCallback(() => adapter.getAccount(), [adapter]),\r\n [adapter],\r\n );\r\n const account = accountResource.data;\r\n\r\n const approvalLoader = useCallback(async (): Promise<readonly ApprovalRequirement[]> => {\r\n if (tokenIn === null || amountIn === null || account === null) return [];\r\n return adapter.getApprovalRequirements(tokenIn, account, amountIn);\r\n }, [adapter, tokenIn, amountIn, account]);\r\n\r\n const approvalResource = useAsyncResource<readonly ApprovalRequirement[]>(\r\n approvalLoader,\r\n [\r\n adapter,\r\n tokenIn?.address ?? null,\r\n amountIn === null ? null : amountIn.toString(),\r\n account,\r\n approvalToken,\r\n ],\r\n { enabled: tokenIn !== null && amountIn !== null && amountIn > 0n && account !== null },\r\n );\r\n\r\n const approvals = approvalResource.data ?? [];\r\n const needsApproval = approvals.length > 0;\r\n\r\n const canExecute =\r\n tokenIn !== null &&\r\n tokenOut !== null &&\r\n amountIn !== null &&\r\n amountIn > 0n &&\r\n quote !== null &&\r\n breakdown !== null &&\r\n account !== null &&\r\n !needsApproval &&\r\n (step === \"idle\" || step === \"error\" || step === \"success\");\r\n\r\n const approve = useCallback(async (): Promise<void> => {\r\n const next = approvals[0];\r\n if (next === undefined) return;\r\n setError(null);\r\n setStep(\"approving\");\r\n try {\r\n const transaction = await adapter.buildApproval(next);\r\n const hash = await adapter.sendTransaction(transaction);\r\n await adapter.waitForTransaction(hash);\r\n setApprovalToken((token) => token + 1);\r\n setStep(\"idle\");\r\n } catch (cause: unknown) {\r\n const wrapped = toError(cause);\r\n setError(wrapped);\r\n setStep(\"error\");\r\n params.onError?.(wrapped);\r\n }\r\n }, [adapter, approvals, params]);\r\n\r\n const execute = useCallback(async (): Promise<void> => {\r\n if (tokenIn === null || tokenOut === null || amountIn === null) return;\r\n if (quote === null || breakdown === null) return;\r\n if (account === null) {\r\n const wrapped = new WalletNotConnectedError(\"swap\");\r\n setError(wrapped);\r\n setStep(\"error\");\r\n params.onError?.(wrapped);\r\n return;\r\n }\r\n\r\n setError(null);\r\n setTxHash(null);\r\n setStep(\"building\");\r\n try {\r\n const transaction = await adapter.buildSwap({\r\n quote,\r\n tokenIn,\r\n tokenOut,\r\n amountIn,\r\n minAmountOutGross: breakdown.minAmountOutGross,\r\n minAmountOutNet: breakdown.minAmountOutNet,\r\n // The validated config from context. Never a raw prop.\r\n integrator,\r\n recipient: params.recipient ?? account,\r\n deadline: await chainDeadline(chain, adapter),\r\n });\r\n setPrepared(transaction);\r\n\r\n setStep(\"awaiting-signature\");\r\n const hash = await adapter.sendTransaction(transaction);\r\n setTxHash(hash);\r\n\r\n setStep(\"pending\");\r\n const outcome = await adapter.waitForTransaction(hash);\r\n if (outcome.status === \"reverted\") {\r\n throw new Error(`The swap was mined but reverted (${hash}).`);\r\n }\r\n setStep(\"success\");\r\n params.onSuccess?.(hash);\r\n } catch (cause: unknown) {\r\n const wrapped = toError(cause);\r\n setError(wrapped);\r\n setStep(\"error\");\r\n params.onError?.(wrapped);\r\n }\r\n }, [\r\n adapter,\r\n account,\r\n amountIn,\r\n breakdown,\r\n chain,\r\n integrator,\r\n params,\r\n quote,\r\n tokenIn,\r\n tokenOut,\r\n ]);\r\n\r\n const reset = useCallback(() => {\r\n setStep(\"idle\");\r\n setError(null);\r\n setTxHash(null);\r\n setPrepared(null);\r\n }, []);\r\n\r\n const effectiveStep: SwapExecutionStep =\r\n step === \"idle\" && needsApproval ? \"needs-approval\" : step;\r\n\r\n const statusMessage = useMemo(\r\n () => describeStep(effectiveStep, approvals[0], error, adapter.isMock),\r\n [effectiveStep, approvals, error, adapter.isMock],\r\n );\r\n\r\n return {\r\n step: effectiveStep,\r\n error,\r\n txHash,\r\n approvals,\r\n needsApproval,\r\n canExecute,\r\n statusMessage,\r\n preparedTransaction: prepared,\r\n approve,\r\n execute,\r\n reset,\r\n };\r\n}\r\n\r\nfunction describeStep(\r\n step: SwapExecutionStep,\r\n pending: ApprovalRequirement | undefined,\r\n error: Error | null,\r\n isMock: boolean,\r\n): string {\r\n const mockPrefix = isMock ? \"Simulated (mock adapter): \" : \"\";\r\n switch (step) {\r\n case \"idle\":\r\n return \"\";\r\n case \"needs-approval\":\r\n return pending === undefined\r\n ? \"Approval required\"\r\n : pending.kind === \"erc20-to-permit2\"\r\n ? `Approve ${pending.token.symbol} for Permit2 before swapping`\r\n : `Approve the router to spend ${pending.token.symbol} via Permit2`;\r\n case \"approving\":\r\n return `${mockPrefix}Waiting for the approval transaction to confirm`;\r\n case \"building\":\r\n return `${mockPrefix}Preparing the swap transaction`;\r\n case \"awaiting-signature\":\r\n return `${mockPrefix}Confirm the transaction in your wallet`;\r\n case \"pending\":\r\n return `${mockPrefix}Swap submitted, waiting for confirmation`;\r\n case \"success\":\r\n return `${mockPrefix}Swap confirmed`;\r\n case \"error\":\r\n return error === null ? \"Something went wrong\" : describeError(error, \"swap\");\r\n default:\r\n return \"\";\r\n }\r\n}\r\n","// SPDX-License-Identifier: MIT\n/**\n * Headless swap quoting.\n *\n * Returns the adapter's raw quote *and* the derived\n * {@link ../core/math.js | QuoteBreakdown}, which already has the integrator fee\n * split out. A custom UI built on this hook shows the integrator's cut - and\n * the user's true net - without having to know the fee mechanism exists.\n */\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport type { SwapQuoteResult, TokenInfo } from \"../adapters/protocol.js\";\nimport { useWidgetContext } from \"../context/WidgetProvider.js\";\nimport {\n buildQuoteBreakdown,\n exchangeRate,\n MAX_SLIPPAGE_BPS,\n type QuoteBreakdown,\n} from \"../core/math.js\";\nimport type { PoolId } from \"@latchprotocol/sdk\";\nimport { useAsyncResource, type AsyncStatus } from \"./useAsyncResource.js\";\n\n/** Parameters for {@link useSwapQuote}. */\nexport interface UseSwapQuoteParams {\n readonly tokenIn: TokenInfo | null;\n readonly tokenOut: TokenInfo | null;\n /** Input amount in the smallest unit, or `null` while the field is empty. */\n readonly amountIn: bigint | null;\n /** Overrides the provider's default slippage. */\n readonly slippageBps?: number;\n /** Re-quote interval. Quotes go stale; 15s is a sane default for a UI. */\n readonly refetchIntervalMs?: number;\n readonly enabled?: boolean;\n /** Quote through this pool only. See `SwapQuoteRequest.poolId`. */\n readonly poolId?: PoolId;\n}\n\n/** Result of {@link useSwapQuote}. */\nexport interface UseSwapQuoteResult {\n readonly status: AsyncStatus;\n readonly quote: SwapQuoteResult | null;\n /** Fee-aware derivation of the quote. `null` until a quote arrives. */\n readonly breakdown: QuoteBreakdown | null;\n readonly error: Error | null;\n readonly isRefreshing: boolean;\n readonly updatedAt: number | null;\n /** True when the numbers came from the mock adapter and are not real. */\n readonly isMock: boolean;\n /** Output units per input unit, for display only. */\n readonly rate: number | null;\n readonly slippageBps: number;\n refetch(): void;\n}\n\n/** Quotes a swap and derives the fee-inclusive breakdown. */\nexport function useSwapQuote(params: UseSwapQuoteParams): UseSwapQuoteResult {\n const { adapter, integrator, defaultSlippageBps } = useWidgetContext();\n const { tokenIn, tokenOut, amountIn } = params;\n\n const slippageBps = params.slippageBps ?? defaultSlippageBps;\n if (!Number.isInteger(slippageBps) || slippageBps < 0 || slippageBps > MAX_SLIPPAGE_BPS) {\n throw new RangeError(\n `[@latchprotocol/widgets] slippageBps must be an integer in [0, ${MAX_SLIPPAGE_BPS}]: ${slippageBps}`,\n );\n }\n\n const enabled =\n (params.enabled ?? true) &&\n tokenIn !== null &&\n tokenOut !== null &&\n amountIn !== null &&\n amountIn > 0n &&\n tokenIn.address.toLowerCase() !== tokenOut.address.toLowerCase();\n\n const loader = useCallback(async (): Promise<SwapQuoteResult> => {\n if (tokenIn === null || tokenOut === null || amountIn === null) {\n throw new Error(\"useSwapQuote: called without a complete request\");\n }\n return adapter.quoteSwap({ tokenIn, tokenOut, amountIn, ...(params.poolId === undefined ? {} : { poolId: params.poolId }) });\n }, [adapter, tokenIn, tokenOut, amountIn, params.poolId]);\n\n const resource = useAsyncResource<SwapQuoteResult>(\n loader,\n [\n adapter,\n tokenIn?.address ?? null,\n tokenOut?.address ?? null,\n amountIn === null ? null : amountIn.toString(),\n params.poolId ?? null,\n ],\n {\n enabled,\n refetchIntervalMs: params.refetchIntervalMs ?? 15_000,\n },\n );\n\n /* Only a quote FOR THE CURRENT REQUEST is ever returned. The resource keeps\n its last data through a reload and through an error, so after a flip or an\n edit the previous quote - for the other direction, or another amount -\n would otherwise render as this trade's output and rate. A quote whose\n request failed is no quote either. */\n const current = useMemo<SwapQuoteResult | null>(() => {\n const data = resource.data;\n if (data === null || !enabled || (resource.status === \"error\" && !resource.isRefreshing)) return null;\n if (tokenIn === null || tokenOut === null || amountIn === null) return null;\n if (data.amountIn !== amountIn) return null;\n const first = data.route[0];\n const last = data.route[data.route.length - 1];\n if (first !== undefined && first.tokenIn.address.toLowerCase() !== tokenIn.address.toLowerCase()) return null;\n if (last !== undefined && last.tokenOut.address.toLowerCase() !== tokenOut.address.toLowerCase()) return null;\n return data;\n }, [resource.data, resource.status, resource.isRefreshing, enabled, tokenIn, tokenOut, amountIn]);\n\n /* While the current request is in flight over an older answer (or an older\n error), the honest status is \"loading\", not the old one. */\n const status: AsyncStatus = !enabled\n ? \"idle\"\n : current !== null\n ? \"success\"\n : resource.isRefreshing || resource.status === \"success\"\n ? \"loading\"\n : resource.status;\n\n const breakdown = useMemo<QuoteBreakdown | null>(() => {\n if (current === null) return null;\n return buildQuoteBreakdown({\n amountIn: current.amountIn,\n grossAmountOut: current.grossAmountOut,\n spotAmountOut: current.spotAmountOut,\n lpFeeAmount: current.lpFeeAmount,\n lpFeePips: current.lpFeePips,\n ...(current.lpFeeUnknown === undefined ? {} : { lpFeeUnknown: current.lpFeeUnknown }),\n slippageBps,\n integrator,\n });\n }, [current, slippageBps, integrator]);\n\n const rate = useMemo(() => {\n if (breakdown === null || tokenIn === null || tokenOut === null) return null;\n return exchangeRate(\n breakdown.amountIn,\n tokenIn.decimals,\n breakdown.netAmountOut,\n tokenOut.decimals,\n );\n }, [breakdown, tokenIn, tokenOut]);\n\n return {\n status,\n quote: current,\n breakdown,\n error: status === \"error\" ? resource.error : null,\n isRefreshing: resource.isRefreshing && current !== null,\n updatedAt: resource.updatedAt,\n isMock: adapter.isMock,\n rate,\n slippageBps,\n refetch: resource.refetch,\n };\n}\n\n/** Tracks a slippage setting with validation, for UIs that expose the control. */\nexport function useSlippageSetting(initialBps?: number): {\n slippageBps: number;\n setSlippageBps(next: number): void;\n error: string | null;\n} {\n const { defaultSlippageBps } = useWidgetContext();\n const [slippageBps, setValue] = useState(initialBps ?? defaultSlippageBps);\n const [error, setError] = useState<string | null>(null);\n\n const setSlippageBps = useCallback((next: number) => {\n if (!Number.isInteger(next) || next < 0) {\n setError(\"Slippage must be a whole number of basis points\");\n return;\n }\n if (next > MAX_SLIPPAGE_BPS) {\n setError(`Slippage above ${MAX_SLIPPAGE_BPS / 100}% is not accepted`);\n return;\n }\n setError(null);\n setValue(next);\n }, []);\n\n return { slippageBps, setSlippageBps, error };\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Headless launch participation.\n *\n * A launch is a pool with `LaunchGuardHook` attached, so buying into one is a\n * swap and this module owns exactly two things a swap does not have:\n *\n * 1. **The schedule.** `startBlock`, `decayBlocks`, and the fee decaying from\n * `initialFeePips` to `finalFeePips` between them. All block-denominated,\n * never time-denominated: the hook counts blocks, and converting to seconds\n * would require a block time this package cannot know.\n * 2. **The gates.** `TradingNotOpen` before the open, and `BuyExceedsMaxPerTx`\n * while the window is live. Both are evaluated here so the button can be\n * disabled with the reason, rather than reverting inside the vault lock\n * after the user has paid for the whole plan.\n *\n * There is no third thing. In particular there is no per-account state to load:\n * the hook cannot identify a buyer (see {@link ../callpath/launch.js}), so a\n * \"your remaining allocation\" row would be fiction with a number on it.\n */\n\nimport { useCallback, useMemo } from \"react\";\nimport type { Address, Hex } from \"viem\";\nimport type { PoolId } from \"@latchprotocol/sdk\";\nimport type { LaunchInfo } from \"../adapters/protocol.js\";\nimport {\n evaluateLaunchBuy,\n launchScheduleAt,\n type LaunchBuyGate,\n type LaunchSchedule,\n} from \"../callpath/launch.js\";\nimport { ChainConfigError } from \"../config/chain.js\";\nimport { useWidgetContext } from \"../context/WidgetProvider.js\";\nimport type { QuoteBreakdown } from \"../core/math.js\";\nimport { useAsyncResource, type AsyncResource, type AsyncStatus } from \"./useAsyncResource.js\";\nimport { useSwapExecute, type UseSwapExecuteResult } from \"./useSwapExecute.js\";\nimport { useSwapQuote } from \"./useSwapQuote.js\";\n\n/**\n * The four states a launch surface can be in, plus the one where it works.\n *\n * They are kept distinct on purpose, because they call for four different\n * sentences and only one of them is the user's problem:\n *\n * - `loading` — a read is in flight.\n * - `error` — the read failed. The chain is unreachable or the address is not\n * a `LaunchGuardHook`. Say so; never fall back to an example.\n * - `not-configured` — this chain's config carries no `launchGuardHook`\n * address, because no `LaunchGuardHook` is deployed on it. Nothing is wrong\n * and nothing will load.\n * - `empty` — the hook is there and answered, and no launch is registered for\n * the pool (or for any configured pool).\n * - `ready` — a launch record was read.\n */\nexport type LaunchDataState = \"loading\" | \"error\" | \"not-configured\" | \"empty\" | \"ready\";\n\n/**\n * `true` when the failure was \"there is no launchpad on this chain\" rather than\n * \"the read broke\".\n *\n * The adapters signal it by throwing `ChainConfigError` naming\n * `launchGuardHook`, which is the same mechanism every other missing-contract\n * path in this package uses.\n */\nexport function isLaunchpadNotConfigured(error: Error | null): boolean {\n return error instanceof ChainConfigError && error.contract === \"launchGuardHook\";\n}\n\n/** Maps an async resource onto {@link LaunchDataState}. */\nexport function resolveLaunchDataState(resource: {\n readonly status: AsyncStatus;\n readonly error: Error | null;\n readonly data: unknown;\n}): LaunchDataState {\n if (resource.status === \"error\") {\n return isLaunchpadNotConfigured(resource.error) || isLaunchKitNotConfigured(resource.error)\n ? \"not-configured\"\n : \"error\";\n }\n if (resource.status === \"loading\" || resource.status === \"idle\") return \"loading\";\n if (resource.data === null) return \"empty\";\n if (Array.isArray(resource.data) && resource.data.length === 0) return \"empty\";\n return \"ready\";\n}\n\n/**\n * Every launch the adapter surfaces.\n *\n * Polled, because the schedule is a function of the block height and a stale\n * \"opens in 12 blocks\" is worse than no number.\n */\nexport function useLaunchList(): AsyncResource<readonly LaunchInfo[]> {\n const { adapter } = useWidgetContext();\n return useAsyncResource(\n useCallback(() => adapter.listLaunches(), [adapter]),\n [adapter],\n { refetchIntervalMs: 12_000 },\n );\n}\n\n/**\n * `true` when the failure was \"no `LaunchpadKitV2` is configured\" — the\n * by-token lookup's own not-configured state.\n */\nexport function isLaunchKitNotConfigured(error: Error | null): boolean {\n return error instanceof ChainConfigError && error.contract === \"launchpadKitV2\";\n}\n\n/**\n * Every pool a `LaunchpadKitV2` launch opened for `token`, as launches, in\n * leg order. Polled like the list. `[]` for a token the kit never launched.\n */\nexport function useLaunchesForToken(token: Address | null): AsyncResource<readonly LaunchInfo[]> {\n const { adapter } = useWidgetContext();\n const loader = useCallback(async (): Promise<readonly LaunchInfo[]> => {\n if (token === null) return [];\n return adapter.getLaunchesForToken(token);\n }, [adapter, token]);\n return useAsyncResource(loader, [adapter, token], { enabled: token !== null, refetchIntervalMs: 12_000 });\n}\n\n/** One launch, by pool id. */\nexport function useLaunch(poolId: PoolId | null): AsyncResource<LaunchInfo | null> {\n const { adapter } = useWidgetContext();\n const loader = useCallback(async (): Promise<LaunchInfo | null> => {\n if (poolId === null) return null;\n return adapter.getLaunch(poolId);\n }, [adapter, poolId]);\n return useAsyncResource(loader, [adapter, poolId], {\n enabled: poolId !== null,\n refetchIntervalMs: 12_000,\n });\n}\n\n/** Everything a launch UI needs, derived from one read. Pure. */\nexport interface LaunchView {\n readonly launch: LaunchInfo;\n /** The schedule as of the point (on the hook's clock) the launch was read at. */\n readonly schedule: LaunchSchedule;\n /**\n * Where the fee the hook is charging sits between `initialFeePips` and\n * `finalFeePips`, in bps: `0` at the opening tax, `10_000` once settled.\n * `null` when the two ends are equal, where there is no span to be inside of.\n */\n readonly feeSpanProgressBps: number | null;\n /**\n * `currentFeePips` (read from the hook) minus the locally projected fee for\n * the same block.\n *\n * Expected to be exactly `0`: {@link ../callpath/launch.js | launchFeeAt}\n * reproduces `LaunchGuardHook.feeAt` including its rounding. Anything else\n * means the two disagree, and a UI should show the chain's number and say the\n * projection is off rather than quietly preferring one.\n */\n readonly feeProjectionDriftPips: number | null;\n}\n\n/** Derives the presentational view of a launch. Pure. */\nexport function buildLaunchView(launch: LaunchInfo): LaunchView {\n const schedule = launchScheduleAt(launch.guard, launch.readAt);\n const { initialFeePips, finalFeePips } = launch.guard;\n const span = initialFeePips - finalFeePips;\n const feeSpanProgressBps =\n span <= 0\n ? null\n : Math.max(\n 0,\n Math.min(10_000, Math.round(((initialFeePips - launch.currentFeePips) * 10_000) / span)),\n );\n return {\n launch,\n schedule,\n feeSpanProgressBps,\n feeProjectionDriftPips:\n schedule.feePips === null ? null : launch.currentFeePips - schedule.feePips,\n };\n}\n\n/** Parameters for {@link useLaunchBuy}. */\nexport interface UseLaunchBuyParams {\n readonly launch: LaunchInfo | null;\n /** Input amount in the quote currency's smallest unit. */\n readonly amountIn: bigint | null;\n readonly slippageBps?: number;\n readonly recipient?: `0x${string}`;\n readonly onSuccess?: (hash: Hex) => void;\n}\n\n/** Result of {@link useLaunchBuy}. */\nexport interface UseLaunchBuyResult {\n /** The hook's gates, evaluated against the point the launch was read at. */\n readonly gate: LaunchBuyGate;\n /** Swap quote breakdown, or `null` while there is nothing to quote. */\n readonly breakdown: QuoteBreakdown | null;\n readonly quoteStatus: AsyncStatus;\n readonly quoteError: Error | null;\n readonly quoteIsRefreshing: boolean;\n /** Output units per input unit, for display only. */\n readonly rate: number | null;\n /** The swap execution controller. Approvals, signature, confirmation. */\n readonly execution: UseSwapExecuteResult;\n /** `true` when the gates pass and the swap layer is ready to send. */\n readonly canBuy: boolean;\n}\n\n/**\n * Quotes and executes a launch buy.\n *\n * Deliberately a thin composition of `useSwapQuote` and `useSwapExecute` rather\n * than a parallel implementation: a launch buy that took a different code path\n * from a swap would be a second call path to keep correct, and the second one\n * is always the one that rots.\n *\n * Quoting is suppressed while the hook would reject the swap. Quoting a trade\n * that reverts in `beforeSwap` gets a revert, not a price, and rendering that\n * as a failed quote would blame the pool for a closed gate.\n */\nexport function useLaunchBuy(params: UseLaunchBuyParams): UseLaunchBuyResult {\n const { launch, amountIn } = params;\n\n const gate = useMemo<LaunchBuyGate>(() => {\n if (launch === null) {\n return { reason: \"not-configured\", message: \"No launch loaded\", revert: null };\n }\n return evaluateLaunchBuy({\n guard: launch.guard,\n now: launch.readAt,\n amountIn,\n });\n }, [launch, amountIn]);\n\n const quote = useSwapQuote({\n tokenIn: launch?.quoteToken ?? null,\n tokenOut: launch?.launchToken ?? null,\n amountIn,\n ...(params.slippageBps === undefined ? {} : { slippageBps: params.slippageBps }),\n /* THIS pool. A v2 token can have a CL and a Bin leg against the same quote;\n the schedule shown and the pool bought through must be the same one. */\n ...(launch === null ? {} : { poolId: launch.poolId }),\n enabled: launch !== null && gate.reason === null,\n });\n\n const execution = useSwapExecute({\n tokenIn: launch?.quoteToken ?? null,\n tokenOut: launch?.launchToken ?? null,\n amountIn,\n quote: quote.quote,\n breakdown: quote.breakdown,\n ...(params.recipient === undefined ? {} : { recipient: params.recipient }),\n ...(params.onSuccess === undefined ? {} : { onSuccess: params.onSuccess }),\n });\n\n return {\n gate,\n breakdown: quote.breakdown,\n quoteStatus: quote.status,\n quoteError: quote.error,\n quoteIsRefreshing: quote.isRefreshing,\n rate: quote.rate,\n execution,\n canBuy: gate.reason === null && execution.canExecute && quote.status === \"success\",\n };\n}\n","// SPDX-License-Identifier: MIT\n/** Token, balance, pool and account resources. All headless. */\n\nimport { useCallback } from \"react\";\nimport type { Address } from \"viem\";\nimport type { PoolInfo, PoolState, TokenInfo } from \"../adapters/protocol.js\";\nimport { useWidgetContext } from \"../context/WidgetProvider.js\";\nimport { useAsyncResource, type AsyncResource } from \"./useAsyncResource.js\";\n\n/** The tokens this deployment offers. */\nexport function useTokenList(): AsyncResource<readonly TokenInfo[]> {\n const { adapter } = useWidgetContext();\n return useAsyncResource(useCallback(() => adapter.listTokens(), [adapter]), [adapter]);\n}\n\n/** The connected account, or `null`. */\nexport function useAccount(): AsyncResource<Address | null> {\n const { adapter } = useWidgetContext();\n return useAsyncResource(useCallback(() => adapter.getAccount(), [adapter]), [adapter]);\n}\n\n/** Balance of `token` for `owner`. Idle until both are known. */\nexport function useTokenBalance(\n token: TokenInfo | null,\n owner: Address | null,\n): AsyncResource<bigint> {\n const { adapter } = useWidgetContext();\n const loader = useCallback(async (): Promise<bigint> => {\n if (token === null || owner === null) return 0n;\n return adapter.getBalance(token, owner);\n }, [adapter, token, owner]);\n return useAsyncResource(loader, [adapter, token?.address ?? null, owner], {\n enabled: token !== null && owner !== null,\n refetchIntervalMs: 30_000,\n });\n}\n\n/** Every pool the adapter knows about. */\nexport function usePools(): AsyncResource<readonly PoolInfo[]> {\n const { adapter } = useWidgetContext();\n return useAsyncResource(useCallback(() => adapter.listPools(), [adapter]), [adapter]);\n}\n\n/** Live state for one pool. */\nexport function usePoolState(pool: PoolInfo | null): AsyncResource<PoolState | null> {\n const { adapter } = useWidgetContext();\n const loader = useCallback(async (): Promise<PoolState | null> => {\n if (pool === null) return null;\n return adapter.getPoolState(pool);\n }, [adapter, pool]);\n return useAsyncResource(loader, [adapter, pool?.id ?? null], { enabled: pool !== null });\n}\n","// SPDX-License-Identifier: MIT\r\n/**\r\n * Concentrated-liquidity arithmetic, transcribed from the pool's own formulas.\r\n *\r\n * The live adapter uses this to turn desired amounts into a liquidity figure\r\n * (`quoteAddLiquidity`), a position's liquidity back into the amounts a\r\n * withdrawal returns (`quoteRemoveLiquidity`, `listPositions`) and its\r\n * uncollected fees. Nothing here estimates: a wrong constant would render a\r\n * number that LOOKS real and is not, so the constants are copied verbatim from\r\n * `TickMath.sol` and {@link assertTickMathSelfConsistent} checks the\r\n * transcription against values the chain publishes.\r\n *\r\n * Rounding directions match the contracts: an add rounds **up** (the pool takes\r\n * one wei more), a remove rounds **down** (it returns one wei less).\r\n *\r\n * - `TickMath.getSqrtRatioAtTick`\r\n * - `SqrtPriceMath.getAmount{0,1}Delta`\r\n * - `LiquidityAmounts.getLiquidityForAmounts`\r\n * - `Tick.getFeeGrowthInside` + `CLPosition.update` (fees owed)\r\n */\r\n\r\n/** 2^96. */\r\nexport const Q96 = 1n << 96n;\r\nconst Q128 = 1n << 128n;\r\nconst MAX_UINT256 = (1n << 256n) - 1n;\r\nconst U256_MOD = 1n << 256n;\r\n\r\n/** Lowest tick a pool can quote. */\r\nexport const MIN_TICK = -887272;\r\n/** Highest tick a pool can quote. */\r\nexport const MAX_TICK = 887272;\r\n\r\nconst RATIOS: readonly [bigint, bigint][] = [\r\n [0x2n, 0xfff97272373d413259a46990580e213an],\r\n [0x4n, 0xfff2e50f5f656932ef12357cf3c7fdccn],\r\n [0x8n, 0xffe5caca7e10e4e61c3624eaa0941cd0n],\r\n [0x10n, 0xffcb9843d60f6159c9db58835c926644n],\r\n [0x20n, 0xff973b41fa98c081472e6896dfb254c0n],\r\n [0x40n, 0xff2ea16466c96a3843ec78b326b52861n],\r\n [0x80n, 0xfe5dee046a99a2a811c461f1969c3053n],\r\n [0x100n, 0xfcbe86c7900a88aedcffc83b479aa3a4n],\r\n [0x200n, 0xf987a7253ac413176f2b074cf7815e54n],\r\n [0x400n, 0xf3392b0822b70005940c7a398e4b70f3n],\r\n [0x800n, 0xe7159475a2c29b7443b29c7fa6e889d9n],\r\n [0x1000n, 0xd097f3bdfd2022b8845ad8f792aa5825n],\r\n [0x2000n, 0xa9f746462d870fdf8a65dc1f90e061e5n],\r\n [0x4000n, 0x70d869a156d2a1b890bb3df62baf32f7n],\r\n [0x8000n, 0x31be135f97d08fd981231505542fcfa6n],\r\n [0x10000n, 0x9aa508b5b7a84e1c677de54f3e99bc9n],\r\n [0x20000n, 0x5d6af8dedb81196699c329225ee604n],\r\n [0x40000n, 0x2216e584f5fa1ea926041bedfe98n],\r\n [0x80000n, 0x48a170391f7dc42444e8fa2n],\r\n];\r\n\r\n/** `TickMath.getSqrtRatioAtTick`. */\r\nexport function getSqrtRatioAtTick(tick: number): bigint {\r\n if (!Number.isInteger(tick) || tick < MIN_TICK || tick > MAX_TICK) {\r\n throw new RangeError(`tick out of range: ${tick}`);\r\n }\r\n const absTick = BigInt(Math.abs(tick));\r\n let ratio = (absTick & 0x1n) !== 0n ? 0xfffcb933bd6fad37aa2d162d1a594001n : Q128;\r\n for (const [bit, factor] of RATIOS) {\r\n if ((absTick & bit) !== 0n) ratio = (ratio * factor) >> 128n;\r\n }\r\n if (tick > 0) ratio = MAX_UINT256 / ratio;\r\n // Downcast from Q128.128 to Q96.64, rounding up.\r\n return (ratio >> 32n) + (ratio % (1n << 32n) === 0n ? 0n : 1n);\r\n}\r\n\r\nfunction mulDivRoundingUp(a: bigint, b: bigint, denominator: bigint): bigint {\r\n const product = a * b;\r\n return product % denominator === 0n ? product / denominator : product / denominator + 1n;\r\n}\r\n\r\nfunction divRoundingUp(a: bigint, b: bigint): bigint {\r\n return a % b === 0n ? a / b : a / b + 1n;\r\n}\r\n\r\nfunction sorted(a: bigint, b: bigint): [bigint, bigint] {\r\n return a <= b ? [a, b] : [b, a];\r\n}\r\n\r\n/** `SqrtPriceMath.getAmount0Delta`. */\r\nexport function getAmount0Delta(\r\n sqrtRatioAX96: bigint,\r\n sqrtRatioBX96: bigint,\r\n liquidity: bigint,\r\n roundUp: boolean,\r\n): bigint {\r\n const [lower, upper] = sorted(sqrtRatioAX96, sqrtRatioBX96);\r\n const numerator1 = liquidity << 96n;\r\n const numerator2 = upper - lower;\r\n return roundUp\r\n ? divRoundingUp(mulDivRoundingUp(numerator1, numerator2, upper), lower)\r\n : (numerator1 * numerator2) / upper / lower;\r\n}\r\n\r\n/** `SqrtPriceMath.getAmount1Delta`. */\r\nexport function getAmount1Delta(\r\n sqrtRatioAX96: bigint,\r\n sqrtRatioBX96: bigint,\r\n liquidity: bigint,\r\n roundUp: boolean,\r\n): bigint {\r\n const [lower, upper] = sorted(sqrtRatioAX96, sqrtRatioBX96);\r\n return roundUp\r\n ? mulDivRoundingUp(liquidity, upper - lower, Q96)\r\n : (liquidity * (upper - lower)) / Q96;\r\n}\r\n\r\n/** `LiquidityAmounts.getLiquidityForAmount0`. */\r\nexport function getLiquidityForAmount0(\r\n sqrtRatioAX96: bigint,\r\n sqrtRatioBX96: bigint,\r\n amount0: bigint,\r\n): bigint {\r\n const [lower, upper] = sorted(sqrtRatioAX96, sqrtRatioBX96);\r\n const intermediate = (lower * upper) / Q96;\r\n return (amount0 * intermediate) / (upper - lower);\r\n}\r\n\r\n/** `LiquidityAmounts.getLiquidityForAmount1`. */\r\nexport function getLiquidityForAmount1(\r\n sqrtRatioAX96: bigint,\r\n sqrtRatioBX96: bigint,\r\n amount1: bigint,\r\n): bigint {\r\n const [lower, upper] = sorted(sqrtRatioAX96, sqrtRatioBX96);\r\n return (amount1 * Q96) / (upper - lower);\r\n}\r\n\r\n/** `LiquidityAmounts.getLiquidityForAmounts`. */\r\nexport function getLiquidityForAmounts(\r\n sqrtRatioX96: bigint,\r\n sqrtRatioAX96: bigint,\r\n sqrtRatioBX96: bigint,\r\n amount0: bigint,\r\n amount1: bigint,\r\n): bigint {\r\n const [lower, upper] = sorted(sqrtRatioAX96, sqrtRatioBX96);\r\n if (sqrtRatioX96 <= lower) return getLiquidityForAmount0(lower, upper, amount0);\r\n if (sqrtRatioX96 < upper) {\r\n const liquidity0 = getLiquidityForAmount0(sqrtRatioX96, upper, amount0);\r\n const liquidity1 = getLiquidityForAmount1(lower, sqrtRatioX96, amount1);\r\n return liquidity0 < liquidity1 ? liquidity0 : liquidity1;\r\n }\r\n return getLiquidityForAmount1(lower, upper, amount1);\r\n}\r\n\r\n/**\r\n * Amounts the pool will move for a liquidity change spanning `sqrtRatioX96`.\r\n *\r\n * `adding` selects the rounding direction: the contracts round **towards the\r\n * pool** either way, so an add costs one wei more and a remove returns one wei\r\n * less than the unrounded figure.\r\n */\r\nexport function amountsForLiquidity(\r\n sqrtRatioX96: bigint,\r\n tickLower: number,\r\n tickUpper: number,\r\n liquidity: bigint,\r\n adding: boolean,\r\n): { amount0: bigint; amount1: bigint } {\r\n const lower = getSqrtRatioAtTick(tickLower);\r\n const upper = getSqrtRatioAtTick(tickUpper);\r\n if (sqrtRatioX96 <= lower) {\r\n return { amount0: getAmount0Delta(lower, upper, liquidity, adding), amount1: 0n };\r\n }\r\n if (sqrtRatioX96 < upper) {\r\n return {\r\n amount0: getAmount0Delta(sqrtRatioX96, upper, liquidity, adding),\r\n amount1: getAmount1Delta(lower, sqrtRatioX96, liquidity, adding),\r\n };\r\n }\r\n return { amount0: 0n, amount1: getAmount1Delta(lower, upper, liquidity, adding) };\r\n}\r\n\r\n/** Which tokens a CL range takes at the pool's current price. */\r\nexport type ClRangeSide = \"both\" | \"token0-only\" | \"token1-only\";\r\n\r\n/**\r\n * Which tokens a deposit into `[tickLower, tickUpper)` takes at `sqrtRatioX96`:\r\n * a range entirely above the price holds only token0, one entirely below only\r\n * token1, and a range spanning the price holds both in a ratio the price fixes.\r\n */\r\nexport function clRangeSide(sqrtRatioX96: bigint, tickLower: number, tickUpper: number): ClRangeSide {\r\n const lower = getSqrtRatioAtTick(tickLower);\r\n const upper = getSqrtRatioAtTick(tickUpper);\r\n if (sqrtRatioX96 <= lower) return \"token0-only\";\r\n if (sqrtRatioX96 >= upper) return \"token1-only\";\r\n return \"both\";\r\n}\r\n\r\n/**\r\n * The other token's amount for a one-sided entry into an in-range CL\r\n * position: the liquidity the entered amount buys, and what that liquidity\r\n * costs of the other token (rounded up, as the position manager settles an\r\n * add). `null` when the range takes only one token - the other side is then\r\n * zero by construction, and no amount of it can be deposited.\r\n */\r\nexport function pairedAmountForRange(\r\n sqrtRatioX96: bigint,\r\n tickLower: number,\r\n tickUpper: number,\r\n entered: \"token0\" | \"token1\",\r\n amount: bigint,\r\n): bigint | null {\r\n if (clRangeSide(sqrtRatioX96, tickLower, tickUpper) !== \"both\") return null;\r\n const lower = getSqrtRatioAtTick(tickLower);\r\n const upper = getSqrtRatioAtTick(tickUpper);\r\n if (amount <= 0n) return 0n;\r\n if (entered === \"token0\") {\r\n const liquidity = getLiquidityForAmount0(sqrtRatioX96, upper, amount);\r\n return getAmount1Delta(lower, sqrtRatioX96, liquidity, true);\r\n }\r\n const liquidity = getLiquidityForAmount1(lower, sqrtRatioX96, amount);\r\n return getAmount0Delta(sqrtRatioX96, upper, liquidity, true);\r\n}\r\n\r\n/** Wrap to uint256, reproducing Solidity `unchecked` subtraction. */\r\nconst u256 = (v: bigint): bigint => ((v % U256_MOD) + U256_MOD) % U256_MOD;\r\n\r\n/** Fee growth recorded on one initialised tick (`Tick.Info`). */\r\nexport interface TickFeeGrowth {\r\n readonly feeGrowthOutside0X128: bigint;\r\n readonly feeGrowthOutside1X128: bigint;\r\n}\r\n\r\n/**\r\n * Fees a position has earned since it was last touched, exactly as\r\n * `CLPosition.update` credits them on the next `modifyLiquidity`.\r\n *\r\n * All subtractions wrap at 2^256 on purpose: the pool's own arithmetic is\r\n * `unchecked`, and fee-growth values are only meaningful modulo 2^256.\r\n */\r\nexport function uncollectedFees(args: {\r\n readonly liquidity: bigint;\r\n readonly tickLower: number;\r\n readonly tickUpper: number;\r\n readonly currentTick: number;\r\n readonly feeGrowthGlobal0X128: bigint;\r\n readonly feeGrowthGlobal1X128: bigint;\r\n readonly lower: TickFeeGrowth;\r\n readonly upper: TickFeeGrowth;\r\n readonly feeGrowthInside0LastX128: bigint;\r\n readonly feeGrowthInside1LastX128: bigint;\r\n}): { fees0: bigint; fees1: bigint } {\r\n const { currentTick, tickLower, tickUpper, lower, upper } = args;\r\n const g0 = args.feeGrowthGlobal0X128;\r\n const g1 = args.feeGrowthGlobal1X128;\r\n const below0 = currentTick >= tickLower ? lower.feeGrowthOutside0X128 : u256(g0 - lower.feeGrowthOutside0X128);\r\n const below1 = currentTick >= tickLower ? lower.feeGrowthOutside1X128 : u256(g1 - lower.feeGrowthOutside1X128);\r\n const above0 = currentTick < tickUpper ? upper.feeGrowthOutside0X128 : u256(g0 - upper.feeGrowthOutside0X128);\r\n const above1 = currentTick < tickUpper ? upper.feeGrowthOutside1X128 : u256(g1 - upper.feeGrowthOutside1X128);\r\n const inside0 = u256(g0 - below0 - above0);\r\n const inside1 = u256(g1 - below1 - above1);\r\n return {\r\n fees0: (u256(inside0 - args.feeGrowthInside0LastX128) * args.liquidity) / Q128,\r\n fees1: (u256(inside1 - args.feeGrowthInside1LastX128) * args.liquidity) / Q128,\r\n };\r\n}\r\n\r\n/**\r\n * Checks this transcription against values the chain publishes.\r\n *\r\n * @throws when the bit-magic constants have been corrupted.\r\n */\r\nexport function assertTickMathSelfConsistent(): void {\r\n if (getSqrtRatioAtTick(0) !== Q96) {\r\n throw new Error(`getSqrtRatioAtTick(0) is ${getSqrtRatioAtTick(0)}, expected 2^96 (${Q96})`);\r\n }\r\n // getSqrtRatioAtTick(MAX_TICK), published as TickMath.MAX_SQRT_RATIO.\r\n const maxSqrtRatio = 1461446703485210103287273052203988822378723970342n;\r\n if (getSqrtRatioAtTick(MAX_TICK) !== maxSqrtRatio) {\r\n throw new Error(\r\n `getSqrtRatioAtTick(MAX_TICK) is ${getSqrtRatioAtTick(MAX_TICK)}, expected ${maxSqrtRatio}`,\r\n );\r\n }\r\n const minSqrtRatio = 4295128739n;\r\n if (getSqrtRatioAtTick(MIN_TICK) !== minSqrtRatio) {\r\n throw new Error(\r\n `getSqrtRatioAtTick(MIN_TICK) is ${getSqrtRatioAtTick(MIN_TICK)}, expected ${minSqrtRatio}`,\r\n );\r\n }\r\n}\r\n","// SPDX-License-Identifier: MIT\n/**\n * Pure guards for the liquidity flow: what a deposit will take from the wallet,\n * and whether the wallet holds it.\n *\n * WHY THIS EXISTS. Without it an add that the wallet cannot pay reaches gas\n * estimation and comes back as `TRANSFER_FROM_FAILED` (or an out-of-funds\n * error for native), after the visitor may already have signed an approval\n * for tokens they do not hold. The widget checks the balances first and says\n * \"Insufficient <SYMBOL>\" before anything is signed.\n *\n * WHAT IS COMPARED, exactly:\n * - native: the transaction's `value`, which is the side's slippage-bounded\n * MAXIMUM (the adapter sends the whole cap and the position manager refunds\n * the rest). No gas reserve is invented on top: the wallet refuses a\n * transaction it cannot pay gas for, and a made-up margin would refuse\n * deposits that fit.\n * - ERC-20: the QUOTED amount, which is what the position manager pulls at\n * the current price. The slippage cap is only an allowance ceiling; a wallet\n * holding the quoted amount but not the cap can still deposit.\n */\n\nimport { isAddressEqual, zeroAddress } from \"viem\";\nimport type { TokenInfo } from \"../adapters/protocol.js\";\n\n/** True for the chain's native asset. */\nexport function isNativeToken(token: TokenInfo): boolean {\n return token.isNative === true || isAddressEqual(token.address, zeroAddress);\n}\n\n/** One side of a deposit: the token and what the wallet must hold of it. */\nexport interface DepositRequirement {\n readonly token: TokenInfo;\n readonly required: bigint;\n}\n\n/**\n * What an add-liquidity takes from the wallet, per token, in pool order. A side\n * that deposits nothing is left out.\n */\nexport function depositRequirements(\n quote: {\n readonly pool: { readonly token0: TokenInfo; readonly token1: TokenInfo };\n readonly amount0: bigint;\n readonly amount1: bigint;\n },\n amount0Max: bigint,\n amount1Max: bigint,\n): readonly DepositRequirement[] {\n const out: DepositRequirement[] = [];\n const side = (token: TokenInfo, quoted: bigint, max: bigint): void => {\n const required = isNativeToken(token) ? max : quoted;\n if (required > 0n) out.push({ token, required });\n };\n side(quote.pool.token0, quote.amount0, amount0Max);\n side(quote.pool.token1, quote.amount1, amount1Max);\n return out;\n}\n\n/**\n * The first token the wallet holds too little of, or `null` when every balance\n * covers its requirement. `balances[i]` is the wallet's balance of\n * `requirements[i].token`; a `null` balance (not read) is never reported as a\n * shortfall - the widget does not claim what it has not read.\n */\nexport function findShortfall(\n requirements: readonly DepositRequirement[],\n balances: readonly (bigint | null)[],\n): TokenInfo | null {\n for (const [i, requirement] of requirements.entries()) {\n const balance = balances[i] ?? null;\n if (balance !== null && balance < requirement.required) return requirement.token;\n }\n return null;\n}\n\n/** Refusal raised before an approval or a deposit the wallet cannot pay. Nothing was signed. */\nexport class InsufficientBalanceError extends Error {\n readonly token: TokenInfo;\n\n constructor(token: TokenInfo) {\n super(`Insufficient ${token.symbol}: the wallet holds less than this deposit needs. Nothing was signed.`);\n this.name = \"InsufficientBalanceError\";\n this.token = token;\n }\n}\n","// SPDX-License-Identifier: MIT\n/**\n * What a pool key already says about a pool.\n *\n * `PoolInfo.tickSpacing` and `PoolInfo.binStep` are optional because a host\n * that lists pools from an indexer may not fill them in - but both live in the\n * key's `parameters` word, so nothing needs to guess. These read the key when\n * the field is absent, and every range editor and quote goes through them.\n */\n\nimport {\n encodeAbiParameters,\n keccak256,\n type Hex,\n} from \"viem\";\nimport { readBinPoolKeyParameters, readCLPoolKeyParameters, type PoolId } from \"@latchprotocol/sdk\";\nimport type { PoolInfo } from \"../adapters/protocol.js\";\n\n/** The tick spacing of a concentrated-liquidity pool, from the info or its key. */\nexport function tickSpacingOf(pool: PoolInfo): number {\n if (pool.tickSpacing !== undefined) return pool.tickSpacing;\n return readCLPoolKeyParameters(pool.key).tickSpacing;\n}\n\n/** The bin step of a liquidity-book pool, from the info or its key. */\nexport function binStepOf(pool: PoolInfo): number {\n if (pool.binStep !== undefined) return pool.binStep;\n return readBinPoolKeyParameters(pool.key).binStep;\n}\n\n/**\n * `BinTokenLibrary.toTokenId`: the fungible token id `BinPositionManager`\n * mints for one bin of one pool, `keccak256(abi.encode(poolId, binId))`.\n */\nexport function binTokenId(poolId: PoolId, binId: number): bigint {\n const encoded: Hex = encodeAbiParameters(\n [\n { name: \"poolId\", type: \"bytes32\" },\n { name: \"binId\", type: \"uint256\" },\n ],\n [poolId, BigInt(binId)],\n );\n return BigInt(keccak256(encoded));\n}\n\n/**\n * The reserves a holder's shares of one bin are worth right now, rounded\n * DOWN exactly as `BinPool.burn` computes them (`amount * shares / totalShares`).\n */\nexport function binShareAmounts(args: {\n readonly shares: bigint;\n readonly totalShares: bigint;\n readonly reserveX: bigint;\n readonly reserveY: bigint;\n}): { amount0: bigint; amount1: bigint } {\n if (args.totalShares === 0n || args.shares === 0n) return { amount0: 0n, amount1: 0n };\n return {\n amount0: (args.reserveX * args.shares) / args.totalShares,\n amount1: (args.reserveY * args.shares) / args.totalShares,\n };\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Headless liquidity provision, for both pool types.\n *\n * The pool-type difference lives entirely in the {@link LiquidityRange} union\n * and in {@link ../callpath/liquidity.js}. Everything a UI touches here - the\n * range editor state, the quote, the execution state machine - is identical for\n * concentrated liquidity and for the liquidity book.\n */\n\nimport { useCallback, useMemo, useState } from \"react\";\nimport type { Address, Hex } from \"viem\";\nimport type {\n AddLiquidityQuote,\n ApprovalRequirement,\n LiquidityRange,\n PoolInfo,\n PositionInfo,\n RemoveLiquidityQuote,\n TokenInfo,\n} from \"../adapters/protocol.js\";\nimport { WalletNotConnectedError } from \"../adapters/protocol.js\";\nimport { chainDeadline } from \"../config/chain.js\";\nimport { useWidgetContext } from \"../context/WidgetProvider.js\";\nimport { describeError } from \"../core/errors.js\";\nimport { InsufficientBalanceError, depositRequirements, findShortfall } from \"../core/liquidityGuards.js\";\nimport { ceilTickToSpacing, floorTickToSpacing, maximumSpent, minimumReceived } from \"../core/math.js\";\nimport { tickSpacingOf } from \"../core/pool.js\";\nimport { useAsyncResource, type AsyncResource, type AsyncStatus } from \"./useAsyncResource.js\";\n\n/** Lifecycle of a liquidity transaction. */\nexport type LiquidityExecutionStep =\n | \"idle\"\n | \"needs-approval\"\n | \"approving\"\n | \"building\"\n | \"awaiting-signature\"\n | \"pending\"\n | \"success\"\n | \"error\";\n\n/** Builds a default range around the pool's current position. */\nexport function defaultRangeFor(\n pool: PoolInfo,\n currentTick: number | null,\n activeId: number | null,\n widthFactor = 10,\n): LiquidityRange | null {\n if (pool.poolType === \"CL\") {\n const spacing = tickSpacingOf(pool);\n if (currentTick === null) return null;\n const halfWidth = spacing * widthFactor;\n return {\n type: \"CL\",\n tickLower: floorTickToSpacing(currentTick - halfWidth, spacing),\n tickUpper: ceilTickToSpacing(currentTick + halfWidth, spacing),\n };\n }\n if (activeId === null) return null;\n return {\n type: \"BIN\",\n activeIdDesired: activeId,\n binIdLower: activeId - widthFactor,\n binIdUpper: activeId + widthFactor,\n idSlippage: 5,\n };\n}\n\n/** Widens or narrows a range symmetrically, respecting the pool's granularity. */\nexport function adjustRange(\n range: LiquidityRange,\n pool: PoolInfo,\n deltaSteps: number,\n): LiquidityRange {\n if (range.type === \"CL\") {\n const spacing = tickSpacingOf(pool);\n const lower = range.tickLower - deltaSteps * spacing;\n const upper = range.tickUpper + deltaSteps * spacing;\n if (lower >= upper) return range;\n return { type: \"CL\", tickLower: lower, tickUpper: upper };\n }\n const lower = range.binIdLower - deltaSteps;\n const upper = range.binIdUpper + deltaSteps;\n if (lower > upper) return range;\n return { ...range, binIdLower: lower, binIdUpper: upper };\n}\n\n/** Human-readable description of a range, for labels and summaries. */\nexport function describeRange(range: LiquidityRange): string {\n if (range.type === \"CL\") {\n return `Ticks ${range.tickLower} to ${range.tickUpper}`;\n }\n const count = range.binIdUpper - range.binIdLower + 1;\n return `Bins ${range.binIdLower} to ${range.binIdUpper} (${count} bins, active ${range.activeIdDesired})`;\n}\n\n/** Parameters for {@link useAddLiquidityQuote}. */\nexport interface UseAddLiquidityQuoteParams {\n readonly pool: PoolInfo | null;\n readonly range: LiquidityRange | null;\n readonly amount0Desired: bigint | null;\n readonly amount1Desired: bigint | null;\n readonly enabled?: boolean;\n}\n\n/** Quotes an add-liquidity operation. */\nexport function useAddLiquidityQuote(\n params: UseAddLiquidityQuoteParams,\n): AsyncResource<AddLiquidityQuote | null> & { readonly isMock: boolean } {\n const { adapter } = useWidgetContext();\n const { pool, range, amount0Desired, amount1Desired } = params;\n\n const enabled =\n (params.enabled ?? true) &&\n pool !== null &&\n range !== null &&\n (amount0Desired ?? 0n) + (amount1Desired ?? 0n) > 0n;\n\n const loader = useCallback(async (): Promise<AddLiquidityQuote | null> => {\n if (pool === null || range === null) return null;\n return adapter.quoteAddLiquidity({\n pool,\n range,\n amount0Desired: amount0Desired ?? 0n,\n amount1Desired: amount1Desired ?? 0n,\n });\n }, [adapter, pool, range, amount0Desired, amount1Desired]);\n\n const resource = useAsyncResource<AddLiquidityQuote | null>(\n loader,\n [\n adapter,\n pool?.id ?? null,\n range === null ? null : JSON.stringify(range),\n amount0Desired?.toString() ?? null,\n amount1Desired?.toString() ?? null,\n ],\n { enabled },\n );\n\n return { ...resource, isMock: adapter.isMock };\n}\n\n/** Result of {@link useAddLiquidityExecute}. */\nexport interface UseLiquidityExecuteResult {\n readonly step: LiquidityExecutionStep;\n readonly error: Error | null;\n readonly txHash: Hex | null;\n readonly approvals: readonly ApprovalRequirement[];\n readonly needsApproval: boolean;\n /**\n * The token the wallet holds too little of for this deposit, or `null` when\n * every balance covers it (or has not been read yet). While set, neither an\n * approval nor the deposit is offered: `approve` and `execute` re-read the\n * balances and refuse with `InsufficientBalanceError` before anything is signed.\n */\n readonly insufficient: TokenInfo | null;\n readonly statusMessage: string;\n approve(): Promise<void>;\n execute(): Promise<void>;\n reset(): void;\n}\n\nfunction toError(cause: unknown): Error {\n return cause instanceof Error ? cause : new Error(String(cause));\n}\n\n/** Parameters for {@link useAddLiquidityExecute}. */\nexport interface UseAddLiquidityExecuteParams {\n readonly quote: AddLiquidityQuote | null;\n /** Slippage applied to the deposited amounts, in bps. */\n readonly slippageBps?: number;\n readonly recipient?: Address;\n readonly hookData?: Hex;\n readonly onSuccess?: (hash: Hex) => void;\n}\n\n/** Drives approve-then-add-liquidity for either pool type. */\nexport function useAddLiquidityExecute(\n params: UseAddLiquidityExecuteParams,\n): UseLiquidityExecuteResult {\n const { adapter, chain, integrator, defaultSlippageBps } = useWidgetContext();\n const { quote } = params;\n const slippageBps = params.slippageBps ?? defaultSlippageBps;\n\n const [step, setStep] = useState<LiquidityExecutionStep>(\"idle\");\n const [error, setError] = useState<Error | null>(null);\n const [txHash, setTxHash] = useState<Hex | null>(null);\n const [approvalToken, setApprovalToken] = useState(0);\n\n const accountResource = useAsyncResource(\n useCallback(() => adapter.getAccount(), [adapter]),\n [adapter],\n );\n const account = accountResource.data;\n\n const amounts = useMemo(() => {\n if (quote === null) return null;\n return {\n amount0Max: maximumSpent(quote.amount0, slippageBps),\n amount1Max: maximumSpent(quote.amount1, slippageBps),\n };\n }, [quote, slippageBps]);\n\n /* What the deposit takes from the wallet, and whether the wallet holds it.\n Read BEFORE an approval or a deposit is offered, so a wallet that cannot\n pay sees \"Insufficient <SYMBOL>\" instead of an approval it does not need\n and a gas estimate failing with TRANSFER_FROM_FAILED. See core/liquidityGuards. */\n const requirements = useMemo(\n () => (quote === null || amounts === null ? [] : depositRequirements(quote, amounts.amount0Max, amounts.amount1Max)),\n [quote, amounts],\n );\n const requirementsKey = requirements.map((r) => `${r.token.address}:${r.required.toString()}`).join(\",\");\n const readShortfall = useCallback(async (): Promise<TokenInfo | null> => {\n if (account === null || requirements.length === 0) return null;\n const balances = await Promise.all(requirements.map((r) => adapter.getBalance(r.token, account)));\n return findShortfall(requirements, balances);\n }, [adapter, account, requirements]);\n const shortfallResource = useAsyncResource<TokenInfo | null>(\n readShortfall,\n [adapter, account, requirementsKey, approvalToken],\n { enabled: account !== null && requirements.length > 0, refetchIntervalMs: 30_000 },\n );\n const insufficient = requirements.length === 0 || account === null ? null : (shortfallResource.data ?? null);\n const refetchShortfall = shortfallResource.refetch;\n\n /* The deposit is pulled by the POSITION MANAGER, not the router, so that is\n the Permit2 spender the allowance has to name. */\n const approvalLoader = useCallback(async (): Promise<readonly ApprovalRequirement[]> => {\n if (quote === null || account === null || amounts === null) return [];\n const spender = quote.pool.poolType === \"CL\" ? chain.contracts.clPositionManager : chain.contracts.binPositionManager;\n const [first, second] = await Promise.all([\n adapter.getApprovalRequirements(quote.pool.token0, account, amounts.amount0Max, spender),\n adapter.getApprovalRequirements(quote.pool.token1, account, amounts.amount1Max, spender),\n ]);\n return [...first, ...second];\n }, [adapter, chain, quote, account, amounts]);\n\n const approvalResource = useAsyncResource<readonly ApprovalRequirement[]>(\n approvalLoader,\n [adapter, quote?.pool.id ?? null, account, amounts?.amount0Max.toString() ?? null, approvalToken],\n { enabled: quote !== null && account !== null },\n );\n const approvals = approvalResource.data ?? [];\n\n const approve = useCallback(async (): Promise<void> => {\n const next = approvals[0];\n if (next === undefined) return;\n setError(null);\n setStep(\"approving\");\n try {\n /* Re-read at the moment of signing: never approve for a deposit the wallet cannot pay. */\n const short = await readShortfall();\n if (short !== null) {\n refetchShortfall();\n throw new InsufficientBalanceError(short);\n }\n const transaction = await adapter.buildApproval(next);\n const hash = await adapter.sendTransaction(transaction);\n await adapter.waitForTransaction(hash);\n setApprovalToken((token) => token + 1);\n setStep(\"idle\");\n } catch (cause: unknown) {\n setError(toError(cause));\n setStep(\"error\");\n }\n }, [adapter, approvals, readShortfall, refetchShortfall]);\n\n const execute = useCallback(async (): Promise<void> => {\n if (quote === null || amounts === null) return;\n if (account === null) {\n setError(new WalletNotConnectedError(\"add liquidity\"));\n setStep(\"error\");\n return;\n }\n setError(null);\n setStep(\"building\");\n try {\n const short = await readShortfall();\n if (short !== null) {\n refetchShortfall();\n throw new InsufficientBalanceError(short);\n }\n const transaction = await adapter.buildAddLiquidity({\n quote,\n amount0Max: amounts.amount0Max,\n amount1Max: amounts.amount1Max,\n recipient: params.recipient ?? account,\n deadline: await chainDeadline(chain, adapter),\n integrator,\n ...(params.hookData ? { hookData: params.hookData } : {}),\n });\n setStep(\"awaiting-signature\");\n const hash = await adapter.sendTransaction(transaction);\n setTxHash(hash);\n setStep(\"pending\");\n const outcome = await adapter.waitForTransaction(hash);\n if (outcome.status === \"reverted\") throw new Error(`The transaction was mined but reverted (${hash}).`);\n setStep(\"success\");\n /* The deposit spent balance and allowance: re-read both. */\n setApprovalToken((token) => token + 1);\n params.onSuccess?.(hash);\n } catch (cause: unknown) {\n setError(toError(cause));\n setStep(\"error\");\n }\n }, [adapter, account, amounts, chain, integrator, params, quote, readShortfall, refetchShortfall]);\n\n const reset = useCallback(() => {\n setStep(\"idle\");\n setError(null);\n setTxHash(null);\n }, []);\n\n const effectiveStep: LiquidityExecutionStep =\n step === \"idle\" && approvals.length > 0 && insufficient === null ? \"needs-approval\" : step;\n\n return {\n step: effectiveStep,\n error,\n txHash,\n approvals,\n needsApproval: approvals.length > 0,\n insufficient,\n statusMessage: describeLiquidityStep(effectiveStep, approvals[0], error, adapter.isMock),\n approve,\n execute,\n reset,\n };\n}\n\n/**\n * Positions held by `owner`, optionally filtered to one pool. `refreshKey`\n * re-reads the list whenever it changes: pass a counter the host advances on\n * every confirmed add or removal (the LiquidityWidget does), so an emptied\n * position disappears and amounts update without a reload.\n */\nexport function usePositions(\n owner: Address | null,\n pool?: PoolInfo | null,\n refreshKey: unknown = 0,\n): AsyncResource<readonly PositionInfo[]> {\n const { adapter } = useWidgetContext();\n const loader = useCallback(async (): Promise<readonly PositionInfo[]> => {\n if (owner === null) return [];\n return pool === null || pool === undefined\n ? adapter.listPositions(owner)\n : adapter.listPositions(owner, pool);\n }, [adapter, owner, pool]);\n return useAsyncResource(loader, [adapter, owner, pool?.id ?? null, refreshKey], {\n enabled: owner !== null,\n });\n}\n\n/** Parameters for {@link useRemoveLiquidity}. */\nexport interface UseRemoveLiquidityParams {\n readonly position: PositionInfo | null;\n /** Fraction to withdraw, in bps. */\n readonly percentBps: number;\n readonly slippageBps?: number;\n readonly recipient?: Address;\n readonly onSuccess?: (hash: Hex) => void;\n}\n\n/** Result of {@link useRemoveLiquidity}. */\nexport interface UseRemoveLiquidityResult {\n readonly quote: RemoveLiquidityQuote | null;\n readonly quoteStatus: AsyncStatus;\n readonly step: LiquidityExecutionStep;\n readonly error: Error | null;\n readonly txHash: Hex | null;\n readonly statusMessage: string;\n execute(): Promise<void>;\n reset(): void;\n}\n\n/** Quotes and executes a withdrawal from either pool type. */\nexport function useRemoveLiquidity(\n params: UseRemoveLiquidityParams,\n): UseRemoveLiquidityResult {\n const { adapter, chain, integrator, defaultSlippageBps } = useWidgetContext();\n const { position, percentBps } = params;\n const slippageBps = params.slippageBps ?? defaultSlippageBps;\n\n const [step, setStep] = useState<LiquidityExecutionStep>(\"idle\");\n const [error, setError] = useState<Error | null>(null);\n const [txHash, setTxHash] = useState<Hex | null>(null);\n\n const loader = useCallback(async (): Promise<RemoveLiquidityQuote | null> => {\n if (position === null) return null;\n return adapter.quoteRemoveLiquidity(position, percentBps);\n }, [adapter, position, percentBps]);\n\n const resource = useAsyncResource<RemoveLiquidityQuote | null>(\n loader,\n /* Keyed on the position RECORD, not its id: after a partial removal the\n re-read list hands over a new record with less liquidity, and the quote\n must follow it rather than keep pricing the old one. */\n [adapter, position, percentBps],\n { enabled: position !== null && percentBps > 0 },\n );\n\n const execute = useCallback(async (): Promise<void> => {\n const quote = resource.data;\n if (position === null || quote === null) return;\n const account = await adapter.getAccount();\n if (account === null) {\n setError(new WalletNotConnectedError(\"remove liquidity\"));\n setStep(\"error\");\n return;\n }\n setError(null);\n setStep(\"building\");\n try {\n const transaction = await adapter.buildRemoveLiquidity({\n position,\n percentBps,\n amount0Min: minimumReceived(quote.amount0, slippageBps),\n amount1Min: minimumReceived(quote.amount1, slippageBps),\n recipient: params.recipient ?? account,\n deadline: await chainDeadline(chain, adapter),\n integrator,\n });\n setStep(\"awaiting-signature\");\n const hash = await adapter.sendTransaction(transaction);\n setTxHash(hash);\n setStep(\"pending\");\n const outcome = await adapter.waitForTransaction(hash);\n if (outcome.status === \"reverted\") throw new Error(`The transaction was mined but reverted (${hash}).`);\n setStep(\"success\");\n params.onSuccess?.(hash);\n } catch (cause: unknown) {\n setError(toError(cause));\n setStep(\"error\");\n }\n }, [adapter, chain, integrator, params, percentBps, position, resource.data, slippageBps]);\n\n const reset = useCallback(() => {\n setStep(\"idle\");\n setError(null);\n setTxHash(null);\n }, []);\n\n return {\n quote: resource.data,\n quoteStatus: resource.status,\n step,\n error,\n txHash,\n statusMessage: describeLiquidityStep(step, undefined, error, adapter.isMock),\n execute,\n reset,\n };\n}\n\nfunction describeLiquidityStep(\n step: LiquidityExecutionStep,\n pending: ApprovalRequirement | undefined,\n error: Error | null,\n isMock: boolean,\n): string {\n const mockPrefix = isMock ? \"Simulated (mock adapter): \" : \"\";\n switch (step) {\n case \"idle\":\n return \"\";\n case \"needs-approval\":\n return pending === undefined\n ? \"Approval required\"\n : `Approve ${pending.token.symbol} before continuing`;\n case \"approving\":\n return `${mockPrefix}Waiting for the approval to confirm`;\n case \"building\":\n return `${mockPrefix}Preparing the transaction`;\n case \"awaiting-signature\":\n return `${mockPrefix}Confirm the transaction in your wallet`;\n case \"pending\":\n return `${mockPrefix}Submitted, waiting for confirmation`;\n case \"success\":\n return `${mockPrefix}Confirmed`;\n case \"error\":\n return error === null ? \"Something went wrong\" : describeError(error, \"liquidity\");\n default:\n return \"\";\n }\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Keeping the liquidity widget's own lists true after a confirmed add or\n * removal, without a reload.\n *\n * The widget counts confirmed changes (`bumpOnConfirmed`); the positions list,\n * the pool state and the wallet balances take that count as a dependency, so a\n * confirmation re-reads them. The picker then re-selects from the FRESH list\n * (`reconcileSelection`), so a partial removal shows the new amounts and a\n * position emptied to zero disappears (`withdrawablePositions`).\n */\n\nimport type { PositionInfo } from \"../adapters/protocol.js\";\n\n/**\n * Wraps the host's `onLiquidityChanged` so a confirmation also advances the\n * widget's refresh counter. The counter moves first: the host's callback can\n * throw without leaving the widget's lists stale.\n */\nexport function bumpOnConfirmed<H>(\n bump: () => void,\n host: ((hash: H) => void) | undefined,\n): (hash: H) => void {\n return (hash: H) => {\n bump();\n host?.(hash);\n };\n}\n\n/**\n * The positions there is something to withdraw from. A CL position removed to\n * zero keeps its NFT (the widget decreases liquidity and takes the tokens; it\n * does not burn), so the adapter still lists it with zero liquidity and zero\n * owed fees - offering it in the Remove picker would quote a withdrawal of\n * nothing.\n */\nexport function withdrawablePositions(list: readonly PositionInfo[]): readonly PositionInfo[] {\n return list.filter((p) => p.liquidity > 0n || p.feesOwed0 > 0n || p.feesOwed1 > 0n);\n}\n\n/**\n * The selection after the list was re-read: the SAME position as its fresh\n * record (new amounts, new liquidity), else the first position, else `null`.\n * Returning the fresh object matters - a stale one keeps quoting the\n * withdrawal against the liquidity it had before the last removal.\n */\nexport function reconcileSelection<T extends { readonly id: string }>(current: T | null, list: readonly T[]): T | null {\n if (current !== null) {\n const fresh = list.find((p) => p.id === current.id);\n if (fresh !== undefined) return fresh;\n }\n return list[0] ?? null;\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Token lists as the picker consumes them: pure functions from the SDK's\n * `TokenList` documents to the widgets' `TokenInfo`, with the provenance kept\n * on each entry. The React hook (`hooks/useTokenLists.ts`) fetches and calls\n * these; nothing here touches the network or the DOM, so it is testable on its\n * own and reusable by a headless integrator.\n */\n\nimport {\n ipfsToHttp,\n mergeTokenLists,\n stockExtensionOf,\n type MergedTokenList,\n type TokenList,\n} from \"@latchprotocol/sdk\";\nimport { isAddress, type Address } from \"viem\";\nimport type { TokenInfo } from \"../adapters/protocol.js\";\n\n/** One entry of `SwapWidget`'s `tokenLists`: a list already in hand, or a URL to fetch. */\nexport type TokenListInput = TokenList | { readonly url: string };\n\nexport function isTokenListUrl(input: TokenListInput): input is { readonly url: string } {\n return typeof (input as { url?: unknown }).url === \"string\";\n}\n\nconst NATIVE: Address = \"0x0000000000000000000000000000000000000000\";\n\n/**\n * The picker entries a merge yields, for `chainId`. Tokens whose address is not\n * a 20-byte hex address (the schema also admits a Solana form) are skipped:\n * they cannot be a Latch pool currency.\n */\nexport function tokensFromMergedList(merged: MergedTokenList): readonly TokenInfo[] {\n const out: TokenInfo[] = [];\n for (const t of merged.tokens) {\n if (!isAddress(t.address)) continue;\n const stock = stockExtensionOf(t);\n const entry: TokenInfo = {\n address: t.address,\n symbol: t.symbol,\n name: t.name,\n decimals: t.decimals,\n ...(t.logoURI === undefined ? {} : { logoUrl: t.logoURI }),\n ...(t.address.toLowerCase() === NATIVE ? { isNative: true } : {}),\n listSource: { name: t.source.name, alsoIn: t.alsoIn.map((s) => s.name) },\n ...(stock === null ? {} : { stock }),\n ...(t.tags === undefined ? {} : { tags: t.tags }),\n };\n out.push(entry);\n }\n return out;\n}\n\n/**\n * The picker's final order: the adapter's own tokens first (the tokens of the\n * pools this site routes through, read on chain), then every list's tokens in\n * list order, deduped by lowercase address. A token the adapter already knows\n * keeps the adapter's fields — its decimals were read off the contract — and\n * gains the list's provenance, logo, stock badge and tags where the adapter had\n * none.\n */\nexport function combineTokens(adapterTokens: readonly TokenInfo[], listTokens: readonly TokenInfo[]): readonly TokenInfo[] {\n const byAddress = new Map<string, TokenInfo>();\n for (const t of adapterTokens) byAddress.set(t.address.toLowerCase(), t);\n for (const t of listTokens) {\n const key = t.address.toLowerCase();\n const existing = byAddress.get(key);\n if (existing === undefined) {\n byAddress.set(key, t);\n continue;\n }\n byAddress.set(key, {\n ...existing,\n ...(existing.logoUrl === undefined && t.logoUrl !== undefined ? { logoUrl: t.logoUrl } : {}),\n /* The adapter's token stays the adapter's; the lists that also name it are recorded as corroboration. */\n ...(t.listSource !== undefined\n ? { listSource: { name: existing.listSource?.name ?? null, alsoIn: [...(existing.listSource?.alsoIn ?? []), t.listSource.name ?? \"\", ...t.listSource.alsoIn].filter((n) => n !== \"\") } }\n : {}),\n ...(existing.stock === undefined && t.stock !== undefined ? { stock: t.stock } : {}),\n ...(existing.tags === undefined && t.tags !== undefined ? { tags: t.tags } : {}),\n });\n }\n return [...byAddress.values()];\n}\n\n/** `mergeTokenLists` then `tokensFromMergedList`, for callers with every list in hand. */\nexport function tokensFromLists(lists: readonly TokenList[], chainId: number): readonly TokenInfo[] {\n return tokensFromMergedList(mergeTokenLists(lists, { chainId }));\n}\n\n/**\n * The URL an `<img>` can load for a token's logo: `https://` as given,\n * `ipfs://` through the SDK's first allow-listed gateway, anything else\n * `null` (the caller draws a monogram). `http://` is refused: a mixed-content\n * image on an https site is blocked by the browser and reads as a broken logo.\n */\nexport function resolveLogoUrl(logoUrl: string | undefined, gateways?: readonly string[]): string | null {\n if (logoUrl === undefined) return null;\n if (logoUrl.startsWith(\"https://\")) return logoUrl;\n if (logoUrl.startsWith(\"ipfs://\")) {\n const urls = ipfsToHttp(logoUrl, gateways === undefined ? {} : { gateways });\n return urls === null || urls.length === 0 ? null : (urls[0] ?? null);\n }\n return null;\n}\n\n/** Group entries by their list source, in first-seen order; adapter tokens (no source) come first under `null`. */\nexport function groupBySource(tokens: readonly TokenInfo[]): readonly { readonly source: string | null; readonly tokens: readonly TokenInfo[] }[] {\n const groups = new Map<string | null, TokenInfo[]>();\n groups.set(null, []);\n for (const t of tokens) {\n const key = t.listSource?.name ?? null;\n const list = groups.get(key);\n if (list === undefined) groups.set(key, [t]);\n else list.push(t);\n }\n return [...groups.entries()].filter(([, list]) => list.length > 0).map(([source, list]) => ({ source, tokens: list }));\n}\n","// SPDX-License-Identifier: MIT\n/**\n * Fetches, validates and merges the token lists a widget was given, for the\n * adapter's chain. Headless: returns entries and per-URL failures, renders\n * nothing. A list that fails to load is reported by URL and reason and simply\n * contributes no tokens — the picker still works on the adapter's tokens and\n * the lists that did load. Nothing is cached across mounts; caching is the\n * host app's job (the SDK is localStorage-free by design).\n */\n\nimport { fetchTokenList, mergeTokenLists, type TokenList } from \"@latchprotocol/sdk\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { TokenInfo } from \"../adapters/protocol.js\";\nimport { useWidgetContext } from \"../context/WidgetProvider.js\";\nimport { isTokenListUrl, tokensFromMergedList, type TokenListInput } from \"../core/tokenLists.js\";\n\nexport interface TokenListFailure {\n readonly url: string;\n readonly message: string;\n}\n\nexport interface TokenListsResource {\n /** Entries from every list that loaded, merged (first list wins), for the adapter's chain. */\n readonly tokens: readonly TokenInfo[];\n /** `loading` while any URL is in flight; `ready` once every input settled (some may have failed). */\n readonly status: \"idle\" | \"loading\" | \"ready\";\n readonly failures: readonly TokenListFailure[];\n /** The names of the lists that loaded, in input order. */\n readonly sources: readonly string[];\n}\n\nconst EMPTY: TokenListsResource = { tokens: [], status: \"idle\", failures: [], sources: [] };\n\n/** A stable identity for the inputs so a re-render with the same lists does not refetch. */\nfunction keyOf(inputs: readonly TokenListInput[] | undefined): string {\n if (inputs === undefined) return \"\";\n return inputs.map((i) => (isTokenListUrl(i) ? `url:${i.url}` : `list:${i.name}@${i.version.major}.${i.version.minor}.${i.version.patch}:${i.tokens.length}`)).join(\"|\");\n}\n\n/** Loads `inputs` (lists or URLs) and merges them for the adapter's chain. */\nexport function useTokenLists(inputs: readonly TokenListInput[] | undefined): TokenListsResource {\n const { chain } = useWidgetContext();\n const key = keyOf(inputs);\n const [state, setState] = useState<{ key: string; resource: TokenListsResource }>({ key: \"\", resource: EMPTY });\n\n useEffect(() => {\n if (inputs === undefined || inputs.length === 0) {\n setState({ key, resource: EMPTY });\n return;\n }\n let cancelled = false;\n setState((s) => (s.key === key ? s : { key, resource: { ...EMPTY, status: \"loading\" } }));\n void Promise.all(\n inputs.map(async (input): Promise<TokenList | TokenListFailure> => {\n if (!isTokenListUrl(input)) return input;\n try {\n return (await fetchTokenList(input.url)).list;\n } catch (e) {\n return { url: input.url, message: e instanceof Error ? e.message : String(e) };\n }\n }),\n ).then((settled) => {\n if (cancelled) return;\n const lists = settled.filter((s): s is TokenList => !(\"url\" in s && \"message\" in s));\n const failures = settled.filter((s): s is TokenListFailure => \"url\" in s && \"message\" in s);\n const merged = mergeTokenLists(lists, { chainId: chain.chainId });\n setState({ key, resource: { tokens: tokensFromMergedList(merged), status: \"ready\", failures, sources: lists.map((l) => l.name) } });\n });\n return () => {\n cancelled = true;\n };\n // `key` stands in for `inputs`: a new array with the same lists must not refetch.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key, chain.chainId]);\n\n return useMemo(() => (state.key === key ? state.resource : inputs === undefined || inputs.length === 0 ? EMPTY : { ...EMPTY, status: \"loading\" }), [state, key, inputs]);\n}\n","// SPDX-License-Identifier: MIT\n/**\n * The swap widget's state, as pure functions.\n *\n * `SwapWidget` renders; everything it decides lives here so it can be tested\n * without a DOM (the unit suite renders through `react-dom/server`, where no\n * effect runs and no button can be pressed). The shape:\n *\n * - A **pair** is unordered but anchored: `token` is the thing being traded,\n * `quote` what it is priced in. A **side** orients it - `buy` pays the quote\n * and receives the token, `sell` the reverse. The Sell / Buy panels always\n * show the oriented view; the anchor is what a host pins with `pair` and what\n * `side` flips over, so a side change never touches the selection itself.\n * - The flip button turns the trade around: the amount the current quote\n * would have delivered becomes the amount you pay (the widget is exact-input\n * only, so the typed number cannot stay on the panel it was typed for), and\n * with no quote in hand the field is cleared. A side change that did not\n * come from the flip (a host's controlled `side`) keeps the typed amount.\n * Either way the quote re-reads and nothing of the old one is shown. The\n * price-impact acknowledgement is reset because it was given for a\n * different trade.\n * - Portions are fractions of the input balance. There is no balance without\n * a wallet, so a portion without one is refused, never estimated.\n */\n\nimport type { RouteStep, SwapQuoteResult, TokenInfo } from \"../../adapters/protocol.js\";\nimport { formatUnits } from \"viem\";\nimport { formatPercentFromPips } from \"../../core/format.js\";\nimport type { PriceImpactSeverity, QuoteBreakdown } from \"../../core/math.js\";\nimport type { AsyncStatus } from \"../../hooks/useAsyncResource.js\";\n\n/** Which way a pinned pair is traded: `buy` pays the quote for the token. */\nexport type SwapSide = \"buy\" | \"sell\";\n\n/**\n * A pair for {@link SwapWidget}'s `pair` prop, by address or by `TokenInfo`.\n * `{ token, quote }` is the anchored form; `{ tokenIn, tokenOut }` is the same\n * pair given in its `buy` orientation (`tokenIn` is the quote).\n */\nexport type SwapPair =\n | { readonly token: string | TokenInfo; readonly quote: string | TokenInfo }\n | { readonly tokenIn: string | TokenInfo; readonly tokenOut: string | TokenInfo };\n\n/** A pair reduced to its anchored form. */\nexport interface AnchoredPair<T> {\n readonly token: T;\n readonly quote: T;\n}\n\n/** The two panels' tokens. */\nexport interface OrientedPair<T> {\n readonly tokenIn: T;\n readonly tokenOut: T;\n}\n\n/** Reduces either `SwapPair` shape to `{ token, quote }`. */\nexport function normalizePair(pair: SwapPair): AnchoredPair<string | TokenInfo> {\n return \"token\" in pair ? { token: pair.token, quote: pair.quote } : { token: pair.tokenOut, quote: pair.tokenIn };\n}\n\n/** The address of a pair entry, lower-cased. */\nexport function pairEntryAddress(entry: string | TokenInfo): string {\n return (typeof entry === \"string\" ? entry : entry.address).toLowerCase();\n}\n\n/** A stable key for a pair prop, so a re-render with an equal pair is not a re-pin. */\nexport function pairKey(pair: SwapPair | undefined): string | null {\n if (pair === undefined) return null;\n const anchored = normalizePair(pair);\n return `${pairEntryAddress(anchored.token)}:${pairEntryAddress(anchored.quote)}`;\n}\n\n/** Finds a token in a list by address, case-insensitively. */\nexport function findToken(tokens: readonly TokenInfo[], address: string | undefined): TokenInfo | null {\n if (address === undefined) return null;\n const wanted = address.toLowerCase();\n return tokens.find((token) => token.address.toLowerCase() === wanted) ?? null;\n}\n\n/**\n * Resolves a pair entry: a `TokenInfo` is taken as given; an address is looked\n * up in the list. `null` means the list does not carry it (the widget then asks\n * the adapter for the token contract).\n */\nexport function resolvePairEntry(entry: string | TokenInfo, tokens: readonly TokenInfo[]): TokenInfo | null {\n if (typeof entry !== \"string\") return entry;\n return findToken(tokens, entry);\n}\n\n/** Orients an anchored pair for the panels: `buy` pays the quote. */\nexport function orientPair<T>(anchor: AnchoredPair<T>, side: SwapSide): OrientedPair<T> {\n return side === \"buy\" ? { tokenIn: anchor.quote, tokenOut: anchor.token } : { tokenIn: anchor.token, tokenOut: anchor.quote };\n}\n\n/** The inverse of {@link orientPair}: what the panels show, as an anchor. */\nexport function unorientPair<T>(oriented: OrientedPair<T>, side: SwapSide): AnchoredPair<T> {\n return side === \"buy\" ? { token: oriented.tokenOut, quote: oriented.tokenIn } : { token: oriented.tokenIn, quote: oriented.tokenOut };\n}\n\n/** The other side. */\nexport function oppositeSide(side: SwapSide): SwapSide {\n return side === \"buy\" ? \"sell\" : \"buy\";\n}\n\n// --- portions ---------------------------------------------------------------\n\n/** The widget's default portion chips: 25%, 50%, 75% and Max (the design's four quick amounts). */\nexport const DEFAULT_PORTIONS: readonly number[] = [0.25, 0.5, 0.75, 1];\n\n/** A sliver of the native asset kept back for gas when \"Max\" is pressed. */\nconst NATIVE_GAS_RESERVE = 10n ** 15n;\n\n/**\n * Validates a `portions` prop. Every entry must be a finite fraction in\n * `(0, 1]`; the order given is the order rendered. An empty list hides the\n * chips. Throws, like every other bad widget config, rather than rendering a\n * chip that would compute a nonsense amount.\n */\nexport function normalizePortions(portions: readonly number[] | undefined): readonly number[] {\n if (portions === undefined) return DEFAULT_PORTIONS;\n for (const fraction of portions) {\n if (typeof fraction !== \"number\" || !Number.isFinite(fraction) || fraction <= 0 || fraction > 1) {\n throw new RangeError(`[@latchprotocol/widgets] portions must be fractions in (0, 1]: ${String(fraction)}`);\n }\n }\n return portions;\n}\n\n/** The chip label for a fraction: `1` is \"Max\", the rest a percentage. */\nexport function portionLabel(fraction: number): string {\n if (fraction === 1) return \"Max\";\n const percent = fraction * 100;\n return `${Number.isInteger(percent) ? percent : Number(percent.toFixed(2))}%`;\n}\n\n/**\n * A fraction of a balance, in the token's smallest unit. On the native asset\n * the whole balance keeps a sliver for gas; any smaller fraction, and any\n * ERC-20, is exact. Uses basis-point precision so `0.333` is not lost.\n */\nexport function balancePortion(balance: bigint, fraction: number, token: TokenInfo): bigint {\n const bps = BigInt(Math.round(fraction * 10_000));\n const raw = (balance * bps) / 10_000n;\n if (token.isNative === true && fraction === 1) return raw > NATIVE_GAS_RESERVE ? raw - NATIVE_GAS_RESERVE : 0n;\n return raw;\n}\n\n/**\n * The amount text a portion chip writes into the input, or `null` when there\n * is nothing to take a portion of: no input token, or no balance because no\n * wallet is connected. `null` is a refusal - the widget never guesses a\n * balance - and the caller decides whether to ask for a wallet.\n *\n * Plain decimal text, exact to the token's decimals and never grouped: it is\n * parsed back by `parseAmount`, which takes no thousands separator.\n */\nexport function portionAmountText(token: TokenInfo | null, balance: bigint | null, fraction: number): string | null {\n if (token === null || balance === null) return null;\n return formatUnits(balancePortion(balance, fraction, token), token.decimals);\n}\n\n// --- the state machine ------------------------------------------------------\n\n/** What the widget holds between renders. */\nexport interface SwapWidgetState {\n /** The anchored selection; `null` entries mean nothing chosen yet. */\n readonly anchor: AnchoredPair<TokenInfo | null>;\n /** The widget's own side. Ignored while the host controls `side`. */\n readonly side: SwapSide;\n /** The typed input amount, verbatim. */\n readonly amountText: string;\n /** Whether the user acknowledged the current trade's price impact. */\n readonly impactAck: boolean;\n}\n\n/** Every transition the widget makes. */\nexport type SwapWidgetAction =\n /** The token list arrived (or the defaults changed) and nothing is selected yet. */\n | { readonly type: \"seed\"; readonly tokens: readonly TokenInfo[]; readonly defaultTokenIn?: string; readonly defaultTokenOut?: string; readonly side: SwapSide }\n /** The host's `pair` resolved. Overrides the selection; keeps the amount. */\n | { readonly type: \"pin\"; readonly anchor: AnchoredPair<TokenInfo | null> }\n /** The Sell panel's selector picked a token. */\n | { readonly type: \"select-in\"; readonly token: TokenInfo; readonly side: SwapSide }\n /** The Buy panel's selector picked a token. */\n | { readonly type: \"select-out\"; readonly token: TokenInfo; readonly side: SwapSide }\n /** The direction flipped (flip button, `flip()` or a controlled `side` change). */\n | { readonly type: \"set-side\"; readonly side: SwapSide; readonly amountText?: string }\n | { readonly type: \"amount\"; readonly text: string }\n | { readonly type: \"ack\"; readonly value: boolean };\n\n/** The state before anything is known. */\nexport const INITIAL_SWAP_STATE: SwapWidgetState = {\n anchor: { token: null, quote: null },\n side: \"buy\",\n amountText: \"\",\n impactAck: false,\n};\n\n/**\n * The initial state for a mount: a pair given as `TokenInfo`s is selected\n * synchronously, so a locked pair renders its chips on the first frame (and in\n * a server render); an address waits for the list.\n */\nexport function initialSwapState(options: { readonly pair?: SwapPair; readonly side?: SwapSide }): SwapWidgetState {\n const side = options.side ?? \"buy\";\n if (options.pair === undefined) return { ...INITIAL_SWAP_STATE, side };\n const anchored = normalizePair(options.pair);\n return {\n ...INITIAL_SWAP_STATE,\n side,\n anchor: {\n token: typeof anchored.token === \"string\" ? null : anchored.token,\n quote: typeof anchored.quote === \"string\" ? null : anchored.quote,\n },\n };\n}\n\n/** Applies one action. Pure; the component wraps it in `useReducer`. */\nexport function swapWidgetReducer(state: SwapWidgetState, action: SwapWidgetAction): SwapWidgetState {\n switch (action.type) {\n case \"seed\": {\n if (action.tokens.length === 0) return state;\n const shown = orientPair(state.anchor, action.side);\n const tokenIn = shown.tokenIn ?? findToken(action.tokens, action.defaultTokenIn) ?? action.tokens[0] ?? null;\n const tokenOut = shown.tokenOut ?? findToken(action.tokens, action.defaultTokenOut) ?? action.tokens[1] ?? null;\n if (tokenIn === shown.tokenIn && tokenOut === shown.tokenOut) return state;\n return { ...state, anchor: unorientPair({ tokenIn, tokenOut }, action.side) };\n }\n case \"pin\": {\n if (action.anchor.token === state.anchor.token && action.anchor.quote === state.anchor.quote) return state;\n return { ...state, anchor: action.anchor, impactAck: false };\n }\n case \"select-in\": {\n const shown = orientPair(state.anchor, action.side);\n return { ...state, anchor: unorientPair({ tokenIn: action.token, tokenOut: shown.tokenOut }, action.side), impactAck: false };\n }\n case \"select-out\": {\n const shown = orientPair(state.anchor, action.side);\n return { ...state, anchor: unorientPair({ tokenIn: shown.tokenIn, tokenOut: action.token }, action.side), impactAck: false };\n }\n case \"set-side\":\n if (action.side === state.side) return state;\n /* With a carried amount (the flip button), it replaces the typed one; without, the amount stays. */\n return { ...state, side: action.side, impactAck: false, ...(action.amountText === undefined ? {} : { amountText: action.amountText }) };\n case \"amount\":\n if (action.text === state.amountText) return state;\n return { ...state, amountText: action.text, impactAck: false };\n case \"ack\":\n return state.impactAck === action.value ? state : { ...state, impactAck: action.value };\n default:\n return state;\n }\n}\n\n// --- the quote view ---------------------------------------------------------\n\n/** One quote as a host sees it through `onQuote`. Smallest units throughout. */\nexport interface SwapQuoteView {\n readonly tokenIn: TokenInfo;\n readonly tokenOut: TokenInfo;\n readonly amountIn: bigint;\n /** What the user receives after the integrator fee. */\n readonly amountOut: bigint;\n /** Output before the integrator fee, as the pool quotes it. */\n readonly grossAmountOut: bigint;\n /** The floor after slippage and the integrator fee - what the transaction enforces. */\n readonly minReceived: bigint;\n readonly integratorFee: bigint;\n readonly slippageBps: number;\n /** `null` when the pool's fee is hook-set: an impact that silently included it would be an invented number. */\n readonly priceImpactBps: number | null;\n readonly priceImpactSeverity: PriceImpactSeverity;\n readonly lpFee: {\n readonly pips: number;\n readonly unknown: boolean;\n /** Ready to print: a percentage, or `dynamic (hook-set)`. */\n readonly label: string;\n };\n readonly route: readonly RouteStep[];\n /** The route's token symbols, input first. */\n readonly routeSymbols: readonly string[];\n /** Output units per input unit, for display. */\n readonly rate: number | null;\n readonly status: AsyncStatus;\n /** `true` while a newer quote is being read over this one. */\n readonly isRefreshing: boolean;\n readonly isMock: boolean;\n readonly updatedAt: number | null;\n}\n\n/** Symbols along a route, input first, blanks dropped. */\nexport function routeSymbols(route: readonly RouteStep[]): readonly string[] {\n if (route.length === 0) return [];\n const symbols = [route[0]?.tokenIn.symbol ?? \"\"];\n for (const step of route) symbols.push(step.tokenOut.symbol);\n return symbols.filter((symbol) => symbol !== \"\");\n}\n\n/** Builds the `onQuote` payload, or `null` while there is no quote to report. */\nexport function buildSwapQuoteView(input: {\n readonly tokenIn: TokenInfo | null;\n readonly tokenOut: TokenInfo | null;\n readonly quote: SwapQuoteResult | null;\n readonly breakdown: QuoteBreakdown | null;\n readonly rate: number | null;\n readonly status: AsyncStatus;\n readonly isRefreshing: boolean;\n readonly isMock: boolean;\n readonly updatedAt: number | null;\n}): SwapQuoteView | null {\n const { tokenIn, tokenOut, quote, breakdown } = input;\n if (tokenIn === null || tokenOut === null || quote === null || breakdown === null) return null;\n return {\n tokenIn,\n tokenOut,\n amountIn: breakdown.amountIn,\n amountOut: breakdown.netAmountOut,\n grossAmountOut: breakdown.grossAmountOut,\n minReceived: breakdown.minAmountOutNet,\n integratorFee: breakdown.integratorFee,\n slippageBps: breakdown.slippageBps,\n priceImpactBps: breakdown.priceImpactBps,\n priceImpactSeverity: breakdown.priceImpactSeverity,\n lpFee: {\n pips: breakdown.lpFeePips,\n unknown: breakdown.lpFeeUnknown,\n label: breakdown.lpFeeUnknown ? \"dynamic (hook-set)\" : formatPercentFromPips(breakdown.lpFeePips),\n },\n route: quote.route,\n routeSymbols: routeSymbols(quote.route),\n rate: input.rate,\n status: input.status,\n isRefreshing: input.isRefreshing,\n isMock: input.isMock,\n updatedAt: input.updatedAt,\n };\n}\n","// SPDX-License-Identifier: MIT\n/**\n * The lock reads with no React in them: one pool's locks or one token's locks,\n * read through the MIT SDK (`@latchprotocol/sdk/lock`). `usePoolLocks` /\n * `useTokenLocks` wrap these as resources; the framework-free embed\n * (`latch-embed.js`) calls them directly.\n */\n\nimport { erc20Abi, zeroAddress, type Address, type Hex, type PublicClient } from \"viem\";\nimport {\n findClLpLockerTokenIds,\n permanentTokenPools,\n readBinLpLockerLocks,\n readBinPoolPermanent,\n readChainNow,\n readClLpLockerPositionsPriced,\n readClPoolPermanent,\n readCurrencyLocks,\n readPoolLocks,\n summarizePoolLocks,\n type BinPoolPermanentSummary,\n type CurrencyLockSummary,\n type PoolLockSummary,\n type TokenPermanentPool,\n} from \"@latchprotocol/sdk/lock\";\n\nimport type { LocksTokenMeta, LpLockerSource } from \"./model.js\";\nimport { shortAddress } from \"../core/format.js\";\n\n/** What a lock read needs beyond the addresses. */\nexport interface LocksReadOptions {\n readonly native?: NativeCurrencyMeta;\n /** The protocol's LP lockers: their permanent liquidity is read and counted. */\n readonly lp?: LpLockerSource;\n}\n\n/** Native currency display facts (address zero). */\nexport interface NativeCurrencyMeta {\n readonly symbol: string;\n readonly decimals: number;\n}\n\nexport const DEFAULT_NATIVE: NativeCurrencyMeta = { symbol: \"ETH\", decimals: 18 };\n\n/**\n * Symbol and decimals as the token answers them. Read here rather than through\n * the SDK's kit reader so the framework-free embed does not carry the kit's ABI.\n */\nasync function metaOf(client: PublicClient, address: Address, native: NativeCurrencyMeta): Promise<LocksTokenMeta> {\n if (address.toLowerCase() === zeroAddress) return { address: zeroAddress, symbol: native.symbol, decimals: native.decimals };\n const [symbol, decimals] = await Promise.all([\n client.readContract({ address, abi: erc20Abi, functionName: \"symbol\" }).catch(() => null),\n client.readContract({ address, abi: erc20Abi, functionName: \"decimals\" }).catch(() => null),\n ]);\n return { address, symbol: symbol ?? shortAddress(address), decimals: decimals === null ? null : Number(decimals) };\n}\n\nexport interface PoolLocksData {\n /** CL: time locks and the CL LP locker's permanent positions. Bin pool: an empty summary. */\n readonly summary: PoolLockSummary;\n /** Bin pool: what the Bin LP locker holds forever; `null` for a CL pool. */\n readonly bin: BinPoolPermanentSummary | null;\n readonly currency0: LocksTokenMeta;\n readonly currency1: LocksTokenMeta;\n /** The chain's `block.timestamp` when read. */\n readonly chainNow: bigint;\n /** `Date.now()` when read, to advance `chainNow` locally. */\n readonly readAtMs: number;\n}\n\nexport interface TokenLocksData {\n /** `null` when no token lock is deployed (only LP-locker liquidity is read). */\n readonly summary: CurrencyLockSummary | null;\n /** How much of the token the LP lockers hold forever, per pool; `null` when no LP locker was given. */\n readonly permanent: { readonly pools: readonly TokenPermanentPool[]; readonly total: bigint; readonly unpriced: number } | null;\n readonly token: LocksTokenMeta;\n readonly chainNow: bigint;\n readonly readAtMs: number;\n}\n\n\nasync function clLockerTokenIds(client: PublicClient, lp: LpLockerSource, poolId?: Hex): Promise<readonly bigint[]> {\n if (!lp.lpLocker) return [];\n if (lp.lpLockerTokenIds) return lp.lpLockerTokenIds;\n if (lp.lpLockerFromBlock === undefined) return [];\n const toBlock = await client.getBlockNumber();\n return (await findClLpLockerTokenIds(client, lp.lpLocker, { fromBlock: lp.lpLockerFromBlock, toBlock }, poolId)).map((x) => x.tokenId);\n}\n\n/**\n * Every lock in one pool (the SDK's `readPoolLocks`), with both currencies'\n * metadata. The loader behind {@link usePoolLocks}, usable without React (the\n * framework-free embed reads through it).\n */\nexport async function fetchPoolLocks(\n client: PublicClient,\n positionLock: Address | null,\n poolId: Hex,\n options: LocksReadOptions = {},\n): Promise<PoolLocksData> {\n const native = options.native ?? DEFAULT_NATIVE;\n const lp = options.lp ?? {};\n if (lp.poolType === \"bin\") {\n const [bin, now] = await Promise.all([readBinPoolPermanent(client, lp.binLpLocker as Address, poolId), readChainNow(client)]);\n const readAtMs = Date.now();\n const f = bin.locks[0];\n const [currency0, currency1] = await Promise.all([metaOf(client, f?.currency0 ?? zeroAddress, native), metaOf(client, f?.currency1 ?? zeroAddress, native)]);\n const summary = summarizePoolLocks({ poolId, currency0: currency0.address, currency1: currency1.address, pool: null, locks: [] });\n return { summary, bin, currency0, currency1, chainNow: now, readAtMs };\n }\n const ids = await clLockerTokenIds(client, lp, poolId);\n let summary: PoolLockSummary;\n let chainNow: bigint;\n if (positionLock !== null) {\n const s = await readPoolLocks(client, positionLock, poolId, { lpLocker: lp.lpLocker ?? null, lpLockerTokenIds: ids });\n summary = s;\n chainNow = s.now;\n } else {\n const [perm, now] = await Promise.all([readClPoolPermanent(client, lp.lpLocker as Address, poolId, { tokenIds: ids }), readChainNow(client)]);\n const f = perm.permanent[0];\n summary = summarizePoolLocks({ poolId, currency0: f?.currency0 ?? zeroAddress, currency1: f?.currency1 ?? zeroAddress, pool: perm.pool, locks: [], permanent: perm.permanent });\n chainNow = now;\n }\n const readAtMs = Date.now();\n const [currency0, currency1] = await Promise.all([metaOf(client, summary.currency0, native), metaOf(client, summary.currency1, native)]);\n return { summary, bin: null, currency0, currency1, chainNow, readAtMs };\n}\n\n/** Whether {@link fetchPoolLocks} has anything to read for this target. */\nexport function poolLocksEnabled(positionLock: Address | null, lp: LpLockerSource = {}): boolean {\n return lp.poolType === \"bin\" ? !!lp.binLpLocker : positionLock !== null || !!lp.lpLocker;\n}\n\n/**\n * Every lock of one token (the SDK's `readCurrencyLocks`), with its metadata\n * and what the LP lockers hold of it. The loader behind {@link useTokenLocks}.\n */\nexport async function fetchTokenLocks(\n client: PublicClient,\n tokenLock: Address | null,\n token: Address,\n options: LocksReadOptions = {},\n): Promise<TokenLocksData> {\n const native = options.native ?? DEFAULT_NATIVE;\n const lp = options.lp ?? {};\n const hasLp = !!lp.lpLocker || !!lp.binLpLocker;\n const [summary, meta, now, permanent] = await Promise.all([\n tokenLock === null ? Promise.resolve(null) : readCurrencyLocks(client, tokenLock, token),\n metaOf(client, token, native),\n readChainNow(client),\n hasLp\n ? (async () => {\n const ids = await clLockerTokenIds(client, lp);\n const [cl, bin] = await Promise.all([\n lp.lpLocker ? readClLpLockerPositionsPriced(client, lp.lpLocker, ids) : Promise.resolve([]),\n lp.binLpLocker ? readBinLpLockerLocks(client, lp.binLpLocker).then((r) => r.locks) : Promise.resolve([]),\n ]);\n return permanentTokenPools(token, cl, bin);\n })()\n : Promise.resolve(null),\n ]);\n return { summary, permanent, token: meta, chainNow: summary?.now ?? now, readAtMs: Date.now() };\n}\n","// SPDX-License-Identifier: MIT\r\n/**\r\n * Locks: the pure half of `LocksBadge` / `LocksPanel`.\r\n *\r\n * Everything here turns what the SDK read from chain (`readPoolLocks`,\r\n * `readCurrencyLocks` in `@latchprotocol/sdk/lock`) into words, with no\r\n * estimate added. Two rules the copy never breaks:\r\n *\r\n * - A CL pool has no LP token. The pool figure is the locked share of the\r\n * pool's ACTIVE liquidity at the current tick (`lockedActiveBps`), and it is\r\n * called exactly that. When the pool has no active liquidity the share is\r\n * \"not measurable\", never 0% and never 100%.\r\n * - Time is the chain's `block.timestamp`, the clock the contracts compare\r\n * `unlockAt` against. Callers pass `now` from the chain, never `Date.now()`.\r\n *\r\n * - Two kinds of lock, never blurred: \"time-locked until <date>\"\r\n * (`LatchPositionLock`, `LatchTokenLock`) and \"locked permanently (LP\r\n * locker)\" (`LatchLPLocker` / `LatchBinLPLocker`, which hold every Kit v2\r\n * launch's seed liquidity and have NO withdraw path). Permanent in-range CL\r\n * liquidity counts in the locked share and is also shown on its own. A Bin\r\n * pool's permanent figure is the locked fraction of its ACTIVE bin.\r\n *\r\n * No USD anywhere: amounts are token units with a symbol.\r\n */\r\n\r\nimport type { Address, Hex } from \"viem\";\r\nimport { vestedAt, type BinPoolPermanentSummary, type CurrencyLockSummary, type PoolLockSummary, type PositionLockStatus, type TokenLockView, type TokenPermanentPool } from \"@latchprotocol/sdk/lock\";\r\n\r\n/** Which locks a widget shows. `null` lock address = the chain has no address for it; surfaces say \"coming soon\". */\r\nexport type LocksTarget =\r\n | ({ readonly kind: \"pool\"; readonly poolId: Hex; readonly positionLock: Address | null } & LpLockerSource)\r\n | ({ readonly kind: \"token\"; readonly token: Address; readonly tokenLock: Address | null } & LpLockerSource);\r\n\r\n/**\r\n * The protocol's permanent LP lockers (the address book's `launchpadV2.clLPLocker`\r\n * / `binLPLocker`). CL positions are found from the locker's `PositionLocked`\r\n * logs: pass their token ids when you know them, or `lpLockerFromBlock` (the\r\n * locker's deploy block) and one log scan to the latest block is made. Bin locks\r\n * are enumerable and need neither. All optional: omitted = not counted.\r\n */\r\nexport interface LpLockerSource {\r\n readonly lpLocker?: Address | null;\r\n readonly binLpLocker?: Address | null;\r\n readonly lpLockerTokenIds?: readonly bigint[];\r\n readonly lpLockerFromBlock?: bigint;\r\n /** A pool target that is a Bin pool: its permanent share is read from the Bin locker. */\r\n readonly poolType?: \"cl\" | \"bin\";\r\n}\r\n\r\n/** Token display facts. `decimals: null` means amounts are shown in base units. */\r\nexport interface LocksTokenMeta {\r\n readonly address: Address;\r\n readonly symbol: string;\r\n readonly decimals: number | null;\r\n}\r\n\r\n/** The Latch lock page for a target: `<siteUrl>/app/locks/pool/<poolId>` or `/app/locks/token/<address>`. */\r\nexport function lockPageUrl(\r\n siteUrl: string,\r\n target: Pick<LocksTarget, \"kind\"> & { readonly poolId?: Hex; readonly token?: Address },\r\n opts: { readonly pathBase?: string; readonly query?: string } = {},\r\n): string {\r\n const base = siteUrl.replace(/\\/+$/, \"\");\r\n const path = `/${(opts.pathBase ?? \"/app/locks\").replace(/^\\/+|\\/+$/g, \"\")}`;\r\n const q = opts.query ? `?${opts.query.replace(/^\\?/, \"\")}` : \"\";\r\n if (target.kind === \"pool\") return `${base}${path}/pool/${target.poolId ?? \"\"}${q}`;\r\n return `${base}${path}/token/${target.token ?? \"\"}${q}`;\r\n}\r\n\r\n/** Basis points as a percentage: 8234 → \"82.34%\", 10000 → \"100%\", 1 → \"0.01%\". */\r\nexport function formatLockBps(bps: number): string {\r\n const whole = Math.floor(bps / 100);\r\n const frac = bps % 100;\r\n return frac === 0 ? `${whole}%` : `${whole}.${String(frac).padStart(2, \"0\")}%`;\r\n}\r\n\r\n/** `12d 04h 03m` above a day, `4h 03m 20s` below, `now` at zero. */\r\nexport function formatCountdown(seconds: bigint): string {\r\n if (seconds <= 0n) return \"now\";\r\n const s = Number(seconds);\r\n const d = Math.floor(s / 86_400);\r\n const h = Math.floor((s % 86_400) / 3600);\r\n const m = Math.floor((s % 3600) / 60);\r\n const sec = s % 60;\r\n const p = (n: number): string => String(n).padStart(2, \"0\");\r\n if (d >= 365) return `${Math.floor(d / 365)}y ${d % 365}d`;\r\n if (d > 0) return `${d}d ${p(h)}h ${p(m)}m`;\r\n if (h > 0) return `${h}h ${p(m)}m ${p(sec)}s`;\r\n return `${m}m ${p(sec)}s`;\r\n}\r\n\r\n/** Unix seconds → \"2026-10-01 14:05 UTC\". */\r\nexport function formatUtc(unixSeconds: bigint): string {\r\n return `${new Date(Number(unixSeconds) * 1000).toISOString().replace(\"T\", \" \").slice(0, 16)} UTC`;\r\n}\r\n\r\n/** Exact decimal, trimmed, never \"0\" for a non-zero amount. */\r\nexport function formatLockAmount(value: bigint, meta: Pick<LocksTokenMeta, \"symbol\" | \"decimals\">, maxFrac = 6): string {\r\n if (meta.decimals === null) return `${value.toLocaleString(\"en-US\")} base units ${meta.symbol}`;\r\n if (value === 0n) return `0 ${meta.symbol}`;\r\n const base = 10n ** BigInt(meta.decimals);\r\n const whole = value / base;\r\n const frac = (value % base).toString().padStart(meta.decimals, \"0\").slice(0, maxFrac).replace(/0+$/, \"\");\r\n if (whole === 0n && frac === \"\") return `<0.${\"0\".repeat(Math.max(0, maxFrac - 1))}1 ${meta.symbol}`;\r\n return `${whole.toLocaleString(\"en-US\")}${frac === \"\" ? \"\" : `.${frac}`} ${meta.symbol}`;\r\n}\r\n\r\n/** The badge's words. `countdownTo` is the moment the countdown runs to (chain seconds). */\r\nexport interface LocksBadgeView {\r\n /** `locked`: something is locked now. `open`: locks exist, none still locked. `none`: no lock at all. */\r\n readonly tone: \"locked\" | \"open\" | \"none\";\r\n readonly headline: string;\r\n readonly detail: string | null;\r\n readonly countdownTo: bigint | null;\r\n /** What the countdown is to, e.g. \"first unlock\". */\r\n readonly countdownLabel: string | null;\r\n}\r\n\r\nconst plural = (n: number, one: string, many: string): string => `${n.toLocaleString(\"en-US\")} ${n === 1 ? one : many}`;\r\n\r\n/** A pool: the locked share of active liquidity (time-locked + permanent), and the soonest unlock. */\r\nexport function poolBadgeView(\r\n s: Pick<PoolLockSummary, \"locks\" | \"liveCount\" | \"lockedCount\" | \"lockedActiveBps\" | \"outOfRangeLocked\" | \"nextUnlockAt\" | \"lastUnlockAt\" | \"pool\"> &\r\n Partial<Pick<PoolLockSummary, \"permanent\" | \"permanentActiveBps\" | \"timeLockedActiveBps\" | \"permanentOutOfRange\">>,\r\n): LocksBadgeView {\r\n const permanent = s.permanent ?? [];\r\n const hasPermanent = permanent.length > 0;\r\n if (s.locks.length === 0 && !hasPermanent) {\r\n return { tone: \"none\", headline: \"No locked liquidity\", detail: \"No position in this pool is time-locked (LatchPositionLock) or held permanently by the protocol's LP locker.\", countdownTo: null, countdownLabel: null };\r\n }\r\n if (s.lockedCount === 0 && !hasPermanent) {\r\n const open = s.liveCount;\r\n return {\r\n tone: \"open\",\r\n headline: \"No time-locked positions now\",\r\n detail:\r\n open > 0\r\n ? `${plural(open, \"lock is\", \"locks are\")} past the unlock date and can be withdrawn by the lock owner.`\r\n : \"Every lock on this pool has been withdrawn.\",\r\n countdownTo: null,\r\n countdownLabel: null,\r\n };\r\n }\r\n const headline =\r\n s.lockedActiveBps === null\r\n ? hasPermanent && s.lockedCount === 0\r\n ? \"Locked permanently (LP locker) · share of active liquidity not measurable\"\r\n : `${plural(s.lockedCount + permanent.length, \"locked position\", \"locked positions\")} · share of active liquidity not measurable`\r\n : `${formatLockBps(s.lockedActiveBps)} of active liquidity locked`;\r\n const parts: string[] = [];\r\n if (s.lockedActiveBps === null) {\r\n parts.push(s.pool === null ? \"The pool's state could not be read.\" : \"The pool has no liquidity at the current price, so no share can be measured.\");\r\n } else {\r\n const split: string[] = [];\r\n if (hasPermanent) split.push(`${formatLockBps(s.permanentActiveBps ?? 0)} locked permanently (LP locker, no withdraw path)`);\r\n if (s.lockedCount > 0) split.push(`${formatLockBps(s.timeLockedActiveBps ?? 0)} time-locked until a date`);\r\n parts.push(`${split.join(\", \")}. The share is of liquidity at the current price and moves with it.`);\r\n const out = s.outOfRangeLocked + (s.permanentOutOfRange ?? 0);\r\n if (out > 0) parts.push(`${plural(out, \"locked position is\", \"locked positions are\")} out of range and not counted.`);\r\n }\r\n if (s.lastUnlockAt !== null && s.nextUnlockAt !== null && s.lastUnlockAt !== s.nextUnlockAt) parts.push(`Last time-lock unlock ${formatUtc(s.lastUnlockAt)}.`);\r\n return {\r\n tone: \"locked\",\r\n headline,\r\n detail: parts.join(\" \"),\r\n countdownTo: s.nextUnlockAt,\r\n countdownLabel: s.nextUnlockAt === null ? null : `first time-lock unlock ${formatUtc(s.nextUnlockAt)}`,\r\n };\r\n}\r\n\r\n/** A Bin pool: what the protocol's Bin LP locker holds forever. */\r\nexport function binPoolBadgeView(\r\n b: Pick<BinPoolPermanentSummary, \"locks\" | \"activeBinLockedBps\" | \"amount0\" | \"amount1\">,\r\n c0: Pick<LocksTokenMeta, \"symbol\" | \"decimals\">,\r\n c1: Pick<LocksTokenMeta, \"symbol\" | \"decimals\">,\r\n): LocksBadgeView {\r\n if (b.locks.length === 0) {\r\n return { tone: \"none\", headline: \"No locked liquidity\", detail: \"The protocol's Bin LP locker holds nothing in this pool. Time locks cover CL positions only.\", countdownTo: null, countdownLabel: null };\r\n }\r\n const amounts = `${formatLockAmount(b.amount0, c0)} + ${formatLockAmount(b.amount1, c1)}`;\r\n const bins = b.locks.reduce((n, l) => n + l.bins.length, 0);\r\n return {\r\n tone: \"locked\",\r\n headline: b.activeBinLockedBps === null ? \"Locked permanently (LP locker)\" : `${formatLockBps(b.activeBinLockedBps)} of the active bin locked permanently (LP locker)`,\r\n detail: `${amounts} held forever by the Bin LP locker across ${plural(bins, \"bin\", \"bins\")}.${b.activeBinLockedBps === null ? \" No lock holds the bin that trades at the current price.\" : \" The share is of the bin that trades at the current price; a pool-wide share across all bins is not computed.\"}`,\r\n countdownTo: null,\r\n countdownLabel: null,\r\n };\r\n}\r\n\r\n/** A token: the share of `totalSupply` held for locks and not yet vested. */\r\nexport function tokenBadgeView(\r\n s: Pick<CurrencyLockSummary, \"locks\" | \"totalHeld\" | \"unvested\" | \"heldBps\" | \"unvestedBps\" | \"nextCliffOrEnd\" | \"lastEnd\"> & { readonly totalSupply?: bigint | null },\r\n meta: Pick<LocksTokenMeta, \"symbol\" | \"decimals\">,\r\n lp: { readonly pools: readonly TokenPermanentPool[]; readonly total: bigint } | null = null,\r\n): LocksBadgeView {\r\n const lpLine =\r\n lp !== null && lp.pools.length > 0\r\n ? `${formatLockAmount(lp.total, meta)}${s.totalSupply ? ` (${formatLockBps(Number((lp.total * 10_000n) / s.totalSupply))} of supply)` : \"\"} locked permanently as pool liquidity (LP locker) in ${plural(lp.pools.length, \"pool\", \"pools\")}, at the current price.`\r\n : null;\r\n if (s.locks.length === 0 && lpLine !== null) {\r\n return { tone: \"locked\", headline: `${meta.symbol} liquidity locked permanently (LP locker)`, detail: `${lpLine} No time lock or vesting of ${meta.symbol} with the Latch token lock.`, countdownTo: null, countdownLabel: null };\r\n }\r\n if (s.locks.length === 0) {\r\n return { tone: \"none\", headline: `No ${meta.symbol} locked`, detail: \"No lock of this token has been made with the Latch token lock.\", countdownTo: null, countdownLabel: null };\r\n }\r\n if (s.totalHeld === 0n) {\r\n return {\r\n tone: lpLine !== null ? \"locked\" : \"open\",\r\n headline: lpLine !== null ? `${meta.symbol} liquidity locked permanently (LP locker)` : `No ${meta.symbol} locked now`,\r\n detail: `${plural(s.locks.length, \"time lock has\", \"time locks have\")} been fully released and claimed.${lpLine !== null ? ` ${lpLine}` : \"\"}`,\r\n countdownTo: null,\r\n countdownLabel: null,\r\n };\r\n }\r\n const headline =\r\n s.heldBps === null ? `${formatLockAmount(s.totalHeld, meta)} held in locks` : `${formatLockBps(s.heldBps)} of supply held in locks`;\r\n const parts: string[] = [];\r\n parts.push(\r\n s.unvestedBps === null\r\n ? `${formatLockAmount(s.unvested, meta)} not yet vested.`\r\n : `${formatLockBps(s.unvestedBps)} of supply (${formatLockAmount(s.unvested, meta)}) not yet vested; the rest is vested and waiting to be claimed.`,\r\n );\r\n if (s.lastEnd !== null) parts.push(`Fully vested ${formatUtc(s.lastEnd)}.`);\r\n if (lpLine !== null) parts.push(lpLine);\r\n return {\r\n tone: s.unvested > 0n ? \"locked\" : \"open\",\r\n headline,\r\n detail: parts.join(\" \"),\r\n countdownTo: s.nextCliffOrEnd,\r\n countdownLabel: s.nextCliffOrEnd === null ? null : `next release ${formatUtc(s.nextCliffOrEnd)}`,\r\n };\r\n}\r\n\r\nexport const POSITION_STATUS_LABEL: Record<PositionLockStatus, string> = {\r\n locked: \"Locked\",\r\n unlockable: \"Unlockable\",\r\n withdrawn: \"Withdrawn\",\r\n};\r\n\r\nexport const TOKEN_STATUS_LABEL: Record<TokenLockView[\"status\"], string> = {\r\n cliff: \"Before cliff\",\r\n vesting: \"Vesting\",\r\n vested: \"Fully vested\",\r\n claimed: \"Claimed\",\r\n};\r\n\r\n/** `vested / amount` in basis points (floor), for a vesting bar. */\r\nexport function vestedBps(l: Pick<TokenLockView, \"vested\" | \"amount\">): number {\r\n return l.amount === 0n ? 0 : Number((l.vested * 10_000n) / l.amount);\r\n}\r\n\r\n/** The chain's `now` at a later wall-clock moment: `chainNow` read at `readAtMs`, advanced by elapsed seconds. */\r\nexport function advanceChainNow(chainNow: bigint, readAtMs: number, nowMs: number): bigint {\r\n return chainNow + BigInt(Math.max(0, Math.floor((nowMs - readAtMs) / 1000)));\r\n}\r\n\r\n/* ------------------------------------------------------------ chart views --- */\r\n\r\n/** One part of a share bar. `bps` is floored; `nonZero` keeps a sub-0.01% part visible (\"<0.01%\"). */\r\nexport interface SharePart {\r\n readonly key: \"permanent\" | \"time\" | \"unvested\" | \"vested\" | \"lp\";\r\n readonly label: string;\r\n readonly bps: number;\r\n readonly nonZero: boolean;\r\n}\r\n\r\n/** A whole split into locked parts; the rest of the bar is \"not locked\". */\r\nexport interface ShareBarView {\r\n readonly parts: readonly SharePart[];\r\n /** What the share is OF: \"of active liquidity\", \"of the active bin\", \"of supply\". */\r\n readonly of: string;\r\n readonly restBps: number;\r\n}\r\n\r\nconst bpsOf = (part: bigint, whole: bigint): number => {\r\n const b = (part * 10_000n) / whole;\r\n return Number(b > 10_000n ? 10_000n : b);\r\n};\r\n\r\nfunction bar(parts: SharePart[], of: string): ShareBarView {\r\n return { parts: parts.filter((p) => p.bps > 0 || p.nonZero), of, restBps: Math.max(0, 10_000 - parts.reduce((n, p) => n + p.bps, 0)) };\r\n}\r\n\r\n/** A CL pool's active liquidity: permanent (LP locker) and time-locked. `null` when no share is measurable. */\r\nexport function poolShareBar(\r\n s: Pick<PoolLockSummary, \"pool\" | \"lockedActiveLiquidity\"> & Partial<Pick<PoolLockSummary, \"permanentActiveLiquidity\" | \"timeLockedActiveLiquidity\">>,\r\n): ShareBarView | null {\r\n const active = s.pool?.activeLiquidity ?? 0n;\r\n if (s.pool === null || active === 0n) return null;\r\n const perm = s.permanentActiveLiquidity ?? 0n;\r\n const time = s.timeLockedActiveLiquidity ?? s.lockedActiveLiquidity - perm;\r\n return bar(\r\n [\r\n { key: \"permanent\", label: \"Locked permanently (LP locker)\", bps: bpsOf(perm, active), nonZero: perm > 0n },\r\n { key: \"time\", label: \"Time-locked until a date\", bps: bpsOf(time, active), nonZero: time > 0n },\r\n ],\r\n \"of active liquidity\",\r\n );\r\n}\r\n\r\n/** A Bin pool's active bin: the permanent share. `null` when no lock holds it. */\r\nexport function binShareBar(b: Pick<BinPoolPermanentSummary, \"activeBinLockedBps\">): ShareBarView | null {\r\n if (b.activeBinLockedBps === null) return null;\r\n return bar([{ key: \"permanent\", label: \"Locked permanently (LP locker)\", bps: b.activeBinLockedBps, nonZero: b.activeBinLockedBps > 0 }], \"of the active bin\");\r\n}\r\n\r\n/** A token's supply: unvested, vested-unclaimed, and (optionally) its side of permanent LP. `null` without a supply. */\r\nexport function tokenShareBar(\r\n s: Pick<CurrencyLockSummary, \"totalHeld\" | \"unvested\"> & { readonly totalSupply?: bigint | null },\r\n lpTotal: bigint | null = null,\r\n): ShareBarView | null {\r\n const ts = s.totalSupply ?? null;\r\n if (ts === null || ts === 0n) return null;\r\n const vested = s.totalHeld > s.unvested ? s.totalHeld - s.unvested : 0n;\r\n const lp = lpTotal ?? 0n;\r\n return bar(\r\n [\r\n { key: \"unvested\", label: \"Not yet vested\", bps: bpsOf(s.unvested, ts), nonZero: s.unvested > 0n },\r\n { key: \"vested\", label: \"Vested, not yet claimed\", bps: bpsOf(vested, ts), nonZero: vested > 0n },\r\n { key: \"lp\", label: \"In permanent LP (LP locker)\", bps: bpsOf(lp, ts), nonZero: lp > 0n },\r\n ],\r\n \"of supply\",\r\n );\r\n}\r\n\r\n/** A point of a release schedule: `t` unix seconds, `vested` summed over the locks (the contract's `_vested`). */\r\nexport interface SchedulePoint {\r\n readonly t: bigint;\r\n readonly vested: bigint;\r\n}\r\n\r\n/**\r\n * The cumulative release schedule of one token's locks: every start, the\r\n * second before and of each cliff, every end, `now`, and `samples` evenly\r\n * spaced points between, each computed with the SDK's `vestedAt`. A SCHEDULE\r\n * of fixed on-chain terms, not a history of claims. `null` when it has no length.\r\n */\r\nexport function releaseSchedule(\r\n locks: readonly Pick<TokenLockView, \"start\" | \"cliff\" | \"end\" | \"amount\">[],\r\n now: bigint | null,\r\n samples = 24,\r\n): { readonly points: readonly SchedulePoint[]; readonly total: bigint } | null {\r\n if (locks.length === 0) return null;\r\n const lo = locks.reduce((m, l) => (l.start < m ? l.start : m), locks[0]!.start);\r\n const hi = locks.reduce((m, l) => (l.end > m ? l.end : m), locks[0]!.end);\r\n if (hi <= lo) return null;\r\n const xs = new Set<bigint>([lo, hi]);\r\n if (now !== null && now > lo && now < hi) xs.add(now);\r\n for (const l of locks) {\r\n xs.add(l.start);\r\n xs.add(l.end);\r\n if (l.cliff > l.start) {\r\n xs.add(l.cliff - 1n);\r\n xs.add(l.cliff);\r\n }\r\n }\r\n const step = (hi - lo) / BigInt(samples);\r\n if (step > 0n) for (let i = 1n; i < BigInt(samples); i++) xs.add(lo + step * i);\r\n const points = [...xs]\r\n .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\r\n .map((t) => ({ t, vested: locks.reduce((sum, l) => sum + vestedAt(l, t), 0n) }));\r\n return { points, total: locks.reduce((sum, l) => sum + l.amount, 0n) };\r\n}\r\n\r\n/** A share bar from figures already in basis points (the trust read's pool facts). */\r\nexport function shareBarFromBps(parts: readonly { readonly key: SharePart[\"key\"]; readonly label: string; readonly bps: number | null }[], of: string): ShareBarView | null {\r\n if (parts.every((p) => p.bps === null)) return null;\r\n return bar(\r\n parts.map((p) => ({ key: p.key, label: p.label, bps: p.bps ?? 0, nonZero: false })),\r\n of,\r\n );\r\n}\r\n","// SPDX-License-Identifier: MIT\n/**\n * The \"Locked by Latch\" embed badge: its words, pure.\n *\n * The same reads as `LocksBadge`, cut to what a project site shows beside its\n * token or pool. The badge says only what was read:\n *\n * pool \"X% of active liquidity locked\" / \"Locked permanently (LP locker)\"\n * / \"No locked liquidity\" (delegates to `poolBadgeView`)\n * token \"Y% of supply locked\" - the share of supply no beneficiary can\n * take yet (`unvested / totalSupply`), not what merely sits in the\n * locker; plus the permanent LP-locker liquidity when there is some.\n *\n * It never says \"safe\" or \"rug-proof\": a lock is a lock until its date, and\n * that is all the badge claims.\n */\n\nimport type { PoolLocksData, TokenLocksData } from \"./fetch.js\";\nimport { binPoolBadgeView, formatLockAmount, formatLockBps, formatUtc, poolBadgeView, type LocksBadgeView } from \"./model.js\";\n\n/** A pool badge from a pool read (CL or Bin). */\nexport function poolEmbedView(d: PoolLocksData): LocksBadgeView {\n return d.bin !== null ? binPoolBadgeView(d.bin, d.currency0, d.currency1) : poolBadgeView(d.summary);\n}\n\n/** A token badge: the share of supply still locked, and any permanent LP-locker liquidity. */\nexport function tokenEmbedView(d: TokenLocksData): LocksBadgeView {\n const s = d.summary;\n const meta = d.token;\n const lp = d.permanent !== null && d.permanent.pools.length > 0 ? d.permanent : null;\n const supply = s?.totalSupply ?? null;\n const lpLine =\n lp === null\n ? null\n : `${formatLockAmount(lp.total, meta)}${supply !== null && supply > 0n ? ` (${formatLockBps(Number((lp.total * 10_000n) / supply))} of supply)` : \"\"} locked permanently as liquidity (LP locker)`;\n if (s !== null && s.unvested > 0n) {\n const headline = s.unvestedBps === null ? `${formatLockAmount(s.unvested, meta)} locked` : s.unvestedBps === 0 ? \"<0.01% of supply locked\" : `${formatLockBps(s.unvestedBps)} of supply locked`;\n const parts = [`Not yet vested in ${s.locks.length === 1 ? \"1 Latch token lock\" : `${s.locks.length.toLocaleString(\"en-US\")} Latch token locks`}.`];\n if (lpLine !== null) parts.push(`${lpLine}.`);\n return { tone: \"locked\", headline, detail: parts.join(\" \"), countdownTo: s.nextCliffOrEnd, countdownLabel: s.nextCliffOrEnd === null ? null : `next release ${formatUtc(s.nextCliffOrEnd)}` };\n }\n if (lpLine !== null) {\n return { tone: \"locked\", headline: \"Liquidity locked permanently (LP locker)\", detail: `${lpLine}.`, countdownTo: null, countdownLabel: null };\n }\n if (s !== null && s.locks.length > 0) {\n return { tone: \"open\", headline: `No ${meta.symbol} locked now`, detail: \"Every Latch token lock of it has fully vested.\", countdownTo: null, countdownLabel: null };\n }\n return { tone: \"none\", headline: `No ${meta.symbol} locked`, detail: \"No Latch token lock or LP-locker liquidity holds it.\", countdownTo: null, countdownLabel: null };\n}\n","// SPDX-License-Identifier: MIT\n/**\n * The CL LP locker's position ids for one pool (or every pool), from its\n * `PositionLocked` logs, scanned in windows so an RPC that caps `eth_getLogs`\n * ranges still returns every log rather than an error or a truncated list.\n *\n * A window that fails is split in half and retried, down to `minWindow`; a\n * window that still fails throws - a partial scan is never passed off as a\n * complete one.\n */\n\nimport type { Address, Hex, PublicClient } from \"viem\";\nimport { findClLpLockerTokenIds } from \"@latchprotocol/sdk/lock\";\n\nexport interface ScanOptions {\n readonly fromBlock: bigint;\n readonly toBlock?: bigint;\n /** First window size; default 500,000 blocks. */\n readonly window?: bigint;\n /** Smallest window before giving up; default 2,000 blocks. */\n readonly minWindow?: bigint;\n}\n\n/** Pure: `[from, to]` split into consecutive windows of at most `size` blocks. */\nexport function blockWindows(from: bigint, to: bigint, size: bigint): { from: bigint; to: bigint }[] {\n if (size <= 0n) throw new RangeError(\"window size must be positive\");\n const out: { from: bigint; to: bigint }[] = [];\n for (let a = from; a <= to; a += size) out.push({ from: a, to: a + size - 1n > to ? to : a + size - 1n });\n return out;\n}\n\nexport async function scanClLpLockerTokenIds(client: PublicClient, locker: Address, opts: ScanOptions, poolId?: Hex): Promise<bigint[]> {\n const to = opts.toBlock ?? (await client.getBlockNumber());\n const minWindow = opts.minWindow ?? 2_000n;\n const seen = new Set<string>();\n const out: bigint[] = [];\n const scan = async (from: bigint, until: bigint): Promise<void> => {\n try {\n const found = await findClLpLockerTokenIds(client, locker, { fromBlock: from, toBlock: until }, poolId);\n for (const f of found) {\n const k = f.tokenId.toString();\n if (!seen.has(k)) {\n seen.add(k);\n out.push(f.tokenId);\n }\n }\n } catch (error) {\n const span = until - from + 1n;\n if (span <= minWindow) throw error;\n const mid = from + span / 2n;\n await scan(from, mid - 1n);\n await scan(mid, until);\n }\n };\n for (const w of blockWindows(opts.fromBlock, to, opts.window ?? 500_000n)) await scan(w.from, w.to);\n return out;\n}\n"],"names":["ChainConfigError","message","chainId","contract","ZERO","assertAddress","value","label","name","isAddress","checksummed","getAddress","assertValidChainConfig","config","requireContract","usedFor","nextBlockClock","pending","latest","defaultDeadline","nowSeconds","window","local","chain","chainDeadline","adapter","explorerTxUrl","hash","base","BPS_DENOMINATOR","MAX_INTEGRATOR_FEE_BPS","ZERO_ADDRESS","IntegratorConfigError","code","FEE_MODES","isKnownFeeMode","validateIntegratorConfig","feeBps","feeMode","warnings","rawReferrer","active","referrer","NO_INTEGRATOR_FEE","resolveIntegratorConfig","calculateIntegratorFee","grossAmount","splitIntegratorFee","integratorFee","formatBps","bps","percent","BPS","PIPS","MAX_SLIPPAGE_BPS","DEFAULT_SLIPPAGE_BPS","HIGH_PRICE_IMPACT_BPS","SEVERE_PRICE_IMPACT_BPS","assertNonNegative","assertBps","max","portionOf","amount","pipsOf","pips","minimumReceived","expected","slippageBps","maximumSpent","numerator","priceImpactBps","grossAmountOut","spotAmountOut","impact","priceImpactSeverity","buildQuoteBreakdown","input","amountIn","integrator","split","minAmountOutGross","minAmountOutNet","exchangeRate","decimalsIn","amountOut","decimalsOut","scaledIn","scaledOut","progressPercent","sold","total","capped","clampBigInt","min","floorTickToSpacing","tick","tickSpacing","ceilTickToSpacing","WidgetContext","createContext","WidgetProvider","props","defaultSlippageBps","theme","locale","onConnectRequest","children","resolvedIntegrator","useMemo","useEffect","warning","jsx","useWidgetContext","useContext","useOptionalWidgetContext","useProtocolAdapter","useIntegrator","NUMERIC","parseAmount","decimals","allowZero","trimmed","fraction","parseUnits","formatAmount","maxFractionDigits","negative","raw","formatUnits","whole","sign","groupThousands","epsilon","formatRate","rate","symbolIn","symbolOut","digits","formatPercentFromBps","formatPercentFromPips","trimTrailingZeros","shortAddress","address","formatDuration","totalSeconds","seconds","days","hours","minutes","secs","parts","formatTimestamp","unixSeconds","ms","COMMANDS","ACTIONS","MSG_SENDER","ADDRESS_THIS","OPEN_DELTA","CONTRACT_BALANCE","NATIVE_SENTINEL","BIN_DISTRIBUTION_SCALE","UNIVERSAL_ROUTER_ABI","POSITION_MANAGER_ABI","ERC20_ABI","PERMIT2_ABI","MAX_UINT160","MAX_UINT48","MAX_UINT256","ActionPlan","#steps","action","params","step","index","actions","concatHex","encodeAbiParameters","plan","POOL_KEY_COMPONENTS","SWAP_EXACT_IN_SINGLE_PARAMS","PATH_KEY_COMPONENTS","SWAP_EXACT_IN_PARAMS","CURRENCY_AND_UINT256","CURRENCY_ADDRESS_AND_UINT256","isNative","currency","isAddressEqual","isZeroForOne","hop","assertHopsConnected","hops","i","previous","current","assertUniformPoolType","first","encodeSingleHop","minOut","encodeMultiHop","buildSwapPlan","args","poolType","last","currencyIn","currencyOut","assertFeeArgs","single","p","recipientIsSender","takeRecipient","buildSwapCall","actionPlan","commandBytes","inputs","usePayPortion","sweepRecipient","commands","command","data","encodeFunctionData","expectedFee","launchGuardAbiFor","clock","LAUNCH_GUARD_HOOK_ABI","LAUNCH_GUARD_HOOK_BLOCK_ABI","LAUNCH_FEE_DENOMINATOR","decodeLaunchGuard","start","isLaunchConfigured","guard","launchFeeAt","now","elapsed","discount","launchScheduleAt","durationClock","end","feePips","maxBuyPerTx","evaluateLaunchBuy","schedule","hopIsLaunchBuy","zeroForOne","buildLaunchBuyCall","gate","swapArgs","toError","cause","useAsyncResource","loader","deps","options","enabled","refetchIntervalMs","status","setStatus","useState","setData","error","setError","updatedAt","setUpdatedAt","isRefreshing","setIsRefreshing","reloadToken","setReloadToken","mounted","useRef","requestId","loaderRef","refetch","useCallback","token","id","result","handle","UnsupportedOperationError","operation","detail","WalletNotConnectedError","NoRouteError","tokenIn","tokenOut","CORE_ERRORS_ABI","parseAbi","ERROR_ABI","seen","out","abi","CL_QUOTER_ABI","BIN_QUOTER_ABI","CL_POSITION_MANAGER_ABI","BIN_POSITION_MANAGER_ABI","BIN_LAUNCH_GUARD_HOOK_ABI","LATCH_POSITION_LOCK_ABI","LATCH_TOKEN_LOCK_ABI","item","key","EXPLANATIONS","revertDataOf","found","visit","record","v","inner","messageOf","inMessage","signature","BaseError","decodeRevertName","depth","decoded","decodeErrorResult","explainRevert","isUserRejection","hit","firstLine","line","describeError","context","useSwapExecute","quote","breakdown","setStep","txHash","setTxHash","prepared","setPrepared","approvalToken","setApprovalToken","account","approvalLoader","approvals","needsApproval","canExecute","approve","next","transaction","wrapped","execute","reset","effectiveStep","statusMessage","describeStep","isMock","mockPrefix","useSwapQuote","resource","useSlippageSetting","initialBps","setValue","setSlippageBps","isLaunchpadNotConfigured","resolveLaunchDataState","isLaunchKitNotConfigured","useLaunchList","useLaunchesForToken","useLaunch","poolId","buildLaunchView","launch","initialFeePips","finalFeePips","span","feeSpanProgressBps","useLaunchBuy","execution","useTokenList","useAccount","useTokenBalance","owner","usePools","usePoolState","pool","Q96","Q128","U256_MOD","MIN_TICK","MAX_TICK","RATIOS","getSqrtRatioAtTick","absTick","ratio","bit","factor","mulDivRoundingUp","a","b","denominator","product","divRoundingUp","sorted","getAmount0Delta","sqrtRatioAX96","sqrtRatioBX96","liquidity","roundUp","lower","upper","numerator1","numerator2","getAmount1Delta","getLiquidityForAmount0","amount0","intermediate","getLiquidityForAmount1","amount1","getLiquidityForAmounts","sqrtRatioX96","liquidity0","liquidity1","amountsForLiquidity","tickLower","tickUpper","adding","clRangeSide","pairedAmountForRange","entered","u256","uncollectedFees","currentTick","g0","g1","below0","below1","above0","above1","inside0","inside1","assertTickMathSelfConsistent","maxSqrtRatio","minSqrtRatio","isNativeToken","zeroAddress","depositRequirements","amount0Max","amount1Max","side","quoted","required","findShortfall","requirements","balances","requirement","balance","InsufficientBalanceError","tickSpacingOf","readCLPoolKeyParameters","binStepOf","readBinPoolKeyParameters","binTokenId","binId","encoded","keccak256","binShareAmounts","defaultRangeFor","activeId","widthFactor","spacing","halfWidth","adjustRange","range","deltaSteps","describeRange","count","useAddLiquidityQuote","amount0Desired","amount1Desired","useAddLiquidityExecute","amounts","requirementsKey","r","readShortfall","shortfallResource","insufficient","refetchShortfall","spender","second","short","describeLiquidityStep","usePositions","refreshKey","useRemoveLiquidity","position","percentBps","bumpOnConfirmed","bump","host","withdrawablePositions","list","reconcileSelection","fresh","isTokenListUrl","NATIVE","tokensFromMergedList","merged","stock","stockExtensionOf","entry","combineTokens","adapterTokens","listTokens","byAddress","t","existing","n","tokensFromLists","lists","mergeTokenLists","resolveLogoUrl","logoUrl","gateways","urls","ipfsToHttp","groupBySource","tokens","groups","source","EMPTY","keyOf","useTokenLists","state","setState","cancelled","s","fetchTokenList","e","settled","failures","l","normalizePair","pair","pairEntryAddress","pairKey","anchored","findToken","wanted","resolvePairEntry","orientPair","anchor","unorientPair","oriented","oppositeSide","DEFAULT_PORTIONS","NATIVE_GAS_RESERVE","normalizePortions","portions","portionLabel","balancePortion","portionAmountText","INITIAL_SWAP_STATE","initialSwapState","swapWidgetReducer","shown","routeSymbols","route","symbols","symbol","buildSwapQuoteView","DEFAULT_NATIVE","metaOf","client","native","erc20Abi","clLockerTokenIds","lp","toBlock","findClLpLockerTokenIds","x","fetchPoolLocks","positionLock","bin","readBinPoolPermanent","readChainNow","readAtMs","f","currency0","currency1","summarizePoolLocks","ids","summary","chainNow","readPoolLocks","perm","readClPoolPermanent","poolLocksEnabled","fetchTokenLocks","tokenLock","hasLp","meta","permanent","readCurrencyLocks","cl","readClLpLockerPositionsPriced","readBinLpLockerLocks","permanentTokenPools","lockPageUrl","siteUrl","target","opts","path","q","formatLockBps","frac","formatCountdown","d","h","m","sec","formatUtc","formatLockAmount","maxFrac","plural","one","many","poolBadgeView","hasPermanent","open","headline","binPoolBadgeView","c0","c1","bins","tokenBadgeView","lpLine","POSITION_STATUS_LABEL","TOKEN_STATUS_LABEL","vestedBps","advanceChainNow","nowMs","bpsOf","part","bar","of","poolShareBar","time","binShareBar","tokenShareBar","lpTotal","ts","vested","releaseSchedule","locks","samples","lo","hi","xs","sum","vestedAt","shareBarFromBps","poolEmbedView","tokenEmbedView","supply","blockWindows","from","to","size","scanClLpLockerTokenIds","locker","minWindow","scan","until","k","mid","w"],"mappings":"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"}
|