Skip to content
SDK

API reference

Every public symbol — signatures, parameters, return shapes, gotchas.

Mirrors packages/sdk/public

@automark/sdk — LLM Reference

This file is structured for AI coding assistants. It catalogues every public symbol with signatures, parameters, return shape, and common gotchas. If you are an LLM assisting a user with this SDK, read this file before writing code that calls the SDK.

---

Package shape

  • Name: @automark/sdk
  • Peer dep: @mysten/sui ^1.30.0
  • ESM only ("type": "module")
  • Subpath exports:
  • @automark/sdk — barrel (re-exports everything below)
  • @automark/sdk/vaultVault class + creation types
  • @automark/sdk/marketMarket class (builder-facing wrapper over Oracle)
  • @automark/sdk/oracleOracle class (lower-level Predict vocabulary)
  • @automark/sdk/durationseconds, minutes, hours, days helpers
  • @automark/sdk/mathusdFromRaw, usdToRaw, bigintMin/Max/Clamp, USD_SCALE_RAW
  • @automark/sdk/networkgetNetworkConfig, default RPC + predict-server URLs
  • @automark/sdk/permissions — permission bits + helpers
  • @automark/sdk/errors — Move-abort parser + code map
  • @automark/sdk/typesVaultState, MarketKey, RangeKey, etc

Tree-shaking is significantly better via subpath imports.

---

Mental model (read this first)

1. The SDK is a tx builder + a state reader. It never signs and never submits. The caller provides a wallet adapter. 2. All on-chain quantities are bigint. Convert with BigInt(x) from a string or number when in doubt. The SDK serializes to tx.pure.u64() internally. 3. Methods append to a Transaction passed in. They return void. The caller composes PTBs by chaining several method calls on the same tx, then submits once. 4. Vault instances are obtained via Vault.fetch() (async). The constructor is private — the static fetch ensures the instance always carries a real on-chain snapshot. 5. Strikes are scaled 1e9. Quantity is raw (no implicit decimals). Currency quantities are raw (e.g. dUSDC × 1e6). 6. Trade ops (mintBinary/mintRange) call into a strategy template package, not directly into the vault. You need strategyPackageId + strategyModule (the latter defaults to "strategy"). You can derive them from vault.parseStrategyType(). 7. PM custody is a 2-step convention: pmDepositmint* in the same PTB; redeem*pmWithdraw in the closing PTB. Otherwise capital sits idle in the PredictManager and falls out of NAV. 8. Market and Oracle describe the same thing in two vocabularies. Oracle matches the Move/Predict naming. Market is a wrapper with builder-facing strike helpers (strikeNear, strikeAbove, etc.). Pick whichever feels right for your layer — both can drive mintBinary/mintRange.

---

API — Vault class

Construction

Vault.fetch(id, { suiClient }) → Promise<Vault>

Reads the vault on-chain. Captures packageId, shareType, quoteType from the objectType (these never change). All getters reflect the snapshot.

const vault = await Vault.fetch("0xVAULT_ID", { suiClient });

Throws if id does not resolve to a Move object or if the type does not match 0x...::vault::Vault<P, Q>.

vault.refresh({ suiClient }) → Promise<void>

Re-reads on-chain state and mutates the instance in place. Use after a tx that touched the vault. Does not re-fetch the type.

---

Read-only getters (post-fetch)

GetterTypeNotes
idstringVault object ID
packageIdstringFrom the objectType
shareTypestringFull ${pkg}::${mod}::${STRUCT}
quoteTypestringE.g. dUSDC type
rawStateVaultStateThe full struct (see @automark/sdk/types)
quoteBalancebigintIdle quote balance in the vault
plpBalancebigintPLP supplied balance
totalSharesbigintOutstanding share supply
navbigintNAV in quote terms (last snapshot)
navPerSharebigintNAV / totalShares (last snapshot)
aggregateExposurebigintSum of notional across positions
highWaterMarkbigintFor performance-fee accounting
lastSnapshotTsbigintUnix seconds
pendingDepositsTotalbigintQueued, not yet processed
pendingWithdrawalSharesTotalbigintQueued, in shares
accruedFeesQuotebigintCrystallizable balance
lastCrystallizationTsbigint24h cooldown anchor
predictManagerId`string \null`Null if vault never minted
authorizedWitnessTypestring${pkg}::${mod}::${Struct} of the strategy witness
strategyPermissionsbigintBitwise OR of PERMISSIONS.*
pausedbooleanVault-wide pause
pauseReasonnumberu8 from vault.move
pauseTs`bigint \null`When paused, null otherwise
strategyPausedbooleanStrategy-specific pause
governanceAdminstringAddress
emergencyAdminstringAddress
trackedMarketKeysMarketKey[]Open binary positions
trackedRangeKeysRangeKey[]Open range positions
navParamsNavParamsIntervals/cooldowns
riskParamsRiskParamsStateCaps (max position bps, exposure, drawdown, share concentration)
feeParamsFeeParamsStatePerformance/management/entry/exit fees + platform split
uniqueOracleIdsstring[]Deduplicated + sorted, derived from tracked_*_keys

Computed getters (derived — no extra RPC)

GetterTypeNotes
isFrozenboolean`paused \\strategyPaused`
maxSinglePositionbigintnav × max_position_bps / 10_000 — cap for one new position
maxAggregateExposurebigintnav × max_aggregate_exposure_bps / 10_000 — total exposure cap
exposureHeadroombigintmaxAggregateExposure − aggregateExposure, clamped to >= 0n. Size new positions against this
openPositionsCountnumberCount of open positions (binary + range)
canMintBinary / canRedeemBinary / canMintRange / canRedeemRange / canSupplyPlp / canWithdrawPlp / canPmDeposit / canPmWithdrawbooleanPer-permission convenience checks against strategyPermissions
grantedPermissionsPermissionName[]Decomposed list of the strategy's permission bits

---

Tx builders (instance methods)

All take a Transaction as first argument, mutate it in place, return void.

vault.refreshNavSnapshot(tx, refs?) → void

Auto-picks between the simple path (1 moveCall) and the with-positions path (2+N moveCalls).

  • No positions → emits update_nav_snapshot.
  • Has positions → emits begin_nav_snapshot + N×add_oracle_to_snapshot + finalize_nav_snapshot, where N = uniqueOracleIds.length.
vault.refreshNavSnapshot(tx, { predictPackageId, predictObjectId });

Throws:

  • refs missing while vault has positions
  • predict_manager_id null while tracked_keys non-empty (inconsistent state)
  • More than 10 unique oracles (split into multiple PTBs)

vault.updateNavSnapshot(tx) → void

Direct shortcut to update_nav_snapshot. Will abort on-chain with E_INVALID_PARAM if the vault has positions. Prefer refreshNavSnapshot unless you know there are none.

vault.crystallizeFees(tx, opts?) → void

Adds crystallize_fees (and optionally a NAV refresh beforehand). Permissionless.

  • opts.includeNavRefresh (default true) prepends refreshNavSnapshot.
  • opts.refs required if the vault has positions AND includeNavRefresh is true.
vault.crystallizeFees(tx, { refs: { predictPackageId, predictObjectId } });

On-chain cooldown: 24h between crystallizations. Aborts with E_TOO_EARLY if called sooner.

vault.mintBinary(tx, params) → void

Calls ${strategyPackageId}::${strategyModule}::mint_binary. Defaults strategyModule to "strategy".

vault.mintBinary(tx, {
  strategyPackageId, strategyModule: "strategy",
  predictPackageId, predictObjectId, oracleId,
  strike: 60_000_000_000n,   // raw, 1e9 scale
  isUp: true,                // "closes above"
  quantity: 100_000_000n,    // raw contracts
});

Throws: vault has no predict_manager_id.

Common on-chain failures (use parseMoveAbort):

  • E_POSITION_TOO_LARGE — exceeds max_position_bps × NAV
  • E_EXPOSURE_LIMIT_EXCEEDED — aggregate exposure cap
  • E_VAULT_PAUSED / E_STRATEGY_PAUSED
  • E_INSUFFICIENT_PERMISSIONS — strategy doesn't have MINT_BINARY bit
  • E_WRONG_PREDICT_MANAGERpredict_manager_id mismatch

vault.mintRange(tx, params) → void

Same shape as mintBinary but with lowerStrike + higherStrike instead of strike + isUp.

Throws additionally: higherStrike <= lowerStrike.

vault.pmDeposit(tx, params) → void

Moves quote from vault → PredictManager.balance. Call before mintBinary/mintRange in the same PTB.

vault.pmDeposit(tx, { strategyPackageId, amount: 500_000_000n });

vault.pmWithdraw(tx, params) → void

Inverse of pmDeposit. Call after redeem* to bring proceeds back to the vault.

vault.parseStrategyType() → { packageId, module }

Parses authorizedWitnessType (format ${pkg}::${module}::${struct}) to derive the strategy package + module. Saves you from hardcoding.

Throws: format doesn't have exactly 3 ::-separated parts.

---

Static helpers (Vault.* — no instance needed)

These build Transaction objects from scratch — the creation flow is sequential, each tx signed independently.

Vault.publishShareTokenTx({ modules, dependencies, sender }) → Transaction

Publishes the share-token Move package. After execution, call Vault.parsePublishedShareToken(res, moduleName, structName) on the response.

Vault.parsePublishedShareToken(res, moduleName, structName) → PublishedShareToken

Returns { sharePackageId, shareType, treasuryCapId, currencyReceivingId }.

Throws on missing package, missing TreasuryCap, or missing Currency receiving object.

Vault.publishStrategyTx({ modules, dependencies, sender }) → Transaction

Publishes the strategy template package. After execution, call Vault.parsePublishedStrategy(res, moduleName, structName).

Vault.parsePublishedStrategy(res, moduleName, structName) → PublishedStrategy

Returns { strategyPackageId, witnessType }. witnessType is ready to pass into Vault.create.

Vault.finalizeShareRegistrationTx(params) → Transaction

Promotes Currency<P> to a shared object via 0x2::coin_registry::finalize_registration. Requires currencyReceivingVersion + currencyReceivingDigest (TTO receiving ref).

Vault.create(params) → Transaction

Atomic PTB: predict::create_manager + vault::create_vault. See CreateVaultParams interface for the full param shape.

After execution, use Vault.parseCreatedVault(res) (recommended) or Vault.parseCreatedVaultId(res).

Vault.crystallizeFeesTx({ sender, vaultPackageId, shareType, quoteType, vaultId, includeNavRefresh? }) → Transaction

Standalone-tx version of crystallizeFees (when you don't want to bother fetching the Vault first). includeNavRefresh (default true) prepends update_nav_snapshot — only safe for vaults without positions; pass false and refresh NAV separately for vaults with positions.

Vault.parseCrystallizedFees(res) → { totalQuote, platformShare, creatorShare } | null

Returns the FeesCrystallized event data, or null when the event was not emitted (e.g. cooldown still active).

Vault.parseCreatedVaultId(res) → string | null

Quick way to grab the vault ID. Returns null on no match.

Vault.parseCreatedVault(res) → { vaultId, vaultPackageId, predictManagerId, strategyPackageId, strategyModuleName, shareType } | null

Full breakdown — combines objectChanges (vault + package) with the VaultCreated event (predict manager + witness type, with strategy package/module inferred). strategyPackageId/strategyModuleName are null when the witness lives in the vault's own module.

Returns null on unexpected shape.

---

API — @automark/sdk/market

Market is the builder-facing wrapper over Oracle. Same underlying object, vocabulary tuned for strategy authors who think in markets/strikes/forwards rather than Predict object IDs.

Static constructors

Market.find(opts: MarketFindOpts) → Promise<Market>

Find a single market by asset + expiry filter. Throws if no candidate matches.

const btc = await Market.find({
  asset: "BTC",
  expiryAfterMs: Date.now() + 5 * 60 * 1000,
  client: suiClient,
});

MarketFindOpts extends OracleFindOpts and adds client?: SuiClient + predictPackageId?: string — both optional, but client is needed if you plan to call .price() later. Store it on the Market via find/list/byId so .price() can reuse it.

Market.list(opts?: MarketListOpts) → Promise<Market[]>

List all active markets, optionally filtered by asset. Sorted ascending by expiry.

Market.byId(id, opts?: MarketByIdOpts) → Promise<Market | null>

Look up by oracle id. Returns null if not found in the active set.

Instance properties (readonly)

PropertyTypeNotes
idstringOracle object ID — pass directly to mintBinary/mintRange
assetstringE.g. "BTC", "ETH"
expiresAtMsnumberUnix ms epoch
minStrikebigintLowest valid strike on this market's grid
tickSizebigintSpacing between adjacent strikes
statusstring"active" while open, "settled" after settle
activatedAtMs`number \null`When it transitioned from pending to active
maxStrikebigintminStrike + tickSize × 100_000 (computed getter)

Instance methods

market.price(opts?: MarketPriceOpts) → Promise<MarketPrice>

Live spot / forward / SVI sigma via on-chain DevInspect. ~200-400ms typical, gasless. Requires a SuiClient (passed at find/list/byId time, or via opts.client).

const p = await btc.price();
// MarketPrice: { spotUsd, forwardUsd, spotRaw, forwardRaw, sviSigmaRaw, atMs }

market.strikeNear(target: bigint | number) → bigint

Snap a target price to the nearest strike on this market's grid. Accepts USD (67_500) or raw u64 (67_500_000_000_000n). Clamps to [minStrike, maxStrike].

market.strikeAbove(reference, { pctBps }) → bigint

Strike at reference × (1 + pctBps/10_000), snapped to grid. pctBps in basis points (300 = 3%).

market.strikeBelow(reference, { pctBps }) → bigint

Strike at reference × (1 − pctBps/10_000), snapped to grid.

market.strikeAtSigma(snap, { k, direction, atMs? }) → bigint

Strike at forward ± k × σ × √T, snapped to grid. snap has forwardRaw + sviSigmaRaw (from price()). Falls back to ATM when T ≤ 0 or σ = 0. atMs defaults to Date.now(); pass explicitly in plugin ticks for deterministic logic.

const p = await btc.price();
const upper = btc.strikeAtSigma(p, { k: 1, direction: "up",   atMs: ctx.now });
const lower = btc.strikeAtSigma(p, { k: 1, direction: "down", atMs: ctx.now });

---

API — @automark/sdk/oracle

Oracle is the lower-level wrapper using Predict/Move vocabulary. Use it when you want oracle-level concepts (status, activation, settlement) without the strike-helper sugar. Internally, Market delegates to Oracle.

Static methods

Oracle.listActive(opts?: OracleListOpts) → Promise<OracleSummary[]>

All oracles with status === "active", optionally filtered by asset + time. Sorted by expiry ascending.

const opts: OracleListOpts = {
  asset: "BTC",                                  // case-insensitive
  expiryAfterMs: Date.now() + 5 * 60 * 1000,    // optional floor
  expiringWithinMs: 7 * 24 * 3600 * 1000,       // optional ceiling (mutex w/ expiringBetweenMs)
  expiringBetweenMs: [from, to],                // optional absolute range (mutex w/ expiringWithinMs)
  network: "testnet",                            // default; resolves predictServerUrl
  predictServerUrl: "https://...",               // override
  signal: ctrl.signal,                           // optional AbortSignal
};

Throws on invalid filter combinations (both expiringWithinMs + expiringBetweenMs, expiringWithinMs ≤ 0, expiringBetweenMs[0] >= expiringBetweenMs[1]).

Oracle.findActive(opts: OracleFindOpts) → Promise<OracleSummary>

Single oracle by asset + filters. Throws if no candidate matches.

OracleFindOpts extends OracleListOpts and adds pick?: "nearest" | "furthest" (default "nearest").

Oracle.getById(id: string, opts?: OracleFetchBase) → Promise<OracleSummary | null>

Look up by oracle ID (case-insensitive). Returns null if not in the active set.

Oracle.getSnapshot(opts: OracleSnapshotOpts) → Promise<OracleSnapshot>

Live spot / forward / SVI sigma via on-chain DevInspect. Requires id + client + predictPackageId (or network).

Types

interface OracleSummary {
  id: string;
  predictId: string;
  asset: string;
  expiresAtMs: number;
  status: "active" | "settled" | string;
  activatedAtMs: number | null;
  minStrike: bigint;
  tickSize: bigint;
}

interface OracleSnapshot {
  id: string;
  spotUsd: number;       // 4-decimal display
  forwardUsd: number;    // SVI center
  spotRaw: bigint;       // u64 scale 1e9
  forwardRaw: bigint;
  sviSigmaRaw: bigint;   // u64 scale 1e9; for sigma × sqrt(T) math
  atMs: number;
}

---

API — @automark/sdk/duration

export function seconds(n: number): number;   // n * 1_000
export function minutes(n: number): number;   // n * 60_000
export function hours(n: number): number;     // n * 3_600_000
export function days(n: number): number;      // n * 86_400_000

Plain ms math, but reads as intent. Accepts fractions (seconds(0.5) === 500).

Common use:

await Market.list({ asset: "BTC", expiringWithinMs: days(7), client });
await ctx.state.setWithTTL("ban", 1, hours(2));

---

API — @automark/sdk/math

export const USD_SCALE_RAW = 1_000_000_000n;   // 1 USD in u64 scale

export function bigintMin(a: bigint, b: bigint): bigint;
export function bigintMax(a: bigint, b: bigint): bigint;
export function bigintClamp(value: bigint, min: bigint, max: bigint): bigint;  // throws if min > max

export function usdFromRaw(raw: bigint): number;    // 4-decimal precision; for display only
export function usdToRaw(usd: number): bigint;      // safe for ≤9 fractional digits

bigintClamp throws on min > max instead of silently swapping or returning — a swapped pair is almost always a bug.

usdFromRaw is for display: round-tripping usdFromRaw → usdToRaw will lose precision past 4 decimals.

---

API — @automark/sdk/network

export type SuiNetwork = "testnet" | "mainnet" | "devnet";

export interface NetworkConfig {
  vaultPackageId: string;
  predictPackageId: string;
  predictObjectId: string;
  quoteType: string;          // e.g. dUSDC type on testnet
  platformTreasury: string;
}

export const NETWORK_CONFIG: Record<SuiNetwork, NetworkConfig | null>;
export const DEFAULT_RPC_URLS: Record<SuiNetwork, string>;
export const DEFAULT_PREDICT_SERVER_URLS: Record<SuiNetwork, string | null>;

export function getNetworkConfig(network: SuiNetwork): NetworkConfig;       // throws if not configured
export function getDefaultRpcUrl(network: SuiNetwork): string;
export function getDefaultPredictServerUrl(network: SuiNetwork): string;    // throws if not published upstream

Testnet is fully configured today. Mainnet/devnet entries return null from NETWORK_CONFIG and throw from getNetworkConfig until published.

Usage:

import { getNetworkConfig } from "@automark/sdk/network";

const cfg = getNetworkConfig("testnet");
// cfg.predictPackageId, cfg.predictObjectId, cfg.quoteType, ...

---

API — @automark/sdk/permissions

export const PERMISSIONS = {
  MINT_BINARY:    1 << 0,  // 1
  REDEEM_BINARY:  1 << 1,  // 2
  MINT_RANGE:     1 << 2,  // 4
  REDEEM_RANGE:   1 << 3,  // 8
  SUPPLY_PLP:     1 << 4,  // 16
  WITHDRAW_PLP:   1 << 5,  // 32
  PM_DEPOSIT:     1 << 6,  // 64
  PM_WITHDRAW:    1 << 7,  // 128
} as const;

export const PERMISSIONS_WHITELIST = 255; // bits 0-7

hasPermission(perms: number | bigint, perm: PermissionBit): boolean
combinePermissions(...perms: PermissionBit[]): number
decomposePermissions(perms: number | bigint): PermissionName[]

Accepts bigint (the on-chain representation) and number interchangeably. decomposePermissions ignores unknown bits defensively (e.g. bit 8+).

---

API — @automark/sdk/errors

parseMoveAbort(err: unknown): { code: number; name: VaultErrorName | null; raw: string } | null
parseMoveAbortCode(message: string): number | null
getErrorName(code: number): VaultErrorName | null

export const VAULT_ERROR_CODES = {
  E_VAULT_PAUSED: 1, E_STRATEGY_PAUSED: 2, E_UNAUTHORIZED: 3,
  E_NOT_OPERATOR: 4, E_ZERO_DEPOSIT: 5, E_ZERO_SHARES: 6,
  E_INSUFFICIENT_SHARES: 7, E_SNAPSHOT_TOO_EARLY: 8, E_SNAPSHOT_STALE: 9,
  E_TOO_EARLY: 10, E_UPGRADE_ALREADY_PENDING: 11,
  E_UPGRADE_TIMELOCK_NOT_ELAPSED: 12, E_NO_UPGRADE_PENDING: 13,
  E_INVALID_PARAM: 14, E_PARAM_CHANGE_NOT_ALLOWED: 15, E_ADMIN_CONFLICT: 16,
  E_LIQUIDATION_INSUFFICIENT: 17, E_WRONG_PREDICT_MANAGER: 18,
  E_WRONG_ORACLE: 19, E_POSITION_TOO_LARGE: 20,
  E_EXPOSURE_LIMIT_EXCEEDED: 21, E_MAX_POSITIONS_EXCEEDED: 22,
  E_INSUFFICIENT_PERMISSIONS: 23, E_SHARE_DECIMALS_NOT_6: 24,
  E_SHARE_SYMBOL_EMPTY: 25, E_SHARE_CURRENCY_NO_TREASURY: 26,
  E_SHARE_CURRENCY_MISMATCH: 27, E_WRONG_WITNESS: 30,
};

parseMoveAbort returns null for non-MoveAbort errors (network, user reject, RPC). The app handles those separately.

Usage pattern:

try {
  await wallet.signAndExecuteTransaction({ transaction: tx });
} catch (err) {
  const info = parseMoveAbort(err);
  if (!info) throw err; // not a Move abort — bubble up
  if (info.name === "E_SNAPSHOT_TOO_EARLY") return "wait before retrying";
  // ...
}

---

API — @automark/sdk/types

export interface VaultState {
  quote_balance: bigint;
  plp_balance: bigint;
  total_shares: bigint;
  nav: bigint;
  nav_per_share: bigint;
  aggregate_exposure: bigint;
  high_water_mark: bigint;
  last_snapshot_ts: bigint;
  pending_deposits_total: bigint;
  pending_withdrawal_shares_total: bigint;
  accrued_fees_quote: bigint;
  last_crystallization_ts: bigint;
  predict_manager_id: string | null;
  authorized_witness_type: string;
  strategy_permissions: bigint;
  paused: boolean;
  pause_reason: number;
  pause_ts: bigint | null;
  strategy_paused: boolean;
  governance_admin: string;
  emergency_admin: string;
  tracked_market_keys: MarketKey[];
  tracked_range_keys: RangeKey[];
  nav_params: NavParams;
  risk_params: RiskParamsState;
  fee_params: FeeParamsState;
  raw_fields: unknown;
}

export interface MarketKey {
  oracle_id: string;
  expiry: bigint;
  strike: bigint;
  direction: number; // 0=UP, 1=DOWN
  is_up: boolean;
}

export interface RangeKey {
  oracle_id: string;
  expiry: bigint;
  lower_strike: bigint;
  higher_strike: bigint;
}

export interface NavParams {
  snapshot_interval_seconds: bigint;
  deposit_cooldown_seconds: bigint;
  withdrawal_cooldown_seconds: bigint;
}

// On-chain state caps (set at construction, mutable via governance upgrade).
export interface RiskParamsState {
  max_position_bps: bigint;
  max_aggregate_exposure_bps: bigint;
  max_drawdown_bps: bigint;
  max_share_concentration_bps: bigint;
}

export interface FeeParamsState {
  performance_fee_bps: bigint;
  management_fee_bps_annual: bigint;
  entry_fee_bps: bigint;
  exit_fee_bps: bigint;
  platform_split_bps: bigint;
}

export interface PMPositionSummary {
  oracle_id: string;
  strike: bigint;
  is_up: boolean;
  minted_quantity: bigint;
  redeemed_quantity: bigint;
  open_quantity: bigint;
  total_cost: bigint;
  total_payout: bigint;
  realized_pnl: bigint;
  status: string;
}

export interface OracleState {
  is_settled: boolean;
  settlement_price: bigint | null;
  expiry: bigint;
}

// SDK input shapes (camelCase variants used at Vault.create time)
export interface RiskParams {
  maxPositionBps: number;
  maxAggregateExposureBps: number;
  maxDrawdownBps: number;
  maxShareConcentrationBps: number;
}

export interface FeeParams {
  performanceFeeBps: number;
  managementFeeBpsAnnual: number;
  entryFeeBps: number;
  exitFeeBps: number;
  platformSplitBps: number;
}

export interface NavParamsInput {
  snapshotIntervalSeconds: number;
  depositCooldownSeconds: number;
  withdrawalCooldownSeconds: number;
}

---

Common patterns

Atomic mint with auto-funded PM

const vault = await Vault.fetch(vaultId, { suiClient });
const { packageId, module } = vault.parseStrategyType();

const tx = new Transaction();
vault.pmDeposit(tx, { strategyPackageId: packageId, strategyModule: module, amount });
vault.mintBinary(tx, {
  strategyPackageId: packageId, strategyModule: module,
  predictPackageId, predictObjectId, oracleId,
  strike, isUp: true, quantity,
});
await wallet.signAndExecuteTransaction({ transaction: tx });
await vault.refresh({ suiClient }); // sync state for next read

Discover market + size strike by sigma

import { Market, days } from "@automark/sdk";

const btc = await Market.find({
  asset: "BTC",
  expiringWithinMs: days(7),
  client: suiClient,
});

const p = await btc.price();
const upper = btc.strikeAtSigma(p, { k: 1, direction: "up", atMs: Date.now() });
// upper is now snapped to the on-chain grid and ready for mintBinary

Multi-oracle NAV refresh with cap awareness

const vault = await Vault.fetch(vaultId, { suiClient });
const oracles = vault.uniqueOracleIds;

if (oracles.length > 10) {
  // Split into chunks of ≤10. Two PTBs, each calling refreshNavSnapshot
  // on a Vault instance with a tracked_keys subset would require splitting
  // upstream — currently the SDK throws above 10 to force this decision.
  throw new Error("Too many oracles for a single refresh; split upstream");
}

const tx = new Transaction();
vault.refreshNavSnapshot(tx, { predictPackageId, predictObjectId });
await wallet.signAndExecuteTransaction({ transaction: tx });

Display vault with permission decomposition

import { Vault, decomposePermissions } from "@automark/sdk";

const vault = await Vault.fetch(vaultId, { suiClient });
const perms = decomposePermissions(vault.strategyPermissions);
// → ["MINT_BINARY", "REDEEM_BINARY", "PM_DEPOSIT", "PM_WITHDRAW"]

return {
  name: vault.authorizedWitnessType,
  navPerShare: Number(vault.navPerShare) / 1e9,
  totalShares: Number(vault.totalShares) / 1e6,
  permissions: perms,
  paused: vault.isFrozen,
};

---

Things the SDK does NOT do (today)

  • No LP-facing builders yet (requestDeposit, requestWithdrawal, cancels, process_*). Use raw tx.moveCall against vault::request_deposit etc until they ship.
  • No separate Strategy class. Operator-facing trade ops (mintBinary/mintRange/pmDeposit/pmWithdraw) live as instance methods on Vault.
  • No replace_strategy / governance helpers.
  • No React hooks. Wrap Vault.fetch in your own useQuery / useEffect.
  • No keeper scheduler. Use vault.rawState + your own scheduler to drive process_pending_*.
  • No tx signing. Pass the Transaction to a wallet adapter (@mysten/dapp-kit, Suiet, Slush, etc).
  • No batch reads. Vault.fetchMany is on the roadmap — for now, Promise.all([fetch(a), fetch(b), ...]).

---

When the user asks for X, suggest Y

Asks forSuggest
"Show me vault TVL / shares / pause"Vault.fetch + getters (nav, totalShares, paused)
"Find a BTC market expiring next week"Market.find({ asset: "BTC", expiringWithinMs: days(7), client })
"Get live spot/forward of a market"await market.price() (needs client passed earlier or here)
"Sane strike, x% above forward"market.strikeAbove(p.forwardRaw, { pctBps: 300 })
"Sane strike, k-sigma away"market.strikeAtSigma(p, { k: 1, direction: "up", atMs: ctx.now })
"Place a trade"Vault.fetch + Market.find + pmDeposit + mintBinary/mintRange in one PTB
"Settle accumulated fees"vault.crystallizeFees(tx, { refs }) or Vault.crystallizeFeesTx(...) for a standalone tx
"Refresh NAV"vault.refreshNavSnapshot(tx, { refs }) — auto-handles both paths
"Deploy a new vault"Sequence: publishShareTokenTxfinalizeShareRegistrationTxpublishStrategyTx (if separate) → create
"Parse this tx error"parseMoveAbort(err) — returns { code, name, raw } or null
"Check whether the strategy can do X"hasPermission(vault.strategyPermissions, PERMISSIONS.X)
"Show oracle dependencies for NAV refresh"vault.uniqueOracleIds
"Convert raw u64 strike to USD for display"usdFromRaw(strikeRaw)
"Get the testnet predict-server URL"getDefaultPredictServerUrl("testnet")