import { type Address, type Hex, type PublicClient } from 'viem'; import { V4_QUOTER_ABI } from './abis'; import { type TransactionRequest } from './build'; import { type ContractCall } from './reads'; import type { Uerc20Metadata } from './types'; /** * Instant Launch — the canonical preset + transaction assembler, mirroring `quickLaunch`'s role for * the CCA path. Launch params in → one signable transaction out. * * On-chain flow (hookless InstantLaunchStrategy): one `LiquidityLauncher.multicall` wrapping * 1. `createToken(uerc20Factory, name, symbol, 18, 1e27, launcher, tokenData)` * — mints the fixed 1B supply straight to the launcher, and * 2. `distributeToken(token, { strategy, amount: 1e27, * configData: abi.encode(InstantLaunchConfig{feeBeneficiary}) }, salt)` * — the strategy pulls the full supply, initializes the hookless native-ETH v4 pool * (LP_FEE=2500; TICK_SPACING and the price-fixing `initialTick` are per-generation — 25 and * 198,050 since the 2026-08-05 redeploy, 60 and 198,060 on every earlier generation), * optionally registers `feeBeneficiary` with the beneficiary vault (minting the transferable * beneficiary ERC721, keyed by the LP position's tokenId) and parks the single-sided LP NFT in * the strategy's FeeSplitter forever. `msg.value` is always 0. * * Creator fees are a **deployment variant, not a launch parameter**: each chain deploys two strategy * instances — one whose immutable `beneficiaryVault` is set (fees on) and one where it is zero (fees * off) — and the builder selects between them via `creatorFeesEnabled`. `configData` encodes * identically against both (the strategy requires a non-zero, non-launcher beneficiary either way); * on the fees-off instance the beneficiary is unused, so the builder encodes * {@link DISABLED_CREATOR_FEE_BENEFICIARY} internally. * * The token address is deterministic (CREATE2 keyed on name/symbol/decimals/creator/graffiti), * read from the factory's `getUERC20Address` view — see {@link predictInstantLaunchTokenAddressCall}. * * Addresses come from the `addresses.ts` Instant Launch deployment registry * (`INSTANT_LAUNCH_DEPLOYMENTS` / `INSTANT_LAUNCH_CONTRACTS`) — the one swap point for redeploys. */ /** * The fully-resolved Instant Launch stack for one (chain, creator-fee variant) pair: the * launcher-side contracts every launch uses plus the variant's strategy deployment and the chain * singletons. {@link getInstantLaunchAddresses} only resolves where the strategy variant is * deployed; `beneficiaryVault` and `compoundingClaimRecipient` are omitted on chains that do not * deploy those singletons (Arc has neither a fees-on vault nor a current compounding recipient). */ export interface InstantLaunchAddresses { /** LiquidityLauncher singleton — the `multicall` entrypoint the wallet calls. */ liquidityLauncher: Address; /** uERC20 token factory `createToken` targets. */ uerc20Factory: Address; /** The variant's hookless InstantLaunchStrategy (`Distribution.strategy`). */ strategy: Address; /** The strategy's immutable FeeSplitter — permanent LP-NFT custodian + fee distributor. */ feeSplitter: Address; /** * UERC20BeneficiaryVault singleton — the fee-beneficiary ERC721 registry + the creator share's * vault. Only the fees-on strategy registers beneficiaries with it. Optional: omitted on chains * with no fees-on FeeSplitter (Arc). */ beneficiaryVault?: Address; /** * CompoundingClaimRecipient singleton — the autocompound recipient of the chain's current * FeeSplitters. Optional: omitted on chains whose current splitters do not compound (Arc). */ compoundingClaimRecipient?: Address; /** BuybackAndBurnRecipient singleton, where the chain's current FeeSplitters forward to it. */ buybackAndBurnRecipient?: Address; /** Which variant this stack is ({@link InstantLaunchDeployment.creatorFeesEnabled}). */ creatorFeesEnabled: boolean; } /** * Returns the Instant Launch stack for a chain and creator-fee variant, or `undefined` where any * piece of it is not deployed. Derived from the deployment registry, never a second copy. */ export declare function getInstantLaunchAddresses(chainId: number, options: { creatorFeesEnabled: boolean; }): InstantLaunchAddresses | undefined; /** * Whether Instant Launch is deployed on `chainId` — i.e. {@link getInstantLaunchAddresses} resolves * for at least one creator-fee variant. */ export declare function isInstantLaunchSupportedChain(chainId: number): boolean; /** Factory tokens are fixed at 18 decimals (the strategy reverts otherwise). */ export declare const INSTANT_LAUNCH_TOKEN_DECIMALS = 18; /** Fixed, standardized total supply: 1,000,000,000 (1B) whole tokens (minted via the Token Factory). */ export declare const INSTANT_LAUNCH_TOTAL_SUPPLY = 1000000000n; /** * Total supply in raw base units, required exactly by InstantLaunchStrategy: 1B @ 18 decimals = 1e27. */ export declare const INSTANT_LAUNCH_TOTAL_SUPPLY_RAW: bigint; /** * The `feeBeneficiary` the builder encodes when `creatorFeesEnabled` is `false`. The strategy's * `InstantLaunchConfig{feeBeneficiary}` is **mandatory on every instance** — including the fees-off * one, where the value goes unused (its `beneficiaryVault` immutable is zero, so registration is * skipped entirely) — and the strategy reverts on a zero or launcher beneficiary either way. So the * placeholder must be a non-zero address that is not the LiquidityLauncher; it is deliberately a * protocol-owned contract (the current 4663 CompoundingClaimRecipient — the 2026-08-05 full * redeploy) rather than a user address, since it must never be mistaken for a creator claim. */ export declare const DISABLED_CREATOR_FEE_BENEFICIARY: Address; export interface PredictInstantLaunchTokenParams { chainId: number; /** Original creator (tx sender); folded into the CREATE2 graffiti. */ wallet: Address; name: string; symbol: string; } /** * The factory view descriptor for the deterministic new-token address — `predictTokenAddressCall` * preconfigured for Instant Launch (uERC20 factory, fixed 18 decimals, the launcher as the on-chain * `creator` since it is the factory's msg.sender inside the multicall; the wallet rides in the * graffiti). Variant-independent: both strategy instances launch the same token. Execute it with * `readContract` / `predictTokenAddress` or any rpc client. */ export declare function predictInstantLaunchTokenAddressCall(params: PredictInstantLaunchTokenParams): ContractCall; /** The creator-fee choice: on with an explicit beneficiary, or off (no beneficiary accepted). */ export type InstantLaunchCreatorFeeParams = { /** Launch through the fees-on strategy; `feeBeneficiary` receives the creator share. */ creatorFeesEnabled: true; /** LP-fee beneficiary — required; the strategy/vault revert on zero, the launcher, or the vault itself. */ feeBeneficiary: Address; } | { /** Launch through the fees-off strategy; 100% of fees autocompound. */ creatorFeesEnabled: false; /** Must be omitted — the builder encodes {@link DISABLED_CREATOR_FEE_BENEFICIARY} internally. */ feeBeneficiary?: undefined; }; export type BuildInstantLaunchParams = { chainId: number; name: string; symbol: string; /** Deterministic new-token address from {@link predictInstantLaunchTokenAddressCall}. */ predictedTokenAddress: Address; /** On-chain uERC20 metadata (`image` is the uploaded ipfs:// URL, '' when absent). */ metadata: Uerc20Metadata; /** bytes32 user salt (the singleton strategies ignore it, but the launcher call carries it). */ salt: Hex; } & InstantLaunchCreatorFeeParams; /** A signable Instant Launch transaction — the single launcher `multicall`, tagged with its chain. */ export interface InstantLaunchTransaction extends TransactionRequest { chainId: number; } /** * Pure assembler: builds the one-transaction Instant Launch multicall (createToken then * distributeToken; `value` is always 0). `creatorFeesEnabled` selects the strategy instance — * fees-on launches require a real `feeBeneficiary`, fees-off launches must not pass one (the * mandatory config field is filled with {@link DISABLED_CREATOR_FEE_BENEFICIARY}, which the fees-off * instance never reads). Mirrors the on-chain guards where they are cheap to check client-side (a * zero/launcher feeBeneficiary reverts in the strategy; the vault rejects itself at registration). */ export declare function buildInstantLaunchTransaction(params: BuildInstantLaunchParams): InstantLaunchTransaction; /** InstantLaunchStrategy's compile-time pool LP fee (pips) — `LP_FEE`, unchanged across deploys. */ export declare const INSTANT_LAUNCH_POOL_LP_FEE = 2500; /** * InstantLaunchStrategy's compile-time pool tick spacing — `TICK_SPACING`. Per-generation since the * 2026-08-05 chain-4663 full redeploy recompiled the strategy at 25 (every earlier generation is * 60; both values read back from the deployed strategies' `TICK_SPACING()` getters). This constant * is the CURRENT generation's value — the authoritative value for any strategy instance is * {@link InstantLaunchDeployment.tickSpacing} in the deployment registry, and a token's launch pool * keeps its minting generation's spacing forever (see * {@link INSTANT_LAUNCH_ALLOWED_POOL_TICK_SPACINGS}). */ export declare const INSTANT_LAUNCH_POOL_TICK_SPACING = 25; /** * Every tick spacing an Instant Launch pool has ever been minted at, newest first — the append-only * grandfather set (same shape as `QUICK_LAUNCH_ALLOWED_POOL_TICK_SPACINGS`). Pools are permanent, * so a superseded spacing never leaves this list; routing/discovery consumers deriving a token's * candidate launch pools must race a `(INSTANT_LAUNCH_POOL_LP_FEE, spacing)` key for EVERY entry * ({@link getInstantLaunchPoolKeys}), because the token address alone cannot say which generation * minted the pool. * Every entry is a pinned literal: if a future generation changes * {@link INSTANT_LAUNCH_POOL_TICK_SPACING}, the new spacing must be APPENDED here rather than a * derived entry silently replacing 25 — the tests asserting this set's contents force that append. * - 25: since the 2026-08-05 chain-4663 full redeploy ({@link INSTANT_LAUNCH_POOL_TICK_SPACING}). * - 60: every earlier generation. */ export declare const INSTANT_LAUNCH_ALLOWED_POOL_TICK_SPACINGS: readonly [25, 60]; /** The launch pool is hookless. */ export declare const INSTANT_LAUNCH_POOL_HOOKS: Address; /** The launch pool's raise currency: native ETH (address(0)), which always sorts as `currency0`. */ export declare const INSTANT_LAUNCH_POOL_CURRENCY0: Address; /** * InstantLaunchStrategy's compile-time lower tick of every launch position (`MIN_LAUNCH_TICK`) and * the exclusive floor for `initialTick`. Per-generation since the 2026-08-05 chain-4663 full * redeploy recompiled the strategy at -160,100 (every earlier generation is -208,980, the OZ H01 * floor; both values read back from the deployed strategies' `MIN_LAUNCH_TICK()` getters). This * constant is the CURRENT generation's value — the authoritative value for any strategy instance is * {@link InstantLaunchDeployment.minLaunchTick} in the deployment registry. */ export declare const INSTANT_LAUNCH_MIN_LAUNCH_TICK = -160100; /** * The current 4663 deployments' immutable `initialTick` — the aligned tick the launch pool opens at * (highest price; the launch position's upper bound). 198,050 since the 2026-08-05 full redeploy * (aligned to the new spacing 25; every earlier generation opened at 198,060, aligned to 60). A * per-deployment immutable, not a compile-time constant: the authoritative value for any strategy * instance is {@link InstantLaunchDeployment.initialTick} in the deployment registry. */ export declare const INSTANT_LAUNCH_INITIAL_TICK = 198050; /** A Uniswap v4 `PoolKey` struct mirror (currencies sorted ascending, as the PoolManager requires). */ export interface V4PoolKey { currency0: Address; currency1: Address; fee: number; tickSpacing: number; hooks: Address; } /** * The v4 pool an Instant Launch token trades in: hookless native-ETH pool at the strategy's * fee/spacing. Native ETH (address(0)) sorts below every token, so `currency0` is always ETH and an * ETH→token swap is always `zeroForOne`. The token address is EIP-55 normalized. Identical for both * creator-fee variants — but NOT across generations: `tickSpacing` defaults to the current * generation's {@link INSTANT_LAUNCH_POOL_TICK_SPACING}, so for a token launched before the * 2026-08-05 redeploy pass its minting generation's spacing (from * {@link InstantLaunchDeployment.tickSpacing} when the strategy is known, or race every candidate * via {@link getInstantLaunchPoolKeys}). */ export declare function getInstantLaunchPoolKey(token: Address, tickSpacing?: number): V4PoolKey; /** * Every launch pool the token COULD trade in, newest generation first — one candidate per * {@link INSTANT_LAUNCH_ALLOWED_POOL_TICK_SPACINGS} entry. Exactly one is initialized on-chain (the * minting generation's); when the minting strategy is unknown, quote/probe all of them and keep the * one that answers — the token address alone cannot say which generation minted the pool. */ export declare function getInstantLaunchPoolKeys(token: Address): readonly V4PoolKey[]; /** * The launch pool's v4 PoolId — `keccak256(abi.encode(poolKey))`, matching the on-chain * `PoolKey.toId()`. Use it with `slot0Call` / `isV4PoolInitialized` or any StateView read. * `tickSpacing` defaults to the current generation — same caveat as {@link getInstantLaunchPoolKey} * for tokens launched before the 2026-08-05 redeploy. */ export declare function getInstantLaunchPoolId(token: Address, tickSpacing?: number): Hex; export interface QuoteInstantLaunchBuyParams { /** The chain's v4 View Quoter (caller-supplied, like every read in `reads.ts`). */ v4Quoter: Address; /** The Instant Launch token being bought. */ token: Address; /** Exact ETH input, in wei. */ exactAmountInWei: bigint; /** * The launch pool's tick spacing — the minting generation's value. Defaults to the current * generation ({@link INSTANT_LAUNCH_POOL_TICK_SPACING}); pass 60 (or race every * {@link INSTANT_LAUNCH_ALLOWED_POOL_TICK_SPACINGS} entry) for tokens launched before the * 2026-08-05 redeploy. */ tickSpacing?: number; } /** * `V4Quoter.quoteExactInputSingle` descriptor for an exact-in ETH→token buy on the launch pool * (`zeroForOne` since ETH is always `currency0`; no hook data). The quoter quotes by * revert-and-catch, so execute this as an `eth_call` simulation (viem `readContract` / * {@link quoteInstantLaunchBuy}), never as a transaction. Returns `(amountOut, gasEstimate)`. */ export declare function quoteInstantLaunchBuyCall(params: QuoteInstantLaunchBuyParams): ContractCall; /** Executes {@link quoteInstantLaunchBuyCall} against a viem `PublicClient`. */ export declare function quoteInstantLaunchBuy(client: PublicClient, params: QuoteInstantLaunchBuyParams): Promise<{ amountOut: bigint; gasEstimate: bigint; }>;