> For the complete documentation index, see [llms.txt](https://docs.doppler.lol/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.doppler.lol/reference/api-reference.md).

# SDK API

***

## DopplerSDK (EVM)

The top-level entry point for all EVM SDK operations. Import from `@whetstone-research/doppler-sdk`.

```ts
import { DopplerSDK } from '@whetstone-research/doppler-sdk'

const sdk = new DopplerSDK({
  publicClient,   // viem PublicClient
  walletClient,   // viem WalletClient (optional for read-only)
  chainId,        // SupportedChainId
})
```

### Builder shortcuts

```ts
sdk.buildStaticAuction()       // → StaticAuctionBuilder<C>
sdk.buildDynamicAuction()      // → DynamicAuctionBuilder<C>
sdk.buildMulticurveAuction()   // → MulticurveBuilder<C>
sdk.buildOpeningAuction()      // → OpeningAuctionBuilder<C>
```

### Token / governance helpers

| Method                           | Returns                                                   |
| -------------------------------- | --------------------------------------------------------- |
| `getAirlockOwner()`              | `Promise<Address>`                                        |
| `getAirlockBeneficiary(shares?)` | `Promise<BeneficiaryData>` — defaults to 5% (0.05e18 WAD) |
| `getPoolInfo(poolAddress)`       | `Promise<PoolInfo>`                                       |
| `getHookInfo(hookAddress)`       | `Promise<HookInfo>`                                       |

### Entity getters

These return entity instances bound to a specific on-chain address.

| Method                                                                                                       | Returns                                                                                       |
| ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------- |
| `getStaticAuction(poolAddress)`                                                                              | `Promise<StaticAuction>`                                                                      |
| `getDynamicAuction(hookAddress)`                                                                             | `Promise<DynamicAuction>`                                                                     |
| `getMulticurvePool(tokenAddress)`                                                                            | `Promise<MulticurvePool>`                                                                     |
| `getRehypeDopplerHook(hookAddress)`                                                                          | `Promise<RehypeDopplerHook>`                                                                  |
| `getOpeningAuction(hookAddress)`                                                                             | `Promise<OpeningAuction>`                                                                     |
| `getOpeningAuctionLifecycle(initializerAddress?)`                                                            | `Promise<OpeningAuctionLifecycle>` — falls back to chain config; throws if unconfigured       |
| `getOpeningAuctionPositionManager(positionManagerAddress?)`                                                  | `Promise<OpeningAuctionPositionManager>` — falls back to chain config; throws if unconfigured |
| `getOpeningAuctionBidManager({ openingAuctionHookAddress, openingAuctionPoolKey, positionManagerAddress? })` | `Promise<OpeningAuctionBidManager>`                                                           |
| `getDerc20(tokenAddress)`                                                                                    | `Derc20`                                                                                      |

***

## Builder API Reference

Builders assemble type‑safe parameter objects for `DopplerFactory.createStaticAuction`, `DopplerFactory.createDynamicAuction`, and `DopplerFactory.createMulticurve`.

* Static auctions: Uniswap V3 style, fixed price range liquidity bootstrapping
* Dynamic auctions: Uniswap V4 hook, dynamic Dutch auction with epoch steps
* Multicurve auctions: Uniswap V4 initializer with multiple curves

### Common Concepts

* Governance defaults to `noOp` on supported chains (all except Ink)
* Fee tiers and tick spacing: 100→1, 500→10, 3000→60, 10000→200

***

## StaticAuctionBuilder

Methods (chainable):

* `tokenConfig({ name, symbol, tokenURI, yearlyMintRate? })`
* `saleConfig({ initialSupply, numTokensToSell, numeraire })`
* `withMarketCapRange({ marketCap: { start, end }, numerairePrice, fee?, numPositions?, maxShareToBeSold? })`
  * `marketCap.start` and `marketCap.end` are fully diluted market caps in USD (or whatever unit your numeraire is priced in)
  * Requires `saleConfig()` first
* `poolByTicks({ startTick, endTick, fee?, numPositions?, maxShareToBeSold? })`
* `withVesting({ duration?, cliffDuration?, recipients?, amounts? })`
* `withGovernance({ type: 'default' | 'custom' | 'noOp' })`
* `withMigration(MigrationConfig)`
* `withUserAddress(address)`
* `build()` → `CreateStaticAuctionParams`

***

## DynamicAuctionBuilder

Methods (chainable):

* `tokenConfig({ name, symbol, tokenURI, yearlyMintRate? })`
* `saleConfig({ initialSupply, numTokensToSell, numeraire? })`
* `poolConfig({ fee, tickSpacing })`
* `withMarketCapRange({ marketCap: { start, min }, numerairePrice, minProceeds, maxProceeds, duration?, epochLength? })`
  * `marketCap.start` is the starting market cap (auction begins here), `marketCap.min` is the floor price the auction descends to
  * Both values are fully diluted market caps in USD (or whatever unit your numeraire is priced in)
  * Requires `saleConfig()` first (do NOT use `poolConfig()` with this method - they are mutually exclusive)
* `auctionByTicks({ startTick, endTick, minProceeds, maxProceeds, duration?, epochLength?, gamma? })`
* `withVesting({ duration?, cliffDuration?, recipients?, amounts? })`
* `withGovernance({ type: 'default' | 'custom' | 'noOp' })`
* `withMigration(MigrationConfig)`
* `withUserAddress(address)`
* `withTime({ startTimeOffset?, blockTimestamp? })`
* `build()` → `CreateDynamicAuctionParams`

***

## MulticurveBuilder

Methods (chainable):

* `tokenConfig({ name, symbol, tokenURI, yearlyMintRate? })`
* `saleConfig({ initialSupply, numTokensToSell, numeraire })`
* `withCurves({ numerairePrice, curves, fee?, tickSpacing?, beneficiaries? })`
  * Requires `saleConfig()` first
  * `curves`: Array of `{ marketCap: { start, end }, numPositions, shares }`
  * `marketCap.start` and `marketCap.end` are fully diluted market caps in USD (or whatever unit your numeraire is priced in)
  * Shares must sum to 1e18 (100%)
* `poolConfig({ fee, tickSpacing, curves, beneficiaries? })`
  * `curves`: Array of `{ tickLower, tickUpper, numPositions, shares }`
* `withRehypeDopplerHook({ hookAddress, buybackDestination, customFee, assetBuybackPercentWad, numeraireBuybackPercentWad, beneficiaryPercentWad, lpPercentWad, graduationCalldata? })`
  * `hookAddress` — Deployed RehypeDopplerHook (must be whitelisted)
  * `buybackDestination` — Receives bought-back tokens
  * `customFee` — Swap fee in bps (3000 = 0.3%)
  * `assetBuybackPercentWad` — % for asset buyback (WAD, 1e18 = 100%)
  * `numeraireBuybackPercentWad` — % for numeraire buyback (WAD)
  * `beneficiaryPercentWad` — % for beneficiaries (WAD)
  * `lpPercentWad` — % for LPs (WAD)
  * `graduationCalldata` — Optional calldata executed on graduation
* `withVesting({ duration?, cliffDuration?, recipients?, amounts? })`
* `withGovernance({ type: 'default' | 'custom' | 'noOp' })`
* `withMigration(MigrationConfig)`
* `withUserAddress(address)`
* `build()` → `CreateMulticurveParams`

### Multicurve rules

* First curve's `marketCap.start` = the launch price
* Curves must be contiguous or overlapping (no gaps)
* Shares must sum to exactly 1e18 (100%)

***

## OpeningAuctionBuilder

An auction used to place single sided LP positions in advance of a Doppler Dynamic auction. It can be used to mitigate sniping or more effectively set the clearing price prior to other price discovery auctions. Obtain via `sdk.buildOpeningAuction()`.

Methods (chainable):

* `tokenConfig(params)` — standard or doppler404 token
  * Standard: `{ name, symbol, tokenURI, yearlyMintRate? }`
  * Doppler404: `{ type: 'doppler404', name, symbol, baseURI, unit? }`
* `saleConfig({ initialSupply, numTokensToSell, numeraire })` — `numTokensToSell ≤ initialSupply`
* `openingAuctionConfig(params: OpeningAuctionConfig)`:
  * `auctionDuration` — opening auction duration in seconds (positive integer)
  * `tickSpacing` — opening auction pool tick spacing
  * `fee` — opening auction pool fee (0–`V4_MAX_FEE`)
  * `minAcceptableTickToken0` / `minAcceptableTickToken1` — int24 price floor/ceiling
  * `minLiquidity` — minimum liquidity the auction must attract (bigint, positive)
  * `shareToAuctionBps` — share of `numTokensToSell` allocated to the opening pool (1–10000)
  * `incentiveShareBps` — bidder incentive share in bps (0–10000)
* `dopplerConfig(params: OpeningAuctionDopplerConfig)`:
  * `minProceeds`, `maxProceeds` — soft and hard raise targets (bigint)
  * `startTick`, `endTick` — Doppler price range (direction depends on numeraire token ordering)
  * `duration?` — Doppler auction duration in seconds
  * `epochLength?` — Doppler epoch length in seconds; must divide `duration` evenly
  * `gamma?` — tick step per epoch; computed optimally when omitted
  * `numPdSlugs?` — number of price-discovery slugs
  * `fee?` — Doppler pool fee
  * `tickSpacing?` — Doppler pool tick spacing; must divide `openingAuction.tickSpacing` evenly
* `withVesting({ duration?, cliffDuration?, recipients?, amounts? })`
* `withGovernance(params: GovernanceOption<C>)` — `{ type: 'default' | 'noOp' | 'launchpad' | 'custom' }`
* `withMigration(migration: MigrationConfig)` — required; e.g. `{ type: 'uniswapV2' }`
* `withUserAddress(address)` — required
* `withIntegrator(address?)` — optional integrator fee recipient
* `withGasLimit(gas?)` — optional gas override (bigint)
* `withTime({ startTimeOffset?, startingTime?, blockTimestamp? })` — mutually exclusive: use `startTimeOffset` (seconds from now) or `startingTime` (absolute unix timestamp or Date)
* Module overrides (advanced): `withOpeningAuctionInitializer(address)`, `withOpeningAuctionPositionManager(address)`, `withAirlock(address)`, `withTokenFactory(address)`, `withDopplerDeployer(address)`, `withGovernanceFactory(address)`, `withV2Migrator(address)`, `withV4Migrator(address)`, `withNoOpMigrator(address)`
* `build()` → `CreateOpeningAuctionParams` — validates all constraints; throws descriptive errors on invalid config

Factory method:

```ts
const { hookAddress, tokenAddress, poolId } = await sdk.factory.createOpeningAuction(params)
```

***

## Factory methods

```ts
const { poolAddress, tokenAddress } = await sdk.factory.createStaticAuction(params)
const { hookAddress, tokenAddress, poolId } = await sdk.factory.createDynamicAuction(params)
const { poolId, tokenAddress } = await sdk.factory.createMulticurve(params)
const { hookAddress, tokenAddress, poolId } = await sdk.factory.createOpeningAuction(params)
```

***

## Solana SDK

Import Solana helpers from the package subpath:

```ts
import {
  cpmm,
  cpmmMigrator,
  initializer,
  deriveSolanaCpmmDeployment,
  DOPPLER_SOLANA_DEVNET_PROGRAM_ADDRESSES,
} from '@whetstone-research/doppler-sdk/solana'
```

### Initializer

The `initializer` namespace handles Doppler launches on Solana.

**`createInitializeLaunchInstruction(accounts, args)`**

Builds the on-chain instruction for a new Doppler launch.

Accounts (key fields):

| Account                                  | Description                                                       |
| ---------------------------------------- | ----------------------------------------------------------------- |
| `config`                                 | Global initializer config PDA                                     |
| `launch`                                 | New launch PDA                                                    |
| `launchAuthority`                        | Launch authority PDA                                              |
| `baseMint`                               | New base token mint keypair (signer)                              |
| `quoteMint`                              | Numeraire mint (e.g. WSOL)                                        |
| `baseVault` / `quoteVault`               | Token vault keypairs (signers)                                    |
| `launchFeeState`                         | Launch fee state PDA                                              |
| `payer` / `authority`                    | Fee payer and launch authority (signers)                          |
| `hookProgram`                            | Hook program ID, or omit for no hook                              |
| `migratorProgram`                        | Migrator program ID (e.g. `CPMM_MIGRATOR_PROGRAM_ID`)             |
| `cpmmConfig`                             | CPMM config address when using the CPMM migrator                  |
| `baseTokenProgram` / `quoteTokenProgram` | Token program IDs for each mint                                   |
| `metadataAccount`                        | Token metadata account, required when `metadataName` is non-empty |

Args (key fields):

| Arg                                               | Type                          | Description                                                                 |
| ------------------------------------------------- | ----------------------------- | --------------------------------------------------------------------------- |
| `namespace`                                       | `Address`                     | Namespace for PDA uniqueness (typically payer address)                      |
| `launchId`                                        | `Uint8Array`                  | 8-byte launch ID (from `launchIdFromU64`)                                   |
| `baseDecimals`                                    | `number`                      | Decimals of the base token                                                  |
| `baseTotalSupply`                                 | `bigint`                      | Total base token supply (with decimals)                                     |
| `baseForDistribution`                             | `bigint`                      | Tokens reserved for creator at graduation                                   |
| `baseForLiquidity`                                | `bigint`                      | Tokens reserved for post-graduation liquidity                               |
| `curveVirtualBase`                                | `bigint`                      | XYK virtual base reserves (from `marketCapToCurveParams`)                   |
| `curveVirtualQuote`                               | `bigint`                      | XYK virtual quote reserves (from `marketCapToCurveParams`)                  |
| `swapFeeBps`                                      | `number`                      | Swap fee during bonding curve phase (e.g. 100 = 1%)                         |
| `curveKind`                                       | `number`                      | Curve type — use `CURVE_KIND_XYK`                                           |
| `curveParams`                                     | `Uint8Array`                  | Curve encoding — use `new Uint8Array([CURVE_PARAMS_FORMAT_XYK_V0])`         |
| `allowBuy` / `allowSell`                          | `boolean`                     | Enables curve buys and sells                                                |
| `hookFlags`                                       | `number`                      | Hook flags, e.g. `HF_BEFORE_SWAP`                                           |
| `hookPayload`                                     | `Uint8Array`                  | Hook payload forwarded to the hook program                                  |
| `hookRemainingAccountsHash`                       | `Uint8Array`                  | Hash of swap hook remaining accounts                                        |
| `migratorInitPayload`                             | `Uint8Array`                  | Encoded graduation params (from `cpmmMigrator.encodeRegisterLaunchPayload`) |
| `migratorMigratePayload`                          | `Uint8Array`                  | Encoded migration args (from `cpmmMigrator.encodeMigratePayload`)           |
| `migratorInitRemainingAccountsHash`               | `Uint8Array`                  | Hash of migrator init remaining accounts                                    |
| `migratorRemainingAccountsHash`                   | `Uint8Array`                  | Hash of migration remaining accounts                                        |
| `feeBeneficiaries`                                | `Array<{ wallet, shareBps }>` | Curve fee beneficiaries                                                     |
| `metadataName` / `metadataSymbol` / `metadataUri` | `string`                      | On-chain token metadata                                                     |

#### Solana cosigner hook payloads

The cosigner hook supports two launch-time payload modes:

| Payload                | Behavior                                                                                                                                                                        |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Empty `Uint8Array`     | Legacy behavior. A configured cosigner must sign swaps while the launch is in the initializer trading phase. After migration, CPMM swaps are not gated by the initializer hook. |
| 42-byte expiry payload | Swaps require a configured cosigner until the encoded expiry is reached. After expiry, the hook allows swaps without a cosigner signature.                                      |

The 42-byte payload layout is:

| Bytes    | Value                                                    |
| -------- | -------------------------------------------------------- |
| `0`      | Version, currently `1`                                   |
| `1`      | Expiry mode: `1` for Unix timestamp, `2` for Solana slot |
| `2..10`  | Little-endian `u64` expiry value                         |
| `10..42` | Cosigner pubkey hint                                     |

For expiring cosigner launches, set `hookRemainingAccountsHash` to the hash of `[namespace, cosigner_config, cosigner]`, where `cosigner_config` is the cosigner hook PDA derived from seed `cosigner_hook_config` under the selected cosigner hook program. Before expiry, the cosigner account must be passed as a readonly signer. After expiry, clients can reconstruct the same remaining-account list from the payload hint without holding the cosigner key.

When `cpmmConfig` is provided, the SDK appends the CPMM migrator init remaining accounts automatically. Use the migrator helper to build the migration account list and committed hash:

```ts
const deployment = await deriveSolanaCpmmDeployment(
  DOPPLER_SOLANA_DEVNET_PROGRAM_ADDRESSES,
)

const migrationAccounts =
  await cpmmMigrator.buildCpmmMigrationRemainingAccounts({
    launch,
    baseMint,
    quoteMint,
    launchAuthority,
    adminBaseAta,
    adminQuoteAta,
    recipientAtas: [],
    cpmmProgram: deployment.cpmmProgram,
    cpmmMigratorProgram: deployment.cpmmMigratorProgram,
  })

const migratorInitRemainingAccountsHash =
  initializer.computeRemainingAccountsHash([
    migrationAccounts.cpmmMigrationState,
    migrationAccounts.cpmmConfig,
  ])
```

***

### CPMM Migrator

The `cpmmMigrator` namespace encodes the calldata forwarded to the CPMM migrator at graduation.

**`buildCpmmMigrationRemainingAccounts(args)`**

Derives the CPMM pool graph, account metas, and `migratorRemainingAccountsHash` used by `initialize_launch` and `migrate_launch`.

```ts
const migrationAccounts =
  await cpmmMigrator.buildCpmmMigrationRemainingAccounts({
    launch,
    baseMint,
    quoteMint,
    launchAuthority,
    adminBaseAta,
    adminQuoteAta,
    recipientAtas,
    cpmmProgram: deployment.cpmmProgram,
    cpmmMigratorProgram: deployment.cpmmMigratorProgram,
  })
```

**`encodeRegisterLaunchPayload(args)`** → `Uint8Array` (`migratorInitPayload`)

Encodes the `migratorInitPayload` passed to `createInitializeLaunchInstruction`. Called once at launch creation to register graduation parameters.

```ts
const migratorInitPayload = cpmmMigrator.encodeRegisterLaunchPayload({
  cpmmConfig:              migrationAccounts.cpmmConfig,
  initialSwapFeeBps:       30,            // Swap fee on graduated CPMM pool (0.3%)
  initialFeeSplitBps:      5000,          // % of fees distributed to LPs (50%)
  recipients: [
    { wallet: creatorAddress, amount: BASE_FOR_DISTRIBUTION },
  ],
  minRaiseQuote:           50_000_000_000n, // Graduation threshold in lamports (50 SOL)
  minMigrationPriceQ64Opt: null,            // Optional minimum graduation price floor
  migratedPoolHookConfig:  null,
})
```

**`encodeMigratePayload(args)`** → `Uint8Array` (`migratorMigratePayload`)

Encodes the `migratorMigratePayload` passed to `createInitializeLaunchInstruction`. Forwarded at graduation time.

```ts
const migratorMigratePayload = cpmmMigrator.encodeMigratePayload({
  baseForDistribution: BASE_FOR_DISTRIBUTION,
  baseForLiquidity:    BASE_FOR_LIQUIDITY,
})
```

***

### CPMM

After graduation the bonding curve becomes a CPMM pool. These are the core helpers for swaps.

**`createSwapInstruction(accounts)` / `createSwapExactInInstruction(accounts, args)`**

`createSwapInstruction` is a convenience wrapper; `createSwapExactInInstruction` is the low-level form.

```ts
const ix = cpmm.createSwapInstruction({
  config,
  pool:        poolAddress,
  authority:   pool.authority,
  vault0:      pool.vault0,
  vault1:      pool.vault1,
  token0Mint:  pool.token0Mint,
  token1Mint:  pool.token1Mint,
  userToken0:  userAta0,
  userToken1:  userAta1,
  user:        payer,
  amountIn:    1_000_000n,
  minAmountOut,
  tradeDirection: 0,
  programId: deployment.cpmmProgram,
})
```

**Swap quote (off-chain, no RPC)**

```ts
const quote = cpmm.getSwapQuote(pool, amountIn, tradeDirection)
// tradeDirection: 0 = token0→token1, 1 = token1→token0
// quote: { amountOut, feeTotal, feeDist, feeComp, priceImpact, executionPrice }
```

**Q64.64 fixed-point helpers**

```ts
const q64 = cpmm.numberToQ64(1.5)
const n = cpmm.q64ToNumber(q64)
```

**Pool fetching**

```ts
const deployment = await deriveSolanaCpmmDeployment(
  DOPPLER_SOLANA_DEVNET_PROGRAM_ADDRESSES,
)
const [poolAddress] = await cpmm.getPoolAddress(
  token0Mint,
  token1Mint,
  deployment.cpmmProgram,
)

// By address
const pool = await cpmm.fetchPool(rpc, poolAddress, {
  programId: deployment.cpmmProgram,
})

// By token pair (order-independent)
const result = await cpmm.getPoolByMints(rpc, mint0, mint1, {
  programId: deployment.cpmmProgram,
})
```
