Skip to main content
This Bun script runs a full paired cycle on devnet. It drips cUSDC from the faucet, checks the market’s price age, estimates the fill, mints a QQQ pair with mint_paired and redeems it with redeem_paired. It needs a funded devnet wallet and nothing else.

Prerequisites

  • A devnet wallet at ~/.config/solana/id.json (or set WALLET_PATH) with some SOL for fees and token-account rent. 0.05 SOL is plenty.
  • The packages from SDK setup: bun add @coral-xyz/anchor@0.32 @solana/web3.js@1 @solana/spl-token.
  • An open underlying market. The keeper stops posting a market’s price while its underlying market is closed, and mint and redeem revert once the price is more than 300 s old.

The script

Run

Expected output for QQQ’s devnet state on 10 Oct 2026 (price $751.27, γ 0.993214606, posted fee 18 bps). Signatures are elided:
When the underlying market is closed, the script stops at step 1. On Saturday 10 Oct 2026 it printed this (Bun’s source excerpt and stack trace trimmed):

What just happened

  • Step 1 read the Market account and stopped if the price was older than 270 s or the market was in Stress. The 270 s is the program’s 300 s limit, minus 30 s for the transaction to land. Stress blocks mint and redeem on every live market, because allow_mint_in_stress and allow_redeem_in_stress are false.
  • Step 2 priced the mint the way mint_paired does. L costs P + c and S costs K / (P − c) × γ, where P is user_twap_price, K is initial_l_price × initial_s_price, and c is oracle_confidence times the risk-state multiplier (1.5× in ProxyMode). QQQ is the one market with worst-case quoting switched off (worst_case_config.enabled is false as of 10 Oct 2026), so its c is 0 and both legs price at NAV. The fee is the posted 18 bps times the same 1.5× multiplier: 27 bps.
  • Step 4 dripped 1,000 cUSDC because the wallet held less than 100. The faucet allows one drip per wallet every 24 hours.
  • Step 5 deposited 100 cUSDC. The program kept a 0.27 cUSDC fee and minted 0.066374 L and 0.163706 S from the other 99.73 cUSDC, half to each leg. A tenth of the fee (dev_tax_pct = 10) went to the fee recipient; the rest stayed in the vault.
  • Step 6 burned both legs and paid 99.460329 cUSDC after the 27 bps redeem fee. The round trip cost 0.539671 cUSDC, about 54 bps.
The estimates match the program exactly while the market is over-collateralized. Below a 100% collateral ratio, redeem_paired pays pro rata (nominal × total_collateral / total_claims), and the redeem estimate comes out high.

Redeeming one leg

There is no single-leg redeem. redeem_paired requires l_amount > 0 and s_amount > 0, and fails with InvalidAmount otherwise. The two amounts are maxima: the program burns the largest value-balanced pair inside them at the worst-case redeem NAVs, and the rest of the larger leg stays in your wallet. The script redeems a pair it just minted, so the trim is at most rounding. If the balanced pair has a zero leg, the call fails with InvalidAmount too. To exit a single leg, sell it through a committed order while the market is open, or on the bin book with pool_swap while its price is stale. You can also buy the other leg and redeem the pair. See Trade flow.

Common errors

→ Full error catalog

Extending the example

  • Mint in several markets at once by adding one mintPaired instruction per market to the same transaction, within Solana’s 1,232-byte transaction size limit.
  • Refresh estimates live: subscribe to the market account with connection.onAccountChange(market, ...) and run quote() on each update.
  • Take a directional position: after step 5, sell the leg you don’t want through a committed order while the market is open (Trade flow).

See also

Reading prices

Read the price, confidence and γ from the Market account.

Composability

Use cases: wrappers, bots, structured products, integrations.