SOL-slot-block-tps-priority fee-epoch-mainnet

Selling: asks

An ask is a resting sell. Tokens sit in escrow at a price you set, and buyers take from it until it is empty or you close it.

Create

TypeScript
import { createListing, PricingKind } from '@otcdex/sdk';

const ix = createListing({
  seller: wallet.publicKey,
  sellerTokenAccount,
  tokenMint,
  tokenProgram,
  quoteMint,                       // USDC or wSOL
  seed: BigInt(Date.now()),        // any u64 you have not used before
  amount: 1_000_000_000n,          // base units to escrow
  minFillAmount: 1_000_000n,       // smallest permitted purchase
  expiryTs: BigInt(Math.floor(Date.now() / 1000) + 86_400),
  allowedBuyer: null,              // or a PublicKey for a private deal
  pricing: { kind: PricingKind.Fixed, pricePerToken: 1_000_000n },
});
NameTypeRequiredDescription
seedbigintrequiredNonce forming part of the order address. Reuse fails.
amountbigintrequiredToken base units to escrow
minFillAmountbigintrequiredSmallest purchase, waived when a fill clears the order
expiryTsbigintrequiredUnix seconds. Between now+60s and now+90 days
allowedBuyerPublicKey | nullrequiredRestrict to one wallet
pricePerTokenbigintrequiredQuote base units per whole token

Pricing example. To sell at 1 USDC per token, with USDC at 6 decimals, pricePerToken is 1_000_000n. The price is always per whole token, never per base unit.

Re-price

TypeScript
import { updatePrice } from '@otcdex/sdk';

const ix = updatePrice({
  signer: wallet.publicKey,        // the seller, OR the order's price authority
  listing: listingAddress,
  quoteMint,
  pricing: { kind: PricingKind.Fixed, pricePerToken: 1_200_000n },
});

Costs one transaction fee. Escrow is untouched, so this is the cheap way to track a moving market: poll a price feed and re-peg on drift rather than cancelling and re-creating.

Track the market

A market-priced ask stores no price at all. It names a pool and an offset, and the price is read from that pool's reserves inside the transaction that settles the fill. Nothing is stored, nothing goes stale, and no keeper has to maintain it.

TypeScript
import { createListing, tracked } from '@otcdex/sdk';

const ix = createListing({
  seller: wallet.publicKey,
  sellerTokenAccount,
  tokenMint,
  tokenProgram,
  quoteMint,
  seed,
  amount: 1_000_000_000n,
  minFillAmount: 0n,
  expiryTs,
  allowedBuyer: null,
  pricing: tracked({
    pool,                          // the constant-product pool to price from
    discountBps: -500,             // 5% below market. Negative is below.
    maxVelocityBps: 0,             // ignored by the program, pass 0
    anchorPrice: spot,             // your market price now, the floor's reference
  }),
  minPrice: (spot * 9_000n) / 10_000n,  // REQUIRED: never fills below this
  // maxPrice: optional ceiling, omit for none
});

minPrice is required on a market-priced ask and is the seller's only protection: the order never fills below it, whatever the pool does. The program refuses a floor more than 25% below anchorPrice, and refuses a listing with no floor at all.

anchorPrice prices nothing. Pass the current market price: its one job is being the reference the floor is measured against. maxVelocityBps is ignored, so pass 0.

Cancel

TypeScript
import { cancelListing } from '@otcdex/sdk';

const ix = cancelListing({
  closer: wallet.publicKey,
  seller: listing.seller,
  listing: listing.address,
  tokenMint: listing.tokenMint,
  tokenProgram: listing.tokenProgram,
  sellerTokenAccount,
});

Returns the unsold remainder plus the account rent. Works even while the protocol is paused.