Skip to main content

Initializing a new pool

Hadron.initialize

Builds all the instructions needed to create a new on-chain pool: account allocation + initialization. Returns the instructions and the derived pool address. The allocate instruction(s) must be confirmed before sending the initialize instruction (they can be in separate transactions, or together if they fit).
import { Hadron, Q32_ONE } from "@hadron-so/sdk";

const { instructions, poolAddress, seed } = Hadron.initialize(payer, {
  mintX,
  mintY,
  authority: payer,
  initialMidpriceQ32: Q32_ONE, // midprice = 1.0
});

// Send the instructions (group into transactions as needed)
// ...

// After confirmation, load the pool
const pool = await Hadron.load(connection, poolAddress);
ParamTypeDescription
payerPublicKeyTransaction fee payer and account funder
params.seed?bigintPool seed. Auto-generated if omitted. Allows multiple pools per token pair.
params.mintXPublicKeyBase token mint
params.mintYPublicKeyQuote token mint
params.authorityPublicKeyPool authority (manages curves, oracle, state)
params.initialMidpriceQ32bigintStarting midprice in Q32 fixed-point format
params.oracleMode?OracleModeAuthority (default) or Relative (vault ratio)
params.tokenProgramX?PublicKeyToken program for X (default: SPL Token)
params.tokenProgramY?PublicKeyToken program for Y (default: SPL Token)
params.maxPrefabSlots?numberMax curve prefab slots (default: 10)
params.maxCurvePoints?numberMax points per curve (default: 16)
Returns { instructions: TransactionInstruction[], poolAddress: PublicKey, seed: bigint }
With default parameters the CurvePrefabs account is ~15 KB, so two allocate instructions are returned (Solana’s single-instruction realloc limit is 10 KB). Send the allocates first, then the initialize.

Loading an existing pool

Hadron.load

Load a pool from its on-chain address. Fetches config, oracle, curve metadata, and prefab data in parallel.
const pool = await Hadron.load(connection, poolAddress);
ParamTypeDescription
connectionConnectionSolana RPC connection
poolAddressPublicKeyThe pool’s on-chain address
Returns Promise<Hadron>

Hadron.loadFromSeed

Derives the pool address from (seed, mintX, mintY) then calls create.
const pool = await Hadron.loadFromSeed(connection, seed, mintX, mintY);
ParamTypeDescription
connectionConnectionSolana RPC connection
seedbigintPool seed
mintXPublicKeyBase token mint
mintYPublicKeyQuote token mint
Returns Promise<Hadron>

Reading pool state

refetchStates

Re-fetches all on-chain accounts (config, oracle, curve metadata, prefabs) in parallel and updates the instance in-place.
await pool.refetchStates();
Returns Promise<void>

getMidprice

Current midprice decoded from the on-chain Q32 oracle value.
const mid = pool.getMidprice(); // e.g. 1.0023
Returns number

getSpreadFactor

Current spread factor decoded from the on-chain Q32 oracle value. A factor of 0.9995 means 5 bps of spread.
const factor = pool.getSpreadFactor(); // e.g. 0.9995
const bps = pool.getSpreadBps();       // e.g. 5
Returns number

getActiveCurveSlots

Returns the slot index for each active curve.
const slots = pool.getActiveCurveSlots();
// { priceBid: 0, priceAsk: 0, riskBid: 0, riskAsk: 0 }
Returns { priceBid: number, priceAsk: number, riskBid: number, riskAsk: number }

getActiveCurves

Decodes and returns all four active curves from prefab data.
const curves = pool.getActiveCurves();
// curves.priceBid.points, curves.priceAsk.points, etc.
Returns { priceBid: CurveSide, priceAsk: CurveSide, riskBid: CurveSide, riskAsk: CurveSide } Each CurveSide contains:
FieldTypeDescription
numPointsnumberNumber of curve points
defaultInterpolationInterpolationDefault interpolation mode
xModeCurveXModeX-axis mode (Native or Alternate)
riskModeRiskModeVirtual or Integrated
pointsCurvePoint[]The curve point array

getCurveSlot

Decode a specific curve slot by type and index.
const curve = pool.getCurveSlot(CurveType.PriceBid, 1);
ParamTypeDescription
curveTypeCurveTypeOne of PriceBid, PriceAsk, RiskBid, RiskAsk
slotnumberSlot index
Returns CurveSide

Building instructions

All methods below return a TransactionInstruction. They do not send a transaction — add the instruction to a Transaction or VersionedTransaction and submit it yourself.

swap

Build a swap instruction.
const ix = pool.swap(user, {
  isX: true,             // true = sell token X for Y, false = sell Y for X
  amountIn: 1_000_000n,
  minOut: 0n,
  feeRecipient: feePk,
});
ParamTypeDescription
userPublicKeyThe user’s wallet
params.isXbooleanDirection: true = X→Y, false = Y→X
params.amountInbigintInput amount in token atoms
params.minOutbigintMinimum output (slippage protection)
params.feeRecipientPublicKeyAddress to receive fees
params.expiration?numberOptional slot expiration

deposit

Build a deposit instruction.
const ix = pool.deposit(user, {
  amountX: 1_000_000n,
  amountY: 2_000_000n,
});
ParamTypeDescription
userPublicKeyThe user’s wallet
params.amountXbigintAmount of token X to deposit (in atoms)
params.amountYbigintAmount of token Y to deposit (in atoms)
params.expiration?numberOptional slot expiration

withdraw

Build a withdraw instruction.
const ix = pool.withdraw(user, {
  amountX: 500_000n,
  amountY: 1_000_000n,
});
ParamTypeDescription
userPublicKeyThe user’s wallet
params.amountXbigintAmount of token X to withdraw (in atoms)
params.amountYbigintAmount of token Y to withdraw (in atoms)
params.expiration?numberOptional slot expiration

Curve management

setCurve

Write a price curve to a prefab slot.
const ix = pool.setCurve(authority, {
  side: Side.Bid,
  defaultInterpolation: Interpolation.Linear,
  points: [
    { amountIn: 100_000n, priceFactor: 0.99 },
    { amountIn: 500_000n, priceFactor: 0.95 },
  ],
  slot: 0,
});
ParamTypeDescription
authorityPublicKeyPool authority
params.sideSideBid or Ask
params.defaultInterpolationInterpolationStep, Linear, MarginalStep, Hyperbolic, Quadratic, Cubic
params.pointsSetCurvePointInput[]Array of { amountIn, priceFactor, interpolation?, params? }
params.slot?numberTarget prefab slot (default: 0)
params.xMode?CurveXModeX-axis mode

setRiskCurve

Write a risk curve using percent-of-vault x-axis.
ParamTypeDescription
authorityPublicKeyPool authority
params.sideSideBid or Ask
params.defaultInterpolationInterpolationInterpolation mode
params.pointsSetRiskCurvePointInput[]{ pctBase: 0.0–1.0, priceFactor, ... }
params.slot?numberTarget prefab slot
params.riskMode?RiskModeVirtual or Integrated

setRiskCurveAbsolute

Write a risk curve using absolute token amounts on the x-axis.
ParamTypeDescription
authorityPublicKeyPool authority
params.sideSideBid or Ask
params.defaultInterpolationInterpolationInterpolation mode
params.pointsSetRiskCurveAbsolutePointInput[]{ vaultBalance, priceFactor, ... }
params.slot?numberTarget prefab slot
params.riskMode?RiskModeVirtual or Integrated

switchPriceCurve / switchRiskCurve

Activate a previously written curve slot (hot path — no curve data uploaded).
pool.switchPriceCurve(authority, { side: Side.Bid, slot: 1 });
pool.switchRiskCurve(authority, { side: Side.Ask, slot: 2 });
ParamTypeDescription
authorityPublicKeyPool authority
params.sideSideBid or Ask
params.slotnumberSlot to activate

submitCurveUpdates / applyCurveUpdates

Two-step batched curve editing. Submit a list of point edits, then apply them.
pool.submitCurveUpdates(authority, [
  { curveType: CurveType.PriceBid, opKind: CurveUpdateOpKind.Edit, pointIndex: 0, ... },
]);
pool.applyCurveUpdates(authority);

Oracle management

updateMidprice

pool.updateMidprice(authority, { midpriceQ32: newMidQ32 });
ParamTypeDescription
params.midpriceQ32bigintNew midprice in Q32 format
params.sequence?bigintOptional sequence number for ordering

updateBaseSpread

pool.updateBaseSpread(authority, { spreadFactorQ32: newSpreadQ32 });
ParamTypeDescription
params.spreadFactorQ32bigintSpread discount factor in Q32 (e.g. toQ32(0.9995) = 5 bps)
params.sequence?bigintOptional sequence number

updateMidpriceAndBaseSpread

Atomic update of both values in a single instruction.
pool.updateMidpriceAndBaseSpread(authority, {
  midpriceQ32: newMidQ32,
  spreadFactorQ32: newSpreadQ32,
});

Admin

nominateAuthority / acceptAuthority

Two-step authority transfer.
pool.nominateAuthority(authority, { newAuthority: newPk, expirySlot: 300_000_000n });
// ... newAuthority signs:
pool.acceptAuthority(newPk);

setPoolState

pool.setPoolState(authority, { newState: PoolState.Paused });
States: Uninitialized, Initialized, Paused, WithdrawOnly

updateDeltaStaleness

pool.updateDeltaStaleness(authority, { deltaStaleness: 150 });

closePool

Closes the pool and reclaims rent. Requires authority and all vaults to be empty.
pool.closePool(authority);

Properties

These are available on any Hadron instance after creation:
PropertyTypeDescription
pool.poolAddressPublicKeyThe pool’s on-chain address
pool.programIdPublicKeyProgram ID
pool.addressesPoolAddressesAll derived PDA addresses for this pool
pool.configDecodedConfigDecoded config account data
pool.oracleDecodedMidpriceOracleDecoded oracle data
pool.curveMetaDecodedCurveMetaDecoded curve metadata