Skip to main content
A TWAP (time-weighted average price) splits a larger trade into smaller slices executed over time. In Velora, a TWAP is a Delta order: the user signs one scheduled order, and Delta settles each eligible slice gaslessly through the Portikus solver network until the order completes or expires. You build TWAPs through the same sdk.delta module as market Delta orders, using submitTWAPDeltaOrder (or the buildTWAPDeltaOrder split flow). The defining inputs are the total amount, the number of slices, and the interval between them.
For the conceptual model (slices, intervals, sell vs. buy, how TWAP differs from a one-shot swap or a limit order), see Product stack → TWAP.

When to use this

  • A one-shot swap is too sensitive to execute at a single market moment (large size, thin pair).
  • You want to spread execution across time to reduce price impact and timing risk.
  • You want the whole schedule to settle gaslessly from a single signature.

Sell vs. buy

  • Sell TWAP (onChainOrderType: "TWAPOrder") fixes the total source amount and splits it across slices. Use totalSrcAmount.
  • Buy TWAP (onChainOrderType: "TWAPBuyOrder"): fixes the total destination amount to receive and splits that target across slices, while capping the total source spent. Use totalDestAmount and maxSrcAmount.

The flow

The build → sign → post → poll flow mirrors a market Delta order, with one wrinkle: you quote a single slice, not the whole order.
1

Quote one slice

Call sdk.delta.getDeltaPrice for a single slice: the per-slice amount, i.e. floor(total / numSlices). The route’s amount must match that per-slice amount; the server multiplies it across the schedule.
2

Approve the source token (or sign a Permit)

Approve the total source amount (totalSrcAmount for sell, maxSrcAmount for buy) with sdk.delta.approveTokenForDelta, or sign a Permit / Permit2 message. Native tokens skip this step.
3

Build, sign, and post the schedule

Call sdk.delta.submitTWAPDeltaOrder with the schedule, or run buildTWAPDeltaOrdersignDeltaOrderpostTWAPDeltaOrder yourself when you need control over signing.
4

Poll for slice execution

Poll sdk.delta.getDeltaOrderById over the order’s lifetime; it completes once the final slice settles, or fails/expires if its constraints can no longer be met.

One-call submit (sell TWAP)

const numSlices = 4;
const totalSrcAmount = "10000000000"; // 10,000 USDC total
const perSlice = (BigInt(totalSrcAmount) / BigInt(numSlices)).toString();

// quote ONE slice; the route amount must equal floor(totalSrcAmount / numSlices)
const price = await sdk.delta.getDeltaPrice({
  srcToken: USDC,
  destToken: ETH,
  amount: perSlice,
  srcDecimals: 6,
  destDecimals: 18,
  userAddress: account,
  partner: "my-app-name",
});

// approve the TOTAL amount, not a single slice
await sdk.delta.approveTokenForDelta(totalSrcAmount, USDC);

const auction = await sdk.delta.submitTWAPDeltaOrder({
  onChainOrderType: "TWAPOrder",
  route: price.route,
  owner: account,
  totalSrcAmount,
  numSlices, // min 2
  interval: 300, // seconds between slices, min 60
  slippage: 50, // 0.5% in bps
  partner: "my-app-name",
  deadline: Math.floor(Date.now() / 1000) + 60 * 60 * 6, // required, unix seconds
});

console.log("twap order id:", auction.id);

Buy TWAP

A buy TWAP fixes how much you want to receive and caps what you’ll spend. Quote a single slice by the per-slice destination amount, then submit with totalDestAmount and maxSrcAmount:
const auction = await sdk.delta.submitTWAPDeltaOrder({
  onChainOrderType: "TWAPBuyOrder",
  route: price.route, // single-slice quote; route.origin.output.amount = floor(totalDestAmount / numSlices)
  owner: account,
  totalDestAmount: "3000000000000000000", // 3 ETH to receive across all slices
  maxSrcAmount: "10100000000", // cap total USDC spent (10,100 USDC)
  numSlices: 4,
  interval: 300,
  slippage: 50,
  partner: "my-app-name",
  deadline: Math.floor(Date.now() / 1000) + 60 * 60 * 6, // required, unix seconds
});

Split flow

Use the three-step flow when you need to customize signing (a hardware wallet, an async multisig, or batched signing).
const built = await sdk.delta.buildTWAPDeltaOrder({
  onChainOrderType: "TWAPOrder",
  route: price.route,
  owner: account,
  totalSrcAmount,
  numSlices,
  interval: 300,
  slippage: 50,
  partner: "my-app-name",
  deadline: Math.floor(Date.now() / 1000) + 60 * 60 * 6, // required, unix seconds
});

const signature = await sdk.delta.signDeltaOrder(built);

const auction = await sdk.delta.postTWAPDeltaOrder({
  order: built.toSign.value,
  signature,
  partner: "my-app-name",
});
signDeltaOrder is the same generic signer used for market and limit orders; there’s no TWAP-specific signing call.

Poll, list, and cancel

import { OrderHelpers } from "@velora-dex/sdk";

// poll until every slice has settled
const updated = await sdk.delta.getDeltaOrderById(auction.id);
if (OrderHelpers.checks.isExecutedAuction(updated)) {
  console.log("twap complete");
}
List a user’s orders with sdk.delta.getDeltaOrders and narrow on onChainOrderType ("TWAPOrder" / "TWAPBuyOrder") to surface their TWAPs. Cancel the remaining (unsettled) slices with sdk.delta.cancelDeltaOrders({ orderIds: [auction.id] }).

Partner fee

Pass partner (and optionally partnerAddress, partnerFeeBps, partnerTakesSurplus) to getDeltaPrice, submitTWAPDeltaOrder, buildTWAPDeltaOrder, and postTWAPDeltaOrder, exactly as with market Delta orders. See Monetize for the full field reference.
Last modified on June 14, 2026