Skip to main content
All PTB construction lives in packages/frontend/src/lib/ptb.ts. Consumers receive a fully-built Transaction they can hand to useTxSigner().sign().

Predict

buildCreatePredictManagerPTB(): Transaction;

buildDepositToPredictManagerPTB({
  managerId: string;
  amountMicro: bigint;
}): Transaction;

buildWithdrawFromPredictManagerPTB({
  managerId: string;
  amountMicro: bigint;
}): Transaction;

buildPredictMintBinaryPTB({
  managerId: string;
  oracleId: string;
  expiryMs: bigint;
  strike: bigint;
  isUp: boolean;
  costMicro: bigint;
  minQty: bigint;
}): Transaction;

buildPredictMintRangePTB({ … }): Transaction;

buildPredictRedeemPTB({ managerId, oracleId, … }): Transaction;
The mint PTB asserts the on-chain ask hasn’t moved more than 105% of the quote before submitting (avoids decrease_position code 3).

Binary markets (scaffolded)

buildMintPairPTB({
  settlementId: string;
  packageId: string;
  amountMicro: bigint;
}): Transaction;

buildBurnPairPTB({ settlementId, packageId, yesCoinIds, noCoinIds }): Transaction;
buildRedeemYesPTB({ … }): Transaction;
buildRedeemNoPTB({ … }): Transaction;
All merge multiple coin objects per leg into one PTB so the user can redeem a basket in a single tx.

DeepBook V3 swap

/**
 * Market buy/sell via pool::swap_exact_quantity with pay_with_deep=false.
 * Fees in the input token; 1% slippage floor.
 */
buildV3SwapPTB({
  poolId: string;
  baseType: string;          // YES type
  quoteType: string;         // DUSDC
  side: 'buy' | 'sell';
  inputAmountMicro: bigint;
  expectedOutMicro: bigint;
  slippageBps: number;        // default 100 = 1%
}): Transaction;

Dark-pool vault

buildVaultDepositPTB({
  vaultId: string;
  amountMicro: bigint;
  accessPolicyId: string;
  encryptedBlobId: Uint8Array;     // or empty
  attributionHash: Uint8Array;     // 32 bytes (zero-padded when Seal is off)
}): Transaction;

buildVaultRedeemPTB({
  vaultId: string;
  receiptId: string;
}): Transaction;

Agent wizard

Not a single builder. The /agents Create wizard inlines the PTB:
const tx = new Transaction();
const [bm] = tx.moveCall({ target: 'balance_manager::new' });
tx.moveCall({ target: 'balance_manager::share', arguments: [bm] });
const [tradeCap] = tx.moveCall({
  target: 'balance_manager::mint_trade_cap',
  arguments: [bm, owner],
});
// optional DUSDC deposit:
if (depositCoin) tx.moveCall({ target: 'balance_manager::deposit<DUSDC>', arguments: [bm, depositCoin] });
const [agent, ownerCap] = tx.moveCall({
  target: `${DARKPOOL_PACKAGE_ID}::agent::register_agent`,
  arguments: [registry, name, strategyBlob, agentAddr, bm, tradeCap, predictManagerId],
});
tx.transferObjects([tradeCap], operatorAddress);
tx.transferObjects([agent, ownerCap], ownerAddress);
Dry-run-verified on testnet (creates BalanceManager, TradeCap, TradeAgent, AgentOwnerCap, registry AgentSummary).

Optimistic Oracle

buildOOProposePTB({ marketLinkId, outcome, bondMicro }): Transaction;
buildOODisputePTB({ proposalId, bondMicro }): Transaction;
buildOOFinalizeAutoPTB({ proposalId }): Transaction;
buildOOFinalizeVotePTB({ proposalId }): Transaction;
Latest finalize_vote matches the multi-return pattern from scripts/oo-finalize.ts, drops the address return, and transferObjects-es both bond coins to sender.

Send DUSDC (zkLogin onramp / offramp)

Inlined in SendDusdcCard.tsx:
const coins = await sui.getCoins({ owner: account.address, coinType: DUSDC_COIN_TYPE });
const sorted = coins.data.sort((a, b) => Number(BigInt(b.balance) - BigInt(a.balance)));
const tx = new Transaction();
const primary = tx.object(sorted[0].coinObjectId);
if (primary.balance < amount) tx.mergeCoins(primary, sorted.slice(1).map(c => tx.object(c.coinObjectId)));
const [out] = tx.splitCoins(primary, [amount]);
tx.transferObjects([out], recipient);
Flows through useTxSigner() so gas is sponsored when allowlisted.