Skip to main content
Two things before you start: a Node API token for authentication (without one, requests return 401 Unauthorized) and an API Wallet to sign transactions.

Purpose

  • Place/cancel orders (limit/market/stop, TP/SL, TWAP).
  • Place/cancel spot orders and spot bulk orders, and manage spot builder fees.
  • Manage collateral, Trading Accounts, delegations, and builder fees.
  • Create, fund, and manage vaults; place orders on behalf of a vault subaccount.

When to use

  • Use when you need to submit transactions or manage trading state.
  • Avoid embedding private keys in browsers. Prefer:
    • Wallets/session keys and pass accountOverride for specific calls.
    • Server-side orchestration where secrets are controlled.

Formatting price and size

See the formatting guide for converting UI values into chain units (e.g., amountToChainUnits).

Initialization

Function reference

The sections below enumerate every callable helper exposed in DecibelWriteDex along with the argument types you should pass. All functions live on an instantiated write client unless otherwise noted.

Utilities

sendSubaccountTx

Returns: Promise<CommittedTransactionResponse>
  • sendTx: (subaccountAddr: string) => Promise<CommittedTransactionResponse> (required)
  • subaccountAddr: string (optional) – defaults to primary subaccount
Resolves the intended Trading Account before running the transaction.

withSubaccount

Returns: Promise<T>
  • fn: (subaccountAddr: string) => Promise<T> (required)
  • subaccountAddr: string (optional) – defaults to primary subaccount
Utility to obtain the resolved Trading Account address inside arbitrary logic.

Trading Accounts and Collateral

renameSubaccount

Returns: Promise<{ subaccount_address: string; new_name: string }>
  • subaccountAddress: string (required)
  • newName: string (required)
Renames a Trading Account.

createSubaccount

Returns: Promise<CommittedTransactionResponse> No arguments. Creates a new Trading Account for the owner.

adminCreateSubaccount

Returns: Promise<CommittedTransactionResponse>
  • ownerAddress: string (required)
Admin-only helper that creates a new Trading Account for another wallet.

deposit

Returns: Promise<CommittedTransactionResponse>
  • amount: number (required) – USDC amount in u64 base units
  • subaccountAddr: string (optional) – defaults to primary subaccount
Deposits collateral to a Trading Account.

withdraw

Returns: Promise<CommittedTransactionResponse>
  • amount: number (required) – USDC amount in u64 base units
  • subaccountAddr: string (optional) – defaults to primary subaccount
Withdraws collateral from a Trading Account.

withdrawNonCollateral

Returns: Promise<CommittedTransactionResponse>
  • assetAddr: string (required)
  • amount: number (required) – asset amount in u64 base units
  • subaccountAddr: string (optional) – defaults to primary subaccount
Withdraws a non-collateral asset from a Trading Account.

configureUserSettingsForMarket

Returns: Promise<CommittedTransactionResponse>
  • marketAddr: string (required)
  • subaccountAddr: string (required)
  • isCross: boolean (required)
  • userLeverage: number (required)
Configures leverage and cross/isolated margin for a market.

buildDeactiveSubaccountTx

Returns: Promise<SimpleTransaction>
  • subaccountAddr: string (required)
  • revokeAllDelegations: boolean (optional, defaults to true)
  • signerAddress: AccountAddress (required)
Builds a transaction to deactivate a Trading Account.

Orders and matching

extractOrderIdFromTransaction

Returns: string | null
  • txResponse: CommittedTransactionResponse (required)
  • subaccountAddr: string (optional; defaults to the signer’s primary subaccount)
Decodes the matching OrderEvent or TwapEvent order ID from an existing transaction. Returns null when no matching event is found; this is not evidence that the transaction was unsubmitted.

placeOrder

Returns: Promise<PlaceOrderResult>
  • marketName: string (required)
  • price: number (required) – in chain units
  • size: number (required) – in chain units
  • isBuy: boolean (required)
  • timeInForce: TimeInForce (required)
  • isReduceOnly: boolean (required)
  • clientOrderId: string (optional)
  • stopPrice: number (optional)
  • tpTriggerPrice: number (optional)
  • tpLimitPrice: number (optional)
  • slTriggerPrice: number (optional)
  • slLimitPrice: number (optional)
  • builderAddr: string (optional)
  • builderFee: number (optional)
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)
  • tickSize: number (optional) – auto-rounds prices to tick multiples
Places a limit, market, or conditional order.

cancelOrder

Returns: Promise<CommittedTransactionResponse>
  • orderId: number | string (required)
  • marketName: string (required if marketAddr not provided)
  • marketAddr: string (required if marketName not provided)
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)
Cancels an order by its ID. Selection rule: if you already have the market object address, prefer marketAddr; if you only have the market name (for example BTC/USD), use marketName.

cancelClientOrder

Returns: Promise<CommittedTransactionResponse>
  • clientOrderId: string (required)
  • marketName: string (required)
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)
Cancels an order by client-provided ID.

cancelBulkOrder

Returns: Promise<CommittedTransactionResponse>
  • marketName: string (required if marketAddr not provided)
  • marketAddr: string (required if marketName not provided)
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)
Cancels all bulk orders for a market on the selected Trading Account. Selection rule: if your flow already has a cached market address, use marketAddr; if your flow is market-name driven, use marketName.

triggerMatching

Returns: Promise<{ success: boolean; transactionHash: string }>
  • marketAddr: string (required)
  • maxWorkUnit: number (required)
Manually advances matching for a market.

placeTwapOrder

Returns: Promise<PlaceOrderResult>
  • marketName: string (required)
  • size: number (required) – in chain units
  • isBuy: boolean (required)
  • isReduceOnly: boolean (required)
  • clientOrderId: string (optional)
  • twapFrequencySeconds: number (required)
  • twapDurationSeconds: number (required)
  • builderAddress: string (optional)
  • builderFees: number (optional)
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)
Schedules recurring order slices over time.

cancelTwapOrder

Returns: Promise<CommittedTransactionResponse>
  • orderId: string (required)
  • marketAddr: string (required)
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)
Stops a TWAP order stream.

updateOrder

Returns: Promise<CommittedTransactionResponse>
  • orderId: number | string (required)
  • marketAddr: string (required)
  • price: number (required) – in chain units
  • size: number (required) – in chain units
  • isBuy: boolean (required)
  • timeInForce: TimeInForce (required)
  • isReduceOnly: boolean (required)
  • tpTriggerPrice: number (optional)
  • tpLimitPrice: number (optional)
  • slTriggerPrice: number (optional)
  • slLimitPrice: number (optional)
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)
Updates an existing order and optionally rewrites attached TP/SL values. placeOrder argument shape

Spot trading

All spot helpers are subaccount-scoped (defaulting to the primary Trading Account) and accept the market as marketName (address derived on the client) or marketAddr — the same selection rule as cancelOrder.
Spot placement is asynchronous when funding requires a rate-limited CBS withdrawal: the transaction succeeds but the order is queued, not resting. placeSpotOrder reports this via pendingCbs: true. Resolve the outcome with read.userOrders.getOrder({ assetType: "spot" }) or read.userOrderHistory.getByAddr({ assetType: "spot" }), which cover every terminal state. read.userOpenOrders.getByAddr({ assetType: "spot" }) only sees orders that rest — an IOC order fills or cancels the moment it is placed and never appears there, so an empty result is not evidence that it is still queued.

placeSpotOrder

Returns: Promise<PlaceSpotOrderResult>
  • marketName: string (required if marketAddr not provided)
  • marketAddr: string (required if marketName not provided)
  • price: number (required) – in chain units (quote decimals)
  • size: number (required) – in chain units (base decimals)
  • isBuy: boolean (required)
  • timeInForce: TimeInForce (required) – GTC, PostOnly, or IOC
  • builderAddr: string (optional)
  • builderFee: number (optional) – in basis points
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)
  • tickSize: number (optional) – auto-rounds the price to a tick multiple in the side-safe direction (buys round down, sells round up — the price is a limit/IOC bound, so rounding never crosses it)
Places a spot limit order. Funds are sourced from the subaccount PFS first, then the remainder from CBS.
There is no market order on chain for spot. A “market” order is an IOC limit submitted at the slippage cap, and that submitted price — not the reference mid — is the price a bid’s escrow is reserved at.To report the price an order was actually submitted at, pre-round with the exported roundToTickSizeForSide helper. It is the same function tickSize applies internally and is idempotent, so it does not change the submitted value.

roundToTickSizeForSide

Returns: number
  • price: number (required) – in chain units
  • tickSize: number (required) – the market’s tick size, in chain units
  • isBuy: boolean (required)
Rounds a price to a tick multiple in the side-safe direction: buys round down so the order never pays above the caller’s cap, sells round up so it never accepts below the caller’s floor. Nearest-tick rounding would let a non-aligned cap cross the configured limit or slippage bound.
Scale to chain units without rounding first. Helpers like amountToChainUnits round to the nearest integer, which can carry a price across a tick boundary before the side-safe pass ever sees it — a buy cap of 4.5450996 scales to 4_545_099.6, which nearest-integer rounding turns into the already-aligned 4_545_100, a price above the cap. Pass the exact fractional value (price * 10 ** px_decimals) instead.

cancelSpotOrder

Returns: Promise<CommittedTransactionResponse>
  • orderId: number | string (required)
  • marketName / marketAddr: string (one required)
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)

placeSpotBulkOrder

Returns: Promise<CommittedTransactionResponse>
  • sequenceNumber: number (required) – strictly increasing per market
  • bidPrices / bidSizes / askPrices / askSizes: number[] (required) – in chain units
  • builderAddr: string (optional), builderFee: number (optional, bps)
  • marketName / marketAddr: string (one required)
  • subaccountAddr: string (optional)
Places (or replaces) a spot bulk order. Funds are sourced from the subaccount’s PFS only — the transaction aborts if the PFS is short on either side.

cancelSpotBulkOrder / cancelSpotBulkOrderAtPriceLevel

Returns: Promise<CommittedTransactionResponse>
  • marketName / marketAddr: string (one required)
  • price: number, isBuy: boolean (at-price-level variant only)
  • subaccountAddr: string (optional)

approveMaxSpotBuilderFee / revokeMaxSpotBuilderFee

Returns: Promise<CommittedTransactionResponse>
  • builderAddr: string (required) – unlike perp, may be a subaccount or a primary wallet
  • maxFee: number (approve only, required) – in basis points
  • subaccountAddr: string (optional)

setHoldAsNonCollateral

Returns: Promise<CommittedTransactionResponse>
  • assetAddr: string (required) – asset metadata object address
  • hold: boolean (required)
  • subaccountAddr: string (optional)
When enabled, future deposits of the asset stay in the PFS (non-collateral) instead of routing into CBS collateral. Flag-only: existing balances are not moved.

processSpotPendingRequests

Returns: Promise<{ success: boolean; transactionHash: string }>
  • marketName / marketAddr: string (one required)
  • maxFills: number (required)
Permissionless crank for pending async spot matching requests (spot analog of triggerMatching).

Position TP/SL helpers

placeTpSlOrderForPosition

Returns: Promise<CommittedTransactionResponse>
  • marketAddr: string (required)
  • tpTriggerPrice: number (optional)
  • tpLimitPrice: number (optional)
  • tpSize: number (optional)
  • slTriggerPrice: number (optional)
  • slLimitPrice: number (optional)
  • slSize: number (optional)
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)
  • tickSize: number (optional) – auto-rounds prices to tick multiples
Places both take-profit and stop-loss orders for a position.

updateTpOrderForPosition

Returns: Promise<CommittedTransactionResponse>
  • marketAddr: string (required)
  • prevOrderId: number | string (required)
  • tpTriggerPrice: number (optional)
  • tpLimitPrice: number (optional)
  • tpSize: number (optional)
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)
  • tickSize: number (optional) – auto-rounds prices to tick multiples
Updates an existing take-profit order.

updateSlOrderForPosition

Returns: Promise<CommittedTransactionResponse>
  • marketAddr: string (required)
  • prevOrderId: number | string (required)
  • slTriggerPrice: number (optional)
  • slLimitPrice: number (optional)
  • slSize: number (optional)
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)
  • tickSize: number (optional) – auto-rounds prices to tick multiples
Updates an existing stop-loss order.

cancelTpSlOrderForPosition

Returns: Promise<CommittedTransactionResponse>
  • marketAddr: string (required)
  • orderId: number | string (required)
  • subaccountAddr: string (optional)
  • accountOverride: Account (optional)
Cancels a TP/SL order.

Delegation and builder fees

delegateTradingToForSubaccount

Returns: Promise<CommittedTransactionResponse>
  • subaccountAddr: string (required)
  • accountToDelegateTo: string (required)
  • expirationTimestampSecs: number (optional)
Grants an operator permission to trade on behalf of the Trading Account.

revokeDelegation

Returns: Promise<CommittedTransactionResponse>
  • subaccountAddr: string (optional) – defaults to primary subaccount
  • accountToRevoke: string (required)
Removes trading delegation from an operator.

approveMaxBuilderFee

Returns: Promise<CommittedTransactionResponse>
  • builderAddr: string (required)
  • maxFee: number (required) – in basis points
  • subaccountAddr: string (optional) – defaults to primary subaccount
Approves a maximum builder fee for a Trading Account.

revokeMaxBuilderFee

Returns: Promise<CommittedTransactionResponse>
  • builderAddr: string (required)
  • subaccountAddr: string (optional) – defaults to primary subaccount
Revokes a previously approved builder fee.

Vault transactions

Vault lifecycle helpers call the same on-chain entry functions documented in the Vault Integration Guide. That guide uses only DecibelWriteDex / DecibelReadDex for TypeScript.On Aptos testnet, a full smoke flow needs about 210 USDC in the contributor subaccount (100_000_000 creation fee + 100_000_000 minimum initialFunding + 10_000_000 minimum follow-on depositToVault). See the funding table in the guide.End-to-end reference: typescript/packages/e2e/src/vault-e2e.ts — run cd typescript/packages/e2e && pnpm start:vault-e2e (.env.example lists required keys).
Gas Station (optional) — Omit gasStationApiKey to have users pay gas with APT; createVault, depositToVault, withdrawFromVault, and placeOrder work as usual. If gasStationApiKey is set, custom Move calls (e.g. testnet restricted_mint) and manually signed build* transactions must use buildTx + submitTx instead of aptos.transaction.build.simple. See Gas Station and vault guide steps 5 and 9. The vault-e2e script enables Gas Station on testnet for convenience only.
createVault, depositToVault, and withdrawFromVault build, sign, and submit in one call. The build* helpers below return a SimpleTransaction for custom signing (for example fee-payer flows).
Redemptions go through withdrawFromVault, which calls dex_accounts_entry::redeem_from_vault. There is no build* counterpart for redemption.

createVault

Returns: Promise<CommittedTransactionResponse> Same parameters as CreateVaultArgs (see type references), plus optional subaccountAddr and accountOverride. Submits vault_api::create_and_fund_vault. Parse the new vault address with extractVaultAddressFromCreateTx.

depositToVault

Returns: Promise<CommittedTransactionResponse>
  • vaultAddress: string (required)
  • amount: number (required) — USDC in chain units (6 decimals)
  • subaccountAddr: string (required) — contributor’s Trading Account

withdrawFromVault

Returns: Promise<CommittedTransactionResponse>
  • vaultAddress: string (required)
  • shares: number (required) — share amount in chain units (minimum redemption is about 5_000_000 units, ~$5 at 6 decimals on testnet)
  • subaccountAddr: string (optional) — defaults to primary subaccount
Read current_num_shares before redeeming: read.vaults.getUserPerformancesOnVaults({ ownerAddr: subaccountAddr }) — ownerAddr must be the contributor’s Trading Account (subaccount), not the wallet address. All build* vault helpers accept WithSignerAddress<T> (payload plus signerAddress).

buildCreateVaultTx

Returns: Promise<SimpleTransaction>
  • contributionAssetType: string (optional)
  • vaultName: string (required)
  • vaultDescription: string (required)
  • vaultSocialLinks: string[] (required)
  • vaultShareSymbol: string (required)
  • vaultShareIconUri: string (optional)
  • vaultShareProjectUri: string (optional)
  • feeBps: number (required)
  • feeIntervalS: number (required)
  • contributionLockupDurationS: number (required)
  • initialFunding: number (optional, default 0)
  • acceptsContributions: boolean (optional, default false)
  • delegateToCreator: boolean (optional, default false)
  • signerAddress: AccountAddress (required)
Builds a transaction to create a new vault. createVault applies the same defaults.

buildActivateVaultTx

Returns: Promise<SimpleTransaction>
  • vaultAddress: string (required)
  • signerAddress: AccountAddress (required)
Builds a transaction to activate a vault.

buildDepositToVaultTx

Returns: Promise<SimpleTransaction>
  • vaultAddress: string (required)
  • amount: number (required)
  • signerAddress: AccountAddress (required)
Builds a transaction to deposit funds into a vault.

buildDelegateDexActionsToTx

Returns: Promise<SimpleTransaction>
  • vaultAddress: string (required)
  • accountToDelegateTo: string (required)
  • signerAddress: AccountAddress (required)
  • expirationTimestampSecs: number (optional)
Builds a transaction to delegate DEX actions for a vault.

Trading on behalf of a vault

Vault trading is not a separate API. After the vault creator (or a delegate) is authorized via delegateToCreator or buildDelegateDexActionsToTx, call placeOrder, cancelOrder, TP/SL, or TWAP with subaccountAddr set to the vault portfolio subaccount — not your wallet’s primary subaccount. Derive the vault subaccount from the vault object address:
Use a market name that exists on your target network. The pattern above matches typescript/packages/e2e/src/vault-e2e.ts in this repository. That script runs create → depositToVault → withdrawFromVault → delegate → placeOrder on testnet. For the full vault launch walkthrough (mint, fund, create, delegate), see the Vault Integration Guide.

TWAP and notification helpers

placeTwapOrder, cancelTwapOrder, and the readers exposed under read.userActiveTwaps bridge the trading + monitoring workflow. For notification rendering, reference the Rust trading API docs.

Campaign rewards

claimCampaignReward

Returns: Promise<CommittedTransactionResponse>
  • campaignId: number (required)
Claims a reward allocation from the campaign package by numeric campaign ID.

Funded First Trade

openFftTrial / claimFftUnlock / settleFftTrial

Returns: Promise<CommittedTransactionResponse>
  • campaignPackage: string (required)
  • campaignAddr: string (required)
  • owner: string (openFftTrial / claimFftUnlock), lockId: bigint (claimFftUnlock), trialId: number (settleFftTrial)
Session-key-friendly FFT entries: openFftTrial and claimFftUnlock accept a signer that is the owner or a TradePerpsAllMarkets delegate on the owner’s primary subaccount; settleFftTrial is permissionless. Locking (buildLockPayload / buildLockFromSubaccountPayload) stays wallet-signed — those entries move the owner’s own funds.

Session keys and overrides

All transaction helpers accept an accountOverride to sign with a different account (e.g., a session key) while the SDK was constructed with the primary account:

Submission failures

Write submission errors throw TransactionSubmissionError(message, submission, cause?). placeOrder instead returns { success: false, error, submission? }. The exported getTransactionSubmissionFailure(error) reads metadata from this typed error, without inspecting private Aptos error fields; untyped errors have no provenance. not-submitted means the SDK proved failure before transport, such as building or signing. reverted means a committed user transaction explicitly failed. unknown means the transaction may have committed; a known acknowledgment hash is retained if waiting fails. Missing provenance from a custom override also means unknown. Custom wallet submitters can use submitAndWaitForTransaction(aptos, () => wallet.signAndSubmitTransaction(...)) to submit once, validate confirmation, and retain the same failure metadata. Untyped callback errors remain unknown; proven pre-submit failures should throw TransactionSubmissionError with outcome: "not-submitted". unknown is unresolved, not terminal. Later evidence can establish success or revert; an empty or failed lookup may leave the attempt unresolved indefinitely and does not authorize another submission. The error is a snapshot: the SDK does not persist attempts or recover them automatically. A successful order result with a missing orderId still carries its committed transactionHash. Read that original transaction and use extractOrderIdFromTransaction to decode its order identity; missing events do not authorize a replacement order.

Type references