Integrate @flaunch/sdk in TypeScript apps to read protocol data, launch coins, trade, manage Permit2 approvals, add liquidity, import tokens, and monitor events on Base and Base Sepolia.
Use this skill when the user needs to build, debug, or review app code using @flaunch/sdk.
This skill is the source-of-truth router for SDK work. Use references/launchpad-flow.md when the builder is assembling a launchpad or app flow around launches.
@flaunch/sdk.This section captures the minimum llms-full.txt context needed for most builder integrations, so this skill remains useful even when the large reference file is not available.
@flaunch/sdk is the TypeScript integration layer for Flaunch + Uniswap V4 interactions. It helps builders:
base) 8453baseSepolia) 84532Always confirm chain before reads/writes. Many integration failures are chain mismatches.
publicClientpublicClient and walletClientcreateFlaunch({ publicClient }) -> read workflowscreateFlaunch({ publicClient, walletClient }) -> read + write workflowsimport { createFlaunch } from '@flaunch/sdk'
import { createPublicClient, http } from 'viem'
import { base, baseSepolia } from 'viem/chains'
Use ReadWriteFlaunchSDK typing only when you specifically need write methods.
flaunchIPFS(...)flaunchIPFSWithRevenueManager(...), flaunchIPFSWithSplitManager(...), and flaunchIPFSWithDynamicSplitManager(...)data:image/...;base64,...)getPoolCreatedFromTx(hash)pollPoolCreatedNow(...)memecoin and tokenId after launch, not only tx hashgetBuyQuoteExactInput / getBuyQuoteExactOutputgetSellQuoteExactInputbuyCoin(...)sellCoin(...)parseSwapTx({ txHash, version, flETHIsCurrencyZero })buyCoin / sellCoin use slippagePercent (not slippageBps)getPermit2TypedData(coinAddress) returns { typedData, permitSingle }sellCoin(...) Permit2 flow expects permitSingle and signaturesetERC20AllowanceToPermit2(coinAddress, amount) is for external tokens when Permit2 allowance is insufficientgetAddLiquidityCalls(...) returns executable call objects (with descriptions)importMemecoin(...) takes coinAddress (not memecoin) in paramstokenImporterVerifyMemecoin(...) and isMemecoinImported(...) should be checked before import writesgetImportAndAddLiquidityCalls(...) builds a batch import + liquidity call sequencewatchPoolCreated, watchPoolSwappollPoolCreatedNow, pollPoolSwapNowThis skill is for SDK integration work, not product-specific ops runbooks.
references/launchpad-flow.md../api/SKILL.md../manager/SKILL.mdUse this before reading the full workflow sections.
| User intent | Workflow | Minimum inputs | Primary methods |
|---|---|---|---|
| Read coin metadata / info | setup-read | chain, publicClient, coinAddress | createFlaunch, getCoinMetadata, getCoinInfo |
| Launch a creator coin | setup-write + launch | chain, publicClient, walletClient, launch params, metadata | flaunchIPFS, getPoolCreatedFromTx |
| Buy a coin | setup-write + trade-buy-sell | chain, clients, coinAddress, amount, slippage | getBuyQuoteExactInput/Output, buyCoin, parseSwapTx |
| Sell a coin | setup-write + trade-buy-sell | chain, clients, coinAddress, amountIn, slippage | getSellQuoteExactInput, sellCoin, parseSwapTx |
| Sell with Permit2 | setup-write + permit2-sell | above + permit signature data | getPermit2TypedData, getPermit2AllowanceAndNonce, sellCoin |
| Add liquidity | setup-write + liquidity | chain, clients, coinAddress, liquidity params | calculateAddLiquidity*, getAddLiquidityCalls |
| Import token to flaunch | setup-write + import | chain, clients, coinAddress, import params | tokenImporterVerifyMemecoin, isMemecoinImported, importMemecoin |
| Import + add liquidity batch | setup-write + import + liquidity | above + liquidity params | getImportAndAddLiquidityCalls |
| Watch launch/swap events | events | chain, active SDK instance, callback | watchPoolCreated, watchPoolSwap, pollPool*Now |
| Build calldata only | calldata-mode | chain, call params | createFlaunchCalldata, call-build helpers |
| Debug failing integration | troubleshoot | failing call, chain, params, tx hash if any | isValidCoin, getCoinVersion, parsing + quote helpers |
Do:
coinAddress, slippagePercent, swapType)memecoin, tokenId, parsed swap logs) not just txHashDon't:
coin instead of coinAddress)parseSwapTx(txHash) directly (use object form)pollPool*Now as data-returning methodsPick the smallest workflow that satisfies the user request:
setup-read for read-only analytics or metadata.setup-write for transactions.launch for creating a memecoin pool.trade-buy-sell for swaps and quote flows.permit2-sell for approval-light selling.liquidity for add-liquidity planning and calldata.import for external token import and post-import liquidity.events for watchers and polling loops.calldata-mode for AA, relayers, or batched execution.troubleshoot for reverts, mismatched chain/state, and version issues.walletClient bound to the intended chain.flaunchIPFS.coinAddress, slippagePercent, swapType) over shorthand placeholders.| Workflow | chain | publicClient | walletClient | coinAddress | Slippage | Version | Approval / Permit |
|---|---|---|---|---|---|---|---|
setup-read | Yes | Yes | No | Optional | No | Optional | No |
setup-write | Yes | Yes | Yes | No | No | No | No |
launch | Yes | Yes | Yes | No | Optional | Optional | No |
trade-buy-sell (buy) | Yes | Yes | Yes | Yes | Yes | Optional | Sometimes |
trade-buy-sell (sell) | Yes | Yes | Yes | Yes | Yes | Optional | Yes (Permit2 path) |
permit2-sell | Yes | Yes | Yes | Yes | Yes | Optional | Yes |
liquidity | Yes | Yes | Yes | Yes | Recommended | Optional | Usually |
import | Yes | Yes | Yes | Yes | No | Optional | No |
events | Yes | Usually | No | Optional | No | Often | No |
calldata-mode | Yes | Optional | No | Depends | Depends | Optional | Depends |
Use these when a builder asks to "get something working" quickly.
Required inputs:
base or baseSepolia)coinAddress (if reading coin-specific data)Minimum outcome:
createFlaunch({ publicClient }) worksStarter snippet:
import { createFlaunch } from '@flaunch/sdk'
import { createPublicClient, http } from 'viem'
import { base } from 'viem/chains'
const publicClient = createPublicClient({
chain: base,
transport: http(process.env.RPC_URL),
})
const flaunch = createFlaunch({ publicClient })
const metadata = await flaunch.getCoinMetadata('0x...')
console.log(metadata)
Common mistakes:
walletClient)Required inputs:
base or baseSepolia)publicClientwalletClient on the same chainMinimum outcome:
Starter snippet:
import { createFlaunch, type ReadWriteFlaunchSDK } from '@flaunch/sdk'
const flaunch = createFlaunch({
publicClient,
walletClient,
}) as ReadWriteFlaunchSDK
const [walletChainId, [account]] = await Promise.all([
walletClient.getChainId(),
walletClient.getAddresses(),
])
if (walletChainId !== publicClient.chain.id) {
throw new Error('wallet/public client chain mismatch')
}
console.log('Signer:', account)
Common mistakes:
walletClient connected to a different chain than publicClientbuyCoin/flaunchIPFS on an SDK instance created without walletClientRequired inputs:
name, symbol, creatorfairLaunchPercent, duration, market cap)base64Image, description)Minimum outcome:
flaunchIPFSgetPoolCreatedFromTxCommon mistakes:
base64Image format (must be a valid data URL when using upload path)memecoin / tokenIdRequired inputs:
Minimum outcome:
Common mistakes:
For builder-facing answers, default to this shape:
Use this as a fast routing table before searching docs.
getCoinMetadata, getCoinInfo, getCoinVersiongetMarketContext, coinPriceInETH, coinPriceInUSD, coinMarketCapInUSDgetFairLaunch, fairLaunchInfo, isFairLaunchActiveflaunchIPFS, flaunch, flaunchIPFSWithRevenueManager, flaunchIPFSWithSplitManagerflaunchWithDynamicSplitManager, flaunchIPFSWithDynamicSplitManagerdeployRevenueManagergetRevenueManagerBalances, getRevenueManagerProtocolBalances, getRevenueManagerTokensCount, getRevenueManagerAllTokensByCreator, getRevenueManagerAllTokensInManagerrevenueManagerProtocolClaim, revenueManagerCreatorClaim, revenueManagerCreatorClaimForTokensReadDynamicAddressFeeSplitManager, allRecipients, recipientCount, recipientAt, recipients, totalActiveSharesReadWriteDynamicAddressFeeSplitManager, updateRecipients, setModerator, transferRecipientShare, claimForDatagetPoolCreatedFromTx, pollPoolCreatedNow, watchPoolCreatedgetBuyQuoteExactInput, getBuyQuoteExactOutputgetSellQuoteExactInputbuyCoin, sellCoinparseSwapTx, pollPoolSwapNow, watchPoolSwapgetERC20AllowanceToPermit2, getPermit2AllowanceAndNonce, getPermit2TypedData, setERC20AllowanceToPermit2calculateAddLiquidityTicks, calculateAddLiquidityAmounts, checkSingleSidedAddLiquiditygetAddLiquidityCalls, getSingleSidedCoinAddLiquidityCallstokenImporterVerifyMemecoin, isMemecoinImported, importMemecoingetImportAndAddLiquidityCalls, getImportAndSingleSidedCoinAddLiquidityCallscreateFlaunchCalldata (+ call-building helpers)Use these when the user asks for a concrete starting point. These examples are aligned to current public method names/argument shapes in src/sdk/FlaunchSDK.ts.
Confidence labels:
Verified Recipe: argument names and method shapes checked against current SDK sourceOutline: flow is correct, but params may need adaptation to the user’s exact version/setupUse this compact index before diving into examples.
buyCoin(params: BuyCoinParams, version?: FlaunchVersion)sellCoin(params: SellCoinParams, version?: FlaunchVersion)getBuyQuoteExactInput({ coinAddress, amountIn, version?, intermediatePoolKey?, hookData?, userWallet? })getBuyQuoteExactOutput({ coinAddress, amountOut, version?, intermediatePoolKey?, hookData?, userWallet? })getSellQuoteExactInput({ coinAddress, amountIn, version?, intermediatePoolKey? })parseSwapTx({ txHash, version, flETHIsCurrencyZero? })getPermit2TypedData(coinAddress, deadline?) -> { typedData, permitSingle }getPermit2AllowanceAndNonce(coinAddress) -> { allowance, nonce }setERC20AllowanceToPermit2(coinAddress, amount)importMemecoin({ coinAddress, creatorFeeAllocationPercent, initialMarketCapUSD | initialPriceUSD, verifier? })getAddLiquidityCalls(params: GetAddLiquidityCallsParams) -> CallWithDescription[]getImportAndAddLiquidityCalls(params: ImportAndAddLiquidity*) -> CallWithDescription[]watchPoolSwap(params, version?) -> { cleanup, pollPoolSwapNow }pollPoolSwapNow(version?) -> Promise<void> | undefined (triggers callbacks)buyCoin (EXACT_IN) + quote + parseLabel: Verified Recipe
import { createFlaunch } from '@flaunch/sdk'
import type { Address } from 'viem'
const coinAddress = '0x...' as Address
const quoteOut = await flaunch.getBuyQuoteExactInput({
coinAddress,
amountIn: 1000000000000000n, // 0.001 ETH (or input token via intermediatePoolKey)
})
const txHash = await flaunch.buyCoin({
coinAddress,
swapType: 'EXACT_IN',
amountIn: 1000000000000000n,
slippagePercent: 5, // 5%
})
const version = await flaunch.getCoinVersion(coinAddress)
const parsed = await flaunch.parseSwapTx({
txHash,
version,
flETHIsCurrencyZero: flaunch.flETHIsCurrencyZero(coinAddress),
})
console.log({ quoteOut, txHash, parsed })
sellCoin with Permit2 (getPermit2TypedData + permitSingle)Label: Verified Recipe
import { maxUint256 } from 'viem'
import type { Address } from 'viem'
const coinAddress = '0x...' as Address
const amountIn = 1_000_000n
// For external tokens (non-flaunch memecoins), approve Permit2 first if needed
const allowance = await flaunch.getERC20AllowanceToPermit2(coinAddress)
if (allowance < amountIn) {
await flaunch.setERC20AllowanceToPermit2(coinAddress, maxUint256)
}
const { typedData, permitSingle } = await flaunch.getPermit2TypedData(coinAddress)
const signature = await walletClient.signTypedData(typedData)
const quoteOut = await flaunch.getSellQuoteExactInput({
coinAddress,
amountIn,
})
const txHash = await flaunch.sellCoin({
coinAddress,
amountIn,
slippagePercent: 5,
permitSingle,
signature,
})
const version = await flaunch.getCoinVersion(coinAddress)
const parsed = await flaunch.parseSwapTx({
txHash,
version,
flETHIsCurrencyZero: flaunch.flETHIsCurrencyZero(coinAddress),
})
console.log({ quoteOut, txHash, parsed })
getAddLiquidityCalls (market cap constrained)Label: Verified Recipe
import { LiquidityMode } from '@flaunch/sdk'
import { parseEther } from 'viem'
import type { Address } from 'viem'
const coinAddress = '0x...' as Address
const calls = await flaunch.getAddLiquidityCalls({
coinAddress,
liquidityMode: LiquidityMode.CONCENTRATED,
coinOrEthInputAmount: parseEther('1'),
inputToken: 'eth',
minMarketCap: '10000',
maxMarketCap: '100000',
initialMarketCapUSD: 50000,
slippagePercent: 5,
})
console.log(calls) // array of { to, data, value?, description? }
importMemecoin (direct write)Label: Verified Recipe
import { Verifier } from '@flaunch/sdk'
import type { Address } from 'viem'
const coinAddress = '0x...' as Address
const isImported = await flaunch.isMemecoinImported(coinAddress)
if (!isImported) {
const verify = await flaunch.tokenImporterVerifyMemecoin(coinAddress)
if (!verify.isValid) throw new Error('Coin is not importable')
const txHash = await flaunch.importMemecoin({
coinAddress,
verifier: Verifier.CLANKER,
creatorFeeAllocationPercent: 5,
initialMarketCapUSD: 50000,
})
console.log({ txHash })
}
getImportAndAddLiquidityCalls (batch call builder)Label: Verified Recipe
import { LiquidityMode, Verifier } from '@flaunch/sdk'
import { parseEther } from 'viem'
import type { Address } from 'viem'
const coinAddress = '0x...' as Address
const calls = await flaunch.getImportAndAddLiquidityCalls({
coinAddress,
verifier: Verifier.CLANKER,
creatorFeeAllocationPercent: 5,
liquidityMode: LiquidityMode.CONCENTRATED,
coinOrEthInputAmount: parseEther('1'),
inputToken: 'eth',
minMarketCap: '10000',
maxMarketCap: '100000',
initialMarketCapUSD: 50000,
slippagePercent: 5,
})
console.log(calls)
Run this checklist whenever a read/write behaves unexpectedly.
base vs baseSepolia) in plain text.publicClient.chain.id.walletClient.getChainId() (for write flows).getPoolCreatedFromTx, parseSwapTx) with the same tx hash on the correct chain client.Goal: initialize a read-only SDK safely.
publicClient on user-selected chain.createFlaunch({ publicClient }).getCoinMetadata, getFlaunchAddress, or getMarketContext.Detailed steps:
base or baseSepolia) from user request.publicClient with http(<RPC_URL>); if no RPC is provided, mention public RPC fallback may be rate-limited.createFlaunch({ publicClient }).getCoinMetadata(coinAddress) when a coin address is knowngetMarketContext(...) for price/context workflowsgetFlaunchAddress() / getPositionManagerAddress() for chain sanity checksCommon mistakes and fixes:
InvalidAddressError or empty metadata: verify the coin exists on the selected chain.publicClient is available: switch to setup-write.Deliverables:
Goal: enable state-changing SDK actions.
walletClient and instantiate read-write SDK.Detailed steps:
setup-read.walletClient exists and is connected.createFlaunch({ publicClient, walletClient })).walletClient.getChainId() matches publicClient.chain.idwalletClient.getAddresses())Common mistakes and fixes:
walletClient.Deliverables:
Goal: launch a new token correctly and extract resulting identifiers.
name, symbol, metadata, market cap, launch settings).flaunchIPFS (or relevant flaunch* variant).getPoolCreatedFromTx and return memecoin + tokenId.Detailed steps:
name, symbol, creatorinitialMarketCapUSDfairLaunchPercent, fairLaunchDuration)creatorFeeAllocationPercent or manager-aware launch path)data:image/png;base64,...)flaunchIPFS (common path)flaunchIPFSWithRevenueManager when launching directly into an existing revenue manager instanceflaunchIPFSWithSplitManager when using the static split-manager pathflaunchIPFSWithDynamicSplitManager when recipient membership or share weights must remain mutable after launchgetPoolCreatedFromTx(hash)memecoin, tokenId, and key launch metadatapollPoolCreatedNow as fallback.Manager-aware launch notes:
flaunchWithSplitManager normalizes recipient percentages into 5-decimal sharesflaunchWithDynamicSplitManager expects raw recipient weights, validates duplicate recipients, and requires a nonzero moderatordeployRevenueManager creates a manager instance before launch; flaunchWithRevenueManager launches directly into that instanceMinimal pattern:
const hash = await flaunch.flaunchIPFS({
name,
symbol,
creator,
fairLaunchPercent: 0,
fairLaunchDuration: 30 * 60,
initialMarketCapUSD: 10_000,
creatorFeeAllocationPercent: 80,
metadata: { base64Image, description },
})
const created = await flaunch.getPoolCreatedFromTx(hash)
if (!created) throw new Error('PoolCreated not found for launch tx')
console.log(created.memecoin, created.tokenId)
Common mistakes and fixes:
PoolCreated parse returns null: wrong chain client, tx not final yet, or wrong hash.Deliverables:
Goal: buy/sell with predictable slippage and result parsing.
getBuyQuote... or getSellQuote...).buyCoin or sellCoin with explicit slippage controls.parseSwapTx, related log parsing).Detailed steps:
getBuyQuoteExactInput / getBuyQuoteExactOutputgetSellQuoteExactInputbuyCoin / sellCoin.parseSwapTx (or related parsing helpers) and return normalized results.Minimal pattern:
const quote = await flaunch.getBuyQuoteExactInput({
coinAddress,
amountIn,
})
const txHash = await flaunch.buyCoin({
coinAddress,
swapType: 'EXACT_IN',
amountIn,
slippagePercent: 5,
})
const version = await flaunch.getCoinVersion(coinAddress)
const parsed = await flaunch.parseSwapTx({
txHash,
version,
flETHIsCurrencyZero: flaunch.flETHIsCurrencyZero(coinAddress),
})
console.log({ quote, txHash, parsed })
Common mistakes and fixes:
Deliverables:
Goal: sell using Permit2 rather than standalone token approval flow.
getERC20AllowanceToPermit2 and nonce helpers as needed).getPermit2TypedData) and sign it.Detailed steps:
getPermit2AllowanceAndNonce, related helpers).getPermit2TypedData.Common mistakes and fixes:
setERC20AllowanceToPermit2) first when needed.Minimal pattern (outline; exact params vary by sell method signature):
const permitState = await flaunch.getPermit2AllowanceAndNonce(coinAddress)
if (permitState.allowance < amountIn) {
await flaunch.setERC20AllowanceToPermit2(coinAddress, maxUint256)
}
const { typedData, permitSingle } = await flaunch.getPermit2TypedData(coinAddress)
const signature = await walletClient.signTypedData(typedData)
// Pass `permitSingle` + `signature` into `sellCoin(...)`
Deliverables:
Goal: add liquidity safely for flaunch/imported tokens.
calculateAddLiquidityTicks, calculateAddLiquidityAmounts).checkSingleSidedAddLiquidity) if applicable.getAddLiquidityCalls, single-sided or batch variants) and execute or return calldata.Detailed steps:
calculateAddLiquidityTickscalculateAddLiquidityAmountscheckSingleSidedAddLiquidity for one-sided depositsgetAddLiquidityCallsgetSingleSidedCoinAddLiquidityCallsCommon mistakes and fixes:
Minimal pattern:
const ticks = await flaunch.calculateAddLiquidityTicks({
coinAddress,
// price/market cap or explicit tick inputs depending on path
})
const amounts = await flaunch.calculateAddLiquidityAmounts({
coinAddress,
...ticks,
// desired deposit inputs
})
const calls = await flaunch.getAddLiquidityCalls({
coinAddress,
...amounts,
...ticks,
})
console.log(calls) // execute or pass to external executor
Deliverables:
Goal: import external token into flaunch ecosystem and optionally add liquidity.
tokenImporterVerifyMemecoin, isMemecoinImported).importMemecoin.getImportAndAddLiquidityCalls or single-sided variant.Detailed steps:
tokenImporterVerifyMemecoinisMemecoinImportedimportMemecoin.getImportAndAddLiquidityCallsgetImportAndSingleSidedCoinAddLiquidityCallsCommon mistakes and fixes:
Minimal pattern:
const isImported = await flaunch.isMemecoinImported(coinAddress)
if (!isImported) {
const verify = await flaunch.tokenImporterVerifyMemecoin(coinAddress)
if (!verify.isValid) throw new Error('Coin is not importable')
const hash = await flaunch.importMemecoin({
coinAddress,
creatorFeeAllocationPercent: 5,
initialMarketCapUSD: 50000,
})
console.log('import tx', hash)
}
const batchCalls = await flaunch.getImportAndAddLiquidityCalls({
coinAddress,
// import + liquidity params
})
Deliverables:
Goal: support realtime UX/bots/indexers around pool lifecycle and swaps.
watchPoolCreated/watchPoolSwap.pollPoolCreatedNow/pollPoolSwapNow) to force an immediate check.Detailed steps:
watchPoolCreated / watchPoolSwap for frontend/live UX.pollPoolCreatedNowpollPoolSwapNowCommon mistakes and fixes:
Minimal pattern (frontend watcher + immediate poll trigger):
const sub = await flaunch.watchPoolSwap({
// filterByCoin is supported by the SDK wrapper
filterByCoin: coinAddress,
onPoolSwap: ({ logs, isFetchingFromStart }) => {
console.log('swap logs', { logs, isFetchingFromStart })
},
})
// Optional: trigger an immediate poll cycle after subscribing
await sub.pollPoolSwapNow()
// or via SDK wrapper (works only when an active watcher has registered the poller)
await flaunch.pollPoolSwapNow()
// later (React cleanup / teardown)
sub.cleanup()
Minimal pattern (backend service pattern):
const sub = await flaunch.watchPoolSwap({
filterByCoin: coinAddress,
onPoolSwap: ({ logs }) => {
if (logs.length) console.log('new swaps', logs)
},
})
// trigger checks on your own schedule (callback receives results)
await flaunch.pollPoolSwapNow()
// shutdown
sub.cleanup()
Deliverables:
pollPool*Now triggers callbacks and returns Promise<void>.Goal: support smart accounts, relayers, or external executors.
createFlaunchCalldata and related call-build helpers.{ to, data, value } plus user-safe notes on signer, chain, and expected effects.Detailed steps:
createFlaunchCalldata{ to, data, value } and document:
Common mistakes and fixes:
value.Deliverables:
Goal: quickly isolate failing integration paths.
Check in this order:
isValidCoin, version detection helpers).Add workflow-specific checks:
Deliverables:
When using this skill, prefer responses that include:
When returning results to builders, include these fields when available.
setup-read: chain, method called, returned shape/sample fieldssetup-write: chain, signer address, confirmation that read-write SDK instance was createdlaunch: txHash, memecoin, tokenId, poolId (if parsed), chaintrade-buy-sell: txHash, quote result, parsed swap summary (type, amounts/fees), chainpermit2-sell: allowance/nonce check summary, permit generated (yes/no), txHash, parsed swap summaryliquidity: computed ticks/amounts summary, number of calls generated, any approvals requiredimport: import status (already imported vs imported now), txHash if write executed, batch call count if builtevents: subscription status, callback shape, whether immediate poll trigger is availablecalldata-mode: to, data, value, intended chain, expected executor/signertroubleshoot: root cause hypothesis, failing precondition, minimal fixIf the user is building from scratch, prefer this order:
setup-readsetup-writelaunch or trade-buy-sell)events for observabilitytroubleshoot only if neededpublicClient, walletClient, and target contract address.llms-full.txt as runtime logic instead of reference material.Ask before proceeding when any of these are missing or ambiguous in a write or money-sensitive flow:
base vs baseSepolia)coinAddress or target token identityReasonable defaults are acceptable for low-risk read examples, but state them explicitly.
This skill includes a mix of:
Verified Recipe sections checked against current SDK source on this branchOutline sections that describe correct flow but may need parameter adaptationRevalidate against src/sdk/FlaunchSDK.ts and src/types.ts if the SDK version changes.
Use these files as needed; do not duplicate large sections into responses.
FlaunchSDK.ts (method signatures / docs): src/sdk/FlaunchSDK.tstypes.ts (exported SDK types): src/types.ts