# List Delta solver agents Source: https://new-docs.velora.xyz/docs/api-reference/delta/agents-list api-reference/specs/delta-v2.json GET /v2/delta/agents/list/{chainId} List the active solver agents competing in the auction for a chain. Use the names to filter pricing via includeAgents / excludeAgents. # List Crosschain Delta bridge protocols Source: https://new-docs.velora.xyz/docs/api-reference/delta/bridge-protocols api-reference/specs/delta-v2.json GET /v2/delta/prices/bridge-protocols Active bridge protocols (slug, display name, icon) for rendering a bridge picker. # List Crosschain Delta bridge routes Source: https://new-docs.velora.xyz/docs/api-reference/delta/bridge-routes api-reference/specs/delta-v2.json GET /v2/delta/prices/bridge-routes Crosschain bridge-route catalogue: every supported (srcChainId, destChainId, tokens) triple. # Check Delta token support Source: https://new-docs.velora.xyz/docs/api-reference/delta/is-token-supported api-reference/specs/delta-v2.json GET /v2/delta/prices/is-token-supported Quick yes/no check for token support on a chain. # Build a Delta order Source: https://new-docs.velora.xyz/docs/api-reference/delta/orders-build api-reference/specs/delta-v2.json POST /v2/delta/orders/build Server-built EIP-712 typed data ready to sign. Pass the route from /v2/delta/prices verbatim. # Cancel Delta orders Source: https://new-docs.velora.xyz/docs/api-reference/delta/orders-cancel api-reference/specs/delta-v2.json POST /v2/delta/orders/cancel Cancel one or more open Delta V2 orders by ID. # Get Delta fillable balance Source: https://new-docs.velora.xyz/docs/api-reference/delta/orders-fillable-balance api-reference/specs/delta-v2.json GET /v2/delta/orders/fillablebalance/{chainId}/{userAddress}/{tokenAddress} User's source-token amounts already committed to open limit orders. Use it when sizing a new limit order. # Get Delta order by hash Source: https://new-docs.velora.xyz/docs/api-reference/delta/orders-get-by-hash api-reference/specs/delta-v2.json GET /v2/delta/orders/hash/{hash} Fetch a Delta V2 order by its EIP-712 hash, useful before the order id is assigned. # Get Delta order by ID Source: https://new-docs.velora.xyz/docs/api-reference/delta/orders-get-by-id api-reference/specs/delta-v2.json GET /v2/delta/orders/{orderId} Fetch a Delta V2 order by its UUID, the id returned by POST /v2/delta/orders. # List Delta orders Source: https://new-docs.velora.xyz/docs/api-reference/delta/orders-list api-reference/specs/delta-v2.json GET /v2/delta/orders Paginated list of a user's Delta V2 orders, filterable by chain, status, type, and on-chain order type. # Submit a Delta order Source: https://new-docs.velora.xyz/docs/api-reference/delta/orders-submit api-reference/specs/delta-v2.json POST /v2/delta/orders Submit a signed Delta V2 order. The relayer validates signature, balance, and allowance, then enrolls it into the sealed-bid auction. # Delta API reference Source: https://new-docs.velora.xyz/docs/api-reference/delta/overview Delta V2 cuts client-side work out of Delta integrations: the server builds EIP-712 orders ready to sign, prices come back as a route with alternatives, order history is paginated, and one status field follows an order end to end. Build new Delta integrations on V2. The server carries most of the protocol work, so your client stays thin: * Orders come back from `POST /v2/delta/orders/build` as EIP-712 typed data ready to sign. You never compose `domain`, `types`, and `value` yourself. * `GET /v2/delta/prices` recommends a `route` and lists `alternatives`, so users can pick a different bridge or path. * Order history is paginated: `GET /v2/delta/orders` returns `{ data, total, page, limit, hasMore }`. * A single `status` field covers the whole lifecycle (`PENDING`, `AWAITING_SIGNATURE`, `ACTIVE`, `SUSPENDED`, `CANCELLING`, `BRIDGING`, `COMPLETED`, `FAILED`, `EXPIRED`, `REFUNDING`, `CANCELLED`, `REFUNDED`), replacing the V1 split between `status` and `bridgeStatus`. * Crosschain bridge refunds include a top-level `refunds[]` array once Velora verifies the refund transaction receipt. Each item carries `tx`, `chainId`, `token`, and raw-unit `amount`. * Partner fees are resolved server-side. Pass `partner` / `partnerAddress` / `partnerFeeBps` raw; the server validates and encodes them, and the `getPartnerFee` round-trip disappears. ## Lifecycle `GET /v2/delta/prices` — returns `route`, `alternatives`, and the `spender` contract address. ERC-20 `approve(spender, amount)` against `price.spender`, or sign Permit / Permit2 with the same `verifyingContract`. Native tokens skip this. `POST /v2/delta/orders/build` — returns `{ toSign: { domain, types, value }, orderHash }`. Sign `toSign` with `signTypedData` on the user's wallet. `POST /v2/delta/orders` — passes `order: toSign.value` and `signature` to the relayer. `GET /v2/delta/orders/{orderId}` until `status === "COMPLETED"` or a terminal status such as `FAILED`, `EXPIRED`, `CANCELLED`, or `REFUNDED`. ## Endpoints | Method | Path | Purpose | | ------ | --------------------------------------- | ---------------------------------------------------------- | | `GET` | `/v2/delta/prices` | Recommended route + alternatives, same-chain or crosschain | | `GET` | `/v2/delta/prices/bridge-routes` | Supported `(srcChainId, destChainId, tokens)` triples | | `GET` | `/v2/delta/prices/bridge-protocols` | Active bridge protocols (slug, name, icon) | | `GET` | `/v2/delta/prices/strategies/{chainId}` | Delta yield strategies with APR | | `GET` | `/v2/delta/prices/is-token-supported` | Quick token-support check | | `POST` | `/v2/delta/orders/build` | Server-built EIP-712 typed data ready to sign | | `POST` | `/v2/delta/orders` | Submit a signed order | | `POST` | `/v2/delta/orders/cancel` | Sign-and-post cancellation | | `GET` | `/v2/delta/orders` | List a user's orders (paginated) | | `GET` | `/v2/delta/orders/{orderId}` | Order by UUID | | `GET` | `/v2/delta/orders/hash/{hash}` | Order by EIP-712 hash | | `GET` | `/v2/delta/orders/fillablebalance/...` | Fillable balance for limit-order sizing | | `GET` | `/v2/delta/agents/list/{chainId}` | List active auction agents | ## SDK shortcut Every endpoint is wrapped by [`sdk.delta.*`](/docs/sdk/products/delta), which handles signing, partner-fee defaults, and the build → sign → post orchestration. For a 5-minute walkthrough see [SDK → Delta](/docs/sdk/products/delta). ## Related pages * [Why Delta](/docs/delta/overview) — protocol overview. * [SDK → Delta](/docs/sdk/products/delta) — TypeScript examples. * [Migrating from Delta V1](/docs/resources/migrations/delta-v1-to-v2) — endpoint-by-endpoint guide from the V1 surface. # Get Delta prices Source: https://new-docs.velora.xyz/docs/api-reference/delta/prices api-reference/specs/delta-v2.json GET /v2/delta/prices Recommended route plus alternatives for a same-chain or crosschain Delta V2 swap. # Get a Delta quote Source: https://new-docs.velora.xyz/docs/api-reference/delta/quote api-reference/specs/delta-v2.json GET /v2/quote Unified Delta V2 quote: a route-based delta price with optional Market fallback. Use mode=DELTA for Delta-only. `GET /v2/quote` is the entry point of the Delta flow: it returns a `delta` block (a gasless, MEV-protected intent price) and, with `mode=ALL`, falls back to a ready-to-build Market route when no solver can fill. You never compare routes client-side; `fallbackReason` tells you why a downgrade happened. See [Trading modes](/docs/integrate/trading-modes) for the `mode` semantics. With `mode=DELTA` the response carries a single `delta` block: a Delta V2 price with `route` + `alternatives` (no `hmac`). Pass `delta.route` verbatim to [`POST /v2/delta/orders/build`](/docs/api-reference/delta/orders-build). For the raw price object without the quote envelope, use [`GET /v2/delta/prices`](/docs/api-reference/delta/prices). # List Delta yield strategies Source: https://new-docs.velora.xyz/docs/api-reference/delta/strategies api-reference/specs/delta-v2.json GET /v2/delta/prices/strategies/{chainId} Delta yield strategies (with APR) wired for ProductiveOrder swaps, keyed by underlying token. # Velora REST API reference Source: https://new-docs.velora.xyz/docs/api-reference/introduction The Velora REST API: gasless Swap (Delta) intents, Market aggregation, and OTC orders across 10+ EVM chains over HTTPS, with no key required to start. The Velora REST API is best execution over HTTPS: gasless intents, DEX aggregation, and on-chain OTC across 10+ EVM chains. It works from any language and stack, with no SDK to install and no key to get started. ## Three APIs, one base URL Everything lives under `https://api.velora.xyz`. Gasless, MEV-protected swaps and signed orders, same-chain or crosschain. One signature. Best price across every major DEX and AMM, returned as ready-to-send calldata. AugustusRFQ orders between known counterparties. A maker signs and posts gasless; the named taker fills on-chain. Partial fills supported. ## Your first call No key required; pass a `partner` value that identifies your app or project (the examples use `my-app-name` as a placeholder — replace it). Quote 1 ETH → USDC and let Velora pick the best path with `mode=ALL`: ```bash theme={null} curl -s "https://api.velora.xyz/v2/quote" \ --data-urlencode "srcToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" \ --data-urlencode "destToken=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" \ --data-urlencode "amount=1000000000000000000" \ --data-urlencode "srcDecimals=18" \ --data-urlencode "destDecimals=6" \ --data-urlencode "side=SELL" \ --data-urlencode "chainId=1" \ --data-urlencode "mode=ALL" \ --data-urlencode "userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" \ --data-urlencode "partner=my-app-name" \ -G | jq ``` The response carries either a `delta` block (gasless: sign and submit later) or a `market` block (calldata: submit now). Branch on whichever is present. See [Trading modes](/docs/integrate/trading-modes), or the [Quickstart](/docs/overview/quickstart) for SDK and Widget versions. ## Auth & rate limits `partner` is your free, no-signup app identifier, not a secret. Pass `&partner=my-app-name` (a placeholder; use a stable value for your integration) on quote, swap, and order endpoints. Need higher RPS, larger quotas, analytics, and SLA support? See [Pro API accounts](/docs/overview/pro-api-accounts). Need contract addresses at runtime? [`contracts.json`](/docs/resources/contracts.json) has canonical per-chain addresses for Augustus v6.2, Delta, and the Fee Vault, keyed by `chainId`. Human-readable: [Chains & contracts](/docs/resources/chains-and-contracts). ## Next steps First quote in 60 seconds with cURL, the SDK, or the Widget. Common failure modes by endpoint: symptom, cause, fix. # Market API reference Source: https://new-docs.velora.xyz/docs/api-reference/market/overview The Market API finds the best price across major DEXs and AMMs on 10+ EVM chains and returns it as ready-to-broadcast Augustus v6.2 calldata. The Market API is Velora's DEX aggregator, served as a REST API. One request prices your swap, a second turns the quote into calldata for the [Augustus v6.2](/docs/resources/chains-and-contracts) router, and you sign and broadcast it yourself. All you need to start is a `partner` string to tag your app. Want gasless, MEV-protected swaps instead of self-broadcast calldata? Call [`GET /v2/quote`](/docs/api-reference/market/quote) with `mode=ALL` and Velora returns a Delta intent or a Market route, whichever is better. See [Trading modes](/docs/integrate/trading-modes). ## Lifecycle `GET /prices` — returns the optimal `priceRoute` (`destAmount`, `gasCostUSD`, `bestRoute`, and an `hmac` integrity tag). `POST /transactions/:chainId` — turns the `priceRoute` into a broadcastable `txParams` envelope. Attach `permit` / `permit2` here to skip the approve tx. ERC-20 `approve(to, amount)` against the Augustus v6.2 router (`txParams.to`). Native sources (ETH) skip this; the amount rides in `txParams.value`. Estimate gas locally, sign `txParams`, and broadcast. Settlement is atomic: it reverts if the delivered amount falls below the slippage-adjusted minimum. In a hurry? [`GET /swap`](/docs/api-reference/market/swap) fuses price + build into one call, at lower rate limits and without RFQ liquidity. ## Endpoints | Method | Path | Purpose | | ------ | -------------------------------------------------------------- | -------------------------------------------------------------------------------- | | `GET` | [`/v2/quote`](/docs/api-reference/market/quote) | Delta intent or Market route from one request (`mode=DELTA`, `MARKET`, or `ALL`) | | `GET` | [`/prices`](/docs/api-reference/market/prices) | Best route for a token pair — inspect, display, or cache it | | `POST` | [`/transactions/:chainId`](/docs/api-reference/market/transactions) | Build ready-to-broadcast calldata from a `priceRoute` | | `GET` | [`/swap`](/docs/api-reference/market/swap) | Route + ready-to-broadcast tx in a single call | ## SDK shortcut Every endpoint is wrapped by [`sdk.swap.*`](/docs/sdk/products/swap). The SDK handles the price → build orchestration, allowance checks, and partner-fee defaults. For a 5-minute walkthrough see [SDK → Market](/docs/sdk/products/swap). ## Related pages * [Why Market API](/docs/market/overview) — when atomic, self-broadcast execution is the right choice. * [How Market works](/docs/market/how-it-works) — price → build → approve → settle, end to end. * [Market examples](/docs/market/examples/typescript) — copy-paste TypeScript, Python, Go, and Rust. * [Monetization](/docs/overview/monetization) — partner fees and positive slippage via `partner` / `partnerFeeBps`. * [Troubleshooting](/docs/api-reference/troubleshooting) — Market failure modes by symptom, cause, and fix. * [Pro API accounts](/docs/overview/pro-api-accounts) — higher RPS, quotas, and SLA support. # Get Market price route Source: https://new-docs.velora.xyz/docs/api-reference/market/prices api-reference/specs/market.json GET /prices Get a Market route from the Velora aggregator. Looking for a single endpoint that returns either a Market route or a Delta intent? Call [`GET /v2/quote`](/docs/api-reference/market/quote) with `mode=ALL`; see [Trading modes](/docs/integrate/trading-modes). # Get a unified quote Source: https://new-docs.velora.xyz/docs/api-reference/market/quote api-reference/specs/delta-v2.json GET /v2/quote Retrieve a Delta price, with optional fallback to Market via mode=ALL or mode=MARKET. With `mode=ALL`, `GET /v2/quote` upgrades a Market swap to a gasless, MEV-protected Delta intent whenever a solver can fill, and otherwise returns a `market` block with the same shape as the [`GET /prices`](/docs/api-reference/market/prices) `priceRoute`, ready for [`POST /transactions/:chainId`](/docs/api-reference/market/transactions). Routing is decided server-side; when the response falls back to Market, `fallbackReason` explains why. This endpoint accepts `mode=DELTA`, `mode=MARKET`, or `mode=ALL`. See [Trading modes](/docs/integrate/trading-modes) for guidance and fallback semantics. # Get Market swap price and calldata Source: https://new-docs.velora.xyz/docs/api-reference/market/swap api-reference/specs/market.json GET /swap Price and calldata in one call: GET /prices and POST /transactions fused into a single Market request. `GET /swap` fuses the two Market steps into one request: it runs aggregator [pricing](/docs/api-reference/market/prices) and [calldata generation](/docs/api-reference/market/transactions) server-side and hands back both the `priceRoute` and ready-to-broadcast `txParams`. One round-trip takes you from "what's the rate?" to a transaction you can sign and send. Prefer the two-step flow ([`GET /prices`](/docs/api-reference/market/prices) → [`POST /transactions/:chainId`](/docs/api-reference/market/transactions)) when you need to inspect or cache the route before committing, manage allowances yourself, or attach `permit` / `permit2` data. `/swap` trades that control for a single call. ## When to use it | Reach for `/swap` when… | Use the two-step flow when… | | --------------------------------------------------- | ------------------------------------------------------------- | | You want the fastest path from quote to signable tx | You need to inspect, display, or cache the `priceRoute` first | | One server round-trip matters (latency, simplicity) | You attach `permit` / `permit2` to skip the approve tx | | Server-built calldata with defaults is fine | You need RFQ liquidity or finer routing/fee control | ## Response A `200` returns two objects: * **`priceRoute`** — the routing plan: `bestRoute`, `srcAmount` / `destAmount`, `gasCost` / `gasCostUSD`, `srcUSD` / `destUSD`, `contractMethod`, `version`, and an `hmac` integrity tag. Same shape as [`GET /prices`](/docs/api-reference/market/prices). * **`txParams`** — a broadcastable tx envelope: `from`, `to` (the Augustus v6.2 router), `value`, `data` (encoded swap), `gasPrice`, and `chainId`. **No `gas` field** — estimate it locally. ```json theme={null} { "priceRoute": { "blockNumber": 20184108, "network": 1, "srcToken": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "srcDecimals": 6, "srcAmount": "1000000", "destToken": "0x6b175474e89094c44da98b954eedeac495271d0f", "destDecimals": 18, "destAmount": "997620341641628401", "bestRoute": ["…"], "gasCostUSD": "5.932529", "contractMethod": "swapExactAmountIn", "version": "6.2", "hmac": "…" }, "txParams": { "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "to": "0x6a000f20005980200259b80c5102003040001068", "value": "0", "data": "0xe3ead59e…", "gasPrice": "16000000000", "chainId": 1 } } ``` ## Broadcasting the transaction `txParams` is ready to send, but `/swap` skips allowance and balance checks and returns no `gas` field. Before broadcasting: Approve the Augustus v6.2 router (`txParams.to`) to spend `srcToken` with a standard `approve(to, amount)`. Native sources (ETH, etc.) skip this; the amount rides along in `txParams.value`. To drop the extra transaction, switch to the two-step flow and pass Permit / Permit2 data in the build call. Run `eth_estimateGas` on `txParams` (or simulate the call). The response omits `gas` by design; never broadcast with a hardcoded limit. Sign `txParams` with the user's wallet and broadcast. Settlement is atomic: the swap completes or reverts, and it reverts if the delivered amount falls below the slippage-adjusted minimum. ## Limitations `/swap` runs at lower rate limits than the individual endpoints ([Pro API accounts](/docs/overview/pro-api-accounts) lift them) and excludes RFQ liquidity (AugustusRFQ). For best price across every venue, or to inspect the route before building, use [`GET /prices`](/docs/api-reference/market/prices). * The endpoint validates neither allowance nor balance; your client must ensure the user has approved and funded the swap. * The response carries no `gas` field. Always estimate locally before broadcasting. * Swap & Transfer and fees don't apply to the `swapOnUniswap*` / `swapOnZeroXv*` contract methods. When you set a `receiver` or a partner fee, constrain routing with `includeContractMethods=simpleSwap,multiSwap,megaSwap`. * For tax tokens, DEXs and methods that can't handle transfer-fee tokens are filtered out; declare the fee via `srcTokenTransferFee` / `destTokenTransferFee`. ## Key parameters * **`userAddress`** (required) — the caller, used as the tx `from` and for fee/surplus accounting. When using an intermediary contract, `userAddress` should correspond to `msg.sender` and `receiver` to the recipient. * **`slippage`** — basis points: `100` = 1%, `250` = 2.5%, max `10000`. * **`version`** — always pass `6.2` (Augustus v6.2); when omitted the API falls back to the legacy v5 router. * **`partner` / `partnerFeeBps` / `partnerAddress`** — monetize the swap; `isSurplusToUser` and `isDirectFeeTransfer` control surplus and fee routing. See [Monetization](/docs/overview/monetization). ## Related pages Pricing only: inspect or cache the route before building. Build calldata from a priceRoute you already hold. Price → build → approve → settle, end to end. Market failure modes: symptom, cause, fix. # Build Market swap transaction Source: https://new-docs.velora.xyz/docs/api-reference/market/transactions api-reference/specs/market.json POST /transactions/{chainId} Build calldata for an Augustus v6.2 swap from a Market priceRoute. # Get OTC fillable balance Source: https://new-docs.velora.xyz/docs/api-reference/rfq/fillable-balance api-reference/specs/rfq.json GET /ft/fillablebalance/{chainId}/{account} A maker's fillable balance per token: the amount reserved by live orders. Return the maker's fillable balance per token: the amount reserved by live orders. Call it before posting a new order so the `makerAmount` is actually backed; an order that exceeds the fillable balance is stored as `SUSPENDED` until the maker tops up balance or allowance. The response maps each lowercase token address to its fillable balance in raw units. Scope to a single token by appending its address: `GET /ft/fillablebalance/:chainId/:account/:token`. ## Related pages Lifecycle, endpoints, and order states end to end. Post an order sized against this balance. AugustusRFQ addresses to approve, per chain. The SDK checks fillable balance before posting. # Get AugustusRFQ order by hash Source: https://new-docs.velora.xyz/docs/api-reference/rfq/orders-get-by-hash api-reference/specs/rfq.json GET /ft/order/{orderHash} Fetch a single AugustusRFQ order by its hash, with current state and remaining fillable balance. Fetch one order by the `orderHash` returned when it was posted. The response is the full order record, including its current `state` and the `fillableBalance` still open for partial fills. Always re-check `expiry` against the current block and confirm `state` is `PENDING` before a taker submits a fill. The on-chain fill reverts if the order is expired, already `FULFILLED`, or `CANCELLED`. ## Related pages Lifecycle, endpoints, and order states end to end. All orders created by a maker, paginated. All orders a given taker can fill. `sdk.otcOrders.getOTCOrders` reads orders by maker or taker. # List maker OTC orders Source: https://new-docs.velora.xyz/docs/api-reference/rfq/orders-list-maker api-reference/specs/rfq.json GET /ft/p2p/{chainId}/maker/{account} List the OTC orders created by a maker on a chain. Paginated, filterable by type. List orders where `account` is the maker. Use `type=P2P` to scope to counterparty-restricted OTC orders. The response is paginated: page through with `limit` and `offset`, and read `total` / `hasMore` to know when you've reached the end. ## Related pages Lifecycle, endpoints, and order states end to end. The mirror endpoint: orders a given taker can fill. Fetch a single order by hash. `sdk.otcOrders.getOTCOrders({ maker })`. # List taker OTC orders Source: https://new-docs.velora.xyz/docs/api-reference/rfq/orders-list-taker api-reference/specs/rfq.json GET /ft/p2p/{chainId}/taker/{account} List the OTC orders addressed to a taker: the orders that account can fill. Paginated. List orders where `account` is the named taker: the orders that address is allowed to fill. Use `type=P2P` to scope to counterparty-restricted OTC orders. Paginated with `limit` and `offset`; `total` / `hasMore` mark the end. This is the endpoint a taker polls to discover orders a maker has addressed to them. ## Related pages Lifecycle, endpoints, and order states end to end. The mirror endpoint: orders created by a maker. Fetch a single order by hash before filling. `sdk.otcOrders.getOTCOrders({ taker })`. # Submit AugustusRFQ OTC order Source: https://new-docs.velora.xyz/docs/api-reference/rfq/orders-submit api-reference/specs/rfq.json POST /ft/p2p/{chainId}/ Post a maker-signed AugustusRFQ order. The server validates the EIP-712 signature, stores the order, and returns it with its orderHash. Submit a maker-signed order to the OTC book. The maker builds the order, signs the EIP-712 typed data, and posts the order fields plus the `signature` here, all without sending a transaction or paying gas. The server verifies the signature against the [AugustusRFQ](/docs/resources/chains-and-contracts) `verifyingContract`, stores the order, and returns it with an `orderHash` and an initial `state`. The `taker` field is what makes an order OTC. Set it to the intended counterparty's address and only that address can fill the order (`type` `P2P`). The EIP-712 domain is `name: "AUGUSTUS RFQ"`, `version: "1"`, the order's `chainId`, and `verifyingContract` set to the AugustusRFQ address for that chain. Size the order against [`GET /ft/fillablebalance/:chainId/:account`](/docs/api-reference/rfq/fillable-balance) first: if `makerAmount` exceeds the maker's balance or AugustusRFQ allowance, the order is accepted but lands in `SUSPENDED`. To skip a separate approve transaction, encode `permitMakerAsset`. ## Related pages Lifecycle, endpoints, and order states end to end. Read back the order you just posted. `sdk.otcOrders.submitOTCOrder` wraps build → sign → post. Signature and order-shape failures: symptom, cause, fix. # OTC API reference Source: https://new-docs.velora.xyz/docs/api-reference/rfq/overview The OTC API settles direct trades between known counterparties: a maker signs an AugustusRFQ order off-chain, and the taker it names fills it on-chain. An OTC trade on Velora is a deal between two parties who already know each other. The **maker** signs an [AugustusRFQ](/docs/resources/chains-and-contracts) order off-chain and posts it to the REST API; the **taker** fills it on-chain. The `taker` field decides who that can be: name an address for a private, P2P trade, or leave the zero address to let anyone fill. To start, tag your app with any `partner` string. * Name the `taker` and the order is fillable by exactly one address: bilateral OTC rather than a public order. * The maker sets price, size, token pair, and `expiry` directly; nothing is exposed as a public order before it settles. * Offering is gasless. The maker only signs (EIP-712) and posts, and the taker pays gas on the fill. * A taker can fill less than the full `makerAmount`; the order stays live for the remainder until `expiry`. * The fill resolves on-chain through AugustusRFQ, so the outcome is auditable and non-custodial. Want an **open, target-price order** any solver can fill, gasless and MEV-protected? That's a Delta limit order, not OTC. Call [`GET /v2/quote`](/docs/api-reference/delta/quote) and submit with `type=LIMIT` via [`POST /v2/delta/orders`](/docs/api-reference/delta/overview). This RFQ surface is specifically for **bilateral OTC/P2P settlement** against a known counterparty. ## Lifecycle The maker approves the **AugustusRFQ** contract to pull the `makerAsset` they're selling. AugustusRFQ is its own contract, separate from the Augustus v6.2 router. Native ETH must be wrapped first. The maker builds the order (`nonceAndMeta`, `expiry`, `makerAsset`, `takerAsset`, `makerAmount`, `takerAmount`, `maker`, `taker`) and signs the EIP-712 typed data. The domain is `name: "AUGUSTUS RFQ"`, `version: "1"`, `chainId`, and `verifyingContract` set to the AugustusRFQ address. `POST /ft/p2p/{chainId}/` with the signed order and `signature`. The server returns the stored order with its `orderHash` and `state`. Size against `GET /ft/fillablebalance/{chainId}/{address}` first; it returns the lesser of the maker's balance, allowance, and unreserved amount. Hand the signed order to the taker over any off-chain channel: your backend, the API listing endpoints, or directly. The taker approves AugustusRFQ for the `takerAsset`, then calls `AugustusRFQ.fillOrder` on-chain. The contract verifies the signature and the named taker, then settles atomically. This is an on-chain transaction, not a REST call. The fill reverts if the order is expired, already filled, or the caller isn't the named taker. ## Endpoints | Method | Path | Purpose | | ------ | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | | `POST` | [`/ft/p2p/{chainId}/`](/docs/api-reference/rfq/orders-submit) | Post a signed maker order — body carries the order fields plus `signature` and optional `permitMakerAsset` | | `GET` | [`/ft/order/{orderHash}`](/docs/api-reference/rfq/orders-get-by-hash) | Fetch a single order by hash | | `GET` | [`/ft/p2p/{chainId}/maker/{address}`](/docs/api-reference/rfq/orders-list-maker) | List a maker's orders — `limit`, `offset`, `orderBy`, `hideSmallBalances` | | `GET` | [`/ft/p2p/{chainId}/taker/{address}`](/docs/api-reference/rfq/orders-list-taker) | List orders addressed to a taker | | `GET` | [`/ft/fillablebalance/{chainId}/{address}`](/docs/api-reference/rfq/fillable-balance) | Maker's fillable balance for order sizing, optionally scoped to a token | Everything lives under `https://api.velora.xyz`. Filling and cancelling are on-chain calls to AugustusRFQ, not REST endpoints (see [Filling an order](#filling-an-order) and [Cancelling an order](#cancelling-an-order)). AugustusRFQ is deployed on Ethereum, Arbitrum, Avalanche, Base, BSC, Gnosis, Optimism, and Polygon; see [Chains & contracts](/docs/resources/chains-and-contracts) for per-chain addresses and availability. ## Filling an order Once the maker has posted an order, the named taker can fill it programmatically or through a Velora interface; both settle through the same `AugustusRFQ.fillOrder` call on-chain. * For bots, backends, and market-maker systems: approve AugustusRFQ for the `takerAsset`, then call `fillOrder` directly, or use [`sdk.otcOrders.fillOTCOrder({ order, signature })`](/docs/sdk/products/otc), which encodes and submits the transaction for you. * From the Velora app: every order has a shareable fill link keyed on its `orderHash`. Hand it to the counterparty and they approve and fill from the web app: ```text theme={null} https://app.velora.xyz/#/FT/OTC/{orderHash} ``` * Inside the [Velora Widget](/docs/widget/overview): the same OTC fill flow runs embedded, so partners can offer it in-app without sending users to `app.velora.xyz`. Whichever path the taker uses, the same on-chain checks apply: expired, already-filled, or wrong-taker fills revert. ## Cancelling an order There is no cancel endpoint. A maker cancels by sending a transaction to the AugustusRFQ contract (the same contract that verifies fills), so cancellation costs gas. This is the one place the OTC flow differs sharply from Delta, where cancellation is a gasless signed message to the relayer. AugustusRFQ exposes two methods, both taking the order's `orderHash` (the EIP-712 hash returned when the order was posted): | Method | Signature | Use | | -------------- | ------------------------------------- | --------------------------------------------------------- | | `cancelOrder` | `cancelOrder(bytes32 orderHash)` | Cancel a single order | | `cancelOrders` | `cancelOrders(bytes32[] orderHashes)` | Cancel many in one transaction — cheaper than one tx each | Cancelling marks the hash as cancelled on-chain, so any later `fillOrder` against it reverts. Send it from the maker wallet. Once the transaction is indexed, the order's `state` flips to `CANCELLED` and its `transactionHash` is populated. From the SDK, use [`sdk.otcOrders.cancelOTCOrder(orderHash)`](/docs/sdk/products/otc). Letting an order lapse past its `expiry` makes it unfillable with no transaction and no gas. For short-lived orders, a tight `expiry` is often cheaper than an explicit cancel. ## Order states An order reports one of six states: `DRAFT`, `PENDING`, `FULFILLED`, `CANCELLED`, `SUSPENDED` (the maker's balance or allowance dropped below the order), and `EXPIRED`. Always re-check `expiry` against the current block before filling. ## SDK shortcut Every step is wrapped by [`sdk.otcOrders.*`](/docs/sdk/products/otc): maker approvals, build → sign → post (`submitOTCOrder`), taker approval and `fillOTCOrder`, plus `getOTCOrders` and `cancelOTCOrder`. For a copy-paste maker/taker walkthrough see [SDK → OTC](/docs/sdk/products/otc). ## Related pages * [OTC, conceptually](/docs/overview/product-stack/otc) — when the counterparty matters as much as the price. * [Market making on Velora](/docs/resources/market-makers) — quoting into Velora with firm quotes settled through AugustusRFQ. * [Delta V2 overview](/docs/api-reference/delta/overview) — open, gasless, MEV-protected limit orders (`type=LIMIT`). * [SDK → OTC](/docs/sdk/products/otc) — maker and taker flows in TypeScript. * [Chains & contracts](/docs/resources/chains-and-contracts) — AugustusRFQ deployment addresses. * [AugustusRFQ security audit](/docs/resources/security/audits/augustus-rfq) — the settlement contract's audit history. * [Troubleshooting](/docs/api-reference/troubleshooting) — failure modes by symptom, cause, and fix. # API troubleshooting guide Source: https://new-docs.velora.xyz/docs/api-reference/troubleshooting Common failure modes across the Velora Delta and Market APIs: symptom, root cause, and fix. Each table covers a single endpoint and is updated from support tickets at each release. Jump straight to the endpoint you're calling. Building error-handling logic or LLM tools? Read [`/resources/errors.json`](/docs/resources/errors.json) — it mirrors every row on this page in machine-readable form, with `endpoint`, `status`, `match`, `cause`, `fix`, and `docs` fields per error. ## Delta V2 API ### GET /v2/delta/prices | Symptom | Root cause | Fix | | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | 400 `No route` for a same-chain pair | Token pair has no liquidity, or `srcDecimals` / `destDecimals` are wrong | Re-check decimals against the token contract; try `mode=ALL` on [GET /v2/quote](/docs/api-reference/delta/quote) to see whether Market can route it | | 400 `No route` for a crosschain pair | `destChainId` lane not supported by any active bridge for this token | Call [GET /v2/delta/prices/bridge-routes](/docs/api-reference/delta/bridge-routes) to see which lanes + tokens are supported | | `route.bridge` is `null` on a crosschain quote | `srcToken` and `destToken` happen to be the same address on different chains and the bridge collapsed | Compare `route.origin.input.token.chainId` vs `route.destination.output.token.chainId` directly; don't infer crosschain from `bridge !== null` alone | | `alternatives` is empty | Same-chain quotes never return alternatives — only crosschain | Use `route` directly for same-chain; check `alternatives.length > 0` before showing a bridge picker | | `partner.feePercent` higher than expected | Registered partner fee + `partnerFeeBps` override compounded | Set `partnerFeeBps=0` (or omit) to use the registered fee only; passing both stacks them | | 400 `Token not supported` | One of `srcToken` / `destToken` isn't whitelisted on `chainId` | Call [GET /v2/delta/prices/is-token-supported](/docs/api-reference/delta/is-token-supported) before quoting | Updated from support tickets at each release. Last updated: 2026-05-27. ### POST /v2/delta/orders/build | Symptom | Root cause | Fix | | ------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 400 `route` validation failed | `route` object was mutated, re-stringified, or had numeric fields cast to numbers (they're strings) | Pass `route` from [GET /v2/delta/prices](/docs/api-reference/delta/prices) **verbatim** — don't normalize, sort, or re-encode amounts | | 400 missing `deadline` | `deadline` is required on every Delta order; the build call rejects when it's absent | Pass `deadline` as unix seconds (e.g. `Math.floor(Date.now() / 1000) + 3600`); past it the order is unfillable | | 400 `InvalidTWAPParams` / `InvalidTWAPBuyParams` | TWAP / TWAPBuy without `interval`, `numSlices`, and a totals field | Provide all four: `interval` (seconds, ≥ 60), `numSlices` (≥ 2), `totalSrcAmount` (TWAP), or `totalDestAmount` + `maxSrcAmount` (TWAPBuy) | | 400 `InvalidTWAPSrcAmount` / `InvalidTWAPBuyDestAmount` | Slice amount in `route.origin` doesn't equal `floor(total / numSlices)` | Re-quote per slice with `amount = floor(total / numSlices)` and pass the totals separately; non-divisible remainders are intentional and you can't ship slice×n | | 400 `InvalidExternalOrderParams` | `orderType: ExternalOrder` without `handler` and `data` | Encode handler-specific bytes into `data` and pass the on-chain handler address as `handler` | | 400 `InvalidProductiveOrderParams` | `orderType: ProductiveOrder` without `strategy` | Pass the on-chain strategy address as `strategy` | | `slippage` results in much worse fills than expected | Slippage is in **basis points**, not percent: `100` = 1.00%, not 100% | Convert mental percent to bps: 0.5% → `50`, 1% → `100`, 5% → `500` (max `10_000` = 100%) | Updated from support tickets at each release. Last updated: 2026-06-09. ### POST /v2/delta/orders | Symptom | Root cause | Fix | | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 400 `Invalid signature` | Signed payload doesn't match `order` byte-for-byte | Sign `toSign` from `POST /v2/delta/orders/build` exactly; pass `order: toSign.value` to submit (not the whole `toSign` object) | | 400 `Order expired` | Long pause between build and submit; `deadline` already passed when relayer validated | Rebuild on submit-time, or pass a longer `deadline` (seconds since epoch) at build | | 400 `InsufficientAllowance` | User approved the wrong spender — usually the Augustus router instead of the Delta contract | Approve `route.spender` (returned by `GET /v2/delta/prices`) — the Delta contract, not Augustus | | 400 `InsufficientBalance` | Source-token balance dropped between price and submit | Re-quote and rebuild; show the user a fresh balance before signing | | 200 OK then stuck at `PENDING` | No agent bid the auction (size, pair, or chain) within the window | Poll [GET /v2/delta/orders/](/docs/api-reference/delta/orders-get-by-id); cancel via [POST /v2/delta/orders/cancel](/docs/api-reference/delta/orders-cancel) and re-quote if past your SLA | | Order transitions to `SUSPENDED` | Allowance was revoked or balance moved post-submission | Re-approve and the relayer will pick the order back up | | 400 `deadline must allow enough time for all slices to execute` | TWAP `deadline` is less than `numSlices × interval` seconds away | Push the deadline past `now + numSlices × interval`, or use fewer slices / a shorter interval | | 400 `totalSrcAmount must be >= numSlices` (also `totalDestAmount`, `maxSrcAmount`) | TWAP total is smaller than the slice count, so a slice would round down to 0 wei | Raise the total or lower `numSlices` so every slice carries at least 1 wei | Updated from support tickets at each release. Last updated: 2026-06-12. ### POST /v2/delta/orders/cancel | Symptom | Root cause | Fix | | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | 400 `Invalid signature` | Cancellation EIP-712 typed data assembled wrong (wrong chainId or wrong domain) | Sign the relayer's cancel payload — the SDK's `signCancelDeltaOrderRequest` handles this for you | | 400 `Order already settled` | One or more `orderIds` are already post-settlement or terminal (`COMPLETED`, `REFUNDING`, `REFUNDED`, `FAILED`, `EXPIRED`, `CANCELLED`) | Pre-filter `orderIds` to those with status in `PENDING` / `AWAITING_SIGNATURE` / `ACTIVE` / `SUSPENDED` | | 200 OK but order doesn't move to `CANCELLING` | An auction had already started for that order — cancellation queues but won't kill an in-flight fill | Wait one polling interval; the order moves to `CANCELLED` once the relayer confirms | | 400 `orderIds.length > 100` | Tried to batch-cancel too many in one call | Chunk into batches of ≤ 100 | Updated from support tickets at each release. Last updated: 2026-06-15. ## Market API ### GET /prices | Symptom | Root cause | Fix | | ------------------------------------------------------------ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | | 400 `Invalid srcToken` or `Invalid destToken` | Native ETH sent as `0x0` or lowercase `0xeee...e` | Use the mixed-case placeholder `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` | | 422 `Unsupported chain` | `network` not in the supported-chain list for the current API host | Hit `GET /chains` to confirm the live list; see [Chains & contracts](/docs/resources/chains-and-contracts) | | `priceRoute.maxImpactReached: true` | Price impact exceeds the configured ceiling for this route | Reduce trade size, split into hops, or pass an explicit higher `maxImpact` if your product accepts the risk | | Stale `priceRoute` rejected by `POST /transactions/:chainId` | More than \~30s elapsed between quote and tx-build, route became invalid | Re-quote and pass the fresh `priceRoute` verbatim; never cache across user gestures | | 429 from the gateway | Free-tier rate limit hit, or your Pro plan quota exceeded | See [Pro API accounts](/docs/overview/pro-api-accounts) to lift rate limits, or back off and retry | Updated from support tickets at each release. Last updated: 2026-05-15. ### POST /transactions/:chainId | Symptom | Root cause | Fix | | ------------------------------------------------------------ | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 400 `Invalid priceRoute` or `Stale priceRoute` | `priceRoute` modified between quote and tx-build, or older than \~30s | Pass the `priceRoute` block from `GET /prices` verbatim; re-quote if more than \~30s elapsed | | Calldata reverts on-chain with `INSUFFICIENT_OUTPUT` | Slippage tolerance too tight for current market depth | Increase `slippage` (in bps) on the rebuild, or surface a higher tolerance to the user before retrying | | Calldata reverts with `TransferHelper: TRANSFER_FROM_FAILED` | ERC-20 allowance to the v6.2 router insufficient (or pointed at the legacy v5 router) | Approve the Augustus v6.2 router address — see [Chains & contracts](/docs/resources/chains-and-contracts); migrating off v5 → [Augustus v5 → v6.2](/docs/resources/migrations/augustus-v5-to-v6-2) | | `txData` gas estimate fails on the user's RPC | RPC gas estimation can't simulate the exact block conditions | Use the `gas` field returned in the response as a baseline + 15–25% headroom | | Calldata builds for the wrong chain | `network` path parameter mismatched against the `priceRoute.network` | Always derive `:network` from `priceRoute.network`, not from a client-side variable | | 422 `Partner not allowed` | Your partner tier doesn't permit the requested fee/surplus configuration | Drop the disallowed param, or [upgrade to a Pro API account](/docs/overview/pro-api-accounts) | Updated from support tickets at each release. Last updated: 2026-05-15. # Crosschain Delta swaps Source: https://new-docs.velora.xyz/docs/delta/crosschain-delta Issue Delta orders that move value between chains in a single user signature. Crosschain Delta lets a user sign one intent on the source chain and receive the output token on another chain. Delta prices the source-chain swap, selects a supported bridge route, encodes the bridge parameters into the signed order, and tracks the destination leg until completion. Use it when you want the Delta execution model across chains: gasless signing, private solver competition, and MEV protection. ## The bridge flow at a glance ```mermaid theme={null} sequenceDiagram autonumber actor User participant DApp as Your app / SDK participant API as Velora API participant OS as Order Server participant Solvers as Solver network
(Portikus) participant Settlement as Protocol settlement participant Delta as Delta contract
source chain participant Bridge as Bridge provider
(CCTP / Across / Relay / ...) participant Dest as Destination chain User->>DApp: "Swap on chain A, receive on chain B" DApp->>API: GET /v2/quote?mode=DELTA&chainId=A&destChainId=B API->>Bridge: Price supported bridge routes Bridge-->>API: estimated time, fees, destination amount API-->>DApp: delta block
(route.bridge populated) DApp->>API: POST /v2/delta/orders/build
(route from prices) API-->>DApp: toSign (EIP-712)
(destination chain + bridge params) DApp->>User: Request signature User-->>DApp: Signed intent DApp->>API: POST /v2/delta/orders API->>OS: Persist signed order rect rgb(232, 245, 233) note over OS,Solvers: Source-chain Delta auction OS->>Solvers: Broadcast order Solvers-->>OS: Competing fill calldata OS->>Solvers: Award winner end OS->>Settlement: Winning calldata + signed order Settlement->>Delta: Settle on source chain Delta->>Bridge: Initiate selected bridge leg API-->>DApp: status = BRIDGING alt bridge leg completes Bridge->>Dest: Finalize destination leg Dest-->>User: output token delivered API-->>DApp: status = COMPLETED else bridge leg refunds Bridge-->>API: refund pending API-->>DApp: status = REFUNDING Bridge-->>User: source-chain refund API-->>DApp: status = REFUNDED
(refunds[] populated when verified) end ``` ## When to use this Use crosschain Delta when: * The user starts on one supported EVM chain and wants output on another. * You want one user signature instead of a manual swap, bridge, and destination-chain claim flow. * Your integration already uses Delta orders and can pass the `delta.route` from the quote response through to `POST /v2/delta/orders/build` unchanged. * You can show bridge-specific timing clearly: destination delivery is asynchronous after source-chain settlement. Keep same-chain Delta for routes where `chainId` and `destChainId` are the same or where no supported bridge route is available. ## What changes from same-chain Delta The integration shape stays close to the standard [Delta flow](/docs/delta/how-it-works). The main difference is that the quote and order include a bridge leg. * Add `destChainId` to `GET /v2/quote`. `chainId` remains the source chain. * When `destChainId` is set, the `delta` block's `route.bridge` is populated and `delta.alternatives` lists other bridge routes. * Treat the returned `delta.route` as the source of truth. Pass it verbatim into `POST /v2/delta/orders/build`. * Read `delta.route.bridge` for the selected bridge route and `delta.route.fees` for gas and bridge fees. * Use `delta.alternatives` when you want to show other bridge routes. * After source-chain settlement, expect an intermediate `BRIDGING` state before `COMPLETED`. Do not recompute or hand-edit the bridge payload. The bridge parameters are covered by the quote integrity envelope and the signable order. ## Quickstart Request a Delta quote with a destination chain: ```bash cURL theme={null} curl -s "https://api.velora.xyz/v2/quote" \ --data-urlencode "srcToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" \ --data-urlencode "srcDecimals=18" \ --data-urlencode "destToken=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" \ --data-urlencode "destDecimals=6" \ --data-urlencode "amount=1000000000000000000" \ --data-urlencode "side=SELL" \ --data-urlencode "chainId=1" \ --data-urlencode "destChainId=8453" \ --data-urlencode "mode=DELTA" \ --data-urlencode "userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" \ --data-urlencode "partner=my-app-name" \ -G | jq ``` Then use the same build, sign, and submit calls as a same-chain Delta order: Send the returned `delta.route` in `POST /v2/delta/orders/build`, with `owner` set to the user's address. Ask the user to sign the returned `toSign` typed data. It includes the destination chain and bridge parameters. Submit the order with `POST /v2/delta/orders`, then poll `GET /v2/delta/orders/{orderId}` until the status reaches a terminal state. ## How bridging works Delta does not ask the user to perform a separate bridge transaction. The user signs a Delta order that already contains the selected destination chain, output token, and bridge execution data. At settlement time, the protocol executes the winning solver's source-chain calldata through Portikus. If the order is crosschain, the settlement module sends the post-swap output into the selected bridge module instead of transferring it locally to the user. The destination output is delivered to the order beneficiary on the destination chain. For USDC routes, CCTP support is USDC-specific. Delta can still quote arbitrary source tokens when the source-chain leg swaps into the bridge token first, but the CCTP bridge leg itself moves USDC between supported chains. Bridge times are estimates. Fast routes can be unavailable on some paths or when provider limits are reached. Always surface the quoted `estimatedTimeMs` and fees rather than hard-coding bridge assumptions. ## Status model Crosschain orders can have extra visible phases after source-chain execution: * `PENDING` — the signed order is waiting for auction or settlement. * `BRIDGING` — source-chain settlement succeeded and the bridge leg is being finalized. * `COMPLETED` — the destination leg was observed as filled. * `REFUNDING` — the bridge leg failed or expired, and Velora is polling until the actual refund transaction can be verified. * `REFUNDED` — the refund is complete. When refund metadata is available, the order response includes `refunds[]` entries with `tx`, `chainId`, `token`, and raw-unit `amount`. * `EXPIRED` or `FAILED` — the order did not complete as intended. Source-chain bridge initiation is not the same as destination-chain completion. Only mark the user flow complete once the order status reaches `COMPLETED`. For refund flows, keep the user in an in-progress state while status is `REFUNDING`. Move the flow to a final refund state only after `REFUNDED`; use `refunds[]` for the verified refund transaction when it is present. ## Implementation notes * Use raw token units for amounts. Do not send decimal strings. * `destToken` is the token address on `destChainId`. * Native ETH-style assets use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`. * Same-token routes may bridge directly. Other routes may swap first, then bridge the intermediate or destination asset. * Some bridge providers expose alternatives with different speed, fee, and output tradeoffs. Show the selected route first and alternatives only when your UI supports a clear choice. ## Related pages * [How Delta works](/docs/delta/how-it-works) — the same-chain Delta lifecycle. * [Delta quote endpoint](/docs/api-reference/delta/quote) — quote parameters and response shape. * [Trading modes](/docs/integrate/trading-modes) — when to request Delta, Market, or automatic routing. * [Chains and contracts](/docs/resources/chains-and-contracts) — supported chains and public contract references. # Delta API Go example Source: https://new-docs.velora.xyz/docs/delta/examples/go End-to-end Go example: call the Velora Delta API to quote a gasless 1 ETH → USDC intent via net/http. A minimal Go program that calls `GET /v2/quote?mode=DELTA` and prints the recommended route's expected output and the `spender` from the returned `delta` block. Standard library only. ## File tree ```text theme={null} my-app/ ├─ go.mod └─ main.go ``` ## Install ```bash theme={null} mkdir my-app && cd my-app go mod init example.com/my-app ``` ## `main.go` ```go theme={null} package main import ( "encoding/json" "fmt" "net/http" "net/url" ) func main() { params := url.Values{ "srcToken": {"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"}, // ETH "destToken": {"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"}, // USDC "amount": {"1000000000000000000"}, // 1 ETH "srcDecimals": {"18"}, "destDecimals": {"6"}, "side": {"SELL"}, "chainId": {"1"}, "mode": {"DELTA"}, "userAddress": {"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"}, "partner": {"my-app-name"}, } res, err := http.Get("https://api.velora.xyz/v2/quote?" + params.Encode()) if err != nil { panic(err) } defer res.Body.Close() if res.StatusCode != http.StatusOK { panic(fmt.Sprintf("HTTP %d", res.StatusCode)) } var body struct { Delta struct { Route struct { Origin struct { Output struct { Amount string `json:"amount"` } `json:"output"` } `json:"origin"` } `json:"route"` Spender string `json:"spender"` } `json:"delta"` } if err := json.NewDecoder(res.Body).Decode(&body); err != nil { panic(err) } fmt.Println("expected output:", body.Delta.Route.Origin.Output.Amount) fmt.Println("spender: ", body.Delta.Spender) } ``` ## Run it ```bash theme={null} go run . ``` You should see the recommended route's expected output (USDC, 6 decimals) and the `spender` address to approve before building the order. ## Next: build, sign, submit Pass the unmodified `delta.route` into `POST /v2/delta/orders/build` (with `owner` set to the user address) to get EIP-712 typed data back as `{ toSign, orderHash }`. Sign `toSign` with an ERC-2098 compact signature, then `POST /v2/delta/orders` with `order` (the `toSign.value`), the `signature`, `chainId`, and your `partner`. Poll `GET /v2/delta/orders/{orderId}` for status. See [Delta → How it works](/docs/delta/how-it-works). Pass `delta.route` **verbatim** to `/v2/delta/orders/build`. Reordering or re-encoding it will cause the build call to reject. ## Related pages * [Delta overview](/docs/delta/overview) — when to use Delta intents. * [Delta → How it works](/docs/delta/how-it-works) — quote → build → sign → auction → settle. * [Delta API reference](/docs/api-reference/delta/overview) — full parameter list. # Delta API Python example Source: https://new-docs.velora.xyz/docs/delta/examples/python End-to-end Python example: call the Velora Delta API to quote a gasless 1 ETH → USDC intent via requests. A minimal Python script that calls `GET /v2/quote?mode=DELTA` and prints the recommended route's expected output and the `spender` from the returned `delta` block. Uses `requests`. ## File tree ```text theme={null} my-app/ ├─ requirements.txt └─ quote.py ``` ## Install ```bash theme={null} mkdir my-app && cd my-app python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install requests ``` ## `quote.py` ```python theme={null} import requests params = { "srcToken": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", # ETH "destToken": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", # USDC "amount": "1000000000000000000", # 1 ETH "srcDecimals": 18, "destDecimals": 6, "side": "SELL", "chainId": 1, "mode": "DELTA", "userAddress": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "partner": "my-app-name", } res = requests.get("https://api.velora.xyz/v2/quote", params=params, timeout=10) res.raise_for_status() delta = res.json()["delta"] print("expected output:", delta["route"]["origin"]["output"]["amount"]) print("spender: ", delta["spender"]) ``` ## Run it ```bash theme={null} python quote.py ``` You should see the recommended route's expected output (USDC, 6 decimals) and the `spender` address to approve before building the order. ## Next: build, sign, submit Pass the unmodified `delta.route` into `POST /v2/delta/orders/build` (with `owner` set to the user address) to get EIP-712 typed data back as `{ toSign, orderHash }`. Sign `toSign` with an ERC-2098 compact signature, then `POST /v2/delta/orders` with `order` (the `toSign.value`), the `signature`, `chainId`, and your `partner`. Poll `GET /v2/delta/orders/{orderId}` for status. See [Delta → How it works](/docs/delta/how-it-works). Pass `delta.route` **verbatim** to `/v2/delta/orders/build`. Reordering or re-encoding it will cause the build call to reject. ## Related pages * [Delta overview](/docs/delta/overview) — when to use Delta intents. * [Delta → How it works](/docs/delta/how-it-works) — quote → build → sign → auction → settle. * [Delta API reference](/docs/api-reference/delta/overview) — full parameter list. # Delta API Rust example Source: https://new-docs.velora.xyz/docs/delta/examples/rust End-to-end Rust example: call the Velora Delta API to quote a gasless 1 ETH → USDC intent via reqwest. A minimal Rust program that calls `GET /v2/quote?mode=DELTA` and prints the recommended route's expected output and the `spender` from the returned `delta` block. Uses `reqwest` with `tokio`. ## File tree ```text theme={null} my-app/ ├─ Cargo.toml └─ src/ └─ main.rs ``` ## Install ```bash theme={null} cargo new my-app cd my-app cargo add reqwest --features json cargo add tokio --features full cargo add serde --features derive ``` ## `src/main.rs` ```rust theme={null} use serde::Deserialize; #[derive(Deserialize, Debug)] struct TokenAmount { amount: String, } #[derive(Deserialize, Debug)] struct RouteStep { output: TokenAmount, } #[derive(Deserialize, Debug)] struct Route { origin: RouteStep, } #[derive(Deserialize, Debug)] struct DeltaPrice { route: Route, spender: String, } #[derive(Deserialize, Debug)] struct QuoteResponse { delta: DeltaPrice, } #[tokio::main] async fn main() -> Result<(), Box> { let params = [ ("srcToken", "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"), // ETH ("destToken", "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"), // USDC ("amount", "1000000000000000000"), // 1 ETH ("srcDecimals", "18"), ("destDecimals", "6"), ("side", "SELL"), ("chainId", "1"), ("mode", "DELTA"), ("userAddress", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"), ("partner", "my-app-name"), ]; let res = reqwest::Client::new() .get("https://api.velora.xyz/v2/quote") .query(¶ms) .send() .await? .error_for_status()? .json::() .await?; println!("expected output: {}", res.delta.route.origin.output.amount); println!("spender: {}", res.delta.spender); Ok(()) } ``` ## Run it ```bash theme={null} cargo run ``` You should see the recommended route's expected output (USDC, 6 decimals) and the `spender` address to approve before building the order. ## Next: build, sign, submit Pass the unmodified `delta.route` into `POST /v2/delta/orders/build` (with `owner` set to the user address) to get EIP-712 typed data back as `{ toSign, orderHash }`. Sign `toSign` with an ERC-2098 compact signature, then `POST /v2/delta/orders` with `order` (the `toSign.value`), the `signature`, `chainId`, and your `partner`. Poll `GET /v2/delta/orders/{orderId}` for status. See [Delta → How it works](/docs/delta/how-it-works). Pass `delta.route` **verbatim** to `/v2/delta/orders/build`. Reordering or re-encoding it will cause the build call to reject. ## Related pages * [Delta overview](/docs/delta/overview) — when to use Delta intents. * [Delta → How it works](/docs/delta/how-it-works) — quote → build → sign → auction → settle. * [Delta API reference](/docs/api-reference/delta/overview) — full parameter list. # Delta API TypeScript example Source: https://new-docs.velora.xyz/docs/delta/examples/typescript End-to-end TypeScript example: call the Velora Delta API to quote a gasless 1 ETH → USDC intent via plain fetch. A minimal Node script that calls `GET /v2/quote?mode=DELTA` and prints the recommended route's expected output and the `spender` from the returned `delta` block. No SDK, just `fetch`. ## File tree ```text theme={null} my-app/ ├─ package.json ├─ tsconfig.json └─ src/ └─ quote.ts ``` ## Install ```bash pnpm theme={null} mkdir my-app && cd my-app pnpm init pnpm add -D typescript tsx @types/node pnpm tsc --init ``` ```bash npm theme={null} mkdir my-app && cd my-app npm init -y npm install -D typescript tsx @types/node npx tsc --init ``` ```bash yarn theme={null} mkdir my-app && cd my-app yarn init -y yarn add -D typescript tsx @types/node yarn tsc --init ``` ## `src/quote.ts` ```ts theme={null} const params = new URLSearchParams({ srcToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH destToken: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC amount: '1000000000000000000', // 1 ETH srcDecimals: '18', destDecimals: '6', side: 'SELL', chainId: '1', mode: 'DELTA', userAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', partner: 'my-app-name', }); const res = await fetch(`https://api.velora.xyz/v2/quote?${params}`); if (!res.ok) { throw new Error(`HTTP ${res.status}: ${await res.text()}`); } const { delta } = await res.json(); console.log('expected output:', delta.route.origin.output.amount); console.log('spender: ', delta.spender); ``` ## Run it ```bash theme={null} pnpm tsx src/quote.ts ``` You should see the recommended route's expected output (USDC, 6 decimals) and the `spender` address to approve before building the order. ## Recommended route vs alternatives The `delta` block carries a single recommended `route`. For crosschain swaps it also returns `alternatives`: other bridge routes you can offer the user. Pass whichever `route` you choose, unmodified, into the build step. ```ts theme={null} const { delta } = await (await fetch(`https://api.velora.xyz/v2/quote?${params}`)).json(); const route = delta.route; // recommended route const others = delta.alternatives; // crosschain only ``` ## Next: build, sign, submit Pass the unmodified `delta.route` into `POST /v2/delta/orders/build` (with `owner` set to the user address) to get EIP-712 typed data back as `{ toSign, orderHash }`. Sign `toSign` with an ERC-2098 compact signature, then `POST /v2/delta/orders` with `order` (the `toSign.value`), the `signature`, `chainId`, and your `partner`. Poll `GET /v2/delta/orders/{orderId}` for status. See [Delta → How it works](/docs/delta/how-it-works). Pass `delta.route` **verbatim** to `/v2/delta/orders/build`. Reordering or re-encoding it will cause the build call to reject. ## Related pages * [Delta overview](/docs/delta/overview) — when to use Delta intents. * [Delta → How it works](/docs/delta/how-it-works) — quote → build → sign → auction → settle. * [Delta API reference](/docs/api-reference/delta/overview) — full parameter list. * [SDK](/docs/sdk/overview) — typed TypeScript wrapper if you'd rather not handle HTTP yourself. # How Delta intent swaps work Source: https://new-docs.velora.xyz/docs/delta/how-it-works From signed intent to on-chain settlement: the full Delta flow end-to-end. Delta separates **what the user wants** (the intent) from **how it gets executed** (the fill). The user signs once, off-chain. Solvers on the [Portikus Network](/docs/solver-network/portikus) race to provide the best executable calldata, and protocol settlement executes the winning calldata through the Delta contract. ## The flow at a glance ```mermaid theme={null} sequenceDiagram autonumber actor User participant DApp as Your app / SDK participant API as Velora API participant OS as Order Server participant Solvers as Portikus Network
(solvers) participant Settlement as Protocol settlement participant Delta as Delta contract
0x...c96d User->>DApp: "Swap 1000 USDC for USDT" DApp->>API: GET /v2/quote?mode=DELTA API-->>DApp: delta block (route + alternatives + spender) DApp->>API: POST /v2/delta/orders/build
(route from prices) API-->>DApp: toSign (EIP-712) + orderHash DApp->>User: Request signature User-->>DApp: ERC-2098 compact signature DApp->>API: POST /v2/delta/orders
(order + signature) API->>OS: Persist signed order rect rgb(232, 245, 233) note over OS,Solvers: Off-chain auction OS->>Solvers: Broadcast order Solvers-->>OS: Competing fill calldata OS->>Solvers: Award winner end OS->>Settlement: Winning calldata + signed order Settlement->>Delta: settle(order, signature, fillData) Delta-->>User: destToken delivered loop Until terminal status DApp->>API: GET /v2/delta/orders/{orderId} API-->>DApp: status = PENDING / COMPLETED / FAILED end ``` ## The five stages ### 1. Quote You call `GET /v2/quote?mode=DELTA`. The API returns a `delta` block with a recommended `route`, optional `alternatives` (crosschain), the resolved `partner` fee, and the `spender` address to approve. There's no separate integrity token to carry forward; you pass `delta.route` into the build step. ### 2. Build You `POST /v2/delta/orders/build` with the unmodified `delta.route` from step 1 and `owner` set to the user's address. The API returns `{ toSign: { domain, types, value }, orderHash }`. The server composes the EIP-712 domain, types, and order struct for you. Pass `delta.route` **verbatim** from the quote response. Reordering or re-encoding it will cause the build call to reject. ### 3. Sign The user signs the returned `toSign` typed data with their wallet. The build response carries the exact domain, types, and struct layout. Delta uses **ERC-2098 compact signatures** (64 bytes, not 65). Most modern libraries (viem, ethers v6, wagmi) produce or accept compact sigs natively. The user pays **no gas** for this step; it's a pure off-chain message. ### 4. Auction You `POST /v2/delta/orders` with `order` (the `toSign.value`), the `signature`, `chainId`, and your `partner`. The order server persists it and runs a [sealed-bid auction](/docs/solver-network/sealed-bid-auctions) across the **Portikus Network**: solvers bid in parallel without seeing each other's offers, and the best simulated outcome wins. The winning solver commits fill calldata and the capital needed to deliver it; they take on inventory and pricing risk in exchange for the spread. ### 5. Settle The protocol settlement layer calls `settle(...)` on the Delta contract (`0x0000000000bbF5c5Fd284e657F01Bd000933C96D`, same address on every supported chain) with the signed order and the winning solver's fill calldata. The contract verifies the signature, pulls `srcToken` from the user via the approved spender (the Delta contract itself), runs the fill, and delivers `destToken` to the user. If settlement fails, nothing is pulled from the user. You track progress via `GET /v2/delta/orders/{orderId}` until the order reaches a terminal status (`COMPLETED`, `EXPIRED`, `FAILED`, `CANCELLED`, or `REFUNDED`). Crosschain orders can report `REFUNDING` before `REFUNDED` while Velora verifies the bridge refund transaction. ## Why this design Users sign off-chain. Settlement gas is handled inside the Delta flow. Orders are auctioned privately. There's no public mempool to sandwich. Solvers compete on price. The user always gets the best committed fill. User funds only leave the wallet when settlement succeeds on-chain. A failed fill costs the user neither funds nor gas. ## Related pages * [Portikus Network](/docs/solver-network/portikus) — the intent infrastructure behind stage 4 and 5. * [Sealed-bid auctions](/docs/solver-network/sealed-bid-auctions) — how the auction picks a winner and resists manipulation. * [Quickstart](/docs/overview/quickstart) — run the flow end-to-end with cURL. * [Integrate → Delta swap](/docs/integrate/api/delta-swap) — this flow as a hands-on API walkthrough. * [Integrate → Limit orders](/docs/integrate/api/limit-orders) and [TWAP](/docs/integrate/api/twap) — the same flow with a price constraint or a schedule. * [Delta contract](/docs/resources/chains-and-contracts) — on-chain entry point and per-chain addresses. # Sell native ETH with Delta Source: https://new-docs.velora.xyz/docs/delta/native-eth Sell native ETH gaslessly through Delta. Native ETH is represented as dETH, the Delta Wrapped Native token, wrapped 1:1, with no need for an ERC-20 approval. When a user sells native ETH through Delta, the ETH is represented as **`dETH`**, the Delta Wrapped Native token, wrapped 1:1. The user still signs one off-chain order and pays no gas, and because of how `dETH` is set up there's no need for an ERC-20 approval on the source side. You don't deploy or call anything extra: pass the native placeholder as `srcToken` and the relayer handles the rest. ## What dETH is `dETH` is an ERC-20 (the `DeltaWrappedNative` contract) that wraps the chain's native token 1:1: ETH on Ethereum, BNB on BSC, and so on. Its underlying is the chain's wrapped native (WETH), so `dETH` and native are interchangeable at a 1:1 rate. The Delta contract holds delegated access to a user's `dETH`. That's what lets a native-ETH Delta order settle without a separate ERC-20 approval: the user signs the order, and settlement moves the wrapped balance on their behalf. An ERC-20 source token still needs its one-time approval; native ETH does not. ## Using it Selling native ETH is the normal [Delta swap](/docs/integrate/api/delta-swap) flow with one difference: you skip the approval step. Pass the native placeholder as `srcToken`: ``` 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE ``` Quote, build, sign, and submit exactly as you would for an ERC-20 source. The relayer resolves the placeholder to `dETH`, and the order settles and delivers the destination token the same way. ## Where it's available `dETH` is deployed alongside the Delta contract, so native ETH works as a Delta source on every chain where Delta is available. It lives at the same address on each of them: ``` 0x0a0d53b6684c7b32b4cbef5fe8483bfcc8406742 ``` This address is for reference and on-chain verification. In the API flow you pass the native placeholder `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` as `srcToken`, and Velora maps it to dETH for you. The [Chains & contracts](/docs/resources/chains-and-contracts) table is the canonical list of Delta-enabled chains. Where Delta isn't deployed, use a [Market swap](/docs/integrate/api/market-swap) instead. ## Unwrapping back to ETH `dETH` works like WETH in both directions, so it's never a lock-in. Any `dETH` a user holds can be unwrapped back to native ETH at any time, 1:1, by calling `withdrawNative` on the `dETH` contract: ```solidity theme={null} withdrawNative(uint256 amount, address owner, address receiver) ``` It burns the `dETH` and sends native ETH to `receiver`. The owner can call it directly; the Delta contract can also do so on their behalf during settlement. This is the same wrap/unwrap model as WETH: `depositNative` mints `dETH` 1:1 (and sending ETH straight to the contract wraps it automatically), and `withdrawNative` redeems it. So if a user ever holds a `dETH` balance, the unfilled remainder of a cancelled or partially filled order, for example, they can convert it back to ETH whenever they want. `dETH` is a normal ERC-20, so unwrapping isn't the only exit. A user can also swap it to ETH (or any token) through a [Market swap](/docs/integrate/api/market-swap), which routes `dETH` through the aggregator like any other token. In the Velora app that's a prefilled swap link, for example `dETH` to ETH on Ethereum: ``` https://app.velora.xyz/#/swap/0x0a0d53B6684C7B32B4cBeF5fE8483bFcc8406742-0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE/1/SELL?network=ethereum ``` `dETH` can also hold yield-bearing positions for Productive orders, where the wrapped balance earns yield in a strategy while the order rests. That's a separate, advanced flow and isn't covered here. ## Related pages * [Delta swap](/docs/integrate/api/delta-swap): the full source-to-destination flow native ETH plugs into. * [Trading modes](/docs/integrate/trading-modes) covers when to use Delta vs Market. * [Delta → How it works](/docs/delta/how-it-works) for the auction and settlement model. * [Chains & contracts](/docs/resources/chains-and-contracts) for supported chains and contract references. # Delta gasless intent swaps Source: https://new-docs.velora.xyz/docs/delta/overview Delta is Velora's intent protocol: gasless, MEV-protected, Crosschain swaps that settle in one signature, with revert protection when a fill fails. Here's what makes it different from a regular swap. Delta is Velora's intent protocol. Instead of building, signing, and submitting an on-chain transaction yourself, you sign an off-chain **order** describing what you want. A competitive network of solvers (the [Portikus Network](/docs/solver-network/portikus)) submits fill calldata, and Delta settles the winning fill for you. ## What you get The user never pays gas. Execution cost is handled inside the Delta settlement flow. Orders are filled via sealed-bid auction. No public mempool. No sandwich risk. A failed order simply expires or is rejected. You never pay for a trade that didn't happen. One signed order can resolve across chains via bridge-aware solvers. No second tx. ## See it work The full lifecycle is four calls (quote, build, sign, submit), then you poll for status: ```bash theme={null} # 1. Get a Delta quote (returns a delta block: route + alternatives + spender) curl -s "https://api.velora.xyz/v2/quote" \ --data-urlencode "srcToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" \ --data-urlencode "destToken=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" \ --data-urlencode "amount=1000000000000000000" \ --data-urlencode "srcDecimals=18" \ --data-urlencode "destDecimals=6" \ --data-urlencode "side=SELL" \ --data-urlencode "chainId=1" \ --data-urlencode "mode=DELTA" \ --data-urlencode "userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" \ --data-urlencode "partner=my-app-name" \ -G -o quote.json # 2. Build the order from the quote's delta.route (returns toSign + orderHash) jq --argjson deadline "$(($(date +%s) + 1800))" \ '{route: .delta.route, owner: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", deadline: $deadline, partner: "my-app-name"}' quote.json > build.json curl -X POST "https://api.velora.xyz/v2/delta/orders/build" \ -H "Content-Type: application/json" -d @build.json # 3. Sign the returned toSign with the user's wallet (ERC-2098 compact) # and write the order + signature to signed.json # 4. Submit the signed order curl -X POST "https://api.velora.xyz/v2/delta/orders" \ -H "Content-Type: application/json" -d @signed.json # 5. Poll status curl "https://api.velora.xyz/v2/delta/orders/{orderId}" ``` Walk through the full flow in the **[Quickstart →](/docs/overview/quickstart)** For a side-by-side breakdown of when to pick `mode=DELTA`, `mode=MARKET`, or `mode=ALL`, see [Trading modes](/docs/integrate/trading-modes). ## Next steps cURL the full lifecycle end-to-end. Order server, solver auction, settlement. One signature, multi-chain settlement. # Velora integration FAQ Source: https://new-docs.velora.xyz/docs/faq Quick answers across trading, slippage, token support, route availability, limit orders, fees, and troubleshooting, with pointers to the canonical pages. Short answers to the questions support and integrators hit most often. Each section links out to the page that owns the topic. Start here, then go deep where you need to. Looking for end-to-end API errors? See [Troubleshooting](/docs/api-reference/troubleshooting) for failure-mode tables per endpoint. Building a wallet or agent? See [Agent decision tables](/docs/for-agents/decision-tables). ## Trading basics ### Do I need an API key? No. Every Velora REST endpoint is public: pass `&partner=` to identify your traffic and you're in. The free tier gives 1 RPS and 3,000 requests/day, which is plenty to prototype and ship a real integration. When you outgrow it, [Pro API accounts](/docs/overview/pro-api-accounts) lift the limits and add a dashboard, early features, and SLA. ### Should I use Delta (gasless) or Market? If the user can wait a few seconds and doesn't want to pay gas, prefer Delta: it's MEV-protected and solvers compete to fill at or above the quoted price. If you need synchronous on-chain settlement (composing with another contract in the same tx) or the trade is small enough that AMM routing wins, use Market. If you don't want to commit upfront, call `GET /v2/quote?mode=ALL` and branch on whichever block (`delta` or `market`) the response carries. Full decision matrix: [Trading modes](/docs/integrate/trading-modes). ## Slippage & price impact ### How do I set slippage? For Market, pass `slippage` (basis points) on the quote, or set `destAmount` directly as a hard floor. Omitting both returns `400`. For Delta, slippage is applied at the build step. Pass `slippage` to [`POST /v2/delta/orders/build`](/docs/api-reference/delta/orders-build); the API returns an order with `destAmount` reduced by that slippage. You then sign and submit via [`POST /v2/delta/orders`](/docs/api-reference/delta/orders-submit). The signed `order.destAmount` is the limit-order floor: solvers must deliver at least that amount or the fill doesn't settle. ### What slippage tolerance should I use? Velora doesn't enforce a default. Typical bps by pair tier: * **Stable ↔ stable** (USDC/USDT, DAI/USDC): \~1 bps. * **High-cap pairs** (ETH/USDC, WBTC/USDC): 2–5 bps. * **Long-tail / low-liquidity**: 10–30 bps, depending on depth. Market volatility can push these higher. The Widget exposes a user-configurable slippage and a Degen Mode for high-impact trades. For agents, the rule is: use the app's configured default, or ask if there isn't one. See [Agent decision tables](/docs/for-agents/decision-tables). ### How is price impact different from slippage? **Price impact** is the trade's expected effect on the market price, driven by liquidity depth. Bigger trades on thinner pools move the price more, and the impact is already reflected in the quoted output. **Slippage** is the tolerance you set on top: the maximum further movement you'll accept between quote and settlement before the trade reverts (Market) or the order doesn't settle (Delta). See [Swaps → Key terms](/docs/overview/product-stack/swaps#key-terms) for the canonical definitions. ## Token support ### How do I trade a token that isn't in the default list? For the API, just pass the token's contract address as `srcToken` or `destToken`, with the matching `srcDecimals` or `destDecimals`. There's no allowlist gating on `/v2/quote` or `/prices` beyond what liquidity venues quote. For the [Widget](/docs/widget/configure#token-lists), add custom token-list URLs via `config.tokenLists` (spread `defaults.tokenLists` to keep the curated set, or replace entirely). If the route comes back unpriced, see [Route availability](#route-availability) below. ### What about tax tokens / fee-on-transfer tokens? Delta doesn't support tax or fee-on-transfer tokens today; route them through Market instead. On [`GET /prices`](/docs/api-reference/market/prices), declare the fees so the quote accounts for them: * `srcTokenTransferFee` / `destTokenTransferFee` — tax in basis points on every transfer of the token. * `srcTokenDexTransferFee` / `destTokenDexTransferFee` — tax in basis points charged only on DEX swaps. ## Route availability ### Why is no route available for my pair? A `400` with `{"errorType":"PricingError"}` from `/v2/quote` or `/prices` means neither Market nor Delta could source the pair on the requested chain. Common causes: the token isn't quoted by any liquidity venue Velora indexes, the trade size exceeds depth, or the chain doesn't have the relevant DEX. Check [Chains & contracts](/docs/resources/chains-and-contracts) for per-chain coverage and [`GET /chains`](/docs/api-reference/market/overview) at runtime for the authoritative supported-chain list. Failure modes per endpoint: [Troubleshooting](/docs/api-reference/troubleshooting). ### Can I filter on specific DEXs? Market only. Pass `includeDEXS` or `excludeDEXS` to [`GET /prices`](/docs/api-reference/market/prices) as a comma-separated list of DEX names and the router will restrict the route to (or exclude) those venues. Delta has no equivalent: solvers pick their own execution path. ## Limit orders & Delta intents ### Why hasn't my limit order filled? A signed Delta order fills only when a solver can hit your limit price and net the spread. If the market hasn't reached your price, it stays pending; if it expires past the `deadline`, it transitions to `EXPIRED`; if your token allowance to the Delta contract was revoked or balance moved, it transitions to `FAILED` post-acceptance. Confirm your approval points at the Delta contract per [Token approvals for agents](/docs/for-agents/token-approvals). ### Does a failed Delta order cost anything? No. Whether the order expires, is rejected, or settlement reverts on-chain, you pay no gas and your funds stay in your wallet. On Market, by contrast, a reverted swap still costs you the gas of the failed call. Side-by-side breakdown: [Trading modes](/docs/integrate/trading-modes). ### How do I cancel a pending order? How you cancel depends on the order type. Non-ETH Delta orders cancel off-chain via signed typed data, so cancellation costs no gas. ETH-source Delta orders cancel on-chain via `withdrawAndCancel`, a single tx that withdraws the ETH and invalidates the order. OTC orders also cancel on-chain. ## Fees & monetization ### How do partner fees work? Pass a `partner` identifier with each request and you can attach one of two revenue levers: a fixed `partnerFeeBps` (basis-point cut, predictable) or `takeSurplus` (50% of any positive slippage from solver competition, variable). The two are mutually exclusive; the fee wins if both are set. On Delta, partners receive 100% of the fee; on Market, Velora takes 15% to fund routing. Full split tables and API parameters: [Monetization](/docs/overview/monetization). ### What's the difference between a free partner ID and a Pro API account? A **free partner ID** is just a string you pass as `&partner=`; there's nothing to sign up for and no key to manage. It identifies your traffic, gets you 1 RPS / 3,000 req/day, and *if* you also attach `partnerAddress` + `partnerFeeBps` or `takeSurplus`, it unlocks the partner-fee economics from [Monetization](/docs/overview/monetization). A **Pro API account** is a paid plan layered on top: higher sustained and burst RPS, larger daily quotas, an analytics dashboard, early-feature access, and SLA-backed support. Full plan comparison: [Pro API accounts](/docs/overview/pro-api-accounts). ## Troubleshooting For failure-mode tables by endpoint (`GET /prices`, `POST /transactions/:chainId`, `GET /v2/quote`, `POST /v2/delta/orders/build`, `POST /v2/delta/orders`), see [Troubleshooting](/docs/api-reference/troubleshooting). Each row maps a symptom to a root cause and a fix, and the same data is available machine-readable at [`/resources/errors.json`](/docs/resources/errors.json). # Velora agent decision tables Source: https://new-docs.velora.xyz/docs/for-agents/decision-tables Deterministic routing rules that map user intent, quote responses, wallet state, and errors to the next Velora action. Use these tables when an agent needs to choose the next Velora action. Prefer explicit rules over model judgment, and branch on the data returned by the API rather than on assumptions from the prompt. ## User intent → Velora surface | User intent | Prefer | Agent action | Why | | -------------------------------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------- | | "Swap token A to token B" | `mode=ALL` | Call [`GET /v2/quote`](/docs/api-reference/market/quote) with `mode=ALL`, `chainId`, token addresses, amount, slippage, and the app or project `partner` value. | Velora can choose the best available path. | | "Gasless swap" or "I have no gas" | Delta | Call `GET /v2/quote` with `mode=DELTA`. Continue only if the response includes a `delta` block. | Delta uses an EIP-712 signature, a solver auction, and protocol settlement. | | "Place a limit order" or "trade only if price reaches X" | Delta `LIMIT` order | Collect the target price, side, token pair, chain, amount, expiry, recipient, and partially-fillable preference before building the order. | New limit orders are Delta orders over the Delta API, not AugustusRFQ. | | "TWAP this trade" or "split this order over time" | Delta TWAP | Collect side, total amount, number of slices, cadence/interval, chain, token pair, slippage/price constraints, deadline/expiry, recipient, and max source spend for buy TWAPs. | TWAP is one scheduled Delta order, not repeated independent swaps. Preserve sell-vs-buy amount semantics. | | "Best price" | `mode=ALL` | Quote with `mode=ALL`, then branch on `delta` vs `market`. | Velora can choose the best available path. | | "Protect me from MEV" | Delta | Call `GET /v2/quote` with `mode=DELTA`. Continue only if the response includes a `delta` block. | MEV protection is a Delta-only scenario. | | "Swap now" or "settle in this transaction" | Market API | Call `GET /v2/quote` with `mode=MARKET`, then build a Market transaction. | Market returns calldata the user sends on-chain. | | "Sell exactly this amount" | Sell quote | Treat the user amount as the source amount. | The user fixed input. Do not reinterpret it as a target output. | | "Buy exactly this amount" | Buy quote | Treat the user amount as the destination amount and cap source spend. | The user fixed output. The agent should protect max spend. | | "Embed swaps in my app" | SDK or Widget | Use the SDK for custom UX, or the Widget for fastest integration. | The agent should not build raw API plumbing when the requested job is app embedding. | | "OTC" or "RFQ with a counterparty" | AugustusRFQ | Route to the AugustusRFQ flow. | AugustusRFQ is for OTC/RFQ settlement, not standard limit orders. | Use `mode=ALL` when the user has not explicitly chosen Delta or Market. A `mode=ALL` response returns one execution path. Do not expect both. ## Quote response → next action | API result | Next action | Preserve | Do not | | ---------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ----------------------------------------------------------------- | | Top-level response field is `delta` | Continue the Delta order flow with [`POST /v2/delta/orders/build`](/docs/api-reference/delta/orders-build). | Pass the `delta` object and matching `hmac` from the same quote response. | Do not normalize, sort, round, or reconstruct the `delta` object. | | Top-level response field is `market` | Continue the Market transaction flow with [`POST /transactions/:chainId`](/docs/api-reference/market/transactions). | Pass the returned `market` object into the transaction build step. | Do not try to submit it as a Delta order. | | Response has neither `delta` nor `market` | Stop the flow and surface the no-route result. | Keep the user's original tokens, chain, amount, and mode for retry suggestions. | Do not fabricate a quote, route, gas estimate, or output amount. | | Quote expired, HMAC invalid, or build rejected | Requote, then rebuild from the fresh response. | Use the newest `delta`, `hmac`, or `market` object. | Do not reuse stale quote payloads. | | Chain or token unsupported | Ask the user to choose a supported chain/token pair. | Link to [chains and contracts](/docs/resources/chains-and-contracts) when useful. | Do not guess a token address from symbol alone. | ## Wallet state → approval or signature | Wallet state | Agent action | Rule | | ------------------------------------------- | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | | Source token is native ETH | Skip ERC-20 approval. | Use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` as the native token placeholder. | | ERC-20 allowance is insufficient for Market | Ask the user to approve the Market spender, then rebuild or send the swap transaction. | Market execution uses Augustus v6.2 calldata. | | ERC-20 allowance is insufficient for Delta | Ask the user to approve the Delta spender before submitting the order. | Do not approve Augustus for a Delta order. | | Wallet can sign EIP-712 | Use Delta when the quote response includes `delta`. | The user signs typed data, not an on-chain transaction. | | Wallet cannot sign EIP-712 | Ask whether to fall back to Market if a Market route is available. | Do not silently change execution mode. | | Connected chain differs from quote chain | Ask the user to switch networks before signing or sending. | The chain used for quote, approval, signature, and execution must match. | | Recipient is not the connected wallet | Ask for explicit confirmation. | Treat third-party recipients as a sensitive action. | ## Execution mode → signing behavior | Flow | User signs | User pays gas | Submit with | Track with | | -------------------- | ----------------------------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------ | -------------------------------- | | Market Swap | On-chain transaction | Yes | Wallet transaction send | Transaction hash | | Delta Swap | EIP-712 typed data | No | [`POST /v2/delta/orders`](/docs/api-reference/delta/orders-submit) | Delta order ID and status | | Delta `LIMIT` order | EIP-712 typed data from `POST /v2/delta/orders/build` | No at order creation | `POST /v2/delta/orders` with `order=toSign.value`, `signature`, `type=LIMIT`, `chainId`, and `partner` | Order ID and fill status | | Delta TWAP | EIP-712 typed data from `POST /v2/delta/orders/build` | No at order creation | `POST /v2/delta/orders` after signing the built `TWAPOrder` or `TWAPBuyOrder` payload | Slice execution and order status | | AugustusRFQ OTC flow | RFQ order or fill transaction, depending on the integration | Depends on fill path | AugustusRFQ flow | RFQ order/fill state | ## Order type → required details | Order type | Agent must collect | Agent must preserve | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | | Market or Delta Swap | Chain, source token, destination token, amount, direction, recipient, slippage. | The selected execution mode and the quote response object used for build. | | Limit order | Chain, token pair, side, amount, target price, expiry/deadline, recipient, and partially-fillable preference. | The user's target-price constraint and `LIMIT` order type. Do not convert a limit order into an immediate swap unless the user confirms. | | Sell TWAP | Source token, destination token, total source amount to sell, slice count, cadence/interval, deadline/expiry, recipient, slippage/price constraints. | The total source amount and `TWAPOrder` family. Split source amount across slices. | | Buy TWAP | Source token, destination token, total destination amount to receive, max source spend, slice count, cadence/interval, deadline/expiry, recipient, slippage/price constraints. | The total destination target and `TWAPBuyOrder` family. Split destination target across slices and cap source spend. | | OTC / AugustusRFQ | Counterparty, token pair, amount, price, expiry, fill permissions. | OTC/RFQ settlement semantics. Do not label it as a standard limit order. | ## Delta advanced orders → API path | Advanced order | API path | Agent rule | | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Limit order | `GET /v2/delta/prices` → `POST /v2/delta/orders/build` → user signs `toSign` → `POST /v2/delta/orders` with `type=LIMIT`. | Pass `route` and `toSign.value` verbatim. Use `limitAmount` when the target-price constraint needs an explicit amount override. | | Sell TWAP | `GET /v2/delta/prices` for one source slice → `POST /v2/delta/orders/build` with `orderType=TWAPOrder`, `interval`, `numSlices`, and `totalSrcAmount`. | Preserve total source amount and split source across slices. `route.origin.input.amount` must equal `floor(totalSrcAmount / numSlices)`. `deadline` must be at least `numSlices * interval` seconds in the future. | | Buy TWAP | `GET /v2/delta/prices` for one destination slice → `POST /v2/delta/orders/build` with `orderType=TWAPBuyOrder`, `interval`, `numSlices`, `totalDestAmount`, and `maxSrcAmount`. | Preserve total destination amount, split destination across slices, and cap source spend. `route.origin.output.amount` must equal `floor(totalDestAmount / numSlices)`. `deadline` must be at least `numSlices * interval` seconds in the future. | | Read status | `GET /v2/delta/orders/{orderId}`, `GET /v2/delta/orders/hash/{hash}`, or paginated `GET /v2/delta/orders`. | Narrow on `type` and `onChainOrderType`: `LIMIT`, `TWAPOrder`, `TWAPBuyOrder`, `FillableOrder`, etc. | ## Missing information → ask or proceed | Situation | Agent decision | Prompt to user | | --------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | | Token, chain, amount, and direction are all clear | Proceed to quote. | None. | | Token symbol exists on multiple chains | Ask for the chain. | "Which chain should I use for USDC?" | | Token symbol maps to multiple token contracts on the same chain | Ask for the token address or show choices. | "I found multiple tokens named X. Which contract should I use?" | | Slippage is missing | Use the app's configured default, or ask if no default exists. | "What slippage tolerance should I use?" | | User asks for maximum balance swap | Ask for confirmation before quoting the full balance. | "Do you want to swap your entire balance, excluding gas if needed?" | | Price impact is high | Warn and ask for confirmation before signing. | "This route has high price impact. Do you want to continue?" | | User asks for an unsupported chain | Stop and show supported alternatives. | "Velora does not support that chain for this flow yet. Choose one of these chains instead." | ## Error or symptom → recovery action | Symptom | Likely cause | Agent recovery | | ------------------------------------------------------------------ | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | `400` for missing slippage | Quote request is incomplete. | Add slippage in basis points and retry. | | Pricing error or no route | No route for the requested pair, size, chain, or mode. | Retry with `mode=ALL`, reduce size, change token, or ask the user for another route. | | HMAC or quote validation error | The quote payload is stale or mismatched. | Requote and rebuild from the same fresh response. | | Approval transaction succeeds but swap still fails allowance check | Approval went to the wrong spender or wrong chain. | Check the spender for the selected mode and ask for a new approval if needed. | | User rejects transaction or signature | User declined the action. | Stop. Do not retry automatically. | | Delta order remains pending | The auction or protocol settlement is still in progress, or the order may expire. | Poll status with backoff and show the latest order state. Do not resubmit blindly. | | Transaction reverts | Market transaction failed on-chain. | Surface the revert, suggest requoting, and avoid replaying the same calldata. | ## Guardrails for agents * Never invent token addresses, chain IDs, quotes, transaction hashes, or order IDs. * Always set `partner` to the integrator's app or project partner key. Treat `my-app-name` as a placeholder, not a literal value. * Branch on the response shape: `delta` means Delta order flow; `market` means Market transaction flow. * Keep the `delta` block and its `hmac` together. Treat them as an opaque pair. * Requote after expiration, HMAC errors, material balance changes, or route failures. * Ask before changing execution mode, recipient, chain, or spend direction. * Ask for user confirmation before submitting a signed order or sending an on-chain transaction. Choose between `mode=DELTA`, `mode=MARKET`, and `mode=ALL`. Quote Delta and Market paths from the same endpoint. Build calldata from a Market response. Check supported chains and canonical contract addresses. Route target-price orders to Delta order flows. Preserve sell-vs-buy amount semantics when splitting trades over time. # Velora agent five-call recipe Source: https://new-docs.velora.xyz/docs/for-agents/five-call-recipe The canonical agent loop for Velora trades: normalize intent, quote or construct, build, authorize, submit, and track. Most Velora agent workflows follow the same loop: 1. Normalize the user intent. 2. Quote or construct the order. 3. Build the executable payload. 4. Ask the user to authorize the exact payload. 5. Submit and track until the flow completes or fails. The exact endpoint sequence depends on the selected execution path. Use [Decision tables](/docs/for-agents/decision-tables) to choose the path before running this recipe. ## Universal agent loop | Step | Agent action | Output | | --------------------- | ------------------------------------------------------------------------------------------- | ----------------------------------------------------- | | 1. Normalize | Resolve chain, tokens, amount, direction, recipient, execution preference, and constraints. | Complete intent object | | 2. Quote or construct | Quote swaps, or construct a limit order, TWAP, or OTC intent. | Top-level `delta`, top-level `market`, or order draft | | 3. Build | Build typed data or transaction calldata. | EIP-712 payload or transaction request | | 4. Authorize | Ask the user to review and sign or send. | Signature or transaction hash | | 5. Track | Poll order status or transaction receipt. | Filled, failed, expired, reverted, or pending | Do not ask the user to sign until chain, tokens, amount, recipient, order type, and execution path are final. If any material field changes, rebuild and ask again. ## Delta Swap Use Delta when the user wants gasless execution, MEV protection, solver competition, or a Delta-only flow. ```text theme={null} 1. GET /v2/quote?mode=DELTA 2. POST /v2/delta/orders/build - pass the returned delta.route verbatim - set owner to the user's address 3. Ask the user to sign the returned toSign EIP-712 payload 4. POST /v2/delta/orders with order=toSign.value, signature, chainId, and partner 5. GET /v2/delta/orders/{orderId} until COMPLETED, FAILED, or EXPIRED ``` Agent rules: * Use `chainId`, not `network`, on quote requests. * Include a `partner` value on quote requests. Use the app or project partner key; examples use `my-app-name` only as a placeholder. * Pass the `delta.route` from the quote response into `/v2/delta/orders/build` unchanged, and submit `toSign.value` unchanged as `order`. * Do not grant approval to Augustus for a Delta order; approve the Delta contract (the `spender` from the quote response). * Track by Delta order ID, not by transaction hash. ## Market Swap Use Market when the user wants immediate on-chain settlement or when the selected quote response has a top-level `market` object. ```text theme={null} 1. GET /v2/quote?mode=MARKET 2. POST /transactions/:chainId 3. Ask the user to review and send the transaction 4. Wait for the transaction receipt 5. Surface success, revert, or timeout ``` Agent rules: * Market is an on-chain transaction flow. * The user signs a transaction and pays gas. * Track with the transaction hash. * Requote if the transaction build fails, the quote expires, or balances materially change. * Do not submit a Market response as a Delta order. ## Auto-route with `mode=ALL` Use `mode=ALL` when the user asks for a normal swap or best available execution without choosing Delta or Market. ```text theme={null} 1. GET /v2/quote?mode=ALL 2. If the top-level response field is delta, continue the Delta Swap flow from build onward 3. If the top-level response field is market, continue the Market Swap flow from transaction build onward 4. If neither field is present, stop and handle no-route ``` Agent rules: * `mode=ALL` returns one selected execution path, not both. * Branch on the top-level response field, not on the requested mode. * Ask before changing execution mode if the user explicitly requested Delta or Market. ## Delta Limit Order Use a Delta Limit Order when the user wants target-price execution, delayed settlement, or “only trade if price reaches X”. New integrations should describe the HTTP API flow directly: price the route, build a Delta order with `type=LIMIT`, sign the returned EIP-712 payload, submit the signed order, then track it through Delta order status. ```text theme={null} 1. Normalize the target-price intent 2. GET /v2/delta/prices for the route 3. POST /v2/delta/orders/build - pass the returned route verbatim - set type=LIMIT at submission time - use limitAmount for the user's target-price constraint when needed 4. Ask the user to sign the returned toSign EIP-712 payload 5. POST /v2/delta/orders with order=toSign.value, signature, type=LIMIT, chainId, and partner 6. Track with GET /v2/delta/orders/{orderId}, GET /v2/delta/orders/hash/{hash}, or GET /v2/delta/orders ``` Agent rules: * Limit orders are Delta orders, not AugustusRFQ orders. * Preserve the user's target price, side, amount, token pair, chain, recipient, expiry/deadline, and partially-fillable preference. * Treat `LIMIT` as the order type constraint; do not turn it into a Market Swap just because a spot quote is available. * Pass `route` into `/v2/delta/orders/build` unchanged, and submit `toSign.value` unchanged as `order`. * If the target price, expiry, amount, or recipient changes, rebuild and ask the user to sign again. ## Delta TWAP Use a Delta TWAP when the user wants one signed order to split execution across time. Delta exposes TWAP as advanced order families in `/v2/delta/orders/build`: `orderType=TWAPOrder` for sell-side schedules and `orderType=TWAPBuyOrder` for buy-side schedules. ```text theme={null} 1. Normalize the TWAP schedule 2. GET /v2/delta/prices for one slice - Sell TWAP: route.origin.input.amount = floor(totalSrcAmount / numSlices) - Buy TWAP: route.origin.output.amount = floor(totalDestAmount / numSlices) 3. POST /v2/delta/orders/build - pass the returned route verbatim - set orderType=TWAPOrder for sell schedules, or orderType=TWAPBuyOrder for buy schedules - include interval and numSlices - include totalSrcAmount for TWAPOrder - include totalDestAmount and maxSrcAmount for TWAPBuyOrder - set deadline at least numSlices * interval seconds in the future 4. Ask the user to sign the returned toSign EIP-712 payload 5. POST /v2/delta/orders with order=toSign.value, signature, chainId, and partner 6. Track with GET /v2/delta/orders/{orderId}, GET /v2/delta/orders/hash/{hash}, or GET /v2/delta/orders ``` Agent rules: * Do not model TWAP as a loop of unrelated swaps; it is one scheduled Delta order. * Sell TWAP: preserve the total source amount to sell and split source amount across slices. * Buy TWAP: preserve the total destination amount to receive and split destination target across slices while capping source spend. * Preserve slice count, cadence/interval, deadline/expiry, token pair, chain, recipient, slippage or price constraints, and partially-fillable behavior. * If any schedule field changes, rebuild the TWAP order and ask the user to sign again. ## Failure handling | Failure | Agent action | | ------------------------------------- | ----------------------------------------------------------------------------- | | Missing required field | Ask the user for the missing field. | | No route | Ask for a different amount, token, chain, or execution mode. | | Quote expired | Requote and rebuild. | | HMAC or quote validation error | Requote and keep the new response object paired with its new validation data. | | User rejects signature or transaction | Stop. Do not retry automatically. | | Transaction reverts | Surface the revert and suggest requoting. | | Delta order remains pending | Poll with backoff and show the latest order status. | | Limit order or TWAP expires | Surface the expiry. Do not recreate automatically. | ## Guardrails * Never invent token addresses, chain IDs, quotes, transaction hashes, or order IDs. * Do not mutate top-level `delta` or `market` response objects. * Do not treat limit orders as AugustusRFQ. * Do not treat TWAP as unrelated swaps. * Do not retry rejected signatures automatically. * Ask before changing chain, recipient, order type, execution mode, amount direction, target price, schedule, or expiry. Route user intent and API responses to the next action. Quote Delta, Market, or auto-routed paths. Build calldata from a Market response. Per-endpoint failure modes: symptom, root cause, fix. # Velora MCP server tools Source: https://new-docs.velora.xyz/docs/for-agents/mcp-server/available-tools Reference for all 9 Velora MCP server tools and 5 resources — parameters, return shapes, and the agent rules each tool enforces. The Velora MCP server exposes 9 tools and 5 read-only resources. Tool and parameter names below are verbatim from the server's public contract; the contract is stable, so agents can hardcode against it. ## Response envelope Every tool returns the same envelope: ```json theme={null} { "result": {}, "agentHints": [], "docs": [{ "title": "...", "url": "https://velora.xyz/docs/...", "uri": "velora://docs/..." }], "warnings": [] } ``` * `result` — the tool-specific payload. Raw API responses appear unmodified under `result.raw`. * `agentHints` — the next safe step, as plain strings. Follow them. * `docs` — links into this documentation relevant to the result. * `warnings` — user-facing caveats (for example, the sign-externally reminder on every built transaction). Errors use the same envelope with `isError: true` and `result.error.{type, message}`. Validation failures and documented upstream errors surface their `errorType` and `details`; unexpected failures stay generic. ## Quoting and building ### velora\_get\_quote Get a Velora quote. Delta, Market, or both modes via the unified quote endpoint. | Parameter | Type | Required | Notes | | -------------- | ---------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------- | | `chainId` | number | Yes | Always `chainId`, never `network`. | | `destChainId` | number | No | Set for Crosschain quotes. Crosschain is Delta-only; `mode=MARKET` with a different `destChainId` is rejected before any API call. | | `srcToken` | string | Yes | Token address. Native token placeholder: `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`. | | `destToken` | string | Yes | Token address, same format. | | `amount` | string | Yes | Raw units (wei-style), digits only. | | `srcDecimals` | number | Yes | Source token decimals. | | `destDecimals` | number | Yes | Destination token decimals. | | `side` | `"SELL"` \| `"BUY"` | Yes | | | `userAddress` | string | No | The wallet that will execute. | | `mode` | `"DELTA"` \| `"MARKET"` \| `"ALL"` | No | Default `ALL`. Use `DELTA` for MEV protection, Limit Orders, TWAP, and Crosschain. | | `partner` | string | No | Your partner key; `my-app-name` is the placeholder to replace. | Returns `{ modeRequested, responseType, raw }` where `responseType` is `"delta"`, `"market"`, or `"unknown"` and `raw` is the upstream payload, preserved unchanged. Agent rules: * Branch on `responseType`, never on what you requested. `mode=ALL` returns either a Delta or a Market response, never both. * A Delta quote is completed through the Delta path (`POST /v2/delta/orders/build`, sign externally, `POST /v2/delta/orders`) — not through `velora_build_transaction`. The quote's `agentHints` repeat these steps. * Preserve the `delta` payload and its `hmac` exactly. Never normalize, reconstruct, or mutate it. * Under `mode=ALL`, a Delta pricing failure falls back to Market and surfaces a structured `fallbackReason` in `warnings`. ### velora\_build\_transaction Build an **unsigned** Market swap transaction from a quote's `priceRoute`. Market only. | Parameter | Type | Required | Notes | | ------------- | ------ | -------- | --------------------------------------------------------- | | `chainId` | number | Yes | | | `srcToken` | string | Yes | Token address. | | `destToken` | string | Yes | Token address. | | `srcAmount` | string | Yes | Raw units. | | `destAmount` | string | Yes | Raw units. | | `userAddress` | string | Yes | The wallet that will sign and send. | | `priceRoute` | object | Yes | Copied **verbatim** from the Market quote's `priceRoute`. | | `partner` | string | No | Your partner key. | Returns `result.raw` with the unsigned transaction fields: `from`, `to` (the Augustus v6.2 router), `value`, `data`, gas pricing, and `chainId`. Agent rules: * The transaction is never signed here. Every response carries the warning "Review and sign externally with the user's wallet." * Delta-shaped input (anything containing `delta`, `orderType`, or `alternatives` keys) is rejected with an error pointing to the Delta build → sign → submit path. ## Agent guidance These three tools are deterministic, rule-based logic. They make no network calls and involve no model, so the same input always produces the same answer. ### velora\_decide\_execution\_route Decide whether a trading intent should use Delta, Market, ALL, or none of the quote modes. Call it before `velora_get_quote` when the mode is unclear. | Parameter | Type | Required | Notes | | ------------- | ------------------- | -------- | ------------------------------------------------------------- | | `userIntent` | string | Yes | The user's request, free-form. | | `chainId` | number | No | | | `destChainId` | number | No | A different `destChainId` forces the Crosschain (Delta) rule. | | `srcToken` | string | No | | | `destToken` | string | No | | | `amount` | string | No | | | `side` | `"SELL"` \| `"BUY"` | No | | Returns `{ recommendedMode, reasoning }` where `recommendedMode` is `"DELTA"`, `"MARKET"`, `"ALL"`, or `"NONE"`. Rule precedence (first match wins): OTC intent → `NONE` (it's the AugustusRFQ maker/taker flow, not a quote mode) · MEV protection → `DELTA` · Crosschain → `DELTA` · Limit Orders → `DELTA` · TWAP or DCA → `DELTA` · explicit Market → `MARKET` · explicit Delta → `DELTA` · best-execution language → `ALL` · default → `ALL`. ### velora\_explain\_quote Classify a raw quote response and return the safe completion path. Never mutates the payload. | Parameter | Type | Required | Notes | | --------------- | ------ | -------- | ----------------------------------------- | | `raw` | object | Yes | The `result.raw` from `velora_get_quote`. | | `modeRequested` | string | Yes | The mode you passed to the quote call. | Returns `{ responseType, summary, fallbackReason }`. A top-level `delta` key classifies as `"delta"`, a top-level `market` key as `"market"`, anything else as `"unknown"`. `fallbackReason` (`{ errorType, details }`) appears when Delta pricing was skipped under `mode=ALL`. ### velora\_validate\_agent\_plan Check a free-form plan against the mistakes agents actually make with Velora, before any of them execute. | Parameter | Type | Required | Notes | | --------- | ------ | -------- | ------------------------------------- | | `plan` | object | Yes | Your plan as a free-form JSON object. | Returns `{ issues }`, each issue carrying `severity` (`"info"`, `"warning"`, or `"critical"`), `message`, and `fix`. Checks include: a `network` key anywhere in the plan (must be `chainId`), MEV intent with a non-Delta mode, Crosschain with `mode=MARKET`, Limit Orders or TWAP treated as RFQ, and any signing, private-key, or Delta-payload-mutation step (critical — the server never signs). ## Market data ### velora\_get\_supported\_chains List the EVM chains Velora supports. No parameters. Returns `result.raw.chains` as `{ chainId, name }` pairs with `source: "server-known"`: Ethereum (1), Optimism (10), BNB Chain (56), Gnosis (100), Unichain (130), Polygon (137), Sonic (146), Base (8453), Arbitrum (42161), Avalanche (43114). This is a server-known list, not a live API response, and may lag actual support. Confirm a specific chain with `velora_get_tokens`; do not assume every EVM chain is supported. ### velora\_get\_tokens List the tokens Velora can route on a chain. Use it to resolve token addresses and decimals before quoting instead of inventing them. | Parameter | Type | Required | Notes | | --------- | ------ | -------- | ---------------------------------- | | `chainId` | number | Yes | Always `chainId`, never `network`. | Returns `result.raw.tokens` as `{ symbol, address, decimals, img, network }` entries. ## Documentation ### velora\_search\_docs Search Velora's canonical documentation. Use it before guessing Velora behavior. | Parameter | Type | Required | Notes | | --------- | ------ | -------- | ---------------- | | `query` | string | Yes | | | `limit` | number | No | 1–20, default 5. | Returns search results as `{ title, url, resourceUri, snippet }`. ### velora\_get\_docs\_page Fetch a single docs page as markdown by its slug. | Parameter | Type | Required | Notes | | --------- | ------ | -------- | --------------------------------------------------------------------------------------------- | | `slug` | string | Yes | A docs slug such as `integrate/trading-modes`. Absolute URLs and path traversal are rejected. | Returns `{ slug, content }`. ## Resources Five read-only documents an MCP client can pull straight into context: | Resource URI | What it is | When to read it | | -------------------------------- | ---------------------------------------------------------------- | --------------------------------------------------------------- | | `velora://docs/llms` | The docs index (`llms.txt`), a compact map of the documentation. | First. Orient before fetching pages. | | `velora://docs/llms-full` | The full documentation concatenated. | When you need authoritative detail and have the context budget. | | `velora://docs/openapi/delta-v2` | OpenAPI spec for the Delta v2 intent API. | Generating or checking Delta integration code. | | `velora://docs/openapi/market` | OpenAPI spec for the Market aggregator API. | Generating or checking Market integration code. | | `velora://docs/openapi/rfq` | OpenAPI spec for AugustusRFQ (OTC maker/taker). | OTC flows. RFQ is not a quote mode. | ## Next steps These tools composed into end-to-end Delta and Market workflows. The full intent-to-action mapping the guidance tools implement. # Velora MCP server examples Source: https://new-docs.velora.xyz/docs/for-agents/mcp-server/examples Worked Velora MCP server workflows — gasless Delta swaps, Market swaps with unsigned transactions, mode=ALL fallback handling, and plan validation. Each example below is a complete tool-call sequence against the hosted server. Arguments are shown as the JSON your MCP client sends; replace `my-app-name` with your partner key and `userAddress` with the executing wallet. ## Gasless Delta swap The default flow for swaps that need MEV protection or gasless execution. The server quotes; the Delta order itself is built, signed, and submitted through the Delta API, outside the server. 1. Route the intent (skip if you already know the mode): ```json velora_decide_execution_route theme={null} { "userIntent": "swap 1 ETH to USDC without paying gas, protect me from MEV", "chainId": 1 } ``` Returns `recommendedMode: "DELTA"` with the reasoning. 2. Quote with `mode=DELTA`: ```json velora_get_quote theme={null} { "chainId": 1, "srcToken": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "destToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "srcDecimals": 18, "destDecimals": 6, "amount": "1000000000000000000", "side": "SELL", "mode": "DELTA", "userAddress": "0xYourUserWallet", "partner": "my-app-name" } ``` The response has `responseType: "delta"` and the raw quote under `result.raw`, with `agentHints` spelling out the completion path. 3. Complete the order outside the MCP server, exactly as the hints say: * Pass the quote's route **verbatim** to [`POST /v2/delta/orders/build`](/docs/api-reference/delta/orders-build), which returns unsigned EIP-712 typed data. * Have the user's wallet sign that typed data. The MCP server never signs. * Submit the signed order via [`POST /v2/delta/orders`](/docs/api-reference/delta/orders-submit) and track it by order ID. Preserve the `delta` payload and its `hmac` exactly between steps. Any mutation invalidates the order. ## Market swap with an unsigned transaction For immediate on-chain settlement where the user pays gas. 1. Quote with `mode=MARKET`: ```json velora_get_quote theme={null} { "chainId": 1, "srcToken": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "destToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "srcDecimals": 18, "destDecimals": 6, "amount": "1000000000000000000", "side": "SELL", "mode": "MARKET", "userAddress": "0xYourUserWallet", "partner": "my-app-name" } ``` The response has `responseType: "market"` and a `priceRoute` inside `result.raw.market`. 2. Build the unsigned transaction, passing `priceRoute` verbatim: ```json velora_build_transaction theme={null} { "chainId": 1, "srcToken": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "destToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "srcAmount": "1000000000000000000", "destAmount": "", "userAddress": "0xYourUserWallet", "priceRoute": { "...": "copied verbatim from the quote" }, "partner": "my-app-name" } ``` `result.raw` is the unsigned transaction (`from`, `to`, `value`, `data`, gas fields). The `warnings` array reminds you every time: review and sign externally with the user's wallet. 3. Sign and broadcast with the user's wallet, then track the transaction hash. For an ERC-20 source token, check the allowance to the Augustus v6.2 router first; see [Token approvals](/docs/for-agents/token-approvals). ## mode=ALL with fallback handling Let Velora pick the best path, then branch on what came back. 1. Quote with `mode: "ALL"` (or omit `mode`; ALL is the default). The same arguments as above apply. 2. Branch on the response shape, never on the request: ```json velora_explain_quote theme={null} { "raw": { "...": "result.raw from the quote" }, "modeRequested": "ALL" } ``` * `responseType: "delta"` → continue with the Delta build → sign → submit path. * `responseType: "market"` → continue with `velora_build_transaction`. * A `fallbackReason` (`{ errorType, details }`) means Delta pricing was skipped and Velora fell back to Market. Surface it to the user if the intent required Delta-only properties such as MEV protection, then requote with `mode=DELTA` or adjust the trade. ## Validate a plan before executing it Run any multi-step plan through the validator before the first call. Here is a plan with two classic mistakes: ```json velora_validate_agent_plan theme={null} { "plan": { "steps": [ { "action": "get quote", "network": 1, "mode": "MARKET", "intent": "MEV-protected swap" }, { "action": "sign transaction with stored private key" } ] } } ``` The response flags every issue with a fix: * `network` must be `chainId` (warning). * MEV protection requires `mode=DELTA`, not `MARKET` (warning). * A signing step with a stored key is flagged **critical** — signing belongs to the user's wallet, never to the agent or the server. Fix the plan, validate again, then execute. ## Ground your agent in the docs Before generating integration code, pull canonical material instead of relying on training data: 1. `velora_search_docs` with a behavior question, for example `{ "query": "mode=ALL response shape" }`. 2. `velora_get_docs_page` with a result's slug, for example `{ "slug": "integrate/trading-modes" }`, to load the full page as markdown. 3. For broad work, read the `velora://docs/llms` resource to map the docs, and `velora://docs/llms-full` when you want the entire documentation in context. The OpenAPI resources (`velora://docs/openapi/delta-v2`, `velora://docs/openapi/market`, `velora://docs/openapi/rfq`) keep generated request and response types honest. ## Next steps The same flows over raw HTTP, with failure handling per step. Full parameter reference for every tool used above. # Install the Velora MCP server Source: https://new-docs.velora.xyz/docs/for-agents/mcp-server/installation Connect Claude Code, Claude Desktop, Cursor, Windsurf, or VS Code to the hosted Velora MCP server — one URL, no API key, no local process. The Velora MCP server is hosted, so installation is one step: point your client at the endpoint. Nothing runs on your machine, and the server requires no API key. ```text theme={null} https://ai.velora.xyz/mcp ``` The endpoint speaks Streamable HTTP, the current MCP transport. Clients that only support the legacy HTTP+SSE transport (pre-2025-03-26 spec) use `https://ai.velora.xyz/mcp/sse` instead. ## Client setup ```bash theme={null} claude mcp add --transport http velora https://ai.velora.xyz/mcp ``` Run `/mcp` inside Claude Code to confirm the server is connected and list its tools. Add the server as a custom connector: 1. Open **Settings → Connectors**. 2. Click **Add custom connector**. 3. Name it `velora` and set the URL to `https://ai.velora.xyz/mcp`. No OAuth or token step appears because the server requires no authentication. Add to `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` globally): ```json theme={null} { "mcpServers": { "velora": { "url": "https://ai.velora.xyz/mcp" } } } ``` Add to `.vscode/mcp.json` in your workspace: ```json theme={null} { "servers": { "velora": { "type": "http", "url": "https://ai.velora.xyz/mcp" } } } ``` Add to `~/.codeium/windsurf/mcp_config.json`: ```json theme={null} { "mcpServers": { "velora": { "serverUrl": "https://ai.velora.xyz/mcp" } } } ``` Any MCP-compatible client works with the generic remote-server config: ```json theme={null} { "mcpServers": { "velora": { "url": "https://ai.velora.xyz/mcp" } } } ``` The server is stateless: each JSON-RPC POST stands alone, no `initialize` handshake or session header is required, and any number of clients can connect concurrently. CORS allows any origin, so browser-based clients work too. ## Verify the connection A correctly connected client lists **9 tools** (all prefixed `velora_`) and **5 resources** (all prefixed `velora://docs/`). 1. List the server's tools (`tools/list`, or your client's MCP panel). Expect 9 tools, from `velora_search_docs` to `velora_validate_agent_plan`. 2. Call `velora_get_supported_chains` with no arguments. Expect a chain list that includes Ethereum (1), Base (8453), and Arbitrum (42161). You can also smoke-test from the command line without any MCP client: ```bash theme={null} curl -s https://ai.velora.xyz/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' ``` The response arrives as a single SSE frame; the JSON-RPC result is on the `data:` line. ## Troubleshooting | Symptom | Cause | Fix | | ---------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | `405` on GET `/mcp` | The stateless endpoint has no standalone SSE stream. | POST JSON-RPC to `/mcp`, or use the legacy transport at `/mcp/sse` if your client requires a GET-opened stream. | | `406 Not Acceptable` from your own client code | Missing `Accept` header values. | Send `Accept: application/json, text/event-stream` on every POST. | | Client expects an SSE `endpoint` event | The client speaks the pre-2025-03-26 HTTP+SSE transport. | Point it at `https://ai.velora.xyz/mcp/sse` instead. | | Client asks for an API key or OAuth flow | Misconfigured auth settings. | Leave authentication empty; the server is public and requires none. | | Connection works but tool calls are rejected | Per-IP rate limiting. | Back off and retry; batch agent work instead of polling in a tight loop. | ## Next steps Parameters, return shapes, and the agent rules each tool enforces. End-to-end tool-call sequences for Delta and Market flows. # Velora MCP server for AI agents Source: https://new-docs.velora.xyz/docs/for-agents/mcp-server/overview The hosted Velora MCP server gives Claude, Cursor, and any other MCP client live DEX quotes, Delta routing guidance, and unsigned swap transactions at one URL, with no API key. The Velora MCP server is a hosted [Model Context Protocol](https://modelcontextprotocol.io) endpoint that connects any MCP client to Velora: live quotes across 10+ EVM chains, deterministic Delta and Market routing guidance, unsigned transaction building, and the full Velora documentation. There is nothing to install and no API key to request. Add the URL and your agent works against live Velora data instead of guessing from training data. ```text theme={null} https://ai.velora.xyz/mcp ``` ```json theme={null} { "mcpServers": { "velora": { "url": "https://ai.velora.xyz/mcp" } } } ``` Works with Claude Code, Claude Desktop, claude.ai, Cursor, Windsurf, VS Code, the MCP Inspector, and custom agents. See [Installation](/docs/for-agents/mcp-server/installation) for per-client setup. ## The server never signs This is the property that makes the server safe to wire into an autonomous agent. No tool accepts a private key, and no tool signs or submits anything: * `velora_build_transaction` returns an **unsigned** Market transaction. Your client signs it with the user's wallet. * Delta quotes hand back the documented build → sign → submit path. The EIP-712 typed data is signed externally, never by the server. * Raw quote payloads, including the `delta` object and its `hmac`, are preserved byte-for-byte. The server never mutates what the API returned. An agent connected to this server can research, quote, and prepare trades. It cannot move funds. ## Velora's rules, encoded as tools LLMs forget API rules under pressure; deterministic tools don't. Three guidance tools run pure rule-based logic, with no network calls and no model in the loop: | Tool | What it prevents | | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `velora_decide_execution_route` | Quoting with the wrong mode. MEV protection, crosschain, Limit Orders, and TWAP all route to Delta; OTC is flagged as the AugustusRFQ flow, not a quote mode. | | `velora_validate_agent_plan` | Shipping a plan with classic mistakes: `network` instead of `chainId`, crosschain with `mode=MARKET`, Limit Orders treated as RFQ, or any signing step (flagged critical). | | `velora_explain_quote` | Misreading a quote. Classifies the response as `delta` or `market` and surfaces any `fallbackReason`, so the agent branches on shape instead of assumptions. | Every tool response also carries `agentHints` (the next safe step) and `docs` (links into this site), so an agent that has never seen Velora can complete a flow correctly on the first pass. ## Tools at a glance | Category | Tools | | -------------------- | ---------------------------------------------------------------------------------------------- | | Quoting and building | `velora_get_quote` (Delta, Market, or ALL), `velora_build_transaction` (unsigned, Market only) | | Agent guidance | `velora_decide_execution_route`, `velora_explain_quote`, `velora_validate_agent_plan` | | Market data | `velora_get_supported_chains`, `velora_get_tokens` | | Documentation | `velora_search_docs`, `velora_get_docs_page` | Five MCP resources expose the docs index (`llms.txt`), the full documentation, and the OpenAPI specs for Delta, Market, and AugustusRFQ. Full schemas are on [Available tools](/docs/for-agents/mcp-server/available-tools). ## When to use it * Trading agents that need live quotes plus a safety rail between the model and the user's wallet. * Coding agents building a Velora integration: the docs tools and OpenAPI resources keep generated code grounded in canonical behavior. * Chat assistants answering "what would this swap cost" questions with real routes. For raw HTTP integrations, start from the [Five-call recipe](/docs/for-agents/five-call-recipe) instead; the MCP server wraps the same API. ## Next steps Add the server to Claude Code, Claude Desktop, Cursor, Windsurf, or VS Code in under a minute. Every tool and resource, with verbatim parameters and the agent rules each one enforces. Worked tool-call sequences: Delta swaps, Market swaps, fallback handling, plan validation. A verified prompt that gets a coding agent to a working client in 50 lines. # AI agent trading with Velora Source: https://new-docs.velora.xyz/docs/for-agents/overview Use Velora as an execution layer for AI agents: quote, route, sign, submit, and recover with deterministic API flows. AI agents are good at orchestration, but bad at guessing financial state. Velora gives agents a small set of deterministic trading primitives: quote, choose an execution path, build the action, collect the right signature, submit, and track status. Use this section when you want Claude, Cursor, Codex, an MCP client, or your own agent runtime to build or operate a Velora integration. ## What agents can do with Velora Map user requests like “swap now”, “gasless swap”, or “protect me from MEV” to the right Velora flow. Quote, build, sign, submit, and poll swaps, limit orders, and TWAPs using deterministic sequences. Copy verified prompts for Claude Code, Cursor, Codex, and other coding agents. Point any MCP client at the hosted Velora server for quotes, guidance, and unsigned transactions. ## Why Velora fits agents Agents need APIs that return structured decisions, not ambiguous text. Velora exposes execution paths as explicit response objects: * Top-level `delta` means continue the Delta order flow. * Top-level `market` means continue the Market transaction flow. * If neither is present, stop and ask the user to change the trade. That lets an agent branch deterministically instead of guessing which route was selected. ## Execution paths | Path | Use when | User signs | Agent tracks | | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | -------------------------------- | | Delta Swap | The user wants gasless execution, MEV protection, or solver competition for an immediate swap. | EIP-712 typed data | Order ID and status | | Delta Limit Order | The user wants to trade only at a target price or better. This is a Delta `LIMIT` order built and submitted through the Delta API, not AugustusRFQ. | EIP-712 typed data | Order ID and fill status | | Delta TWAP | The user wants one signed order that splits execution across time. Sell TWAPs preserve source amount; buy TWAPs preserve destination amount and cap source spend. | EIP-712 typed data | Slice execution and order status | | Market API | The user wants immediate on-chain settlement. | Transaction | Transaction hash | | AugustusRFQ | The user wants OTC/RFQ settlement with a counterparty. | RFQ order or transaction, depending on flow | RFQ fill state | | Widget / SDK | The user wants an app integration, not a raw API flow. | Depends on configured flow | App-level state | ## The agent rule Agents should not infer trading behavior from natural language alone. Always branch on the quote response shape: top-level `delta` means Delta, top-level `market` means Market. ## Where to start * Use [Decision tables](/docs/for-agents/decision-tables) to route user intent and API responses. * Use [Five-call recipe](/docs/for-agents/five-call-recipe) to implement the canonical trade loop. * Use [Prompt library](/docs/for-agents/prompt-library) to generate working integrations with AI coding agents. * Use [Trading modes](/docs/integrate/trading-modes) to understand `mode=DELTA`, `mode=MARKET`, and `mode=ALL`. * Use [Limit orders](/docs/overview/product-stack/limit-orders) and [TWAP](/docs/overview/product-stack/twap) when the user wants delayed execution, target prices, or time-sliced trades. For API-based agents, build these flows through `/v2/delta/prices`, `/v2/delta/orders/build`, `/v2/delta/orders`, and Delta order read endpoints. ## Guardrails Agents should: * Never invent token addresses, chain IDs, quotes, transaction hashes, or order IDs. * Ask before changing chain, recipient, spend direction, or execution mode. * Ask for confirmation before submitting a signed order or sending a transaction. * Requote when the quote expires, validation fails, or balances materially change. * Treat `delta` and `market` as mutually exclusive top-level response paths. # Crosschain Aave deposit prompt Source: https://new-docs.velora.xyz/docs/for-agents/prompt-library/crosschain-aave-deposit Prompt an AI agent to wire a one-tx Crosschain swap-and-deposit into Aave via Delta. ## Outcome A single user signature kicks off a **Crosschain Delta** order: source token on chain A is swapped to USDC on chain B, then immediately deposited into Aave v3 on chain B. The user pays no gas on either side. ## Prompt ```text Claude Code theme={null} You are building a React component that runs a Velora Crosschain Delta flow with a post-fill action hook into Aave v3. Requirements: - The user holds (say) USDC on Polygon. They want to end up with aUSDC supplied to Aave v3 on Base. One signature. - Use Velora's Crosschain Delta V2 API. Endpoints: `GET /v2/quote` (with `mode=DELTA` and `destChainId` per [Crosschain Delta docs]), `POST /v2/delta/orders/build`, `POST /v2/delta/orders`. - Always set `partner` to the host app's partner identifier on every quote call (`my-app-name` is only a placeholder). - The winning fill resolves on Base; you provide a post-fill calldata hook that calls `aavePool.supply(USDC, amount, user, 0)` against Aave v3's Base pool address. - Read the Aave v3 pool address from a constants file (do NOT hardcode in component code). - Surface clear status: "Quoting" → "Signing" → "Filling on Base" → "Depositing into Aave" → "Done". - On failure at any stage, return the user to a recoverable state. Cancel the Delta order if it hasn't filled. Reference these docs and follow them exactly: - https://velora.xyz/docs/delta/overview - https://velora.xyz/docs/delta/crosschain-delta - https://velora.xyz/docs/api-reference/delta/quote - https://velora.xyz/docs/api-reference/delta/orders-build - https://velora.xyz/docs/api-reference/delta/orders-submit Do NOT chain the Aave deposit as a separate signed transaction; it must be part of the Delta fill. Do NOT skip the order-status poll between fill and deposit. ``` ```text Cursor theme={null} [Same prompt body as Claude Code above.] ``` ```text Codex theme={null} [Same prompt body as Claude Code above.] ``` ## End-state check * One signature from the user. No gas paid on either chain. * Aave on Base shows the supplied position under the user's address. # Velora AI agent prompt library Source: https://new-docs.velora.xyz/docs/for-agents/prompt-library/index Curated, copy-paste prompts that get AI coding agents to ship Velora integrations on the first pass. Each prompt is verified at every SDK or API minor release. The prompt library is a curated set of prompts that take an AI coding agent (Claude Code, Cursor, Codex) from cold start to a working Velora integration in one shot. Each prompt lists its outcome, target client, and a `last-verified` date. DevRel re-verifies at each minor release. Prompts ship page-by-page on `main`. The table below previews what's coming. ## Available prompts | # | Slug | Outcome | | - | ------------------------- | --------------------------------------------------------------- | | 1 | `nextjs-delta-swap` | Add Delta gasless swaps to a Next.js dApp | | 2 | `nextjs-market-swap` | Integrate Velora Market Swap into a Next.js dApp (Wagmi + Viem) | | 3 | `parallel-aggregators` | Run Velora alongside another aggregator and route per-quote | | 4 | `telegram-trading-bot` | Telegram bot: quote, slippage check, swap with MEV protection | | 5 | `crosschain-aave-deposit` | One-tx Crosschain swap + Aave deposit via Delta | | 6 | `mcp-client-from-scratch` | Build a Velora MCP client in 50 lines | | 7 | `widget-react-embed` | Embed the Velora Widget with custom theming | | 8 | `rfq-otc-flow` | Sign and fill an AugustusRFQ order off-chain | ## How to use 1. Open the prompt page for the outcome you want. 2. Copy the body for your client (Claude Code, Cursor, Codex; one tab per client in a ``). 3. Paste into a fresh agent session with the linked Velora docs as context. 4. Run the verifiable end-state check listed at the bottom of each prompt page. If a prompt drifts and stops producing working code, [open an issue](https://github.com/VeloraDEX). DevRel re-verifies at every minor release, but real-world drift between releases is what we want to hear about. # Velora MCP client prompt Source: https://new-docs.velora.xyz/docs/for-agents/prompt-library/mcp-client-from-scratch Prompt an AI agent to build a minimal MCP client against the hosted Velora MCP server. ## Outcome A minimal MCP client (≤50 lines of TypeScript) that connects to the hosted Velora MCP server, lists available tools, and runs an end-to-end `velora_get_quote → velora_build_transaction` flow that prints an unsigned Market swap transaction. ## Prompt ```text Claude Code theme={null} You are building a tiny standalone MCP client in TypeScript using the `@modelcontextprotocol/sdk` package. Requirements: - Connect to the Velora MCP server over Streamable HTTP at https://ai.velora.xyz/mcp (no API key; transport details per /for-agents/mcp-server/installation). - After connection, call `tools/list` and print the available tools (expect 9, all prefixed `velora_`). - Call `velora_get_quote` for selling 1 ETH (srcToken 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, srcDecimals 18) to USDC (destDecimals 6) on Ethereum mainnet (chainId 1, never `network`) with `mode: "MARKET"` and `partner` set to the app or project partner key (`my-app-name` is only a placeholder). - Call `velora_build_transaction` with the quote's `priceRoute` passed verbatim, and print the resulting UNSIGNED transaction. Do not sign or broadcast anything — the server never signs, and neither does this client. - Print every tool result, including `agentHints` and `warnings` from the response envelope. Exit cleanly after printing the unsigned transaction or a terminal error. - Total file size: ≤ 50 lines, excluding imports. Reference these docs and follow them exactly: - https://velora.xyz/docs/for-agents/mcp-server/overview - https://velora.xyz/docs/for-agents/mcp-server/installation - https://velora.xyz/docs/for-agents/mcp-server/available-tools - https://velora.xyz/docs/for-agents/mcp-server/examples Do NOT hardcode tool schemas; read them from `tools/list` and use the response shape at runtime. ``` ```text Cursor theme={null} [Same prompt body as Claude Code above.] ``` ```text Codex theme={null} [Same prompt body as Claude Code above.] ``` ## End-state check * The script runs end-to-end and prints an unsigned transaction object (`from`, `to`, `value`, `data`) from `velora_build_transaction`. * Nothing in the script signs, stores keys, or broadcasts. * `wc -l` on the source file (sans imports) reports ≤ 50. # Next.js Delta swap prompt Source: https://new-docs.velora.xyz/docs/for-agents/prompt-library/nextjs-delta-swap Prompt an AI agent to add Velora Delta gasless swaps to a Next.js dApp. ## Outcome A Next.js 14 page that runs the full **Delta** flow: quote → build → EIP-712 sign → submit → poll. The user pays no gas; the solver network fills. ## Prompt ```text Claude Code theme={null} You are working in a Next.js 14 App Router project with Wagmi v2 and Viem already configured. Build a `/swap-gasless` page that lets the user place a Velora Delta intent for any ERC-20 → any ERC-20. Requirements: - Use the Velora Delta V2 REST API at `https://api.velora.xyz`. Endpoints: `GET /v2/quote` (with `mode=DELTA`), `POST /v2/delta/orders/build`, `POST /v2/delta/orders`, `GET /v2/delta/orders/{orderId}`. - Always set `partner` to the host app's partner identifier on every quote call (`my-app-name` is only a placeholder). - For the native ETH placeholder, use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`. - Pass `slippage` (basis points) to `POST /v2/delta/orders/build`; it defaults to 100 (1%) if omitted. - Pass the `delta.route` returned by `/v2/quote` verbatim to `/v2/delta/orders/build`, with `owner` set to the user address. Do not normalize, sort, or re-stringify it. - Use Viem's `signTypedData` to sign the `toSign` payload returned by `/v2/delta/orders/build`. Then submit to `/v2/delta/orders` with `order` set to `toSign.value`, the `signature`, `chainId`, and `partner`. - Poll `GET /v2/delta/orders/{orderId}` and display lifecycle states (`PENDING` → `COMPLETED` / `FAILED`). - Token approvals must be granted to the **Delta contract** (not Augustus). The address is per-chain: fetch from /resources/chains-and-contracts, use the `delta.spender` from the quote response, or read it from the typed-data `domain.verifyingContract`. Reference these docs and follow them exactly: - https://velora.xyz/docs/delta/overview - https://velora.xyz/docs/delta/how-it-works - https://velora.xyz/docs/api-reference/delta/quote - https://velora.xyz/docs/api-reference/delta/orders-build - https://velora.xyz/docs/api-reference/delta/orders-submit Do NOT mutate the `delta.route` between quote and build. Do NOT grant approval to Augustus; Delta has its own spender contract. ``` ```text Cursor theme={null} [Same prompt body as Claude Code above.] ``` ```text Codex theme={null} [Same prompt body as Claude Code above.] ``` ## End-state check * The user signs **once** (EIP-712 typed data) and pays **no gas**. * The order transitions through `PENDING` → `COMPLETED` and the user receives the `destToken`. * The token approval was granted to the Delta contract address from the typed-data domain, not Augustus. # Next.js Market swap prompt Source: https://new-docs.velora.xyz/docs/for-agents/prompt-library/nextjs-market-swap Prompt an AI agent to integrate Velora Market Swap into a Next.js dApp using Wagmi and Viem. Want gasless + MEV-protected fills instead? Start with [`nextjs-delta-swap`](/docs/for-agents/prompt-library/nextjs-delta-swap), or call `GET /v2/quote?mode=ALL` and let Velora pick the path; see [Trading modes](/docs/integrate/trading-modes). ## Outcome A Next.js 14 (App Router) page with a fully working **Velora Market** swap: quote → build calldata → sign and send via Wagmi/Viem. The user signs one transaction. The route uses Augustus v6.2 against the chain selected by their connected wallet. ## Prompt ```text Claude Code theme={null} You are working in a Next.js 14 App Router project with Wagmi v2 and Viem already configured. Build a `/swap` page that lets the user swap any ERC-20 → any ERC-20 on Velora's Market API. Requirements: - Use the Velora Market REST API at `https://api.velora.xyz`. Endpoints: `GET /prices` and `POST /transactions/:chainId`. - Always set `partner` to the host app's partner identifier on every quote call (`my-app-name` is only a placeholder). - For the native ETH placeholder, use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` (mixed case; lowercase is rejected). - Quote first, then call `/transactions/:chainId` with the `priceRoute` returned by the quote, passed verbatim. - Use Viem's `useWalletClient` to send the transaction. Read `chainId` from Wagmi. - Handle the three real failure modes: stale `priceRoute` (re-quote on submit), `INSUFFICIENT_OUTPUT` revert (increase slippage and retry), and ERC-20 allowance missing (prompt approval to the v6.2 router from the quote response's `contractAddress` field). - Show the user `srcUSD`, `destUSD`, `gasCostUSD`, and `partnerFee` from the response before they confirm. Reference these docs and follow them exactly: - https://velora.xyz/docs/overview/quickstart - https://velora.xyz/docs/api-reference/market/prices - https://velora.xyz/docs/api-reference/market/transactions Do NOT invent endpoint paths. Do NOT cache `priceRoute` longer than 30 seconds. Always approve the address returned in `priceRoute.contractAddress` (not a hardcoded address). ``` ```text Cursor theme={null} [Same prompt body as Claude Code above. Cursor reads workspace docs by default. If you have the Velora docs cloned, point Cursor at them via @docs.] ``` ```text Codex theme={null} [Same prompt body as Claude Code above. With Codex, supply the four reference URLs as `--allowed-domains` and run the prompt in workspace-write mode.] ``` ## End-state check * A signed swap transaction lands on-chain in your wallet's history. * `priceRoute.version` on the most recent quote is `"6.2"`. * The token approval (if needed) was granted to `priceRoute.contractAddress`, not to a hardcoded address. # Parallel aggregator routing prompt Source: https://new-docs.velora.xyz/docs/for-agents/prompt-library/parallel-aggregators Prompt an AI agent to wire Velora as a parallel quote source and route per-quote. ## Outcome A backend service that **fans out a single user swap intent** to Velora and one other aggregator, compares the quotes, and returns the winner. Velora is queried either as two parallel calls (`mode=DELTA` and `mode=MARKET`) to compare paths head-to-head, or as a single `mode=ALL` call where Velora has already picked the winner server-side and the client checks which block is present: `delta` or `market`. ## Prompt ```text Claude Code theme={null} You are extending an existing TypeScript backend that already wires one DEX aggregator (assume 1inch or 0x). Add Velora as a parallel quote source. Requirements: - Velora endpoint: `GET https://api.velora.xyz/v2/quote` with `mode=ALL` and `partner` set to the host app's partner identifier (`my-app-name` is only a placeholder). The `mode=ALL` response contains exactly one of `delta` or `market` (server-picked winner). To compare Delta vs Market head-to-head before competing against the other aggregator, issue two requests in parallel (`mode=DELTA` and `mode=MARKET`), then pick the better Velora result. - Compare on `destUSD` (or `destAmount` normalized to a common token) net of `gasCostUSD` and `partnerFee`. - Fan out in parallel; respect a hard 800ms budget per quote source; fall back gracefully if one source times out. - For the Velora native-ETH placeholder use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` (mixed case). - If Velora wins via Delta, return both the `delta` block and `hmac` to the caller so they can sign and submit. If via Market, return the `market` block (same shape as `/prices`'s `priceRoute`). Reference these docs and follow them exactly: - https://velora.xyz/docs/overview/why-velora - https://velora.xyz/docs/api-reference/market/prices - https://velora.xyz/docs/api-reference/market/quote Do NOT race-update shared state across the two aggregators' callbacks. Do NOT fall back silently to the slower source if the budget is exceeded; surface a clear error. ``` ```text Cursor theme={null} [Same prompt body as Claude Code above.] ``` ```text Codex theme={null} [Same prompt body as Claude Code above.] ``` ## End-state check * A side-by-side comparison log shows both aggregators quoting the same trade within the 800ms budget. * When Velora's Delta path wins on a large trade, the response carries the `delta` block + `hmac` ready to sign. # AugustusRFQ OTC flow prompt Source: https://new-docs.velora.xyz/docs/for-agents/prompt-library/rfq-otc-flow Prompt an AI agent to sign and fill an AugustusRFQ order off-chain. ## Outcome A pair of TypeScript scripts: one for the **maker** (constructs and signs an AugustusRFQ order off-chain, supports partial fills) and one for the **taker** (validates the signature and submits the fill on-chain). ## Prompt ```text Claude Code theme={null} You are building two CLI scripts in TypeScript using Viem. Maker script (`make-order.ts`): - Constructs an AugustusRFQ OTC order: sell `srcAmount` of `srcToken` for at least `destAmount` of `destToken`, expires at a configurable timestamp, partial fills allowed. Limit orders are Delta orders; use this RFQ flow only for OTC settlement. - Signs the EIP-712 typed data with the maker's private key. - Outputs the order JSON + signature to stdout (the taker can pick this up via stdin or a side-channel). Taker script (`fill-order.ts`): - Reads the maker's order + signature from stdin. - Validates the signature recovers to the maker's address. - Approves `srcToken` and `destToken` to the AugustusRFQ contract if not already approved. - Submits the fill on-chain via the AugustusRFQ `fillOrderNFT` or equivalent method, supporting partial fill `fillAmount`. Requirements: - Read the AugustusRFQ contract address per chain from `/resources/chains-and-contracts`. - Validate `order.expiry > now()` before submitting. - Catch and surface the common revert reasons (insufficient allowance, expired, already filled). Reference these docs and follow them exactly: - https://velora.xyz/docs/api-reference/rfq/overview - https://velora.xyz/docs/resources/chains-and-contracts - https://velora.xyz/docs/resources/security/audits/augustus-rfq Do NOT submit a fill without re-validating signature and expiry against the on-chain block timestamp. Do NOT skip the partial-fill amount check (taker could fill more than the maker intended otherwise). ``` ```text Cursor theme={null} [Same prompt body as Claude Code above.] ``` ```text Codex theme={null} [Same prompt body as Claude Code above.] ``` ## End-state check * Maker can sign offline; the taker fills on-chain successfully. * A partial fill (e.g. 50%) settles correctly; the remaining 50% is still fillable by a different taker. * Expired or double-fill attempts revert cleanly with the expected error. # Telegram trading bot prompt Source: https://new-docs.velora.xyz/docs/for-agents/prompt-library/telegram-trading-bot Prompt an AI agent to build a Telegram bot that quotes and executes Velora swaps with MEV protection. ## Outcome A Telegram bot in TypeScript that lets a user `/buy ` or `/sell `, quotes via Velora `mode=ALL`, surfaces slippage and price impact, and executes via Delta when available (gasless, MEV-protected). Falls back to Market with a conservative slippage when Delta is unavailable. ## Prompt ```text Claude Code theme={null} You are building a Telegram bot in TypeScript using `grammy` or `telegraf`. The bot has access to a user's connected EVM wallet via a custodied key tied to chat id (assume the wallet infra is solved; just call `signMessage` and `signTransaction`). Implement `/buy ` and `/sell `. Requirements: - Resolve token addresses against Velora's tokens endpoint (`/tokens/:chainId`). - Quote with `mode=ALL` at `GET https://api.velora.xyz/v2/quote`. Always set `partner` to the bot's partner identifier (`my-app-name` is only a placeholder). Native ETH placeholder: `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`. - Show the user `destAmount`, `destUSD`, `gasCostUSD`, and `priceImpact` BEFORE asking them to confirm. - If `response.delta` exists, prefer the Delta path: build → sign EIP-712 → submit → poll. The user pays no gas. - If only `response.market` exists, fall back to Market with `slippage=100` (1%) and warn the user about MEV exposure on larger trades (size > $5k). - Include the `priceImpact` warning at >2%. Reference these docs and follow them exactly: - https://velora.xyz/docs/overview/why-velora - https://velora.xyz/docs/api-reference/market/prices - https://velora.xyz/docs/api-reference/market/quote - https://velora.xyz/docs/api-reference/delta/orders-build - https://velora.xyz/docs/api-reference/delta/orders-submit Do NOT auto-execute trades without explicit user confirmation. Do NOT swallow Delta polling errors silently. ``` ```text Cursor theme={null} [Same prompt body as Claude Code above.] ``` ```text Codex theme={null} [Same prompt body as Claude Code above.] ``` ## End-state check * A `/buy` flow on a \$1k trade routes through Delta and settles gaslessly within the lifecycle window. * On a tiny test trade where Delta returns no quote, Market is used with the slippage and MEV warning surfaced. # Velora Widget React embed prompt Source: https://new-docs.velora.xyz/docs/for-agents/prompt-library/widget-react-embed Prompt an AI agent to embed the Velora Widget into a React app, sync its light/dark theme with the host, and wire up partner attribution and events. ## Outcome A React component that mounts the Velora Widget. Its light/dark theme follows the host app, `partnerConfig.partner` attributes swaps to the host, and lifecycle events feed the host's analytics. The widget is a drop-in React component; there is no iframe build. You can switch between bundled **light** and **dark** themes (or follow system preference). See [Customize](https://velora.xyz/docs/widget/customize). ## Prompt ```text Claude Code theme={null} You are integrating the Velora Widget into an existing React 18+ app. Requirements: - Install `@velora-dex/widget` and `@tanstack/react-query` (peer dependency). - Mount the widget at the `/swap` route via React Router or Next.js routing. - Pass `config.partnerConfig.partner` (a `partner` identifier from env, e.g. `my-app-name`). - Theme: the widget only supports `theme: "light" | "dark"` (omit to follow the OS `prefers-color-scheme`). Drive the `theme` config field from the host app's current light/dark mode so the two stay in sync. Do NOT attempt to pass brand colors, fonts, or border-radius; there is no API for that. - Memoize any non-primitive `config` value (objects/arrays) with `useMemo` or a module-level constant, or the widget will re-render. - Subscribe to widget events via the `events` prop and pipe them into the host's analytics module. Use `onSwap` and branch on `event.name`: `Swap:request` (start), `Swap:confirmed` (success), `Swap:failed` (error). Reference these docs and follow them exactly: - https://velora.xyz/docs/widget/install - https://velora.xyz/docs/widget/configure - https://velora.xyz/docs/widget/customize - https://velora.xyz/docs/widget/events-and-callbacks - https://velora.xyz/docs/widget/monetize Load the `partner` identifier from env so different builds (staging, production, white-label) can use different values. ``` ```text Cursor theme={null} [Same prompt body as Claude Code above.] ``` ```text Codex theme={null} [Same prompt body as Claude Code above.] ``` ## End-state check * Toggling the host app between light and dark flips the widget's `theme` to match. * A successful test swap fires the host's analytics events (`Swap:confirmed`) with the expected payload. * The `partner` identifier is present at runtime but not hardcoded in the source tree. # Token approvals for AI agents Source: https://new-docs.velora.xyz/docs/for-agents/token-approvals Agent decision rules for ERC-20 approvals on Velora: derive the spender from the quote response, check allowances before signing, and recover from approval mistakes. Approvals are the single most common place agents get a Velora flow wrong. The mode you quote against decides the spender, and the spender is **never the same as the swap target**. This page holds the agent decision tables: which contract gets the `approve(spender, amount)` call, what to check before signing, and how to recover when an approval lands on the wrong contract. For how approvals and permits work conceptually, read [Approvals and permit](/docs/resources/approvals). ## When to use this * The user's source token is an ERC-20 and you're about to build a Market transaction, a Delta order, or an AugustusRFQ fill. * You're deciding whether to ask the user for a separate `approve` transaction, or whether to bundle a `permit` / `permit2` payload into the build call instead. * An earlier swap or order failed with an allowance error and you need to figure out which spender actually needed the approval. If the user's source token is the chain's native asset, there is no approval step. Use the canonical placeholder `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` (mixed case) for `srcToken`; Delta moves native ETH as dETH without an approval. See [Native ETH (dETH)](/docs/delta/native-eth). ## The rule (read this first) | Execution mode | Spender to approve | | ------------------------------------- | -------------------------------------------- | | Delta Swap, Delta `LIMIT`, Delta TWAP | **Delta contract** | | Market Swap | **Augustus v6.2** | | AugustusRFQ (OTC/RFQ) | **AugustusRFQ** contract on the target chain | Deployed addresses for each spender, per chain: [Chains & contracts → Addresses by chain](/docs/resources/chains-and-contracts#addresses-by-chain). Delta and AugustusRFQ are not deployed everywhere; code should read availability at runtime via [`/resources/contracts.json`](/docs/resources/contracts.json) keyed by `chainId`. Spenders are mode-specific and **never interchangeable**. An approval to Augustus does not authorize a Delta order. An approval to the Delta contract does not authorize a Market swap. Re-quoting under a different mode changes the spender; re-check the allowance before signing. Agent rules: * Take the spender from the execution mode of the quote response, not from the user's natural-language intent. If the quote response carries a top-level `delta` object, the Delta contract is the spender. If it carries a top-level `market` object, Augustus v6.2 is the spender. * If the user asked for a Delta or RFQ flow on a chain without that contract, surface the limitation and offer the available alternatives. Do not silently fall back to a different mode. ## Permit and Permit2: agent rules When the token supports EIP-2612 Permit or Permit2, you can collect a signature instead of a separate on-chain `approve` transaction. [Approvals and permit](/docs/resources/approvals#approve-or-sign-a-permit) covers how the payload is passed into the Delta and Market build calls. * Detect Permit/Permit2 capability **before** asking the user for an on-chain `approve`; collect the signature instead when supported. * A Permit/Permit2 signature is a user authorization, not a free no-op. Confirm with the user before requesting the signature, the same way you would confirm an on-chain approval. * Permit/Permit2 signatures bind to a specific spender, amount, deadline, and (for Permit2) nonce. If you requote into a different mode, the existing signature is **not transferable**: collect a new one for the new spender. * Delta `LIMIT` orders and TWAP rest or settle over time, so a permit's nonce or deadline expires before settlement. Use an on-chain approval for these, not a permit. See [Limit Orders and TWAP use on-chain approval](/docs/resources/approvals#limit-orders-and-twap-use-on-chain-approval). ## Allowance checks before signing | Allowance state | Agent action | | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `allowance >= amount` for the correct spender on the correct chain | Skip the approval step. Proceed to build → sign → submit. | | `allowance < amount` for the correct spender | Ask the user to approve at least `amount` (or `MaxUint256` if your UX prefers infinite). If the token supports Permit/Permit2, prefer a signed payload over a separate transaction. | | `allowance` was set for a **different spender** (different mode) | Do not retry against the wrong spender. Ask for a fresh approval to the correct spender for the current quote's mode. | | `allowance` is non-zero but you need to lower it for a non-standard ERC-20 (USDT-style) | Approve `0` first, then the new amount. Only required for the small set of tokens that reject non-zero → non-zero. Most modern ERC-20s accept it directly. | | Connected chain differs from quote chain | Stop. The chain used for quote, approval, signature, and execution must match. Ask the user to switch network before reading allowance or sending an approve. | Agent rule: never request an approval before the quote response is final and you know the spender. Approvals to the wrong contract are not refunded by the user's wallet; they leave a stale allowance behind and confuse the next flow. ## Failure modes | Symptom | Likely cause | Agent recovery | | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Approval transaction confirms but the next swap/order still reverts with `insufficient allowance` | Approval was granted to the wrong spender (e.g., Augustus instead of the Delta contract, or vice versa). | Re-read the quote response, identify the correct spender from the spender matrix above, and request a fresh approval to that contract. See the [Delta orders/build failure modes](/docs/api-reference/troubleshooting) row for "Approval reverts before signing". | | Approval confirms on chain A but the swap is on chain B | Wallet was on a different network when the approve was signed. | Ask the user to switch to the quote's chain and re-approve there. Allowances are per-chain. | | `400 Invalid srcToken` on quote or build for native ETH | Sent `0x0` or lowercase `0xeee...e` instead of the canonical placeholder. | Use `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` (mixed case) and requote. | | `400 Permit / Permit2 required` from `POST /v2/delta/orders/build` | Token requires Permit/Permit2 and no payload was attached. | Collect the signed Permit or Permit2 payload up front and include it in the build request. Falling back to a separate `approve` transaction is not supported for these tokens. | | User approved infinite (`MaxUint256`) to one mode's spender, now wants the other mode | Each mode has its own spender. The first allowance is fine but does not authorize the second mode. | Read allowance against the new mode's spender and request a separate approval. Do not treat the existing infinite allowance as universal. | | User rejects the approve transaction or the Permit/Permit2 signature | Explicit user refusal. | Stop. Do not retry automatically. Surface the rejection and ask how to proceed: a different source token, a different mode, or abort. | ## Examples ### Branching by quote response ```text theme={null} 1. GET /v2/quote?mode=ALL with chainId, srcToken, destToken, amount, partner 2. If response has top-level `delta`: - spender = 0x0000000000bbf5c5fd284e657f01bd000933c96d (Delta contract) 3. Else if response has top-level `market`: - spender = 0x6a000f20005980200259b80c5102003040001068 (Augustus v6.2) 4. Else: - Stop. No route. Do not request an approval. 5. If srcToken is native placeholder: - Skip approval. Proceed to build. 6. Else: - Read allowance(srcToken, owner=user, spender) - If allowance < amount: - If srcToken supports Permit/Permit2: collect signature, attach to build - Else: request approve(spender, amount) on the quote's chainId - Wait for approval confirmation before continuing 7. Continue to build → sign → submit ``` ### Switching modes mid-flow If the user accepts a quote, the approval lands on the matching spender, then they ask to switch from Delta to Market (or vice versa) before signing: * Requote in the new mode. * Recheck allowance against the **new** spender. The previous approval does not carry over. * Either approve again to the new spender, or attach a fresh Permit/Permit2 signature to the new build request. * Confirm the user understands they're approving a second contract. ## Guardrails * Take the spender from the **quote response shape**, not from natural language. * Never approve Augustus for a Delta order. Never approve the Delta contract for a Market swap. * Skip ERC-20 approval entirely for native source tokens; use the canonical mixed-case placeholder. * Detect Permit/Permit2 capability before requesting a separate `approve` transaction. * Use an on-chain approval, never a permit, for Delta `LIMIT` orders and TWAP. * Re-check allowance against the new spender any time the execution mode changes. * Treat Permit/Permit2 signatures as one-shot authorizations bound to spender, amount, and deadline; they do not transfer across modes or builds. * Never assume an infinite allowance to one spender covers another. How approvals and permits work: spenders, Permit vs Permit2, native ETH. Route user intent and wallet state to the next agent action. The canonical agent loop: quote, build, authorize, submit, track. Per-chain contract addresses for Delta, Augustus v6.2, and AugustusRFQ. # Velora API integration guide Source: https://new-docs.velora.xyz/docs/integrate/api Velora's REST API is the most flexible way to integrate: it works with any language, any stack, any wallet. The Velora REST API is the most flexible integration path. It works with any language, any framework, and any wallet: server-side, client-side, mobile, agents. If the SDK or Widget don't fit your stack, the API does. ## Why the API A REST API you can call from any language, any runtime. Delta, Market, OTC, quotes, tokens, transactions: everything in one place. No SDK to install, no version drift, just HTTP. ## Build by product Each guide walks one product end to end in raw HTTP, then links to the API reference for full schemas. Gasless, MEV-protected swaps: quote, build, sign, submit, poll. Atomic on-chain swaps the user signs and broadcasts. Delta orders with a target-price constraint. One scheduled Delta order, settled slice-by-slice. Bilateral AugustusRFQ trades between named counterparties. ## Get started See the **[API Reference →](/docs/api-reference/introduction)** for endpoints, parameters, and schemas. ## Examples Language-specific end-to-end snippets live next to the API they target: `GET /v2/quote?mode=DELTA` for a gasless intent quote. TypeScript, Go, Python, Rust. `GET /prices` quote for 1 ETH → USDC. TypeScript, Go, Python, Rust. # Delta swap API integration Source: https://new-docs.velora.xyz/docs/integrate/api/delta-swap Integrate a gasless, MEV-protected Delta swap over the REST API: quote, build, sign, submit, and poll an intent end-to-end with simple HTTP requests. A **Delta swap** lets your user sign one off-chain intent that Delta settles gaslessly through the [Portikus Network](/docs/solver-network/portikus), with MEV protection. This page walks the whole integration end to end: quote the trade, build the order, have the user sign it, submit it, and poll until it settles. Every example is a `curl` or `fetch` call against `https://api.velora.xyz`; no SDK required. For the conceptual model behind the auction and settlement, see [Delta → How it works](/docs/delta/how-it-works). For a typed wrapper over these same calls, see [SDK → Delta](/docs/sdk/products/delta). ## The flow `GET /v2/quote?mode=DELTA` returns a `delta` block with the recommended `route`, the `spender` to approve, and the resolved partner fee. See [`GET /v2/quote`](/docs/api-reference/delta/quote). Authorize the `spender` (the Delta contract) to pull the source token, by on-chain approval or a permit. Native source skips this. See [Approvals and permit](/docs/resources/approvals). `POST /v2/delta/orders/build` with the `delta.route` passed **verbatim**, `owner` set to the user, and a `deadline`. You get back `{ toSign, orderHash }`. See [`POST /v2/delta/orders/build`](/docs/api-reference/delta/orders-build). The user signs `toSign` (ERC-2098 compact signature). `POST /v2/delta/orders` with the `order`, `signature`, `chainId`, and `partner`. See [`POST /v2/delta/orders`](/docs/api-reference/delta/orders-submit). `GET /v2/delta/orders/{orderId}` until the status is terminal (`COMPLETED`, `EXPIRED`, `FAILED`, `CANCELLED`, `REFUNDED`). Crosschain orders can also report `REFUNDING` while Velora waits to verify a bridge refund. See [`GET /v2/delta/orders/{orderId}`](/docs/api-reference/delta/orders-get-by-id). ## 1. Quote ```bash theme={null} curl -G 'https://api.velora.xyz/v2/quote' \ --data-urlencode 'srcToken=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' \ --data-urlencode 'destToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' \ --data-urlencode 'amount=10000000000' \ --data-urlencode 'srcDecimals=6' \ --data-urlencode 'destDecimals=18' \ --data-urlencode 'side=SELL' \ --data-urlencode 'chainId=1' \ --data-urlencode 'mode=DELTA' \ --data-urlencode 'userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' \ --data-urlencode 'partner=my-app-name' ``` The response carries a `delta` block: ```json theme={null} { "delta": { "route": { "origin": { "input": { "amount": "10000000000" }, "output": { "amount": "..." } } }, "spender": "0x...", "destAmount": "..." } } ``` `mode=DELTA` returns a `delta` block or fails with a `400`; it never falls back to Market. If you'd rather let Velora pick the cheaper path, send `mode=ALL` and branch on whether the response has a `delta` or a `market` block. See [Trading modes](/docs/integrate/trading-modes). ## 2. Approve the spender Authorize the Delta contract (the `spender` from the quote) to pull the source token at settlement, with either an on-chain approval or a signed permit. See [Approvals and permit](/docs/resources/approvals) for both methods and when each applies. Selling native ETH skips this step; see [Native ETH (dETH)](/docs/delta/native-eth). ## 3. Build Pass the `delta.route` from the quote **verbatim** into the build call, with `owner` set to the user's address and a `deadline` (unix seconds) after which the order is unfillable: ```bash theme={null} curl -X POST 'https://api.velora.xyz/v2/delta/orders/build' \ -H 'Content-Type: application/json' \ -d '{ "route": { "...": "the delta.route from the quote, unchanged" }, "owner": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "deadline": 1893456000, "partner": "my-app-name" }' ``` ```json theme={null} { "toSign": { "domain": { "...": "..." }, "types": { "...": "..." }, "value": { "...": "..." } }, "orderHash": "0x..." } ``` Pass `delta.route` exactly as the quote returned it. Reordering or re-encoding any field makes the build call reject. ## 4. Sign and submit The user signs the `toSign` typed data. Delta uses **ERC-2098 compact signatures** (64 bytes); viem, ethers v6, and wagmi produce them natively. Then submit the signed order: ```bash theme={null} curl -X POST 'https://api.velora.xyz/v2/delta/orders' \ -H 'Content-Type: application/json' \ -d '{ "chainId": 1, "order": { "...": "toSign.value, sent verbatim" }, "signature": "0x...", "partner": "my-app-name" }' ``` The relayer validates the signature, balance, and allowance, then enrolls the order in the [sealed-bid auction](/docs/solver-network/sealed-bid-auctions). The response is the stored order with its `id`. ## 5. Poll for settlement ```bash theme={null} curl 'https://api.velora.xyz/v2/delta/orders/{orderId}' ``` Poll until the order reaches a terminal status. A same-chain market Delta order usually settles in seconds once the auction has a winning fill, so a short interval is fine. Crosschain orders can spend longer in `BRIDGING`, or in `REFUNDING` if the bridge leg failed and a refund transaction is still being verified. For a human-readable view (status, fills, the settlement transaction), open the order in the Velora explorer at `https://explorer.velora.xyz/order/{orderId}`. It's handy for debugging and for linking users to their order. ## Partner fee Pass `partner` on the quote, build, and submit calls to attribute volume and capture a fee; add `partnerAddress`, `partnerFeeBps`, and `partnerTakesSurplus` to configure it. See [Monetize](/docs/sdk/monetize) for the field reference. ## Related pages * [Delta → How it works](/docs/delta/how-it-works): the auction and settlement model behind these calls. * [Trading modes](/docs/integrate/trading-modes) covers `DELTA` vs `MARKET` vs `ALL` and the fallback envelope. * [Native ETH (dETH)](/docs/delta/native-eth): selling native ETH as a Delta source. * [Limit orders](/docs/integrate/api/limit-orders) and [TWAP](/docs/integrate/api/twap), the same flow with a price constraint or a schedule. * [Delta API reference](/docs/api-reference/delta/overview) for full parameters and response schemas. * [SDK → Delta](/docs/sdk/products/delta), a typed wrapper over this flow. # Limit order API integration Source: https://new-docs.velora.xyz/docs/integrate/api/limit-orders Place a gasless, MEV-protected limit order over the REST API. A limit order is a Delta order with a target-price constraint: build with limitAmount, submit with type=LIMIT, end-to-end. A **limit order** on Velora is a [Delta order](/docs/integrate/api/delta-swap) with a target-price constraint: the user signs once, the [Portikus Network](/docs/solver-network/portikus) fills it at or better than the limit price when the market allows, and the user pays no gas. This page walks the whole integration over the REST API. It's the Delta swap flow with two additions: you set `limitAmount` at build, and submit with `type: "LIMIT"`. Every example targets `https://api.velora.xyz`. For the conceptual model (maker, expiry, how a limit order differs from a swap or OTC), see [Product stack → Limit orders](/docs/overview/product-stack/limit-orders). For a typed wrapper, see [SDK → Limit orders](/docs/sdk/products/limit-orders). ## The flow `GET /v2/quote?mode=DELTA` gives the current route and the `spender` to approve. The market quote is your reference point for setting the limit. See [`GET /v2/quote`](/docs/api-reference/delta/quote). Approve the Delta contract `spender` on-chain for the source token. Limit orders use approval, not a permit; see [Approvals and permit](/docs/resources/approvals). Native source skips this; see [Native ETH (dETH)](/docs/delta/native-eth). `POST /v2/delta/orders/build` with the `route` verbatim, `owner`, a `deadline`, and `limitAmount` (your target output for SELL, or max input for BUY). See [`POST /v2/delta/orders/build`](/docs/api-reference/delta/orders-build). The user signs `toSign`; `POST /v2/delta/orders` with `type: "LIMIT"`. See [`POST /v2/delta/orders`](/docs/api-reference/delta/orders-submit). A limit order rests `ACTIVE` until a solver can meet the price, so poll on a relaxed interval or list the user's open orders. ## 1. Quote and approve Quote exactly as for a [Delta swap](/docs/integrate/api/delta-swap#1-quote) (`mode=DELTA`), then approve the returned `spender` for the source token. Use the quote's expected output as the baseline for the limit price you'll pin in the next step. Approve on-chain rather than with a permit, which a resting order can't rely on (see [Approvals and permit](/docs/resources/approvals)). Selling native ETH skips the approval; see [Native ETH (dETH)](/docs/delta/native-eth). ## 2. Build with a limit price Pass the `delta.route` verbatim and add `limitAmount`. For a SELL order it's the minimum destination amount you'll accept (your limit price). Every Delta order requires a `deadline` (unix seconds); past it the order is unfillable. ```bash theme={null} curl -X POST 'https://api.velora.xyz/v2/delta/orders/build' \ -H 'Content-Type: application/json' \ -d '{ "route": { "...": "the delta.route from the quote, unchanged" }, "owner": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "limitAmount": "3000000000000000000", "deadline": 1893456000, "partner": "my-app-name" }' ``` Setting `limitAmount` above the quoted output is what makes this a limit order rather than a market fill: the solver network only fills once it can deliver at least that much. The response is the same `{ toSign, orderHash }` as a market order. ## 3. Submit as LIMIT The user signs `toSign` (ERC-2098 compact signature). Submit with `type: "LIMIT"`. That field is what marks the order as a resting limit order instead of an immediate fill: ```bash theme={null} curl -X POST 'https://api.velora.xyz/v2/delta/orders' \ -H 'Content-Type: application/json' \ -d '{ "chainId": 1, "order": { "...": "toSign.value, sent verbatim" }, "signature": "0x...", "type": "LIMIT", "partner": "my-app-name" }' ``` ## 4. List and cancel List a user's open limit orders by filtering on `type`: ```bash theme={null} curl -G 'https://api.velora.xyz/v2/delta/orders' \ --data-urlencode 'userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' \ --data-urlencode 'chainId=1' \ --data-urlencode 'type=LIMIT' \ --data-urlencode 'page=1' \ --data-urlencode 'limit=100' ``` To check one order, `GET /v2/delta/orders/{orderId}`, or open it in the Velora explorer at `https://explorer.velora.xyz/order/{orderId}` for a human-readable status view. That's useful for a resting limit order that may sit `ACTIVE` for a while. Cancelling is gasless: the user signs a cancellation payload and you post the order IDs. It only succeeds while the order is still open. ```bash theme={null} curl -X POST 'https://api.velora.xyz/v2/delta/orders/cancel' \ -H 'Content-Type: application/json' \ -d '{ "orderIds": ["..."], "signature": "0x..." }' ``` See [`GET /v2/delta/orders`](/docs/api-reference/delta/orders-list) and [`POST /v2/delta/orders/cancel`](/docs/api-reference/delta/orders-cancel). ## Partner fee Pass `partner` on the quote, build, and submit calls (plus optional `partnerAddress`, `partnerFeeBps`, `partnerTakesSurplus`), exactly as for a Delta swap. See [Monetize](/docs/sdk/monetize). ## Related pages * [Delta swap](/docs/integrate/api/delta-swap): the base flow a limit order extends. * [TWAP](/docs/integrate/api/twap), the other scheduled Delta order type. * [Native ETH (dETH)](/docs/delta/native-eth): selling native ETH as a Delta source. * [Product stack → Limit orders](/docs/overview/product-stack/limit-orders) for the conceptual model. * [Delta API reference](/docs/api-reference/delta/overview) lists full parameters and response schemas. * [SDK → Limit orders](/docs/sdk/products/limit-orders), a typed wrapper over this flow. # Market swap API integration Source: https://new-docs.velora.xyz/docs/integrate/api/market-swap Integrate an atomic on-chain Market swap over the REST API: get a price route, build the transaction, approve, and broadcast end-to-end with direct HTTP calls. A **Market swap** routes through DEX liquidity and settles in a single on-chain transaction that **your user signs and broadcasts**. This page walks the whole integration request by request: get a price route, build the calldata, approve the router, and send the transaction. Every example targets `https://api.velora.xyz`; no SDK required. Market is the right path when the user has gas and wants synchronous, atomic settlement. For gasless, MEV-protected swaps that Delta settles from a signed intent, use a [Delta swap](/docs/integrate/api/delta-swap) instead. For the conceptual model, see [Market → How it works](/docs/market/how-it-works); for a typed wrapper, see [SDK → Market](/docs/sdk/products/swap). ## The flow `GET /prices` returns a `priceRoute`: the best path, the expected `destAmount`, and a gas estimate. See [`GET /prices`](/docs/api-reference/market/prices). `POST /transactions/{chainId}` with the `priceRoute` passed **verbatim** and a slippage tolerance. You get ready-to-broadcast calldata. See [build transaction](/docs/api-reference/market/transactions). For an ERC-20 source, the user approves the Augustus v6.2 router as spender, or passes a permit in the build call to avoid the round-trip. Native source skips this. See [Approvals and permit](/docs/resources/approvals). The user signs the transaction and broadcasts it. Augustus walks the route and delivers `destToken`, or the whole transaction reverts. ## 1. Price ```bash theme={null} curl -G 'https://api.velora.xyz/prices' \ --data-urlencode 'srcToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' \ --data-urlencode 'destToken=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' \ --data-urlencode 'amount=1000000000000000000' \ --data-urlencode 'srcDecimals=18' \ --data-urlencode 'destDecimals=6' \ --data-urlencode 'side=SELL' \ --data-urlencode 'network=1' \ --data-urlencode 'userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' \ --data-urlencode 'partner=my-app-name' \ --data-urlencode 'version=6.2' ``` The `priceRoute` is stateless and unsigned, just a routing plan, and it expires quickly as prices move. Market `/prices` takes `network`; the build call below takes `chainId` in its path. ```json theme={null} { "priceRoute": { "destAmount": "...", "gasCostUSD": "...", "...": "..." } } ``` ## 2. Build the transaction Pass the `priceRoute` **verbatim** and a slippage tolerance (basis points): ```bash theme={null} curl -X POST 'https://api.velora.xyz/transactions/1' \ -H 'Content-Type: application/json' \ -d '{ "priceRoute": { "...": "the priceRoute from /prices, unchanged" }, "srcToken": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "destToken": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "srcAmount": "1000000000000000000", "slippage": 50, "userAddress": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "partner": "my-app-name" }' ``` ```json theme={null} { "to": "0x...", "data": "0x...", "value": "1000000000000000000", "gas": "..." } ``` Pass the `priceRoute` exactly as `/prices` returned it. Mutating any field makes the build call reject. ## 3. Approve the router (ERC-20 only) If the source token is an ERC-20, the user approves the Augustus v6.2 router (the `to` address) before swapping: a standard `approve(spender, amount)`. Augustus v6.2 is the only spender to authorize. Native source tokens skip this; the build call returns the `value` to send with the swap directly. To avoid the extra round-trip, pass an EIP-2612 permit or Permit2 payload in the build call's `permit` field instead of approving on-chain. See [Approvals and permit](/docs/resources/approvals) for the full picture and [build transaction](/docs/api-reference/market/transactions) for the field. Router addresses are in [Chains & contracts](/docs/resources/chains-and-contracts). ## 4. Sign and broadcast Send the `{ to, data, value }` from the build response as a transaction from the user's wallet. Augustus pulls the source token, walks the route, checks the result against the user's minimum (price × `1 − slippage`), and delivers `destToken`. If any hop fails or slippage is exceeded, the transaction reverts; there's no partial-fill state. ## Partner fee Pass `partner` on `/prices` and the build call to attribute volume and capture a fee; add `partnerAddress`, `partnerFeeBps`, and `partnerTakesSurplus` to configure it. See [Monetize](/docs/sdk/monetize) for the field reference. ## Related pages * [Market → How it works](/docs/market/how-it-works): the routing and atomic-settlement model behind these calls. * [Delta swap](/docs/integrate/api/delta-swap), the gasless, MEV-protected alternative. * [Trading modes](/docs/integrate/trading-modes) covers when to pick Market over Delta. * [Market API reference](/docs/api-reference/market/overview) for full parameters and response schemas. * [SDK → Market](/docs/sdk/products/swap), a typed wrapper over this flow. # OTC API integration with AugustusRFQ Source: https://new-docs.velora.xyz/docs/integrate/api/otc Integrate a bilateral OTC trade over the REST API. A maker signs an AugustusRFQ order naming a taker and posts it; the named taker fills it on-chain. Full maker-to-taker walkthrough. An **OTC** trade settles a deal between two known counterparties: a **maker** signs an [AugustusRFQ](/docs/resources/chains-and-contracts) order off-chain naming a specific **taker**, posts it to the API, and only that taker can fill it on-chain. This page walks the whole integration end to end, both sides: the maker approves, signs, and posts; the taker approves and fills. Every REST call targets `https://api.velora.xyz`. OTC is for **bilateral, counterparty-specific** trades. For an open, target-price order that any solver can fill, gasless and MEV-protected, use a [Delta limit order](/docs/integrate/api/limit-orders) instead. For the conceptual model, see [Product stack → OTC](/docs/overview/product-stack/otc); for in-depth field, state, and endpoint detail, see the [OTC API reference](/docs/api-reference/rfq/overview); for a typed wrapper, see [SDK → OTC](/docs/sdk/products/otc). ## The flow The maker approves the AugustusRFQ contract to pull the `makerAsset`. It's a separate contract from the Augustus v6.2 router. Native ETH must be wrapped first. Size against [`GET /ft/fillablebalance`](/docs/api-reference/rfq/fillable-balance), then build the order fields and sign the EIP-712 typed data. `POST /ft/p2p/{chainId}/` with the order and `signature`. The server returns the stored order with its `orderHash`. See [post order](/docs/api-reference/rfq/orders-submit). Hand the signed order to the taker over any channel: your backend, the listing endpoints, or directly. The taker approves AugustusRFQ for the `takerAsset`, then calls `AugustusRFQ.fillOrder` on-chain. This is a transaction, not a REST call. ## 1. Maker: approve and size The maker approves AugustusRFQ for the `makerAsset` they're selling. Then size the order against the maker's fillable balance: the amount reserved by open orders: ```bash theme={null} curl 'https://api.velora.xyz/ft/fillablebalance/1/0xMAKER?token=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' ``` AugustusRFQ addresses per chain are in [Chains & contracts](/docs/resources/chains-and-contracts). ## 2. Maker: build and sign The maker builds the order fields and signs them as EIP-712 typed data. The `taker` field is what makes this bilateral: name an address and only that address can fill; leave the zero address to let anyone fill. The order fields are `nonceAndMeta`, `expiry`, `makerAsset`, `takerAsset`, `makerAmount`, `takerAmount`, `maker`, and `taker`. The signing domain is: ```json theme={null} { "name": "AUGUSTUS RFQ", "version": "1", "chainId": 1, "verifyingContract": "0x... (the AugustusRFQ address for this chain)" } ``` `makerAsset` and `takerAsset` must be ERC-20s. To sell native ETH, wrap it to WETH first. ## 3. Maker: post the order ```bash theme={null} curl -X POST 'https://api.velora.xyz/ft/p2p/1/' \ -H 'Content-Type: application/json' \ -d '{ "nonceAndMeta": "...", "expiry": 1893456000, "makerAsset": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "takerAsset": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "makerAmount": "10000000000", "takerAmount": "3000000000000000000", "maker": "0xMAKER", "taker": "0xTAKER", "signature": "0x..." }' ``` Posting stays off-chain, so the maker pays nothing. The response is the stored order with its `orderHash` and `state`. Pass `permitMakerAsset` instead of a separate approval if the `makerAsset` supports permit. See [post order](/docs/api-reference/rfq/orders-submit). ## 4. Deliver, then the taker fills Hand the signed order to the taker over any off-chain channel, or let them find it through the listing endpoints: [maker orders](/docs/api-reference/rfq/orders-list-maker) and [orders addressed to a taker](/docs/api-reference/rfq/orders-list-taker): ```bash theme={null} curl 'https://api.velora.xyz/ft/p2p/1/taker/0xTAKER' ``` The taker approves AugustusRFQ for the `takerAsset`, then fills **on-chain** by calling `AugustusRFQ.fillOrder` with the order and signature. This settles atomically; the fill reverts if the order is expired, already filled, or the caller isn't the named taker. Always re-check `expiry` against the current block first. From the SDK, [`sdk.otcOrders.fillOTCOrder`](/docs/sdk/products/otc) encodes and submits this transaction for you. ## Cancelling There's no cancel endpoint. The maker cancels by sending a transaction to AugustusRFQ (`cancelOrder(bytes32)` or `cancelOrders(bytes32[])`), so cancellation costs gas. This is the one place OTC differs sharply from Delta's gasless cancel. For a short-lived order, letting it lapse past its `expiry` is often cheaper than an explicit cancel. Once the cancel is indexed, the order's `state` flips to `CANCELLED`. ## Order states and detail An order reports `DRAFT`, `PENDING`, `FULFILLED`, `CANCELLED`, `SUSPENDED`, or `EXPIRED`. Fetch one with [`GET /ft/order/{orderHash}`](/docs/api-reference/rfq/orders-get-by-hash). For the full field semantics, state machine, and per-chain availability, see the [OTC API reference](/docs/api-reference/rfq/overview). ## Related pages * [Product stack → OTC](/docs/overview/product-stack/otc): when the counterparty matters as much as the price. * [Limit orders](/docs/integrate/api/limit-orders), the open, gasless, MEV-protected alternative (Delta). * [OTC API reference](/docs/api-reference/rfq/overview) for in-depth fields, states, and endpoints. * [SDK → OTC](/docs/sdk/products/otc) covers maker and taker flows in TypeScript. * [Chains & contracts](/docs/resources/chains-and-contracts), AugustusRFQ deployment addresses. # TWAP API integration Source: https://new-docs.velora.xyz/docs/integrate/api/twap Schedule a TWAP over the REST API. A TWAP is one Delta order the user signs once; Delta settles it slice-by-slice over time. Quote one slice, build with orderType TWAPOrder, end-to-end. A **TWAP** (time-weighted average price) splits a larger trade into slices executed over time. On Velora it's **one Delta order**, not a loop of swaps: the user signs a single scheduled order, and Delta settles each eligible slice gaslessly through the [Portikus Network](/docs/solver-network/portikus) until the order completes or expires. This page walks the whole integration with direct calls to `https://api.velora.xyz`. It's the [Delta swap](/docs/integrate/api/delta-swap) flow with one wrinkle that trips people up: **you quote a single slice**, not the whole order, and the server multiplies it across the schedule. For the conceptual model, see [Product stack → TWAP](/docs/overview/product-stack/twap). For a typed wrapper, see [SDK → TWAP](/docs/sdk/products/twap). ## Sell vs buy A TWAP is either a sell or a buy, and the field that fixes the total differs: * **Sell TWAP** (`orderType: "TWAPOrder"`) fixes the total **source** amount and splits it across slices. Set `totalSrcAmount`. * **Buy TWAP** (`orderType: "TWAPBuyOrder"`) fixes the total **destination** amount to receive and caps the total source spent. Set `totalDestAmount` and `maxSrcAmount`. ## The flow `GET /v2/quote?mode=DELTA` for the **per-slice** amount, `floor(total / numSlices)`. The route's amount must match that slice; the server applies it across the schedule. Approve the **total** source on-chain (`totalSrcAmount` for sell, `maxSrcAmount` for buy), not one slice. A TWAP uses approval, not a permit; see [Approvals and permit](/docs/resources/approvals). Native source skips this. `POST /v2/delta/orders/build` with the `orderType`, `interval`, `numSlices`, a `deadline`, and the totals. See [`POST /v2/delta/orders/build`](/docs/api-reference/delta/orders-build). The user signs `toSign`; `POST /v2/delta/orders`. See [`POST /v2/delta/orders`](/docs/api-reference/delta/orders-submit). Each slice settles as it becomes eligible; the order completes when the final slice settles, or expires if its constraints can no longer be met. ## 1. Quote one slice Quote the per-slice amount, not the total. For a 4-slice sell of 10,000 USDC, quote `10000000000 / 4 = 2500000000`: ```bash theme={null} curl -G 'https://api.velora.xyz/v2/quote' \ --data-urlencode 'srcToken=0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' \ --data-urlencode 'destToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' \ --data-urlencode 'amount=2500000000' \ --data-urlencode 'srcDecimals=6' \ --data-urlencode 'destDecimals=18' \ --data-urlencode 'side=SELL' \ --data-urlencode 'chainId=1' \ --data-urlencode 'mode=DELTA' \ --data-urlencode 'userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' \ --data-urlencode 'partner=my-app-name' ``` For a sell TWAP, `route.origin.input.amount` must equal `floor(totalSrcAmount / numSlices)`. For a buy TWAP, `route.origin.output.amount` must equal `floor(totalDestAmount / numSlices)`. Each slice executes that floored amount, and the final slice picks up the rounding remainder, so the order settles the exact total. Then approve the **total** source amount, not the slice. Approve on-chain rather than with a permit, which can't cover a multi-slice order (see [Approvals and permit](/docs/resources/approvals)). ## 2. Build the schedule (sell TWAP) ```bash theme={null} curl -X POST 'https://api.velora.xyz/v2/delta/orders/build' \ -H 'Content-Type: application/json' \ -d '{ "orderType": "TWAPOrder", "route": { "...": "the single-slice delta.route, unchanged" }, "owner": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "totalSrcAmount": "10000000000", "numSlices": 4, "interval": 300, "slippage": 50, "deadline": 1893456000, "partner": "my-app-name" }' ``` `numSlices` is at least 2 and `interval` (seconds between slices) at least 60. The `deadline` must leave room for the whole schedule: at least `numSlices × interval` seconds from now, or the submit call rejects the order. The response is the same `{ toSign, orderHash }` as any Delta order. ### Buy TWAP A buy TWAP fixes how much to receive and caps what's spent. Quote a single slice by the per-slice destination amount, then build with `totalDestAmount` and `maxSrcAmount`. Each slice may spend at most its proportional share of `maxSrcAmount`, so a single expensive slice can't eat the whole budget: ```bash theme={null} curl -X POST 'https://api.velora.xyz/v2/delta/orders/build' \ -H 'Content-Type: application/json' \ -d '{ "orderType": "TWAPBuyOrder", "route": { "...": "single-slice route; output.amount = floor(totalDestAmount / numSlices)" }, "owner": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "totalDestAmount": "3000000000000000000", "maxSrcAmount": "10100000000", "numSlices": 4, "interval": 300, "slippage": 50, "deadline": 1893456000, "partner": "my-app-name" }' ``` ## 3. Sign and submit The user signs `toSign` (ERC-2098 compact signature), then you submit the order. There's no TWAP-specific submit; it's the same call as a market Delta order: ```bash theme={null} curl -X POST 'https://api.velora.xyz/v2/delta/orders' \ -H 'Content-Type: application/json' \ -d '{ "chainId": 1, "order": { "...": "toSign.value, sent verbatim" }, "signature": "0x...", "partner": "my-app-name" }' ``` ## 4. Poll, list, and cancel Poll `GET /v2/delta/orders/{orderId}` over the order's lifetime; the `input`/`output` amounts carry expected and executed totals, so you can show fill progress without computing it yourself. For a human-readable view of slice-by-slice progress, open the order in the Velora explorer at `https://explorer.velora.xyz/order/{orderId}`. List a user's TWAPs by filtering on `onChainOrderType`: ```bash theme={null} curl -G 'https://api.velora.xyz/v2/delta/orders' \ --data-urlencode 'userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' \ --data-urlencode 'chainId=1' \ --data-urlencode 'onChainOrderType=TWAPOrder' ``` Cancel the remaining (unsettled) slices with a gasless signed cancellation, the same call as any Delta order: ```bash theme={null} curl -X POST 'https://api.velora.xyz/v2/delta/orders/cancel' \ -H 'Content-Type: application/json' \ -d '{ "orderIds": ["..."], "signature": "0x..." }' ``` See [`GET /v2/delta/orders`](/docs/api-reference/delta/orders-list) and [`POST /v2/delta/orders/cancel`](/docs/api-reference/delta/orders-cancel). ## Partner fee Pass `partner` on the quote, build, and submit calls (plus optional `partnerAddress`, `partnerFeeBps`, `partnerTakesSurplus`), exactly as for a Delta swap. See [Monetize](/docs/sdk/monetize). ## Related pages * [Delta swap](/docs/integrate/api/delta-swap): the base flow a TWAP extends. * [Limit orders](/docs/integrate/api/limit-orders), the other scheduled Delta order type. * [Product stack → TWAP](/docs/overview/product-stack/twap) for the conceptual model. * [Delta API reference](/docs/api-reference/delta/overview) lists full parameters and response schemas. * [SDK → TWAP](/docs/sdk/products/twap), a typed wrapper over this flow. # Velora API rate limits Source: https://new-docs.velora.xyz/docs/integrate/rate-limits Free-tier rate limits for the Velora REST API, and how to lift them with a Pro API account. The free tier is capped at **1 request per second** and **3,000 requests per day**. For higher limits, consider upgrading to a [Pro API account](/docs/overview/pro-api-accounts). # Delta, Market, and fallback modes Source: https://new-docs.velora.xyz/docs/integrate/trading-modes Choose between mode=DELTA, mode=MARKET, and mode=ALL on Velora's /v2/quote endpoint: when to pick each, and how fallback responses work. The `mode` query parameter on [`GET /v2/quote`](/docs/api-reference/market/quote) tells Velora which execution path to consider: `DELTA`, `MARKET`, or `ALL`. `mode=ALL` is the default for clients that don't want to commit upfront. Velora evaluates both paths server-side, picks the winner, and returns **one** response shape: either a `delta` block or a `market` block, never both. Clients must branch on which block is present, not on the mode they requested. ## Delta vs Market | | Delta intent | Normal swap (Market API) | | ------------------ | -------------------------------------------------------------------------------------------------- | -------------------------------------- | | User signs | An EIP-712 order (off-chain message) | A transaction (on-chain tx) | | User pays gas | No | Yes | | MEV exposure | Private solver auction | Public mempool, sandwichable | | Crosschain | One signature, multi-chain settlement | Separate tx per chain | | Price improvements | Solvers compete in an auction to improve the quoted price | Best-effort routing across DEXs | | Failure mode | Revert-protection: failed settlements cost no gas; order expires or is rejected with no funds lost | Tx reverts; gas spent on a failed call | Pick `mode=DELTA` when: * The user can wait a few seconds for solver competition (gasless settlement, MEV-protected fills). * The trade is large enough that solver competition beats AMM routing. * The wallet has no native gas balance and would otherwise need an approval + ETH, typical of mobile, social, and wallet-onboarding flows. * The swap is crosschain: one signed Delta order resolves across chains via bridge-aware solvers. Pick `mode=MARKET` when: * The user needs synchronous, on-chain settlement (for example, composing with another contract in the same transaction). * The trade is small and AMM liquidity is the better route. * Latency matters more than slippage savings. **Fallback envelope.** Fallback runs in one direction only, and only under `mode=ALL`: when Delta can't price the trade, the response carries a `market` block plus a `fallbackReason` (`errorType`, `details`) explaining why Delta was skipped. A `mode=DELTA` request never falls back; with no Delta route it fails with a `400` carrying that same `errorType` and `details`. A `mode=MARKET` request never returns a `delta` block, and when Market pricing fails (including crosschain pairs, which Market doesn't serve) you get a `400` with body `{"errorType":"PricingError","details":"Error getting price data"}`. Branch on which block is present and handle the `400` explicitly. # Market API Go example Source: https://new-docs.velora.xyz/docs/market/examples/go End-to-end Go example: call the Velora Market API to quote 1 ETH → USDC via net/http. A minimal Go program that calls `GET /prices` and prints the quoted `destAmount`. Standard library only. ## File tree ```text theme={null} my-app/ ├─ go.mod └─ main.go ``` ## Install ```bash theme={null} mkdir my-app && cd my-app go mod init example.com/my-app ``` ## `main.go` ```go theme={null} package main import ( "encoding/json" "fmt" "net/http" "net/url" ) func main() { params := url.Values{ "srcToken": {"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"}, // ETH "destToken": {"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"}, // USDC "amount": {"1000000000000000000"}, // 1 ETH "srcDecimals": {"18"}, "destDecimals": {"6"}, "side": {"SELL"}, "network": {"1"}, "userAddress": {"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"}, "partner": {"my-app-name"}, "version": {"6.2"}, } res, err := http.Get("https://api.velora.xyz/prices?" + params.Encode()) if err != nil { panic(err) } defer res.Body.Close() if res.StatusCode != http.StatusOK { panic(fmt.Sprintf("HTTP %d", res.StatusCode)) } var body struct { PriceRoute struct { DestAmount string `json:"destAmount"` GasCostUSD string `json:"gasCostUSD"` } `json:"priceRoute"` } if err := json.NewDecoder(res.Body).Decode(&body); err != nil { panic(err) } fmt.Println("destAmount:", body.PriceRoute.DestAmount) fmt.Println("gasCostUSD:", body.PriceRoute.GasCostUSD) } ``` ## Run it ```bash theme={null} go run . ``` You should see the quoted `destAmount` (USDC, 6 decimals) and `gasCostUSD` printed. ## Next: build the transaction Feed the `priceRoute` into `POST /transactions/:chainId` to get ready-to-broadcast calldata. See [Market API → How it works](/docs/market/how-it-works). ## Related pages * [Market API overview](/docs/market/overview) — when to use Market routing. * [Market API → How it works](/docs/market/how-it-works) — quote → build → broadcast flow. * [Market API reference](/docs/api-reference/market/overview) — full parameter list. # Market API Python example Source: https://new-docs.velora.xyz/docs/market/examples/python End-to-end Python example: call the Velora Market API to quote 1 ETH → USDC via requests. A minimal Python script that calls `GET /prices` and prints the quoted `destAmount`. Uses `requests`. ## File tree ```text theme={null} my-app/ ├─ requirements.txt └─ quote.py ``` ## Install ```bash theme={null} mkdir my-app && cd my-app python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install requests ``` ## `quote.py` ```python theme={null} import requests params = { "srcToken": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", # ETH "destToken": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", # USDC "amount": "1000000000000000000", # 1 ETH "srcDecimals": 18, "destDecimals": 6, "side": "SELL", "network": 1, "userAddress": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "partner": "my-app-name", "version": "6.2", } res = requests.get("https://api.velora.xyz/prices", params=params, timeout=10) res.raise_for_status() price_route = res.json()["priceRoute"] print("destAmount:", price_route["destAmount"]) print("gasCostUSD:", price_route["gasCostUSD"]) ``` ## Run it ```bash theme={null} python quote.py ``` You should see the quoted `destAmount` (USDC, 6 decimals) and `gasCostUSD` printed. ## Next: build the transaction Feed the `priceRoute` into `POST /transactions/:chainId` to get ready-to-broadcast calldata. See [Market API → How it works](/docs/market/how-it-works). ## Related pages * [Market API overview](/docs/market/overview) — when to use Market routing. * [Market API → How it works](/docs/market/how-it-works) — quote → build → broadcast flow. * [Market API reference](/docs/api-reference/market/overview) — full parameter list. # Market API Rust example Source: https://new-docs.velora.xyz/docs/market/examples/rust End-to-end Rust example: call the Velora Market API to quote 1 ETH → USDC via reqwest. A minimal Rust program that calls `GET /prices` and prints the quoted `destAmount`. Uses `reqwest` with `tokio`. ## File tree ```text theme={null} my-app/ ├─ Cargo.toml └─ src/ └─ main.rs ``` ## Install ```bash theme={null} cargo new my-app cd my-app cargo add reqwest --features json cargo add tokio --features full cargo add serde --features derive ``` ## `src/main.rs` ```rust theme={null} use serde::Deserialize; #[derive(Deserialize, Debug)] struct PriceRoute { #[serde(rename = "destAmount")] dest_amount: String, #[serde(rename = "gasCostUSD")] gas_cost_usd: String, } #[derive(Deserialize, Debug)] struct PricesResponse { #[serde(rename = "priceRoute")] price_route: PriceRoute, } #[tokio::main] async fn main() -> Result<(), Box> { let params = [ ("srcToken", "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"), // ETH ("destToken", "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"), // USDC ("amount", "1000000000000000000"), // 1 ETH ("srcDecimals", "18"), ("destDecimals", "6"), ("side", "SELL"), ("network", "1"), ("userAddress", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"), ("partner", "my-app-name"), ("version", "6.2"), ]; let res = reqwest::Client::new() .get("https://api.velora.xyz/prices") .query(¶ms) .send() .await? .error_for_status()? .json::() .await?; println!("destAmount: {}", res.price_route.dest_amount); println!("gasCostUSD: {}", res.price_route.gas_cost_usd); Ok(()) } ``` ## Run it ```bash theme={null} cargo run ``` You should see the quoted `destAmount` (USDC, 6 decimals) and `gasCostUSD` printed. ## Next: build the transaction Feed the `priceRoute` into `POST /transactions/:chainId` to get ready-to-broadcast calldata. See [Market API → How it works](/docs/market/how-it-works). ## Related pages * [Market API overview](/docs/market/overview) — when to use Market routing. * [Market API → How it works](/docs/market/how-it-works) — quote → build → broadcast flow. * [Market API reference](/docs/api-reference/market/overview) — full parameter list. # Market API TypeScript example Source: https://new-docs.velora.xyz/docs/market/examples/typescript End-to-end TypeScript example: call the Velora Market API to quote 1 ETH → USDC via plain fetch. A minimal Node script that calls `GET /prices` and prints the quoted `destAmount`. No SDK, just `fetch`. ## File tree ```text theme={null} my-app/ ├─ package.json ├─ tsconfig.json └─ src/ └─ quote.ts ``` ## Install ```bash pnpm theme={null} mkdir my-app && cd my-app pnpm init pnpm add -D typescript tsx @types/node pnpm tsc --init ``` ```bash npm theme={null} mkdir my-app && cd my-app npm init -y npm install -D typescript tsx @types/node npx tsc --init ``` ```bash yarn theme={null} mkdir my-app && cd my-app yarn init -y yarn add -D typescript tsx @types/node yarn tsc --init ``` ## `src/quote.ts` ```ts theme={null} const params = new URLSearchParams({ srcToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH destToken: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC amount: '1000000000000000000', // 1 ETH srcDecimals: '18', destDecimals: '6', side: 'SELL', network: '1', userAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', partner: 'my-app-name', version: '6.2', }); const res = await fetch(`https://api.velora.xyz/prices?${params}`); if (!res.ok) { throw new Error(`HTTP ${res.status}: ${await res.text()}`); } const { priceRoute } = await res.json(); console.log('destAmount:', priceRoute.destAmount); console.log('gasCostUSD:', priceRoute.gasCostUSD); ``` ## Run it ```bash theme={null} pnpm tsx src/quote.ts ``` You should see the quoted `destAmount` (USDC, 6 decimals) and `gasCostUSD` printed. ## Next: build the transaction Feed the `priceRoute` into `POST /transactions/:chainId` to get ready-to-broadcast calldata. See [Market API → How it works](/docs/market/how-it-works). ## Related pages * [Market API overview](/docs/market/overview) — when to use Market routing. * [Market API → How it works](/docs/market/how-it-works) — quote → build → broadcast flow. * [Market API reference](/docs/api-reference/market/overview) — full parameter list. * [SDK](/docs/sdk/overview) — typed TypeScript wrapper if you'd rather not handle HTTP yourself. # How Market API swaps work Source: https://new-docs.velora.xyz/docs/market/how-it-works From price quote to on-chain settlement: the full Market flow end-to-end. The Market API splits a swap into **price discovery** (off-chain) and **execution** (on-chain). You ask for a route, you build calldata against that route, and your user signs and broadcasts the transaction. Settlement is atomic: the swap either completes in one transaction or reverts. ## The flow at a glance ```mermaid theme={null} sequenceDiagram autonumber actor User participant DApp as Your app / SDK participant API as Velora API participant Router as Augustus v6.2
(per-chain) participant DEXs as DEX liquidity
(Uniswap, Curve, …) User->>DApp: "Swap 1 ETH for USDC" DApp->>API: GET /prices API-->>DApp: priceRoute (best path + expected out) DApp->>API: POST /transactions/:chainId
(priceRoute + slippage) API-->>DApp: tx calldata (to, data, value, gas) opt ERC-20 source token DApp->>User: Request approval for Augustus User->>Router: approve(spender, amount) end DApp->>User: Request transaction signature User-->>Router: Signed tx (calldata) rect rgb(232, 245, 233) note over Router,DEXs: Atomic on-chain execution Router->>DEXs: Execute hops on optimal path DEXs-->>Router: destToken Router-->>User: destToken delivered (or revert) end ``` ## The four stages ### 1. Price You call `GET /prices` with `srcToken`, `destToken`, `amount`, `side` (`SELL` or `BUY`), and `network`. The aggregator scans liquidity across every major DEX it supports on that chain, evaluates multi-hop and multi-DEX paths, and returns a `priceRoute` containing the best path, the expected `destAmount`, the gas estimate, and a USD breakdown (`srcUSD`, `destUSD`, `gasCostUSD`). The `priceRoute` is **stateless and unsigned**: it's just a routing plan. It expires quickly (prices move) but holds no commitment. ### 2. Build You `POST /transactions/:chainId` with the full `priceRoute` from step 1, the user's address, and a slippage tolerance. The API returns ready-to-broadcast calldata: `to` (the Augustus v6.2 router on that chain), `data` (encoded swap call), `value` (native token to send, if any), and a gas estimate. Pass the `priceRoute` **verbatim**. Mutating any field will cause the build call to reject. ### 3. Approve (ERC-20 only) If the source token is an ERC-20, the user must approve the Augustus v6.2 router as a spender before the swap. This is a standard `approve(spender, amount)` call. Native source tokens (ETH, MATIC, etc.) skip this step; `value` is sent with the swap tx directly. You can avoid this round-trip by passing `permit` or `permit2` data in the build call. ### 4. Settle The user signs the swap transaction and broadcasts it. The Augustus router pulls `srcToken`, walks the path returned by the aggregator (each hop calls into the underlying DEX), checks the final `destAmount` against the user's `minDestAmount` (price × `1 − slippage`), and delivers `destToken` to the user. If any hop fails or slippage is exceeded, the entire transaction reverts; there's no partial-fill state. ## Why this design The swap completes in one transaction or reverts. No half-filled state to clean up. Augustus calldata can be wrapped in any contract call: vaults, batches, multicalls. Multi-hop, multi-DEX paths across every venue the aggregator supports on each chain. The user signs and broadcasts. No off-chain solver custody, no auction delay. ## Related pages * [Quickstart](/docs/overview/quickstart) — run the flow end-to-end with cURL. * [Market API reference](/docs/api-reference/market/overview) — endpoints, parameters, response schemas. * [Augustus router](/docs/resources/chains-and-contracts) — per-chain router addresses. # Market API DEX aggregation Source: https://new-docs.velora.xyz/docs/market/overview Velora's aggregation API: best-price routing across DEXs with atomic on-chain settlement in a single transaction. The Market API is Velora's classic swap aggregator. You request a quote, build a transaction, and your user signs and submits it on-chain, in one atomic call. It's the right choice when you need composability inside a larger transaction, when the swap is small, or when you want full control over execution. ## What you get Aggregates liquidity across major DEXs to find the optimal path. Swap settles in a single transaction, composable with any contract call. Ethereum, Polygon, BNB, Arbitrum, Optimism, Base, Avalanche, Gnosis, Unichain. For a side-by-side breakdown of when to pick `mode=DELTA`, `mode=MARKET`, or `mode=ALL`, see [Trading modes](/docs/integrate/trading-modes). ## See it work The basic flow is two calls (get a price, build a transaction), then your user signs and submits it: ```bash theme={null} # 1. Get a price quote (returns a priceRoute) curl -G 'https://api.velora.xyz/prices' \ --data-urlencode 'srcToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' \ --data-urlencode 'destToken=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' \ --data-urlencode 'amount=1000000000000000000' \ --data-urlencode 'srcDecimals=18' \ --data-urlencode 'destDecimals=6' \ --data-urlencode 'side=SELL' \ --data-urlencode 'network=1' \ --data-urlencode 'userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045' \ --data-urlencode 'partner=my-app-name' \ --data-urlencode 'version=6.2' \ -o price.json # 2. Build the transaction: wrap the priceRoute verbatim with the swap params jq '{priceRoute, srcToken: .priceRoute.srcToken, destToken: .priceRoute.destToken, srcAmount: .priceRoute.srcAmount, slippage: 50, userAddress: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", partner: "my-app-name"}' price.json > tx.json curl -X POST 'https://api.velora.xyz/transactions/1' \ -H 'Content-Type: application/json' -d @tx.json # 3. User signs and submits the transaction with their wallet ``` ## Next steps cURL the full flow end-to-end. Price, build, approve, settle: the full Market lifecycle. Endpoints, parameters, and response schemas. # Monetize swaps with partner fees Source: https://new-docs.velora.xyz/docs/overview/monetization Earn revenue from every swap routed through Velora using either partner fees or surplus sharing. ## Monetization models * **Partner fee.**: Take a fixed percentage of every swap. Revenue is predictable, but the fee is reflected in the user's quote. * **Surplus share.**: Earn 50% of any positive slippage captured during execution. The quoted output remains unchanged, but revenue varies from trade to trade. Choose the model that best fits your product. Partner fees maximize predictability, while surplus sharing maximizes quote competitiveness. A swap can use one model or the other, not both. If both are provided, `partnerFeeBps` takes precedence. To activate monetization, include your own `partner` identifier. Requests without one use the default `anon` partner and a flat 1 bps fee. See [Pro API accounts](/docs/overview/pro-api-accounts). ## Revenue split The amount you earn depends on the monetization model and execution path. | Lever | Delta | Market | | ------------- | ------------------------ | ------------------------ | | Partner fee\* | 100% partner | 85% partner / 15% Velora | | Surplus share | 50% partner / 50% Velora | 50% partner / 50% Velora | Why the difference? * **Delta** funds itself through surplus capture, so partner fees are passed through entirely. * **Market** retains 15% of partner fees to fund routing infrastructure. * **Surplus sharing** is always split evenly between the partner and Velora. You can also redirect your share of the surplus to the end user with `isSurplusToUser: true`. \* Tailored arrangements available on request. ## How it maps to the API Delta (`GET /v2/quote`) and Market (`GET /prices`, `POST /transactions`) accept the same monetization parameters per request. `isDirectFeeTransfer` is Market-only. | Parameter | Type | Default | Purpose | | -------------------------------------- | ------------ | ------- | ------------------------------------------------------------------------------ | | `partner` | string | `anon` | Identifies your integration; ties the request to your partner economics | | `partnerAddress` | address | — | On-chain recipient of fees or surplus share | | `partnerFeeBps` | string (bps) | — | Fixed fee in basis points. `"200"` = 2%. Max enforced by your partner tier | | `takeSurplus` | boolean | `false` | Opt into surplus collection. Requires `partner` or `partnerAddress` | | `isSurplusToUser` | boolean | `false` | Route surplus to the end user. Requires `takeSurplus: true` | | `isDirectFeeTransfer`Market | boolean | `false` | Bypass the Fee Claimer contract and transfer fees to `partnerAddress` per swap | `partnerFeeBps` and `takeSurplus` are mutually exclusive: set one or the other. The legacy `positiveSlippageToUser` flag is deprecated; use `isSurplusToUser` instead. Pass `partnerFeeBps` to the quote endpoint (`GET /prices` or `GET /v2/quote`) so the fee is reflected in the displayed quote. ## How payouts work On Market, partner fees accrue inside the Fee Claimer contract by default. Partners claim accumulated balances through the Velora Fee Claimer UI, signed by `partnerAddress`. This batches gas across many swaps but adds a claim step. To skip the Fee Claimer and pay fees directly to `partnerAddress` on every swap, set `isDirectFeeTransfer: true`. There's nothing to claim, but each swap carries an extra fee-transfer, and the user pays that gas on every trade, including very low-value ones where it can eat a meaningful share of the output. On Delta, fees accrue inside the main Delta contract and partners claim them directly from there; there is no separate Fee Claimer contract. This works in Delta's favor: the fee is accounted for as part of the fill itself, with no extra fee-transfer per swap, so taking a partner fee adds essentially no gas overhead to the trade. Surplus routed to the user (`isSurplusToUser: true`) is settled in the same transaction as the swap, so there's no claim step either way. ## How to claim ### Fee Claimer UI Accumulated Market fees are claimable from the [Fee Claimer app](https://velora.xyz/fee_claimer). Connect the wallet matching `partnerAddress`, pick the chain, review the available balances per token, and submit a claim transaction. Each chain is claimed separately; gas is paid by the claimer. The UI covers Market fees only. Delta fees are claimed programmatically from the Delta contract, as shown below. ### Programmatically Both fee contracts can be called directly, so claims can run from a script or a scheduled job instead of the UI. In either case, sign the transaction with the wallet matching `partnerAddress`: balances are keyed to it, and each call sweeps the full accrued balance of one token to a recipient you choose. Delta fees accrue in the Delta contract and are withdrawn with `withdrawAllFees`; Market fees accrue in the Fee Claimer contract and are withdrawn with `withdrawAllERC20`. Each contract uses the same address on every chain where it's deployed (see [Chains & contracts](/docs/resources/chains-and-contracts)), so the same code works on another chain by swapping the viem chain object. ```ts Claim Delta fees theme={null} import { createPublicClient, createWalletClient, http, parseAbi } from "viem"; import { Address, privateKeyToAccount } from "viem/accounts"; import { mainnet } from "viem/chains"; // Delta address on Ethereum mainnet const DELTA_ADDRESS = "0x0000000000bbf5c5fd284e657f01bd000933c96d"; const feeClaimerModuleAbi = parseAbi([ "function getCollectedFees(address partner, address token) view returns (uint256)", "function withdrawAllFees(address token, address recipient) returns (uint256 amount)", ]); const account = privateKeyToAccount(process.env.PRIVATE_KEY); const publicClient = createPublicClient({ chain: mainnet, transport: http(), }); const walletClient = createWalletClient({ account, chain: mainnet, transport: http(), }); async function withdrawAllFees( tokenAddress: Address, recipientAddress: Address ) { const collectedFees = await publicClient.readContract({ address: DELTA_ADDRESS, abi: feeClaimerModuleAbi, functionName: "getCollectedFees", args: [account.address, tokenAddress], }); console.log( `Collected fees for token ${tokenAddress}:`, collectedFees.toString() ); if (collectedFees === 0n) { console.log("No fees to withdraw for this token."); return; } // Simulate first to catch reverts const { request } = await publicClient.simulateContract({ account, address: DELTA_ADDRESS, abi: feeClaimerModuleAbi, functionName: "withdrawAllFees", args: [tokenAddress, recipientAddress], }); const hash = await walletClient.writeContract(request); console.log("Transaction sent:", hash); const receipt = await publicClient.waitForTransactionReceipt({ hash }); console.log("Withdrawal confirmed in block:", receipt.blockNumber); return receipt; } // Withdraw all accrued USDC fees to the caller's address await withdrawAllFees( "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC account.address ); ``` ```ts Claim Market fees theme={null} import { createPublicClient, createWalletClient, http, parseAbi } from "viem"; import { Address, privateKeyToAccount } from "viem/accounts"; import { mainnet } from "viem/chains"; // FeeClaimer on Ethereum mainnet const FEE_CLAIMER_ADDRESS = "0x00700052c0608F670705380a4900e0a8080010CC"; const feeClaimerAbi = parseAbi([ "function getBalance(address token, address partner) view returns (uint256)", "function withdrawAllERC20(address _token, address _recipient) returns (bool)", ]); const account = privateKeyToAccount(process.env.PRIVATE_KEY); const publicClient = createPublicClient({ chain: mainnet, transport: http(), }); const walletClient = createWalletClient({ account, chain: mainnet, transport: http(), }); async function withdrawAllFees( tokenAddress: Address, recipientAddress: Address ) { const balance = await publicClient.readContract({ address: FEE_CLAIMER_ADDRESS, abi: feeClaimerAbi, functionName: "getBalance", args: [tokenAddress, account.address], }); console.log(`Current fee balance for token ${tokenAddress}:`, balance); if (balance === 0n) { console.log("No fees to withdraw for this token."); return; } // Simulate first to catch reverts const { request } = await publicClient.simulateContract({ account, address: FEE_CLAIMER_ADDRESS, abi: feeClaimerAbi, functionName: "withdrawAllERC20", args: [tokenAddress, recipientAddress], }); const hash = await walletClient.writeContract(request); console.log("Transaction sent:", hash); const receipt = await publicClient.waitForTransactionReceipt({ hash }); console.log("Withdrawal confirmed in block:", receipt.blockNumber); return receipt; } // Withdraw all accrued USDC fees to the caller's address await withdrawAllFees( "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC account.address ); ``` Not sure which tokens your fees accrued in? Each side has a fees endpoint that returns every token your address has earned fees in on a chain. The amounts are lifetime totals per token, claimed and unclaimed combined, so check the live on-chain balance (as the claim snippets above do) before withdrawing. ```ts Check Delta fee tokens theme={null} const PARTNER_ADDRESS = "0x..."; // your partnerAddress const CHAIN_ID = 1; const parameters = JSON.stringify([ { type: "category", value: PARTNER_ADDRESS, target: ["variable", ["template-tag", "partner_address"]], }, { type: "category", value: CHAIN_ID, target: ["variable", ["template-tag", "chain_id"]], }, ]); const res = await fetch( `https://proxy.paraswap.io/fees/delta?parameters=${encodeURIComponent( parameters )}` ); const { data } = await res.json(); // Each row is [chain_id, fee_token, total_amount] for (const [, token, total] of data.rows) { console.log(`${token}: ${total}`); } ``` ```ts Check Market fee tokens theme={null} const PARTNER_ADDRESS = "0x..."; // your partnerAddress const CHAIN_ID = 1; const parameters = JSON.stringify([ { type: "category", value: PARTNER_ADDRESS, target: ["variable", ["template-tag", "partneraddress"]], }, { type: "category", value: CHAIN_ID, target: ["variable", ["template-tag", "chainId"]], }, { type: "category", value: "partner", target: ["variable", ["template-tag", "feeType"]], }, ]); const res = await fetch( `https://proxy.paraswap.io/fees/since-v6?parameters=${encodeURIComponent( parameters )}` ); const { data } = await res.json(); // Each row is [corrected_sum, partnerfeetoken, chainid] for (const [total, token] of data.rows) { console.log(`${token}: ${total}`); } ``` ## Next steps Free partner IDs, plus paid tiers for higher rate limits and SLA. Drop-in `partnerConfig` for the React widget. Gasless intents, solver competition, and surplus economics. `GET /v2/quote` and intent submission reference. `GET /prices` and `POST /transactions` reference. Endpoints work without a `partner` identifier, but fees and surplus only activate once one is attached; picking your own `partner` value costs nothing. When you outgrow the free tier, [Pro API accounts](/docs/overview/pro-api-accounts) layer on higher limits, a dashboard, and SLA, or [reach out](https://www.velora.xyz/contact) for custom terms. # Pro API accounts and rate limits Source: https://new-docs.velora.xyz/docs/overview/pro-api-accounts Free partner IDs vs. Pro API accounts: how to identify your integration, lift rate limits, and unlock dashboards, early features, and SLA-backed support. Any caller can get a partner ID for free just by passing `&partner=` on `/v2/quote` or `/prices`, without signing up for anything. **Pro API accounts** layer on top: higher RPS, larger daily quotas, an analytics dashboard, early feature access, and SLA-backed support for production workloads. ## Free tier Pass `&partner=` on any Velora REST endpoint: that string *is* your partner ID. For example: ```bash theme={null} curl -s "https://api.velora.xyz/v2/quote" \ --data-urlencode "srcToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" \ --data-urlencode "destToken=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" \ --data-urlencode "amount=1000000000000000000" \ --data-urlencode "srcDecimals=18" \ --data-urlencode "destDecimals=6" \ --data-urlencode "side=SELL" \ --data-urlencode "chainId=1" \ --data-urlencode "mode=ALL" \ --data-urlencode "userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" \ --data-urlencode "partner=my-super-app" \ -G | jq ``` Default [rate limits](/docs/integrate/rate-limits) apply: 1 RPS and 3,000 requests/day, which leaves plenty of headroom to prototype and run real integrations. When your traffic starts to bump against those limits, a [Pro plan](#pro-plans) lifts them; for anything bespoke, [reach out](https://www.velora.xyz/contact) and we'll size it with you. A free partner ID identifies your traffic but does **not** unlock partner-fee economics. To collect partner fees or share of surplus on swaps, see [Monetization](/docs/overview/monetization). ## Pro plans Subscribing to a Pro plan lifts your rate limits and adds: * Higher sustained RPS and burst RPS * Larger daily request quota * Analytics dashboard (Pro and above) * Early access to new features (Pro and above) * Standard SLA + technical support (Custom SLA on Enterprise) ### Plan comparison | Plan | Rate limit | Burst | Daily quota | Dashboard | Early features | SLA | | ------------------- | ---------- | ------ | ----------- | --------- | -------------- | -------- | | Basic | 10 RPS | 20 RPS | 50,000 | — | — | Standard | | Pro | 20 RPS | 40 RPS | 120,000 | ✓ | ✓ | Standard | | Enterprise | 40 RPS | 80 RPS | 250,000 | ✓ | ✓ | Custom | | Extended Basic | 15 RPS | 25 RPS | 1,000,000 | ✓ | — | Standard | | Extended Pro | 25 RPS | 50 RPS | 2,000,000 | ✓ | ✓ | Standard | | Extended Enterprise | Custom | Custom | Custom | ✓ | — | Custom | All tiers include technical support. Annual billing is offered at a discount. For exact pricing and to subscribe, see [velora.xyz/pro](https://velora.xyz/pro). ### Which plan fits * **Basic / Pro / Enterprise** — workloads bound by sustained RPS, like real-time quoting and frontend integrations. * **Extended Basic / Extended Pro** — high daily volume at moderate RPS, like background indexing, analytics pipelines, and batch quoting. * **Enterprise / Extended Enterprise** — custom SLA, tailored quotas, and bespoke commercial terms. ## Get started Self-serve Basic, Pro, and Extended tiers. Monthly or annual billing. Custom SLA, dedicated support, bespoke quotas. Limits that apply before you subscribe. Partner fees, surplus sharing, and revenue splits. # Crypto limit orders Source: https://new-docs.velora.xyz/docs/overview/product-stack/limit-orders A crypto limit order lets a maker sign a target price and wait for execution. In Velora, limit orders are Delta orders. A **limit order** lets a maker define the price they want, sign the terms, and wait for execution later. In Velora, limit orders are Delta orders: the user signs an intent with target-price constraints, and Delta settles it only when those constraints can be satisfied. Use limit orders when the user cares more about a target price than immediate settlement. ## What problem limit orders solve Limit orders separate **trade intent** from **trade timing**. Delta represents that intent as a signed order: * The maker says what they are willing to sell or buy. * The maker sets constraints such as price, token pair, amount, expiry, and eligible taker behavior. * When the limit price becomes reachable, the order enters the Delta pricing auction. Solvers from the Portikus network act as takers and compete on fill quotes, so the user gets the best committed return, not just the limit price. * Delta settles the order on-chain when the winning solver's fill satisfies it. This gives users price control without forcing them to watch the market and submit a swap at the exact moment liquidity appears. ## Key terms * **Maker:** the user or application that creates and signs the order. * **Taker:** the party that accepts and fills the order. In Velora, takers are Portikus solvers that win the pricing auction. * **Limit price:** the minimum or maximum effective price the maker accepts. * **Delta order:** the signed intent Velora uses to represent and settle the limit order. * **Expiry:** the time after which the order should no longer fill. * **Nonce:** a unique value that helps identify, replace, or cancel an order. * **Fill:** the action that settles the order and transfers tokens. * **Cancellation:** invalidating an unfilled order before it can settle. ## Limit Orders vs Swaps vs OTC Use a swap when the user wants to trade now against available liquidity. Use a limit order when price matters more than timing. The user signs the target-price constraint and waits for Delta to settle it. Use OTC when the trade terms are already agreed off-book with a known counterparty. Limit orders and OTC can look similar because both use signed terms. The difference is intent: a limit order expresses a price condition; OTC expresses a bilateral agreement. ## Build it * Use the [Widget](/docs/widget/overview) if you want limit orders in a ready-made trading interface. * Building the HTTP flow directly? Build the order the user will sign with [`POST /v2/delta/orders/build`](/docs/api-reference/delta/orders-build), then submit it through [`POST /v2/delta/orders`](/docs/api-reference/delta/orders-submit) and track its status from there. * [How Delta works](/docs/delta/how-it-works) covers how signed orders are auctioned, settled, and tracked. * If the trade is negotiated with a known counterparty, you probably want [OTC](/docs/overview/product-stack/otc) instead. # Crypto OTC trades Source: https://new-docs.velora.xyz/docs/overview/product-stack/otc Crypto OTC trades are direct, off-book swaps between counterparties. Velora supports signed maker/taker settlement flows. An **over-the-counter (OTC)** trade is negotiated directly between counterparties instead of discovered through a public swap route or orderbook. The parties agree terms off-book, then settle those terms through a signed order flow. Use OTC when the counterparty matters as much as the price: treasury rebalancing, partner deals, market-maker inventory moves, or block-style trades that should not be exposed as a public order first. ## What problem OTC solves Public execution is not always the right fit. Sometimes the maker and taker need to agree who participates, negotiate price, size, token pair, expiry, and settlement expectations directly, and keep that negotiation off-book until the trade settles. The final fill still resolves on-chain, so the outcome stays auditable. OTC does not mean invisible settlement. It means private negotiation with explicit on-chain execution. ## Key terms * **Maker:** the party that creates and signs the order terms. * **Taker:** the intended counterparty that fills the order. * **Counterparty:** the known party on the other side of the trade. * **Off-book negotiation:** agreeing terms outside a public orderbook or swap route. * **Restricted fill:** an order design where only the intended taker or flow should execute. * **Settlement:** the on-chain fill that transfers tokens according to the signed terms. ## OTC vs Limit Orders vs Swaps In a swap, the user wants immediate execution against available liquidity. In a limit order, the user wants a target price and may wait for a taker. In OTC, two parties agree terms directly and use a signed order to settle. A limit order asks, “Will someone fill this price?” OTC asks, “Will this counterparty settle the terms we already agreed?” ## Build it * [AugustusRFQ](/docs/api-reference/rfq/overview) is the settlement surface: signed maker/taker orders filled on-chain. * The [Widget](/docs/widget/overview) ships an OTC form and fill flow you can embed directly. * Deployment addresses live in [Chains & contracts](/docs/resources/chains-and-contracts). * If the counterparty is not known upfront, compare with [Limit orders](/docs/overview/product-stack/limit-orders). * Professional liquidity providers quote into Velora through the same contract: see [Market making on Velora](/docs/resources/market-makers). # Crypto swaps with Velora Source: https://new-docs.velora.xyz/docs/overview/product-stack/swaps A crypto swap exchanges one token for another. Velora maps swaps to gasless Delta intents or atomic Market routing. A **swap** exchanges one token for another. In DeFi, the transfer itself is the easy part. The work is in finding liquidity, quoting a fair output, limiting slippage, and settling the trade without exposing the user to unnecessary execution risk. Velora gives this primitive two execution paths: Delta for gasless intent swaps, and Market for atomic transaction swaps. If you do not want to choose upfront, Velora can evaluate both and return the best available path. ## What problem swaps solve A wallet usually holds one asset, while the user or app needs another. A swap turns that intent into execution. It starts with price discovery (how much destination token should the user receive?) and liquidity access (which venues can fill the trade?), then applies the constraints the user set: slippage tolerance, recipient, chain, and timing. Settlement delivers the destination token or fails safely according to the selected path. For small trades, this often looks simple. For large trades, thin pairs, volatile markets, or crosschain routes, the execution path matters as much as the headline quote. ## Key terms * **Quote:** an estimate of the output amount for a requested trade. * **Route:** the liquidity path used to reach that output. * **Slippage:** the maximum price movement the user accepts before execution should fail or be rejected. * **Price impact:** the trade's expected effect on the market price because of available liquidity depth. * **Intent:** an off-chain signed instruction describing the outcome the user wants, not the exact transaction path. * **Settlement:** the final on-chain state change that delivers the destination token. * **Revert protection:** a failed trade costs the user nothing. A Delta order that can't settle simply expires or is rejected; on Market the user pays gas even when the swap reverts. ## Build it Start with the [Quickstart](/docs/overview/quickstart) to get a first quote with cURL, the SDK, or the Widget. Then pick the execution path: Gasless, MEV-protected intent swaps filled by competing solvers. Atomic on-chain transactions that compose with other contract calls. Let Velora choose between Delta and Market server-side with `mode=ALL`. # TWAP orders for large trades Source: https://new-docs.velora.xyz/docs/overview/product-stack/twap A TWAP splits a larger crypto trade into scheduled slices. In Velora, TWAP is a Delta order that the user signs once and Velora settles over time. A **TWAP** (time-weighted average price) splits a larger trade into smaller slices executed over time. In Velora, TWAP is a Delta order. The user signs one scheduled order that defines the total trade, number of slices, interval, and deadline. Velora then settles eligible slices over time through Delta instead of asking the user to sign or submit a transaction for every slice. Use TWAP when a one-shot swap is too sensitive to execute at a single market moment. ## What problem TWAP solves A large immediate trade consumes available liquidity and worsens its own execution price. It also stakes the whole trade on one market moment, and executing everything at once makes the trade easier for other participants to detect and react to. TWAP reduces those risks by spreading execution across smaller settlements. It does not remove market risk, and it does not guarantee a better final average price. ## How Velora TWAP works Velora TWAP is scheduled Delta execution: 1. The user chooses the pair, side, total amount, number of slices, interval, deadline, and execution constraints. 2. Velora builds a signable Delta order for the schedule. 3. The user signs once. 4. When a slice becomes eligible, Velora runs execution for that slice. 5. The Delta contract enforces the slice timing on-chain. 6. The order completes after the final slice settles, or fails/expires if its constraints can no longer be met. For a sell TWAP, the user fixes the total source amount to sell, and Velora splits that source amount across slices. For a buy TWAP, the user fixes the total destination amount to receive, and Velora splits that destination target across slices while capping the total source amount spent. ## Key terms * **Scheduled order:** the signed Delta order that defines the TWAP. * **Slice:** one settlement inside the scheduled order. * **Number of slices:** how many settlements the trade is split into. * **Interval:** the minimum time between slices. Velora enforces a schedule; slices are not independent user actions. * **Deadline:** the latest time the order can remain valid. * **Side:** sell TWAPs fix and split the source amount; buy TWAPs fix and split the destination amount while capping source spend. ## TWAP vs Swaps vs Limit Orders A swap executes the full amount now. A [limit order](/docs/overview/product-stack/limit-orders) waits for a target price and fills only if the market reaches it. A TWAP commits the trade upfront and settles slices as they become eligible, whatever the price does within the order's constraints. TWAP and limit orders are both signed Delta orders that settle after signing. The difference is the trigger: a limit order is price-conditional, a TWAP is time-driven. ## Build it * Use the [Widget](/docs/widget/overview) if you want a ready-made TWAP form in your app; [Configure Widget](/docs/widget/configure) controls whether it appears. * Use [`POST /v2/delta/orders/build`](/docs/api-reference/delta/orders-build) if you are building the HTTP flow directly. Submit the signed order through [`POST /v2/delta/orders`](/docs/api-reference/delta/orders-submit) and track slice execution through the Delta order endpoints. * [How Delta works](/docs/delta/how-it-works) explains how signed orders are auctioned and settled. # Velora quickstart: quote your first swap Source: https://new-docs.velora.xyz/docs/overview/quickstart Get a quote for 1 ETH → USDC in 60 seconds with cURL, the SDK, or the Widget. Then choose how to integrate. Get a quote for 1 ETH → USDC on Ethereum mainnet. With `mode=ALL`, Velora picks the best execution path server-side and returns one response shape: either a `delta` block (gasless, signed and submitted later) or a `market` block (calldata-ready, submitted immediately). See [Trading modes](/docs/integrate/trading-modes). ```bash Best path (cURL) theme={null} curl -s "https://api.velora.xyz/v2/quote" \ --data-urlencode "srcToken=0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" \ --data-urlencode "destToken=0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" \ --data-urlencode "amount=1000000000000000000" \ --data-urlencode "srcDecimals=18" \ --data-urlencode "destDecimals=6" \ --data-urlencode "side=SELL" \ --data-urlencode "chainId=1" \ --data-urlencode "mode=ALL" \ --data-urlencode "userAddress=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" \ --data-urlencode "partner=my-app-name" \ -G | jq ``` ```ts SDK (TypeScript) theme={null} import { constructSimpleSDK } from '@velora-dex/sdk'; const sdk = constructSimpleSDK({ chainId: 1, fetch }); const quote = await sdk.quote.getQuote({ srcToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // ETH destToken: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC amount: '1000000000000000000', // 1 ETH srcDecimals: 18, destDecimals: 6, side: 'SELL', mode: 'ALL', userAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', partner: 'my-app-name', }); if ('delta' in quote) { // gasless path: sign and submit via /v2/delta/orders } else { // calldata path: submit `market` to /transactions } ``` ```tsx Widget (React) theme={null} import { Widget } from '@velora-dex/widget'; export default function SwapPage() { return ( ); } ``` `my-app-name` is a placeholder. Replace it with your own app or project partner identifier. It tags your integration for analytics, support, and rate-limit upgrades; it is not an API key, and no signup is required. `GET /v2/quote?mode=DELTA` returns a `delta` block (sign with EIP-712, submit to `/v2/delta/orders`). `GET /v2/quote?mode=MARKET` returns a `market` block (calldata-ready against Augustus v6.2). `GET /v2/quote?mode=ALL` lets Velora pick the path server-side and returns one of `response.delta` (Delta intent) or `response.market` (Market route), never both. Branch on which block is present. See [Trading modes](/docs/integrate/trading-modes). ## Pick your integration path Compare API, SDK, and Widget, then choose the right surface for your stack. All endpoints work as soon as you pass a `partner` identifier; you don't need to sign up for anything. When you're ready for higher throughput, a dashboard, and SLA-backed support, grab a [Pro API account](/docs/overview/pro-api-accounts) or [reach out](https://www.velora.xyz/contact) for bespoke arrangements. # Why integrate with Velora Source: https://new-docs.velora.xyz/docs/overview/why-velora Velora unifies intent-based execution and DEX aggregation in a single platform. With one integration, you can route trades across 10+ EVM chains, execute gasless swaps, and access the best available liquidity without managing multiple providers. One integration gives you: * **Delta intents**: Let users swap on the same chain or across chains through a single gasless, MEV-protected flow secured by one signature. * **Market routing**: Get the best available price across major DEXs and AMMs without building or maintaining your own routing infrastructure. * **OTC**: Enable peer-to-peer token trades with custom pricing and settlement terms, including optional partial fills. You can use Delta, Market, or both through a single integration. The Delta API's `GET /v2/quote` endpoint supports `DELTA`, `MARKET`, and `ALL` modes. With `ALL`, Velora compares intent-based and market-based execution, then automatically returns the better result. If you only need aggregator routing, use the Market API's `GET /prices` endpoint. See [Trading modes](/docs/integrate/trading-modes). ## Choose your integration | You want to… | Use | Time to first swap | | ------------------------------------------ | ------------------------------------------------------------------------------------------------ | ------------------ | | Crosschain, gasless, MEV-protected fills | [Delta](/docs/delta/overview) (via API or SDK) | \~10 minutes | | Maximum control, any language, any backend | [Delta API](/docs/api-reference/delta/overview) / [Market API](/docs/api-reference/market/overview) | \~60 seconds | | Type-safe TypeScript, your own UI | [@velora-dex/sdk](/docs/sdk/install) | \~5 minutes | | Drop-in UI, zero design work | [@velora-dex/widget](/docs/widget/install) | \~10 minutes | | AI agent / LLM integration | [MCP server](/docs/for-agents/mcp-server/overview) + [five-call recipe](/docs/for-agents/five-call-recipe) | \~5 minutes | ## Next steps Get a quote in 60 seconds with cURL, the SDK, or the Widget. Compare API, SDK, and Widget, and pick the right surface for your stack. # Token approvals and permit Source: https://new-docs.velora.xyz/docs/resources/approvals How token approvals work on Velora: the spender to authorize for Delta and Market swaps, approving on-chain vs signing a permit or Permit2, and why limit orders and TWAP need an on-chain approval. Before a swap can pull a user's source token, the user authorizes a **spender**. You can do that with an on-chain `approve`, or by signing a **permit** so there's no separate approval transaction. Which spender you authorize depends on the execution mode; the choice between approve and permit is the same either way. ## Which spender to authorize The spender is always the contract that settles the trade, never a separate proxy: * **Delta** (Swaps, Limit Orders, TWAP): the **Delta contract**. Every Delta quote returns it as `delta.spender`, so you can read it straight from the quote response. * **Market**: the **Augustus v6.2** router. The user approves Augustus v6.2 directly. Each is deployed at the same address on every chain that supports it. See [Chains & contracts](/docs/resources/chains-and-contracts) for the addresses and per-mode availability. ## Approve or sign a permit Both methods work for Delta and for Market: * **On-chain approval**: a standard ERC-20 `approve(spender, amount)`. One transaction, once per token. * **Permit**: sign an EIP-2612 permit or a Permit2 message naming the spender, and pass it in the build call instead of approving on-chain. Delta takes it as the `permit` field on [`POST /v2/delta/orders/build`](/docs/api-reference/delta/orders-build); Market takes it as the `permit` field on [`POST /transactions/{chainId}`](/docs/api-reference/market/transactions). Both the Delta contract and Augustus v6.2 accept either an EIP-2612 or a Permit2 payload. A permit skips the separate approval transaction, which is the reason to use it. ## Native ETH Native ETH is never approved. For a Market swap, the native `value` is sent with the transaction. For Delta, the ETH is represented as `dETH`, which the Delta contract can move without an approval; see [Native ETH (dETH)](/docs/delta/native-eth). ## Limit Orders and TWAP use on-chain approval A permit is bound to a single-use token nonce and a deadline, so it only fits an order that settles right away, like a market Delta swap or a Market swap. A [limit order](/docs/integrate/api/limit-orders) rests until its price is met, and a [TWAP](/docs/integrate/api/twap) settles across slices over time. By the time either settles, the permit's nonce is spent or its deadline has passed. For both, approve the spender on-chain for the total amount instead of signing a permit. ## Related pages * [Chains & contracts](/docs/resources/chains-and-contracts) for spender addresses and per-mode availability. * [Delta swap](/docs/integrate/api/delta-swap) and [Market swap](/docs/integrate/api/market-swap), the flows these approvals belong to. * [Native ETH (dETH)](/docs/delta/native-eth) for selling native ETH without an approval. # Supported chains and contract addresses Source: https://new-docs.velora.xyz/docs/resources/chains-and-contracts Canonical reference for Augustus, Delta, Portikus, AugustusRFQ, and Fee Claimer contract addresses across every supported EVM chain. This page is the single source of truth for contract addresses across Velora's stack. Every other page links here rather than inlining addresses, with one exception: failure-mode rows on API reference pages may cite a specific deployed address inline when the address is the actual diagnostic. Building integrations that need addresses at runtime? Read [`/resources/contracts.json`](/docs/resources/contracts.json) — it mirrors the table on this page in machine-readable form, keyed by `chainId`. ## Supported chains Velora supports the following EVM networks. Each chain has Augustus v6.2 (Market routing) deployed; Delta availability is a subset. * Ethereum (1) * Optimism (10) * BNB Chain (56) * Gnosis (100) * Unichain (130) * Polygon (137) * Base (8453) * Arbitrum One (42161) * Avalanche (43114) The authoritative supported-chain list is queryable at runtime via `GET /chains` on the Market API. Code should treat this page as a human-readable index and `/chains` as the runtime source of truth. ## Addresses by chain Each contract is also the ERC-20 spender for its execution mode — approve Augustus v6.2 for Market swaps, the Delta contract for Delta orders (Swap, Limit, TWAP), and AugustusRFQ for OTC/RFQ fills. A `—` means the contract isn't deployed on that chain and the corresponding mode is unavailable there. See [Token approvals for agents](/docs/for-agents/token-approvals) for the spender-by-mode decision rules. **Augustus v6.2** is deployed at `0x6a000f20005980200259b80c5102003040001068` on every supported chain. **Delta** is deployed at `0x0000000000bbf5c5fd284e657f01bd000933c96d` and **Delta Wrapped Native (dETH)** at `0x0a0d53b6684c7b32b4cbef5fe8483bfcc8406742`, both at the same address on every Delta-enabled chain. **Fee Claimer** is deployed at `0x00700052c0608F670705380a4900e0a8080010CC` on every supported chain. AugustusRFQ addresses vary per chain and are listed below. | Chain (ID) | Delta | AugustusRFQ | | -------------------- | ----- | -------------------------------------------- | | Ethereum (1) | ✓ | `0xe92b586627ccA7a83dC919cc7127196d70f55a06` | | Optimism (10) | ✓ | `0x0927FD43a7a87E3E8b81Df2c44B03C4756849F6D` | | BNB Chain (56) | ✓ | `0x8DcDfe88EF0351f27437284D0710cD65b20288bb` | | Gnosis (100) | — | `0x92EaD5bACf6F0E995FA46Ad8215A9b11f67ca241` | | Unichain (130) | ✓ | `0x92EaD5bACf6F0E995FA46Ad8215A9b11f67ca241` | | Polygon (137) | ✓ | `0xF3CD476C3C4D3Ac5cA2724767f269070CA09A043` | | Base (8453) | ✓ | `0xa003dFBA51C9e1e56C67ae445b852bdEd7aC5EEd` | | Arbitrum One (42161) | ✓ | `0x0927FD43a7a87E3E8b81Df2c44B03C4756849F6D` | | Avalanche (43114) | — | `0x34302c4267d0dA0A8c65510282Cc22E9e39df51f` | ## Contracts ### Augustus v6.2 The Market router. All Market [`POST /transactions/:chainId`](/docs/api-reference/market/transactions) calldata targets the Augustus v6.2 contract on the requested chain. Deployed at the same address across every supported chain. ### Augustus v6.1, v5 Legacy router versions. Still operational but new integrations should target v6.2. Calldata returned by the Market API automatically uses v6.2 unless overridden. Migration: [Augustus v5 → v6.2](/docs/resources/migrations/augustus-v5-to-v6-2). ### Delta contract On-chain entry point that validates signed Delta orders and executes the winning Portikus fill through settlement. The Delta contract is the spender on EIP-712 typed-data approvals: token approvals for Delta flows must be granted to this address, **not** to Augustus. Deployed at the same address across every Delta-enabled chain. ### Delta Wrapped Native (dETH) The wrapped-native token Delta uses to represent native ETH (and other native gas tokens) as an ERC-20, at a 1:1 rate. When a user sells native ETH through Delta, their ETH is represented as dETH, which is why a native source needs no ERC-20 approval. Deployed alongside the Delta contract at the same address on every Delta-enabled chain, so native ETH works as a source wherever Delta does. See [Native ETH (dETH)](/docs/delta/native-eth) for the integration detail. ### Portikus settlement The solver-facing settlement infrastructure. Solvers compete by providing fills through Portikus; the Delta contract reconciles the winning outcome back to the user. ### AugustusRFQ On-chain OTC and RFQ settlement contract. Supports partial fills and bilateral signed orders. Market makers settle their firm quotes through it; see [Market making on Velora](/docs/resources/market-makers). ### Fee Claimer Holds partner fees accrued from Market swaps until the partner claims them. Fees taken via `partnerAddress` accumulate in this contract per chain, and partners withdraw them through the [Fee Claimer app](https://velora.xyz/fee_claimer). Delta fees never pass through it; they accrue in the Delta contract itself. Deployed at the same address on every supported chain. See [Monetization](/docs/overview/monetization) for fee parameters and the claim flow. ## Related * [Market API → Overview](/docs/api-reference/market/overview) * [Delta → How it works](/docs/delta/how-it-works) * [Security → Audits](/docs/resources/security/audits) * Machine-readable: [`/resources/contracts.json`](/docs/resources/contracts.json) # Market maker API specification Source: https://new-docs.velora.xyz/docs/resources/market-makers/api-specification The chain-scoped market maker API Velora consumes: token and pair listings, a bid/ask price grid, signed AugustusRFQ firm quotes, and a user blacklist. This is the API contract Velora consumes from market makers. You expose one chain-scoped surface for each chain you trade on. That can mean separate hosts, separate base paths on the same host, or any other layout that gives Velora a distinct base URL per chain. Velora caches your `/prices` grid for routing and calls `POST /firm` only when a user executes a swap against your liquidity. ## Endpoint map Each chain-scoped surface implements the same five HTTP endpoints: | Endpoint | Purpose | | ---------------- | ----------------------------------------------------- | | `GET /tokens` | Tokens you trade on this chain | | `GET /pairs` | Base/quote pairs Velora may route through | | `GET /prices` | Bid/ask grids used for cached routing | | `POST /firm` | Firm quote returned as a signed AugustusRFQ order | | `GET /blacklist` | User addresses you do not want Velora to route to you | You may also expose a WebSocket stream for cache updates. The WebSocket is optional, but it is the preferred path once pricing changes often enough that polling becomes wasteful. ## General requirements All HTTP endpoints for a given chain share a common base URL. For example, both of these layouts work: * Separate hosts: `https://base.example-mm.com/tokens`, `https://mainnet.example-mm.com/tokens` * Shared host, chain-specific paths: `https://mm.example.com/base/tokens`, `https://mm.example.com/mainnet/tokens` For Velora, those are simply two chain-scoped base URLs: `https://base.example-mm.com`, `https://mainnet.example-mm.com`, or `https://mm.example.com/base`, `https://mm.example.com/mainnet`. The WebSocket interface may live on a different URL, or on the same chain-scoped surface with a path such as `/ws`. * Every response is JSON, including errors. * Error responses use a 4xx or 5xx status and a body containing an `"error"` string. * Any successful response may include a `"message"` key alongside the payload. Velora logs it on every request, which is useful when you need diagnostics from your side to appear in integration logs. * You may additionally whitelist Velora server IPs, but the endpoints should still implement the authentication below. ## Authentication (optional) If you want Velora's requests authenticated, exchange three credentials during onboarding: * `Domain` — a string identifying the traffic source, so you can tell Velora apart from other integrations and, if you want, distinguish production from staging. * `Access Key` — a passcode Velora echoes back in request headers for a quick origin check. Per-domain, and shared with no one but Velora. * `Secret Key` — the key Velora uses to sign requests. Per-domain, and shared with no one but Velora. Velora signs each request as follows: 1. Take the current timestamp in milliseconds since the Unix epoch (what `Date.now()` returns in JavaScript). 2. Build the signed payload by concatenating these values with no separator: 1. The timestamp as a decimal string. 2. The HTTP method in uppercase (`GET` or `POST`). 3. The request path, beginning with `/`, e.g. `/prices`. If your base URL itself contains a path such as `/mainnet`, it is included. 4. The query string exactly as sent, including the leading `?`, or an empty string if there is none. No endpoint in this specification uses query parameters, so this is normally empty. 5. The request body exactly as sent (always a JSON object in this spec), or an empty string for `GET` requests. For a request to `https://example-mm.com/endpoint?key=value`, the payload looks like: ```text theme={null} 1234512345123POST/endpoint?key=value{"amount":"123"} ``` For WebSocket connections, the handshake is signed assuming the current timestamp, method `GET`, the path of the connect URL, no query parameters, and no body. 3. Compute the HMAC-SHA256 of that payload in hexadecimal, keyed with the Secret Key: ```javascript theme={null} const { createHmac } = require('crypto'); const hmac = createHmac('sha256', ''); hmac.update(''); console.log(hmac.digest('hex')); ``` 4. Attach the headers: * `X-AUTH-DOMAIN` — the Domain * `X-AUTH-ACCESS-KEY` — the Access Key for that Domain * `X-AUTH-TIMESTAMP` — the timestamp used in the signature * `X-AUTH-SIGNATURE` — the HMAC-SHA256 from the previous step Your side verifies all four headers and rejects stale timestamps. A tolerance of around ±30 seconds is enough for normal clock drift. Return a JSON error when verification fails, and make the error specific enough to debug during onboarding. ## GET /tokens Lists every token you trade on this chain. The response has a `"tokens"` object keyed by Token ID. A token symbol is a good ID when it is unique within the chain-scoped surface. Most fields are informational, but `address`, `decimals`, and `type` need to be correct for routing and amount handling. * `symbol` (string) — the token's symbol, normally matching the token contract. * `name` (string) — the token's full name, normally matching the token contract. * `description` (string) — free-form notes, e.g. flagging a token deprecated in favor of another. * `address` (string) — the token contract address. Case is ignored and normalized to lowercase on Velora's side. * `decimals` (number) — the token's decimals, normally the value returned by the contract's `decimals()` method. * `type` (string) — only `"ERC20"` is supported for market making today. The AugustusRFQ contract itself also settles `ERC721` and `ERC1155` orders, so other types may be enabled later. Example response: ```json theme={null} { "tokens": { "WETH": { "symbol": "WETH", "name": "Wrapped Ether", "description": "Canonical wrapped Ether on Ethereum mainnet", "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "decimals": 18, "type": "ERC20" }, "USDC": { "symbol": "USDC", "name": "USD Coin", "description": "Popular US dollar stablecoin, provided by Circle", "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "decimals": 6, "type": "ERC20" } } } ``` ## GET /pairs Lists the trading pairs you support, or have recently disabled, on this chain. Each pair points to two Token IDs from `/tokens` and includes a rough USD liquidity estimate. Velora uses that estimate when it searches for routes between tokens. Quote each pair in one direction only. Velora derives reverse pricing from the same grid. The response has a `"pairs"` object keyed by Pair ID. The recommended Pair ID format is `BASE/QUOTE`, e.g. `WETH/USDC`. * `base` (string) — Token ID of the base token, the one bids and asks are denominated in. * `quote` (string) — Token ID of the quote token, the one prices are given in. * `liquidityUSD` (number) — an estimate of the liquidity backing this pair in US dollars. One way to compute it: the maximum you are willing to sell in both tokens, converted to USD and summed. ```json theme={null} { "pairs": { "WETH/USDC": { "base": "WETH", "quote": "USDC", "liquidityUSD": 468000 }, "WETH/USDT": { "base": "WETH", "quote": "USDT", "liquidityUSD": 512500 }, "WBTC/WETH": { "base": "WBTC", "quote": "WETH", "liquidityUSD": 129800 } } } ``` ## GET /prices Returns the full bid/ask grid Velora should cache for routing. This endpoint is the live pricing source for indicative routes; `POST /firm` is only called later, when a user is ready to execute. The response has a `"prices"` object keyed by Pair ID. Each pair may contain `"bids"`, `"asks"`, or both: * Omitting `"bids"` disables trading in the bid direction and clears that cached side. * Omitting `"asks"` disables trading in the ask direction and clears that cached side. * Returning an empty object, `{}`, disables the pair entirely. `"bids"` and `"asks"` are arrays of `[price, amount]` tuples. `price` is the price of one base token in quote-token terms. `amount` is the base-token quantity available at that level. Both values are strings, and Velora parses them with `bignumber.js` so decimal precision is preserved. Velora consumes each side in array order until the requested amount is reached. Put the best price first and worsen from there. The generic RFQ harness rejects crossed books, where the highest bid is greater than or equal to the lowest ask, so keep the best ask above the best bid. ```json theme={null} { "prices": { "WETH/USDC": { "bids": [ ["1540", "0.5"], ["1500", "1.5"], ["1480", "3"] ], "asks": [ ["1560", "1"], ["1580", "1.5"], ["1600", "2"], ["1650", "9"] ] }, "WETH/USDT": {} } } ``` In this example, WETH/USDT trading is disabled and its cached prices are cleared. For WETH/USDC: * A user selling 1.5 WETH receives `1540 * 0.5 + 1500 * 1 = 2270` USDC, an average price of `1513.333`. * A user buying 10 WETH spends `1560 * 1 + 1580 * 1.5 + 1600 * 2 + 1650 * 5.5 = 16205` USDC, an average price of `1620.5`. When the user specifies an amount in the quote token instead, Velora inverts the book: bids become asks, asks become bids, each price becomes `1 / price`, and each amount becomes `price * amount`. It then applies the same fill process. To retire a pair, don't drop it from `/pairs` immediately. Keep it listed and serve `{}` for its prices for a period, as WETH/USDT above, then remove it. If this endpoint fails or returns an error, Velora temporarily disables your market making on that chain. That behavior is also the off switch: serve an error here when you want to stop trading for a while. ## POST /firm Returns a firm quote as a signed order for the AugustusRFQ contract. Within Velora, the order's `taker` is set to a Velora execution contract (Augustus v6.2 or one of its executors, depending on execution context), and the actual user (the `msg.sender` to the router) is encoded in the `nonceAndMeta` field. Velora's contracts always check that the user and the metadata match when filling through AugustusRFQ. That has two effects: nobody can steal the order from the user it was quoted for, and a firm quote always burns a real user address, so an address that spams firm quotes without executing can be blacklisted. The request body: * `makerAsset` (string) — address of the token you (the maker) are selling. * `takerAsset` (string) — address of the token the taker is selling. * `makerAmount` or `takerAmount` (string) — the traded amount of the maker or taker asset, as an integer scaled by token decimals. Exactly one is given; you compute the other from your current prices. * `userAddress` (string) — the end user's address, as described above. * `takerAddress` (string) — the Velora contract that will fill the order. Velora picks it per execution context; the current whitelist for a chain is at `https://api.velora.xyz/adapters/contract-takers?network={chainId}`, and the contracts themselves are listed on [Chains & contracts](/docs/resources/chains-and-contracts#addresses-by-chain). Example request, here a user selling 1.5 WETH for USDC (address casing is unspecified; normalize it on your side): ```json theme={null} { "makerAsset": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "takerAsset": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "takerAmount": "1500000000000000000", "userAddress": "0x05182E579FDfCf69E4390c3411D8FeA1fb6467cf", "takerAddress": "0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57" } ``` The requested amount may be slightly larger than what the user can actually swap. This leaves room for routes where the RFQ leg is not the first hop and the previous hop delivers a little more or less than expected. The response has an `"order"` object: * `nonceAndMeta` (string) — a `uint256` encoding the user's address in the lower 160 bits, with the rest filled with random or unpredictable data. Convert the address to an integer and add a random integer below `2**96` shifted left by 160 bits: `(random.randint(0, 2**96 - 1) << 160) + int(address, 16)`. * `expiry` (number) — Unix timestamp in seconds after which the order is no longer executable. At least 2 minutes in the future. * `makerAsset` (string) — as passed in. * `takerAsset` (string) — as passed in. * `maker` (string) — the address holding your funds. It must approve the AugustusRFQ contract, not Augustus v6.2, to spend the maker token. It is the order's signer if it's an EOA; otherwise it's a smart contract implementing EIP-1271. * `taker` (string) — the contract that fills the order, taken from the request's `takerAddress`. * `makerAmount` (string) — as passed in, or computed from the taker amount. * `takerAmount` (string) — as passed in, or computed from the maker amount. * `signature` (string) — `0x` followed by lowercased hex bytes: the `bytes` signature AugustusRFQ expects. The order hash over all fields above is computed with EIP-712 and signed by an EOA or via an EIP-1271 contract signature. For EOA signing, the Velora SDK has working sample code; see [Order structure and signing](/docs/resources/market-makers/order-structure) for the typed-data domain and [SDK → OTC](/docs/sdk/products/otc) for the build → sign flow. With EIP-1271 the signing depends on your contract, so you will likely need custom code. ```json theme={null} { "order": { "nonceAndMeta": "77194726158210796949047323338180021686013833221005105572687668833110133598159", "expiry": 1667344557, "makerAsset": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "takerAsset": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "maker": "0x7777777777777777777777777777777777777777", "taker": "0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57", "makerAmount": "2270000000", "takerAmount": "1500000000000000000", "signature": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcc" } } ``` If the request fails because `userAddress` is blacklisted, return a successful response without the `"order"` key. You may include a `"message"` explaining the blacklisting. Velora then caches the address as blacklisted, exactly as if it had come from the `/blacklist` endpoint. Use this response shape only for blacklisted users. Other failures should return an error response. The generic RFQ harness currently validates direct `/firm` calls with an order-bearing response. For harness runs, rely on `/blacklist` to test blacklisted users and test this no-order `/firm` shortcut separately. See [Testing your integration](/docs/resources/market-makers/testing#current-harness-notes). ## GET /blacklist Lists the user addresses you currently blacklist. The response has a `"blacklist"` array with no duplicate addresses: ```json theme={null} { "blacklist": [ "0x05182E579FDfCf69E4390c3411D8FeA1fb6467cf", "0x0000000000000000000000000000000000000000" ] } ``` ## WebSocket connection (optional) You may additionally serve a WebSocket interface: a one-way channel from you to Velora that delivers cache updates more efficiently than polling. Each message is a JSON object that can carry any HTTP payload except `"order"`. After the first message, send only updates: created entries, changed entries, or price removals. Do not send deletions for tokens or pairs over the WebSocket. * `tokens` — newly supported tokens or corrections to existing ones. * `pairs` — newly added pairs or corrections. Updating `liquidityUSD` over WebSocket is pointless; it isn't read from this source and changes constantly anyway. * `prices` — pairs whose prices need updating, refreshing in the cache after going stale, or removal from the cache (bids, asks, or both). * `blacklist` — newly added addresses only. * `message` — anything you want logged on Velora's servers, at any time. The first message after connecting must contain the complete responses of `/tokens`, `/pairs`, `/prices`, and `/blacklist` in a single JSON object. That lets Velora start with a synchronized cache without making separate HTTP requests. `/blacklist` is still polled periodically afterwards, because blacklist status is only cached temporarily. To stop trading entirely, disconnect the WebSocket and refuse reconnections until you want to resume. # Market maker integration Source: https://new-docs.velora.xyz/docs/resources/market-makers/index Market makers connect to Velora by exposing chain-scoped endpoints, publishing live liquidity, and returning signed AugustusRFQ orders when a user accepts a firm quote. Market makers can plug private liquidity into Velora without changing their trading stack around Velora's API. You expose chain-scoped endpoints, publish the pairs and size you are willing to trade, and Velora routes user swaps against that live inventory. When a user accepts your price, you return a signed [AugustusRFQ](/docs/resources/chains-and-contracts#addresses-by-chain) order and the fill settles on-chain. The model is deliberately simple: your infrastructure owns pricing, Velora owns routing and execution, and AugustusRFQ verifies the signed order at settlement. Tell us the chains, pairs, expected liquidity, and chain-scoped endpoints you want to connect. Run Velora's generic RFQ harness before onboarding. ## Integration flow 1. Expose one chain-scoped API surface for each chain you trade on. This can be a separate base URL per chain, or one service with chain-specific paths such as `/mm/base/tokens` and `/mm/mainnet/tokens`. 2. Publish your supported tokens, tradable pairs, and bid/ask grid for each pair. 3. Keep Velora's cache fresh through polling or, preferably, a WebSocket stream. 4. Receive `POST /firm` only when a user is ready to trade against your liquidity. 5. Return a signed AugustusRFQ order for the requested amount, priced consistently with your published grid. 6. Keep enough balance on the maker wallet, and approve AugustusRFQ as the spender for the maker tokens, so the order can settle. Velora does not call you for every indicative user quote. At production volume, that would add latency and put unnecessary load on market-maker infrastructure. The cached grid handles routing; the firm quote endpoint is reserved for trades that are ready to execute. Users who repeatedly request firm quotes without executing on-chain can be blacklisted on your side. Velora honors your blacklist by hiding your pricing from those users before transaction building. ## What Velora expects from your service Your market-maker service needs to be deterministic enough for routing and strict enough for settlement: * `/tokens` lists every asset you trade on the chain. * `/pairs` lists the base/quote pairs Velora may route through. * `/prices` returns the current bid/ask grid Velora should cache. * `/firm` returns the signed order when a user commits. * `/blacklist` lets you block users who request firm quotes without executing. The full endpoint contract is in the [Market maker API specification](/docs/resources/market-makers/api-specification). The order fields and EIP-712 signing details are in [Order structure and signing](/docs/resources/market-makers/order-structure). ## What you provide at onboarding Before the integration can go live, Velora's team needs: * A chain-scoped base URL for each chain you trade on, either as separate hosts or distinct paths on the same host. * An optional WebSocket URL for price and blacklist updates. * Authentication credentials, if you want Velora's requests signed: a Domain string, an Access Key, and a Secret Key, as described in the [authentication section](/docs/resources/market-makers/api-specification#authentication-optional) of the spec. * A funded maker wallet, either an EOA or an EIP-1271 contract, with allowance to the AugustusRFQ contract on each chain. Approve AugustusRFQ, not Augustus v6.2. Per-chain addresses are on [Chains & contracts](/docs/resources/chains-and-contracts#addresses-by-chain). * The latest output from the [generic RFQ test harness](/docs/resources/market-makers/testing), or the commit and config you used to run it. There is no self-serve registration. [Contact Velora](https://www.velora.xyz/contact) to exchange credentials and schedule integration testing. ## Reliability rules Velora keeps a market maker enabled only while quotes remain executable and consistent with the published grid. | Situation | Result | | ---------------------------------------------- | ----------------------------------------------------------- | | `/prices` fails or returns an error | Trading pauses until the endpoint recovers. | | `/firm` refuses an amount covered by the grid | Repeated refusals can disable the integration. | | Firm pricing drifts from the cached grid | Velora treats it as a bad quote. | | The signature fails EOA or EIP-1271 validation | The order cannot settle and counts against the integration. | | The maker wallet has not approved AugustusRFQ | The order cannot settle. | | The maker wallet lacks inventory | The order cannot settle. | You can also pause trading deliberately by serving an error from `/prices` or closing the WebSocket until you are ready to resume. ## Related pages * [Market maker API specification](/docs/resources/market-makers/api-specification) — every endpoint you need to implement, with payloads. * [Testing your integration](/docs/resources/market-makers/testing) — validate your endpoints with the generic RFQ harness. * [Order structure and signing](/docs/resources/market-makers/order-structure) — the AugustusRFQ order format and EIP-712 signing. * [Chains & contracts](/docs/resources/chains-and-contracts#addresses-by-chain) — AugustusRFQ addresses per chain. * [OTC API overview](/docs/api-reference/rfq/overview) — the taker-facing side of AugustusRFQ orders. * [AugustusRFQ security audit](/docs/resources/security/audits/augustus-rfq) — the settlement contract's audit history. # AugustusRFQ order structure and signing Source: https://new-docs.velora.xyz/docs/resources/market-makers/order-structure How to build and sign an AugustusRFQ order for Velora: order fields, nonceAndMeta encoding, the EIP-712 domain, and off-chain tracking fields. Every trade that settles through [AugustusRFQ](/docs/resources/chains-and-contracts#addresses-by-chain) uses the same object: a maker signs an order off-chain, then the AugustusRFQ contract verifies that signature and transfers tokens on-chain. Market-maker firm quotes and bilateral OTC deals use this same shape. For market makers, the important detail is that the signed order names a Velora execution contract as `taker`, while `nonceAndMeta` embeds the actual user address. That lets Velora execute through its router without letting another user steal the quote. ## What you sign The EIP-712 hash covers the eight order fields below: who gives which token, who may fill, the amounts, expiry, and `nonceAndMeta`. The `signature` is returned alongside those fields after signing. Velora may store extra metadata after the order is posted, but that metadata is not part of the EIP-712 hash. ## On-chain order ```json theme={null} { "maker": "0x05182E579FDfCf69E4390c3411D8FeA1fb6467cf", "taker": "0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57", "nonceAndMeta": "7433034152904838547212883274543254857465784035140417181410394112", "expiry": 0, "makerAsset": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", "takerAsset": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", "makerAmount": "10000000000000000", "takerAmount": "7775870000000000", "signature": "0x43de8dbc8228594171d0ed3e623ca0ab5c24f46bf0575800624ae56723712f807ecaf7dc8edfcf0d4517f80f11bf016bde0a9a20e243eea2bb32e55eadbb6b0d1b" } ``` * `maker` — the order's owner: the account swapping `makerAsset` for `takerAsset`. This account must hold enough `makerAsset` and approve AugustusRFQ, not Augustus v6.2, before the order can settle. * `taker` — who may fill the order on-chain. With the zero address, anybody can fill; with any other address, the contract requires `msg.sender == taker`. In market-maker flows this is a Velora execution contract, and the real user is enforced through `nonceAndMeta` instead. * `nonceAndMeta` — a `uint256` combining a nonce (which makes the order unique) with metadata; see [below](#the-nonceandmeta-field). * `expiry` — Unix timestamp in seconds after which the order is unfillable. `0` means the order never expires. * `makerAsset` — address of the ERC-20 token the maker sells. * `takerAsset` — address of the ERC-20 token the maker buys. * `makerAmount` — amount of `makerAsset` the maker gives. * `takerAmount` — amount of `takerAsset` the maker receives in exchange. * `signature` — the maker's EIP-712 signature over the eight order fields above, excluding `signature` itself. The contract also settles ERC-721 and ERC-1155 orders through a variant of this structure with packed asset fields, but market making on Velora uses ERC-20 orders only. ## EIP-712 signing The order is hashed as EIP-712 typed data. Use this domain: | Domain field | Value | | ------------------- | ------------------------------------- | | `name` | `"AUGUSTUS RFQ"` | | `version` | `"1"` | | `chainId` | The chain where the order will settle | | `verifyingContract` | That chain's AugustusRFQ address | The contract accepts two signature types at settlement: * An EOA signature: the maker signs the typed data with its private key (`eth_signTypedData`). * An EIP-1271 signature: the maker is a smart contract, and AugustusRFQ calls its `isValidSignature` to verify the bytes. How those bytes are produced depends entirely on your contract. For EOA examples, the [Velora SDK](/docs/sdk/products/otc) wraps build → sign → post, and the [agent prompt library](/docs/for-agents/prompt-library/rfq-otc-flow) has a self-contained TypeScript flow. ## The nonceAndMeta field On-chain, `nonceAndMeta` only has to make the order hash unique. In Velora's market-maker flow, it also binds the firm quote to the actual user. The lower 160 bits carry the user address. The upper bits carry random or unpredictable data, which makes the order unique: ```text theme={null} nonceAndMeta = userAddress + (randomInt << 160) ``` Velora's API constructs the random part from integers up to 2^53 − 1. Firm quotes from market makers may use any random integer below 2^96. Velora's execution contracts extract the embedded address and verify it matches the user actually swapping. An order quoted for one user cannot be filled on behalf of another. The same check also makes blacklisting meaningful: requesting a firm quote burns a real user address, not just an anonymous routing attempt. ## Off-chain representation When an order is posted to Velora's API, Velora stores the signed order plus tracking data: the maker's live balance and allowance, the decoded counterparty, and the order's lifecycle state. ```json theme={null} { "expiry": 0, "createdAt": 1661165141, "updatedAt": 1661165141, "transactionHash": null, "chainId": 137, "nonceAndMeta": "7433034152904838547212883274543254857465784035140417181410394112", "maker": "0x05182e579fdfcf69e4390c3411d8fea1fb6467cf", "taker": "0xdef171fe48cf0115b1d80b88dc8eab59176fee57", "takerFromMeta": "0x0000000000000000000000000000000000000000", "makerAsset": "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270", "takerAsset": "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063", "makerAmount": "10000000000000000", "fillableBalance": "10000000000000000", "swappableBalance": "10000000000000000", "makerBalance": "10000000000000000", "takerAmount": "7775870000000000", "signature": "0x43dd8dbc8228594171d0ed3e633ca0eb5c24f46bf0575100623ae56723712f807ecaf7dc8edfcf0d4517f80f11bf016bde0a9a20e243eea2bb32e55eadbb6b0d1b", "orderHash": "0xdef400fd95d028d8caaba2c4887d2694563e0bc7f73c17d747feac2e24ed411d", "permitMakerAsset": null, "type": "LIMIT", "state": "PENDING" } ``` The fields beyond the signed on-chain order: * `orderHash` — the EIP-712 hash of the on-chain order; the order's unique ID, used to fetch, fill, and cancel it. * `takerFromMeta` — the counterparty address decoded from `nonceAndMeta`. The zero address means the order wasn't restricted to a counterparty. * `fillableBalance` — the amount still unfilled. When it differs from `makerAmount`, the order has been partially filled. * `swappableBalance` — the amount that can actually be filled right now. * `makerBalance` — the maximum the maker can currently cover after considering balance and allowance. * `permitMakerAsset` — always `null` for now; reserved for a future permit flow. * `type` — `P2P` when `takerFromMeta` names a counterparty, `LIMIT` when it's the zero address and anyone can fill. Despite the legacy value name, these are AugustusRFQ orders; on Velora today, [Limit Orders](/docs/api-reference/delta/overview) are a Delta product. * `state` — the order's lifecycle state. The states and their meaning are documented in the [OTC API overview](/docs/api-reference/rfq/overview#order-states). Only the original order fields and `signature` are needed for settlement. The additional fields help clients decide whether an order is still usable before they try to fill it. ## Related pages * [Market making on Velora](/docs/resources/market-makers) — how the firm-quote flow uses these orders. * [Market maker API specification](/docs/resources/market-makers/api-specification) — the `POST /firm` endpoint that returns a signed order. * [OTC API overview](/docs/api-reference/rfq/overview) — posting, filling, and cancelling orders as a taker or maker. * [Chains & contracts](/docs/resources/chains-and-contracts#addresses-by-chain) — AugustusRFQ addresses per chain. # Test a market maker integration Source: https://new-docs.velora.xyz/docs/resources/market-makers/testing How to test a market maker API with Velora's generic RFQ harness before onboarding: schema checks, live endpoint checks, and route-level E2E tests. Before onboarding, test your market maker API with Velora's generic RFQ harness in [`paraswap-dex-lib`](https://github.com/VeloraDEX/paraswap-dex-lib/tree/master/src/dex/generic-rfq). The harness is the same adapter shape Velora uses internally: it fetches your token, pair, price, blacklist, and firm quote endpoints, validates the responses, and can run route-level E2E swaps against your quoted liquidity. This is not a replacement for Velora's onboarding tests, but it catches most integration mistakes before credentials are exchanged. ## What the harness checks The generic RFQ folder contains the files you need most: | File | Use | | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | | [`validators.ts`](https://github.com/VeloraDEX/paraswap-dex-lib/blob/master/src/dex/generic-rfq/validators.ts) | Validates `/tokens`, `/pairs`, `/prices`, `/blacklist`, and `/firm` response shapes. | | [`fetch-mm-api.ts`](https://github.com/VeloraDEX/paraswap-dex-lib/blob/master/src/dex/generic-rfq/fetch-mm-api.ts) | Calls a live market maker API with HMAC authentication and prints validation results. | | [`generic-rfq-e2e.test.ts`](https://github.com/VeloraDEX/paraswap-dex-lib/blob/master/src/dex/generic-rfq/generic-rfq-e2e.test.ts) | Adds your RFQ endpoint to a local dex-lib config and runs route-level E2E swaps. | | [`example-api.test.ts`](https://github.com/VeloraDEX/paraswap-dex-lib/blob/master/src/dex/generic-rfq/example-api.test.ts) | Starts a dummy RFQ server that shows the expected endpoint behavior. | Use the schema tests first, then the live endpoint fetcher, then route-level E2E tests. If the first layer fails, the later layers will be noisy. ## Prerequisites Clone the repo and install dependencies: ```bash theme={null} git clone https://github.com/VeloraDEX/paraswap-dex-lib.git cd paraswap-dex-lib pnpm install ``` The current package requires Node.js `>=22` and pnpm `>=11`. Your API needs a chain-scoped base URL. For example, if Velora should call `https://mm.example.com/mainnet/tokens`, set: ```bash theme={null} export GENERIC_RFQ_URL="https://mm.example.com/mainnet" ``` If your HMAC signature should be computed over `/tokens` rather than `/mainnet/tokens`, also set: ```bash theme={null} export GENERIC_RFQ_PATH_TO_OVERRIDE="mainnet" ``` Leave `GENERIC_RFQ_PATH_TO_OVERRIDE` unset if the chain prefix is part of the signed path. ## Smoke-test response schemas Run the local validator tests before pointing the harness at your service: ```bash theme={null} pnpm test src/dex/generic-rfq/validators.test.ts --runInBand ``` These tests are small, but they document what the adapter accepts. They also catch details that are easy to miss: * Token entries must include an `address` string. The schema does not checksum or EVM-validate token addresses at this layer, so catch bad token addresses in your own tests too. * `decimals` must be present. * Price levels must be string numbers. * Empty price objects are allowed for disabled pairs. * Crossed books are rejected: the highest bid must be lower than the lowest ask. * Firm quotes must return an `order` with a valid `maker`, `taker`, token addresses, amounts, `nonceAndMeta`, and `signature`. ## Test your live endpoints Set the live endpoint credentials: ```bash theme={null} export GENERIC_RFQ_URL="https://mm.example.com/mainnet" export GENERIC_RFQ_ACCESS_KEY="" export GENERIC_RFQ_SECRET_KEY="" export HTTP_PROVIDER_1="" ``` `GENERIC_RFQ_SECRET_KEY` is base64 encoded. The fetcher decodes it before signing requests. The live fetcher uses `paraswap` as the auth domain; use that Domain value for this test unless you edit the script. The current `fetch-mm-api.ts` script is hardcoded to `network = 1`, so it reads `HTTP_PROVIDER_1` and validates firm quotes against the mainnet taker address declared in the script. Edit those constants if you want to use it against another chain. Then run the live fetcher: ```bash theme={null} pnpm exec ts-node src/dex/generic-rfq/fetch-mm-api.ts ``` By default, the fetcher checks: * `GET /tokens` * `GET /pairs` * `GET /prices` * `GET /blacklist` The same file also includes a `mainFirm()` helper for `POST /firm`, but it is disabled and its payload uses placeholders. Fill `makerAsset`, `takerAsset`, either `makerAmount` or `takerAmount`, and `userAddress`. Then add the required `takerAddress` field to the payload, and call `mainFirm()` at the bottom of the file. For `takerAddress`, use the Velora execution contract that will fill the order on that chain. During onboarding, Velora will confirm the exact value to test. The harness validates that your returned order uses the expected `taker`. ## Run route-level E2E tests After the endpoint checks pass, test whether dex-lib can route through your RFQ liquidity. Edit [`e2e-test-config.ts`](https://github.com/VeloraDEX/paraswap-dex-lib/blob/master/src/dex/generic-rfq/e2e-test-config.ts) with the token pairs, side, and amounts you want to test: ```typescript theme={null} export const testConfig = { [Network.MAINNET]: [ { srcToken: 'USDC', destToken: 'USDT', amount: '10000', swapSide: SwapSide.SELL, }, ], }; ``` Then edit `dexKey` in [`generic-rfq-e2e.test.ts`](https://github.com/VeloraDEX/paraswap-dex-lib/blob/master/src/dex/generic-rfq/generic-rfq-e2e.test.ts): ```typescript theme={null} const dexKey = 'YOUR_NAME'; ``` Set the E2E environment: ```bash theme={null} export GENERIC_RFQ_URL="https://mm.example.com/mainnet" export GENERIC_RFQ_ACCESS_KEY="" export GENERIC_RFQ_SECRET_KEY="" export GENERIC_RFQ_MAKER_ADDRESS="0x..." export HTTP_PROVIDER_1="" ``` The E2E config also uses `paraswap` as the auth domain. Run the E2E test: ```bash theme={null} pnpm test src/dex/generic-rfq/generic-rfq-e2e.test.ts --runInBand ``` A useful passing run proves three things: dex-lib can ingest your cached grid, route through it for the configured token pair, and request a firm quote that produces a signed AugustusRFQ order. ## What to send Velora When you [contact Velora](https://www.velora.xyz/contact) to become a market maker, include: * Chain-scoped base URLs for each chain. * The chains, token pairs, and expected liquidity you want to start with. * Whether you use HMAC authentication, IP allowlisting, or both. * Maker wallet addresses and whether they are EOAs or EIP-1271 contracts. * The `paraswap-dex-lib` commit you tested against. * The endpoint fetcher output and E2E test output. Do not send private keys or raw Secret Keys. Share credentials through the onboarding channel Velora gives you. ## Current harness notes The harness is useful because it is strict. Two details matter: * It rejects crossed books. Keep the highest bid below the lowest ask. * Its direct `/firm` validator expects an `order`. If you support the production blacklist shortcut, where `/firm` returns success without `order` for a blacklisted `userAddress`, test that behavior separately and rely on `/blacklist` for the harness run. Velora's onboarding tests may exercise additional chain-specific takers, maker allowance to AugustusRFQ, and settlement paths. # Move to api.velora.xyz Source: https://new-docs.velora.xyz/docs/resources/migrations/apiv5-to-api-host Move off the deprecated apiv5.paraswap.io and api.paraswap.io hosts to api.velora.xyz, the production endpoint. ## What breaks if you do nothing The legacy hosts `apiv5.paraswap.io` and `api.paraswap.io` are deprecated. They still answer today, but they are not the production endpoint and will be retired. Code pinned to either host will start failing once it goes offline; some endpoints have already moved. The production host is `https://api.velora.xyz`. ## Steps 1. Replace `https://apiv5.paraswap.io` and `https://api.paraswap.io` with `https://api.velora.xyz` in your code, env vars, and config files. 2. Re-check the endpoints you use. Most map 1:1; a small set were renamed when consolidated. 3. Re-run your integration tests against `api.velora.xyz` before flipping production traffic. ## End-state check `grep -RE "(apiv5\.paraswap\.io|api\.paraswap\.io)"` in your codebase returns zero hits. Smoke test: a known `GET /prices` call against `api.velora.xyz` returns the same `priceRoute` it did on the legacy host. # Migrate Augustus v5 to v6.2 Source: https://new-docs.velora.xyz/docs/resources/migrations/augustus-v5-to-v6-2 Contract-integrator upgrade: calldata diffs, removed TokenTransferProxy, parameter renames. ## What breaks if you do nothing Calldata returned by `POST /transactions` now targets Augustus v6.2 by default. If your contract integration hardcoded the v5 router or `TokenTransferProxy` address, those approvals and contract calls will silently route to a deprecated surface. ## High-level diffs * `TokenTransferProxy` is gone. v6.2 pulls tokens directly via the router contract, so ERC-20 approvals must be granted to the v6.2 router address, not to a separate proxy. * `excludeContractMethodsWithoutFeeModel` has been renamed (see the new param list in [API Reference](/docs/api-reference/market/overview)). * Method signatures changed: v6.2 introduces `swapExactAmountIn` and `swapExactAmountOut` as canonical entry points, and v5's `multiSwap`/`megaSwap` are deprecated. ## Steps 1. Look up the v6.2 router address per chain on [Chains & contracts](/docs/resources/chains-and-contracts). 2. Re-grant ERC-20 approvals to the v6.2 router. Revoke the legacy v5 TokenTransferProxy approval if you want cleanup. 3. If you decode calldata server-side, regenerate ABIs against v6.2. 4. Update any hardcoded contract-method names in your dApp. ## End-state check `GET /prices` response → `priceRoute.version` is `"6.2"` and `priceRoute.contractAddress` matches the v6.2 router for the chain. # Migrate from Delta V1 to V2 Source: https://new-docs.velora.xyz/docs/resources/migrations/delta-v1-to-v2 Endpoint-by-endpoint migration for direct HTTP integrators moving to Delta V2's crosschain-first route model, server-built orders, /v2/quote, and limitAmount. This page is for integrators calling the Velora Delta HTTP API directly. If you're on the [Velora SDK](/docs/sdk/products/delta), the SDK-level migration walks the same path with TypeScript snippets; see [SDK → Migrate from V1 to V2](/docs/sdk/products/delta#migrate-from-v1-to-v2). ## What breaks if you do nothing Nothing. Delta V1 (`/delta/*`) remains fully supported and shares on-chain contracts with V2. Your existing integration keeps working as-is. ## Why migrate V2 keeps the same on-chain settlement model. The main reason to migrate is that V2 is built crosschain-first: same-chain and crosschain intents share one route model, so you quote the source chain, optionally add `destChainId`, and pass the returned `route` into build unchanged. That crosschain-first model also cleans up the protocol surface: * Crosschain is native to pricing. `GET /v2/quote` or `GET /v2/delta/prices` returns a recommended `route` with `route.bridge` populated for crosschain, plus `alternatives` when other bridge routes are available. * Orders are built server-side. `POST /v2/delta/orders/build` returns EIP-712 typed data ready to sign, and you stop composing `domain`, `types`, and `value` on the client. * Pricing is route-based. The route replaces the `bridge` / `bridgeInfo` / `availableBridges` triple V1 returns. * Limit orders use the same build flow. Add `limitAmount` to `POST /v2/delta/orders/build`, then submit the signed order with `type: "LIMIT"`. * Order history is paginated. `GET /v2/delta/orders` returns `{ data, total, page, limit, hasMore }` where V1 returns a flat array with no total. * Status is a single field. Twelve values (`PENDING`, `AWAITING_SIGNATURE`, `ACTIVE`, `SUSPENDED`, `CANCELLING`, `BRIDGING`, `COMPLETED`, `FAILED`, `EXPIRED`, `REFUNDING`, `CANCELLED`, `REFUNDED`) replace V1's `status` + `bridgeStatus` pair. * Partner fees resolve on the server. Pass `partner` / `partnerAddress` / `partnerFeeBps` directly on every call; the separate `GET /prices/partnerfee/{chainId}` round-trip goes away. * The `hmac` is gone. V2 doesn't sign the price payload, so there's no opaque blob to thread from `/prices` into `/orders/build`. ## Endpoint mapping | V1 | V2 | Notes | | ---------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- | | `GET /delta/prices` | [`GET /v2/delta/prices`](/docs/api-reference/delta/prices) | Response carries `route` + `alternatives`; `price.hmac` removed | | `GET /delta/prices/bridge-info` | [`GET /v2/delta/prices/bridge-routes`](/docs/api-reference/delta/bridge-routes) | Flat `routes[]` array instead of nested `srcChainId → destChainId → tokens[]` map | | `GET /delta/prices/bridge-protocols` | [`GET /v2/delta/prices/bridge-protocols`](/docs/api-reference/delta/bridge-protocols) | Same shape | | `GET /delta/prices/strategies/{chainId}` | [`GET /v2/delta/prices/strategies/{chainId}`](/docs/api-reference/delta/strategies) | Same shape | | `GET /delta/prices/is-token-supported` | [`GET /v2/delta/prices/is-token-supported`](/docs/api-reference/delta/is-token-supported) | Same shape | | `GET /prices/partnerfee/{chainId}` | *Not needed* | Pass `partner` / `partnerAddress` / `partnerFeeBps` raw on every V2 call | | `POST /delta/orders/build` | [`POST /v2/delta/orders/build`](/docs/api-reference/delta/orders-build) | Different body — pass `route` (not `price` + `hmac`); response wraps typed data in `toSign` | | `POST /delta/orders` | [`POST /v2/delta/orders`](/docs/api-reference/delta/orders-submit) | Submit `order: built.toSign.value` instead of `data` from V1 build | | `POST /delta/orders/cancel` | [`POST /v2/delta/orders/cancel`](/docs/api-reference/delta/orders-cancel) | Same shape | | `GET /delta/orders` | [`GET /v2/delta/orders`](/docs/api-reference/delta/orders-list) | Wraps array in `{ data, total, page, limit, hasMore }` | | `GET /delta/orders/{orderId}` | [`GET /v2/delta/orders/{orderId}`](/docs/api-reference/delta/orders-get-by-id) | New response shape — `input` / `output` carry expected + executed amounts | | `GET /delta/orders/hash/{hash}` | [`GET /v2/delta/orders/hash/{hash}`](/docs/api-reference/delta/orders-get-by-hash) | Same as above | | `GET /delta/orders/fillablebalance/...` | [`GET /v2/delta/orders/fillablebalance/...`](/docs/api-reference/delta/orders-fillable-balance) | Same shape | | `GET /delta/agents/list/{chainId}` | [`GET /v2/delta/agents/list/{chainId}`](/docs/api-reference/delta/agents-list) | Same shape | | `GET /quote` (`mode=ALL`) | [`GET /v2/quote`](/docs/api-reference/delta/quote) | Delta-or-Market fallback still exists; branch on top-level `delta` or `market` | ## Steps ### 1. Pricing V1 returns a flat price object with a server-signed `hmac`. V2 returns a structured route plus alternatives. You can read that Delta route directly from `GET /v2/delta/prices`, or from the `delta` block of `GET /v2/quote?mode=DELTA`. ```diff theme={null} - GET /delta/prices?chainId=1&srcToken=0x...&destToken=0x...&amount=...&partner=my-app-name + GET /v2/delta/prices?chainId=1&srcToken=0x...&destToken=0x...&amount=...&partner=my-app-name ``` If your V1 integration used the unified quote path, migrate it to `/v2/quote`: ```diff theme={null} - GET /quote?chainId=1&srcToken=0x...&destToken=0x...&amount=...&mode=ALL&partner=my-app-name + GET /v2/quote?chainId=1&srcToken=0x...&destToken=0x...&amount=...&mode=ALL&partner=my-app-name ``` With `mode=ALL`, V2 returns one path for you to handle: a top-level `delta` block when Delta can price the trade, or a top-level `market` block when it falls back to Market. Do not expect both blocks in one response. V1 response: ```json theme={null} { "price": { "srcToken": "0x...", "destToken": "0x...", "srcAmount": "...", "destAmount": "...", "partner": "my-app-name", "partnerFee": 0.05, "bridge": { "destinationChainId": 0, "protocolSelector": "0x00000000", ... }, "hmac": "0x..." }, "deltaAddress": "0x..." } ``` V2 response: ```json theme={null} { "id": "req_...", "side": "SELL", "inputToken": { "chainId": 1, "address": "0x..." }, "outputToken": { "chainId": 8453, "address": "0x..." }, "route": { "origin": { "input": { ... }, "output": { ... } }, "destination": { "input": { ... }, "output": { ... } }, "bridge": { "...": "present for crosschain, null for same-chain" }, "fees": { "gas": { ... }, "bridge": [] } }, "alternatives": [], "partner": { "name": "my-app-name", "feePercent": 0.05 }, "spender": "0x..." } ``` Handle these in your client: * `price.hmac` is gone; don't thread it into `/orders/build`. * `deltaAddress` moved to `spender`. Approve `spender` as the ERC-20 spender (the on-chain Delta contract address itself is unchanged). * Bridge detection changed. V1 used `bridge.destinationChainId !== 0`; V2 sets `route.bridge` to `null` for same-chain and populates it for crosschain. Read `route.origin.input.token.chainId` vs `route.destination.output.token.chainId` if you need a direct check. ### 2. Build V1 takes the price object + hmac. V2 takes the route plus order params on top. Pass the route from `GET /v2/delta/prices`, or `delta.route` from `GET /v2/quote`, without editing it. ```diff theme={null} POST /delta/orders/build { - "chainId": 1, - "owner": "0x...", - "price": { /* the full delta price object including hmac */ }, - "slippage": 100 + /* request goes to /v2/delta/orders/build instead */ } + POST /v2/delta/orders/build + { + "owner": "0x...", + "route": { /* the route from /v2/delta/prices, verbatim */ }, + "side": "SELL", + "slippage": 100, + "deadline": 1893456000, + "partner": "my-app-name", + "partnerFeeBps": 25 + } ``` > The chain ID is no longer part of the build request; V2 derives it from the `route`. V1 returned `{ data, orderHash, domain, types }`, where `data` was the on-chain Order struct. V2 returns `{ toSign: { domain, types, value }, orderHash }`: `value` is the on-chain Order struct, wrapped one level deeper. ```diff theme={null} // V1 response - { - "data": { /* on-chain Order struct */ }, - "orderHash": "0x...", - "domain": { ... }, - "types": { ... } - } // V2 response + { + "toSign": { + "domain": { ... }, + "types": { ... }, + "value": { /* on-chain Order struct, same shape as V1's `data` */ } + }, + "orderHash": "0x..." + } ``` ### 3. Sign The EIP-712 domain (`name: "Portikus"`, `version: "2.0.0"`, `chainId`, `verifyingContract`) is unchanged. The signature you compute over V2's `toSign` is the same string V1 would produce over its `data`/`domain`/`types` triple. ### 4. Submit V1 took `{ order, signature, partner, ... }`. V2 is the same shape; only the source of `order` changes. ```diff theme={null} - POST /delta/orders + POST /v2/delta/orders { "chainId": 1, - "order": /* V1 build response's `data` */, + "order": /* V2 build response's `toSign.value` */, "signature": "0x...", "type": "MARKET", "partner": "my-app-name" } ``` V2 doesn't accept `referrerAddress` differently: same field, same semantics. ### 5. Limit orders V1 limit-order code often had a separate builder path. In V2, a limit order is a Delta order with a target-price constraint, so you use the same `POST /v2/delta/orders/build` endpoint and add `limitAmount`. ```diff theme={null} + POST /v2/delta/orders/build + { + "owner": "0x...", + "route": { /* the route from /v2/quote or /v2/delta/prices, verbatim */ }, + "side": "SELL", + "deadline": 1893456000, + "limitAmount": "3000000000000000000", + "partner": "my-app-name" + } ``` For SELL orders, `limitAmount` is the minimum destination amount the user accepts. For BUY orders, it is the maximum source amount the user is willing to spend. The response is still `{ toSign, orderHash }`; after the user signs, submit `toSign.value` with `type: "LIMIT"`: ```diff theme={null} + POST /v2/delta/orders + { + "chainId": 1, + "order": /* V2 build response's `toSign.value` */, + "signature": "0x...", + "type": "LIMIT", + "partner": "my-app-name" + } ``` For the full flow, see [Limit order API integration](/docs/integrate/api/limit-orders). ### 6. Poll for status V1 status (`DeltaAuctionStatus`) splits into `status` + `bridgeStatus`. V2 collapses both into one `status` field. ```diff theme={null} - GET /delta/orders/{orderId} + GET /v2/delta/orders/{orderId} ``` Status mapping you'll need on the client when migrating queries: | V1 (`status` + `bridgeStatus`) | V2 (`status`) | | --------------------------------------------------- | -------------------- | | `NOT_STARTED` | `PENDING` | | `AWAITING_PRE_SIGNATURE` | `AWAITING_SIGNATURE` | | `RUNNING`, `EXECUTING` | `ACTIVE` | | Suspension states (insufficient balance/allowance) | `SUSPENDED` | | `CANCELLING` | `CANCELLING` | | `EXECUTED` + `bridgeStatus: PENDING` | `BRIDGING` | | `EXECUTED` + (same-chain OR `bridgeStatus: FILLED`) | `COMPLETED` | | `FAILED`, `INVALIDATED` | `FAILED` | | `EXPIRED` (or `bridgeStatus: EXPIRED`) | `EXPIRED` | | `EXECUTED` + `bridgeStatus: REFUNDING` | `REFUNDING` | | `CANCELLED` | `CANCELLED` | | `REFUNDED` (or `bridgeStatus: REFUNDED`) | `REFUNDED` | V2 separates an in-flight bridge refund from a verified refund. `REFUNDING` means the bridge leg failed or expired and Velora is still polling for the actual refund transaction. `REFUNDED` means the refund is complete. V1 order endpoints temporarily map `bridgeStatus: REFUNDING` back to `REFUNDED` for compatibility, so migrate status handling before relying on that distinction. The V2 response also restructures order details: `input` and `output` each carry `{ chainId, token, amount }` (SELL: input has `amount`, output has `expectedAmount` + `executedAmount`; BUY: vice versa). V1 returned `order.srcToken` / `order.destToken` plus a separate `transactions[]` array. V2 keeps both, but the headline numbers move to `input` / `output`. For crosschain refunds, V2 also adds top-level `refunds[]` to the order response. Each verified refund item has: ```json theme={null} { "tx": "0x...", "chainId": 42161, "token": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", "amount": "1454437" } ``` Treat amounts as raw token units. `refunds[]` can stay empty while the order is `REFUNDING`, and it can also be empty for bridge-provider failure modes that do not emit source-chain token refund metadata. ### 7. List orders ```diff theme={null} - GET /delta/orders?userAddress=0x...&page=1&limit=100 + GET /v2/delta/orders?userAddress=0x...&page=1&limit=100 ``` V1 returns a plain array; V2 wraps it: ```diff theme={null} - [ { "id": "...", "status": "...", ... }, ... ] + { + "data": [ { "id": "...", "status": "...", ... }, ... ], + "total": 1234, + "page": 1, + "limit": 100, + "hasMore": true + } ``` You now know how many pages remain, which is useful for "load more" UIs without falling back to "fetch until you get fewer than `limit`". ### 8. Cancel No semantic change: same path under `/v2`, same request body. ```diff theme={null} - POST /delta/orders/cancel + POST /v2/delta/orders/cancel { "orderIds": ["..."], "signature": "0x..." } ``` ### 9. Partner fee V1: integrators called `GET /prices/partnerfee/{chainId}?partner=...` to look up the registered config, then encoded it into the order locally. V2: just pass `partner` on every call (`/v2/delta/prices`, `/v2/delta/orders/build`, `/v2/delta/orders`). The server resolves the registered config, validates the fee, and encodes it into the on-chain order. To override per call, pass `partnerAddress` and `partnerFeeBps` (and/or `partnerTakesSurplus`) on the same call. ```diff theme={null} - // V1: separate round-trip, then re-encode in build params - const { partnerAddress, partnerFee, takeSurplus } = - await fetch(`/prices/partnerfee/${chainId}?partner=${key}`).then(r => r.json()); - POST /delta/orders/build { ..., partnerAddress, partnerFeeBps: partnerFee * 100, ... } + // V2: server resolves; just pass `partner` + POST /v2/delta/orders/build { ..., partner: "my-app-name" } ``` `GET /prices/partnerfee/{chainId}` still exists; keep using it if you need the resolved config for your UI (e.g., to show "0.25% fee" alongside the quote). ## Breaking changes you might miss * `price.hmac` is gone in V2. Existing code that re-attaches `hmac` to the build payload will fail validation. * The replacement for V1 `GET /quote` is `GET /v2/quote`, not "no quote endpoint." With `mode=ALL`, branch on top-level `delta` or `market`. * Limit orders move onto the standard V2 build path. Add `limitAmount` to `POST /v2/delta/orders/build`, then submit with `type: "LIMIT"`. * The `bridge.destinationChainId !== 0` check breaks. V2 sets `route.bridge = null` for same-chain; the V1 sentinel is no longer present in V2 responses. * `bridge-info` changed shape, from a nested object to a flat `routes[]` array, and the replacement endpoint is named `bridge-routes`. * The status enum changed, so your status-handling code needs the mapping table above. Don't rely on `EXECUTED` alone: V2 reports `COMPLETED` for executed-and-finalized orders, `BRIDGING` while the destination leg is still pending, and `REFUNDING` while a failed bridge leg is waiting for a verified refund transaction. * `REFUNDED` is now distinct from `REFUNDING` in V2. If your V1 UI showed any refund state as final, add an in-progress state before moving users to V2. * The order list response changed from `Order[]` to `{ data: Order[], total, page, limit, hasMore }`. Code that does `orders.length` or `orders.map(...)` on the response needs to unwrap `.data` first. ## End-state check 1. `GET /v2/quote?mode=DELTA` or `GET /v2/delta/prices` returns a `route` and a non-empty `spender`. 2. `POST /v2/delta/orders/build` returns `{ toSign, orderHash }`. 3. The signature your wallet produces over `toSign` is accepted by `POST /v2/delta/orders` (status `200`, response carries the new order shape with `id` and `status: "PENDING"`). 4. `GET /v2/delta/orders/{id}` polls through `ACTIVE` → `COMPLETED` (or `BRIDGING` → `COMPLETED` for crosschain). If a bridge refund happens, your UI can show `REFUNDING` until the order reaches `REFUNDED` and any verified `refunds[]` entries appear. 5. A limit-order build with `limitAmount` returns `{ toSign, orderHash }`, and the signed order submits with `type: "LIMIT"`. 6. `grep -r "partnerfee\|/delta/prices\b\|/delta/orders\b" your-codebase/`: every hit is intentional (e.g., `/prices/partnerfee` for UI lookup; `/delta/orders` only if you intentionally stayed on V1). ## Related pages * [Delta V2 API overview](/docs/api-reference/delta/overview) — the recommended surface. * [SDK → Migrate from V1 to V2](/docs/sdk/products/delta#migrate-from-v1-to-v2) — same migration at the TypeScript SDK level. * [Crosschain Delta swaps](/docs/delta/crosschain-delta) — how `destChainId`, bridge routes, and crosschain status work. * [Limit order API integration](/docs/integrate/api/limit-orders) — build with `limitAmount`, then submit with `type: "LIMIT"`. # Velora migration guides Source: https://new-docs.velora.xyz/docs/resources/migrations/index Internal upgrades for existing Velora integrators — Market → Delta, Augustus v5 → v6.2, legacy hosts, SDK rename. These pages are for engineers already shipping on Velora. They cover the only kinds of changes that should ever break your integration: internal protocol upgrades, host cutovers, and SDK renames. Nothing here is about migrating *to* Velora from a third party. ## Available migrations Endpoint-by-endpoint migration: server-built orders, route-based pricing, unified status model. Keep Market wired, add Delta via `mode=ALL`, branch per response shape. When to fully cut over: gasless UX, MEV exposure, surplus economics. Contract integrators: calldata diffs, no more TokenTransferProxy, parameter renames. Move off `apiv5.paraswap.io` and `api.paraswap.io` to `api.velora.xyz`. Package rename, breaking changes, and step-by-step upgrade. Each migration page leads with **what breaks if you do nothing** and ends with a verifiable end-state check. # Run Market and Delta in parallel Source: https://new-docs.velora.xyz/docs/resources/migrations/market-to-delta-parallel Keep your Market integration wired, opt into Delta intents alongside it, and branch on the response shape. ## What breaks if you do nothing Nothing. This migration is opt-in. Your existing Market integration keeps working as-is. ## Why migrate Delta intents are gasless and MEV-protected: users sign once, solvers compete to fill, and Delta settles the winning fill. And you don't rewrite anything to get there. `GET /v2/quote` with `mode=ALL` returns either a Delta `delta` block or a Market `market` block (the same shape as `/prices`'s `priceRoute`). Velora picks the winner server-side; you branch on which block is present. See [Trading modes](/docs/integrate/trading-modes). ## Steps 1. Switch from `GET /prices` to `GET /v2/quote?mode=ALL`. 2. Branch on the response: if `response.delta` exists, take the gasless path; else fall back to `response.market` and the existing calldata flow (it's the same shape your code already handles). 3. For the Delta path, call `POST /v2/delta/orders/build`, sign the EIP-712 typed data, then `POST /v2/delta/orders`. ## End-state check Run a quote with `mode=ALL`. Confirm the response carries either a `market` or `delta` block (the server-picked winner) and complete a swap end-to-end. # Replace Market with Delta Source: https://new-docs.velora.xyz/docs/resources/migrations/market-to-delta-replace When and how to fully cut over from Market routing to Delta intents. ## What breaks if you do nothing Nothing. Market routing isn't going away. This migration is for teams who want to consolidate on Delta for product reasons, not a forced cutover. ## When to fully cut over * Gasless UX is a real differentiator for your users (consumer wallets, agent flows, sub-\$50 swaps). * MEV is a known problem in your current Market flow, typically on large trades or low-liquidity pairs. * You want the surplus: solver competition routinely returns positive slippage to your users on Delta orders. ## When to keep Market * Latency budget under \~1s end-to-end. * Heavy token coverage on pairs that Delta solvers don't yet quote. * You already amortize gas across many users (batched executor, account abstraction with paymaster). ## Steps 1. Call `GET /v2/quote?mode=DELTA` instead of `GET /prices`. Treat a missing `delta` block as a routing failure for your UX. 2. Remove Augustus calldata signing paths. All execution goes through `/v2/delta/orders`. 3. Update your token-approval flow: the Delta contract, not Augustus, is the spender. ## End-state check Wallet, balance, and history pages show only Delta-style settlements. Augustus calldata flow is no longer reachable from your UI. # Migrate from @paraswap/sdk Source: https://new-docs.velora.xyz/docs/resources/migrations/paraswap-sdk-to-velora-sdk Step-by-step migration from the legacy @paraswap/sdk package to @velora-dex/sdk. ## What breaks if you do nothing `@paraswap/sdk` is no longer actively developed. New API features (latest Augustus version, Delta enhancements, Crosschain) land in `@velora-dex/sdk` only. Your build will keep compiling, but you'll silently fall behind. ## Steps 1. Remove `@paraswap/sdk` from `package.json`. Install `@velora-dex/sdk`. 2. Replace imports. Most named exports kept the same shape. The factory rename is `constructSimpleSDK` (the function name itself is unchanged; only the package source changed). 3. Re-run your TypeScript build. Most projects compile clean on the first pass. ## Code diff (illustrative) ```diff theme={null} - import { constructSimpleSDK } from '@paraswap/sdk'; + import { constructSimpleSDK } from '@velora-dex/sdk'; const sdk = constructSimpleSDK({ chainId: 1, fetch }); ``` ## End-state check `grep -R "@paraswap/sdk"` returns zero hits. Existing quote-and-swap flow returns the same `priceRoute` shape it did before. # Velora smart contract audits Source: https://new-docs.velora.xyz/docs/resources/security/audits Velora's smart-contract audits and security approach across Augustus, RFQ, and supporting infrastructure. Every line of Velora's on-chain code goes through independent third-party audits before reaching production. This page lists every audit on record, plus the wider security posture: formal verification, monitoring, and Web2 testing. ## Smart-contract audits | Surface | Auditors | Notes | Detail | | ------------- | --------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------- | | Augustus v6.2 | Certora, PeckShield, AstraSec | Refinements to fee-claiming on top of v6.1; prior v6.1 audits remain applicable | [v6.2 audits](/docs/resources/security/audits/augustus-v6-2) | | Augustus v6.1 | Certora, Hexens, PeckShield, Hacken, AstraSec | First DEX aggregator with formal verification (Certora) | [v6.1 audits](/docs/resources/security/audits/augustus-v6-1) | | Augustus v5 | PeckShield, Solidified | Production-grade aggregator router | [v5 audits](/docs/resources/security/audits/augustus-v5) | | AugustusRFQ | PeckShield | Fungible-token RFQ contracts | [RFQ audits](/docs/resources/security/audits/augustus-rfq) | ## Web3 security ### Independent audits Every contract that handles user funds (Augustus router, Delta settlement, Portikus, RFQ) is reviewed by at least one independent security firm before deployment. Reports are publicly disclosed. ### Formal verification Augustus v6.1 underwent **formal verification by Certora**, mathematically proving correctness for critical invariants. To our knowledge, ParaSwap was the first DEX aggregator to ship a formally-verified router. ### Continuous monitoring Live monitoring on production contracts detects abnormal flows, suspicious transaction patterns, and unexpected state transitions. Emergency pause mechanisms are in place for critical surfaces. ## Web2 security Annual third-party penetration testing covers the Velora API, the partner portal, and supporting backend infrastructure. ## Reporting a vulnerability Found something? Email [security@velora.xyz](mailto:security@velora.xyz) with a clear description, reproduction steps, affected surfaces, and your assessment of impact. Do not file public issues or post details on social media until the team has acknowledged the report and coordinated disclosure. ## Related pages * [Augustus v6.2 audits](/docs/resources/security/audits/augustus-v6-2) * [Augustus v6.1 audits](/docs/resources/security/audits/augustus-v6-1) * [Chains & contracts](/docs/resources/chains-and-contracts) # AugustusRFQ audit report Source: https://new-docs.velora.xyz/docs/resources/security/audits/augustus-rfq Independent audit of the AugustusRFQ contracts for ERC-20 OTC settlement. The AugustusRFQ contracts (used for ERC-20 OTC settlement on Velora) were audited by an independent security firm. Limit orders are Delta orders. ## Audits RFQ contracts security review ## Scope The RFQ audit covers the AugustusRFQ contract suite for ERC-20 OTC settlement. NFT settlement paths have been removed from production and are out of scope. ## Related pages * [Audits overview](/docs/resources/security/audits) * [AugustusRFQ API](/docs/api-reference/rfq/overview) * [Limit orders](/docs/overview/product-stack/limit-orders) # Augustus v5 audit reports Source: https://new-docs.velora.xyz/docs/resources/security/audits/augustus-v5 Independent audits of the Augustus v5 aggregator router. Augustus v5 (the production aggregator router prior to v6) was reviewed by independent security firms before deployment. ## Audits v5 security review v5 security review ## Scope Augustus v5 audits cover the v5 router, fee logic, and supported swap methods. ## Related pages * [Augustus v6.1 audits](/docs/resources/security/audits/augustus-v6-1) * [Audits overview](/docs/resources/security/audits) * [Chains & contracts](/docs/resources/chains-and-contracts) # Augustus v6.1 audit reports Source: https://new-docs.velora.xyz/docs/resources/security/audits/augustus-v6-1 Five independent audits plus formal verification by Certora, a first for DEX aggregators. Augustus v6.1 went through one of the most comprehensive audit programs in DEX aggregator history: five independent firms reviewed the contracts, and Certora delivered a formal verification, making ParaSwap the first DEX aggregator to ship a formally-verified router. ## Audits **Formal verification.** Mathematical proofs of critical contract invariants, a first for DEX aggregators. Independent security review of the Augustus v6.1 contract suite. Independent security review of the Augustus v6.1 contract suite. Independent security review of the Augustus v6.1 contract suite. Independent security review of the Augustus v6.1 contract suite. ## Formal verification Certora's formal verification proves that core invariants of Augustus v6.1 hold for *every* possible input, not just the ones a manual auditor tested. This is the strongest correctness guarantee available short of a full mathematical proof of the whole system, and at the time it was a first for any DEX aggregator. ## Scope The five-firm audit set covered the full Augustus v6.1 router, fee distribution, partner integrations, and supported swap methods. ## Related pages * [Augustus v6.2 audits](/docs/resources/security/audits/augustus-v6-2) * [Augustus v5 audits](/docs/resources/security/audits/augustus-v5) * [Audits overview](/docs/resources/security/audits) # Augustus v6.2 audit reports Source: https://new-docs.velora.xyz/docs/resources/security/audits/augustus-v6-2 Independent audits for Augustus v6.2: fee-claiming refinements on top of the v6.1 audit baseline. Augustus v6.2 refines the partner fee-claiming flow on top of v6.1 with minimal contract surface changes. The [v6.1 audits](/docs/resources/security/audits/augustus-v6-1) therefore remain applicable; three additional independent firms reviewed the v6.2 delta. ## Audits Review of the v6.2 fee-claiming changes. Independent review of the v6.2 delta over v6.1. Independent review of the v6.2 delta over v6.1. ## Scope Augustus v6.2 audits focused on the fee-claiming flow changes since v6.1. All other invariants are covered by the [v6.1 audit set](/docs/resources/security/audits/augustus-v6-1). ## Related pages * [Augustus v6.1 audits](/docs/resources/security/audits/augustus-v6-1) * [Audits overview](/docs/resources/security/audits) * [Chains & contracts](/docs/resources/chains-and-contracts) # Velora tools and status Source: https://new-docs.velora.xyz/docs/resources/tools Velora tools for tracking orders, checking API status, and getting help. Three tools sit alongside the API. Check the status page when a call behaves unexpectedly and you want to rule out an outage. Open the Explorer to follow an order or transaction through to settlement. Head to the Help Center when you need support or a walkthrough. Live API uptime and incident history. Look up any Market swap or Delta order by transaction hash or order ID. Support, FAQs, and integration guides. # Choose a Velora SDK variant Source: https://new-docs.velora.xyz/docs/sdk/choose-a-variant Pick between Simple, Full, and Partial SDK constructors based on bundle size, API shape, and how much wiring you want to do. The SDK ships three constructors that wrap the same per-method `construct*` primitives. They differ in how much of the SDK comes pre-wired and what the resulting API surface looks like. ## At a glance | | Simple | Full | Partial | | ---------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | | Constructor | `constructSimpleSDK` | `constructFullSDK` | `constructPartialSDK` | | API shape | Namespaced: `sdk.swap.getRate(...)`, `sdk.delta.submitDeltaOrder(...)`, `sdk.quote.getQuote(...)` | Same namespaces, typed against your transaction-response generic (`sdk.swap.*`, `sdk.delta.*`) | Flat: `sdk.getRate(...)`, `sdk.approveToken(...)`. Whatever you import is what you get. | | Bundle size | Includes every module | Includes every module | Tree-shaken to the constructors you import | | Provider wiring | Pass `{ axios }` or `{ fetch }` and (optionally) `providerOptions`; SDK builds the fetcher and contract caller for you | You build `fetcher` and `contractCaller` and pass them in | You build `fetcher` and `contractCaller` and pass them in | | `` generic | Returns `TxHash` (string) for write calls | You choose: viem `Hex`, `ethers.ContractTransaction`, etc. | Inherits from the `contractCaller` you pass | | Best for | Quickstarts, server-side scripts, integrators who want one import | Apps that use most modules and want typed transaction responses | Bundle-size-sensitive front-ends | ## Pick by use case * **"I just want a quote and a swap."** Use the **Simple SDK**: one constructor, ready to call. * **"I have a Node service that does Delta orders, Market Swaps, and price polling."** Use the **Full SDK**. You get namespaced access plus a typed `` so your code knows what `approveToken` returns. * **"I'm shipping a front-end and only sign Delta orders."** Use the **Partial SDK**: import `constructBuildDeltaOrder`, `constructSignDeltaOrder`, `constructPostDeltaOrder` and tree-shake the rest. * **"I want a custom HTTP client (got, undici, superagent…)."** All three variants accept a custom `fetcher`. See [Configure providers](/docs/sdk/configure-providers#custom-fetcher). ## What stays the same Every variant ultimately calls the same `construct*` factories under [`@velora-dex/sdk` `src/methods/`](https://github.com/VeloraDEX/sdk/tree/master/src/methods). That means: * Same method signatures across variants: `getRate`, `buildDeltaOrder`, `submitDeltaOrder`, etc. behave identically. * Same partner-fee handling. See [Monetize](/docs/sdk/monetize). * Same retries, errors, and `FetcherError` semantics regardless of constructor. ## Related pages `constructSimpleSDK`: one constructor, sensible defaults. `constructFullSDK`. Namespaced, with typed transaction responses. `constructPartialSDK`: cherry-pick constructors, tree-shake the rest. # Configure SDK wallet providers Source: https://new-docs.velora.xyz/docs/sdk/configure-providers Wire your wallet library (viem, ethers v5/v6, web3) and HTTP client (axios, fetch, custom) into the SDK. The SDK separates **what** (the Velora methods) from **how it talks to the chain and the API**. You wire two things: * A **contract caller** bridges between the SDK's `transactCall` / `signTypedDataCall` / `staticCall` interface and your wallet library. * A **fetcher** bridges between the SDK's `FetcherFunction` and your HTTP client. [Simple SDK](/docs/sdk/simple-sdk) builds both for you from a single options object. [Full SDK](/docs/sdk/full-sdk) and [Partial](/docs/sdk/partial-sdk) SDKs take them as constructor arguments. ## Contract callers ### viem ```ts theme={null} import { createWalletClient, custom } from "viem"; import { mainnet } from "viem/chains"; import { constructViemContractCaller } from "@velora-dex/sdk"; const walletClient = createWalletClient({ chain: mainnet, transport: custom(window.ethereum!), }); const [account] = await walletClient.getAddresses(); const contractCaller = constructViemContractCaller(walletClient, account); ``` Write methods resolve to a viem `Hex` (the transaction hash). For sending the result of `sdk.swap.buildTx` via viem, the SDK exports `txParamsToViemTxParams` to cast all string-numbers to `BigInt`: ```ts theme={null} import { txParamsToViemTxParams } from "@velora-dex/sdk"; const tx = await sdk.swap.buildTx({ /* ... */ }); const viemTx = txParamsToViemTxParams(tx); const hash = await walletClient.sendTransaction({ ...viemTx, account }); ``` ### ethers v5 ```ts theme={null} import { ethers } from "ethers"; import { constructEthersContractCaller } from "@velora-dex/sdk"; const contractCaller = constructEthersContractCaller( { ethersProviderOrSigner: signer, // JsonRpcProvider, Wallet, or Web3Provider EthersContract: ethers.Contract, }, account, ); ``` Write methods resolve to `ethers.ContractTransaction`. You can call `.wait()` directly on the result. ### ethers v6 ```ts theme={null} import { ethers } from "ethers"; import { constructEthersV6ContractCaller } from "@velora-dex/sdk"; const contractCaller = constructEthersV6ContractCaller( { ethersV6ProviderOrSigner: signer, EthersV6Contract: ethers.Contract, }, account, ); ``` Write methods resolve to ethers v6's `ContractTransactionResponse`. ### web3.js ```ts theme={null} import Web3 from "web3"; import { constructWeb3ContractCaller } from "@velora-dex/sdk"; const web3 = new Web3(Web3.givenProvider); const contractCaller = constructWeb3ContractCaller(web3, account); ``` Write methods resolve to web3's `PromiEvent`. Listen on `transactionHash` for early notification: ```ts theme={null} const eventfulTx = await sdk.swap.approveToken(amount, USDC); eventfulTx.once("transactionHash", (hash: string) => console.log("tx sent:", hash), ); ``` ## Fetchers ### axios ```ts theme={null} import axios from "axios"; import { constructAxiosFetcher } from "@velora-dex/sdk"; const fetcher = constructAxiosFetcher(axios); ``` ### fetch (Node 18+ and the browser) ```ts theme={null} import { constructFetchFetcher } from "@velora-dex/sdk"; const fetcher = constructFetchFetcher(fetch); ``` ### Custom fetcher Any HTTP client works: implement `FetcherFunction` and pass it through. Useful for adding retries, logging, header injection, or wrapping an unusual transport. ```ts theme={null} import { constructSimpleSDK, type FetcherFunction } from "@velora-dex/sdk"; const customFetcher: FetcherFunction = async (options) => { // requestParams may include AbortSignal; honor it for cancellation const res = await myHttpClient(options.url, { method: options.method, headers: options.headers, body: options.method === "POST" ? options.data : undefined, signal: options.requestParams?.signal, }); if (!res.ok) throw new Error(`HTTP ${res.status}`); return res.body; }; const sdk = constructSimpleSDK({ chainId: 1, fetcher: customFetcher, }); ``` For richer error semantics, throw a `FetcherError` and the SDK will re-throw it untouched so calling code can `isFetcherError(err)` and inspect the response. ## wagmi recipe If your app already uses [wagmi](https://wagmi.sh), reuse the viem wallet client it manages: ```ts theme={null} import axios from "axios"; import { useConnection, useWalletClient } from "wagmi"; import { constructPartialSDK, constructAxiosFetcher, constructViemContractCaller, constructGetRate, constructBuildTx, constructApproveToken, } from "@velora-dex/sdk"; const fetcher = constructAxiosFetcher(axios); function useVeloraSDK() { const { address } = useConnection(); const { data: walletClient } = useWalletClient(); if (!walletClient || !address) return null; const contractCaller = constructViemContractCaller(walletClient, address); return constructPartialSDK( { chainId: walletClient.chain.id, fetcher, contractCaller, }, constructGetRate, constructBuildTx, constructApproveToken, ); } ``` Memoize the result (with `useMemo` on the wallet client and address) to avoid rebuilding the SDK on every render. ## Related pages * [Install](/docs/sdk/install) covers peer dependencies for each wallet library. * [Simple SDK](/docs/sdk/simple-sdk): uses these callers and fetchers via a single options object. * [Full SDK](/docs/sdk/full-sdk) — takes the caller and fetcher you construct here. * [Partial SDK](/docs/sdk/partial-sdk), same wiring, smallest bundle. # Full SDK constructor Source: https://new-docs.velora.xyz/docs/sdk/full-sdk constructFullSDK gives you every namespace (sdk.swap, sdk.delta, sdk.quote) over a fetcher and contract caller you construct yourself, with a typed transaction-response generic. `constructFullSDK` returns the same namespaced API as the [Simple SDK](/docs/sdk/simple-sdk) (`sdk.swap.*`, `sdk.delta.*`, `sdk.quote`), but you construct the fetcher and contract caller yourself. That extra wiring buys you a typed `` generic and the freedom to share one caller across multiple SDK instances or chains. ## When to use this * You want write methods to return your wallet library's native response type (e.g., viem `Hex` or `ethers.ContractTransaction`) instead of a bare transaction hash. * You need one `contractCaller` to back several SDKs — for example, the same signer used on mainnet (`chainId: 1`) and Optimism (`chainId: 10`). * You're building infrastructure that abstracts the fetcher (custom retry, caching, logging) and don't want the Simple SDK to wrap it. If none of those apply, prefer the [Simple SDK](/docs/sdk/simple-sdk); it has fewer moving parts. ## Construct it ```ts theme={null} import axios from "axios"; import { createWalletClient, custom } from "viem"; import { mainnet } from "viem/chains"; import { constructFullSDK, constructAxiosFetcher, constructViemContractCaller, } from "@velora-dex/sdk"; const walletClient = createWalletClient({ chain: mainnet, transport: custom(window.ethereum!), }); const [account] = await walletClient.getAddresses(); const contractCaller = constructViemContractCaller(walletClient, account); const fetcher = constructAxiosFetcher(axios); const sdk = constructFullSDK({ chainId: 1, fetcher, contractCaller, }); ``` Swap the contract-caller line for `constructEthersContractCaller`, `constructEthersV6ContractCaller`, or `constructWeb3ContractCaller` to use a different wallet library. See [Configure providers](/docs/sdk/configure-providers) for each variant. ## Typed transaction responses The `` generic is the type that every write method returns. It's inferred from the contract caller you pass. | Contract caller | `` | | ------------------------------------ | ---------------------------------------- | | `constructViemContractCaller` | viem `Hex` (the transaction hash) | | `constructEthersContractCaller` (v5) | `ethers.ContractTransaction` | | `constructEthersV6ContractCaller` | ethers v6 `ContractTransactionResponse` | | `constructWeb3ContractCaller` | web3.js `PromiEvent` | So with the viem caller above: ```ts theme={null} // type Promise const hash = await sdk.swap.approveToken("10000000000", USDC); console.log("approval submitted:", hash); ``` ## What's available The namespaces are identical to [Simple SDK](/docs/sdk/simple-sdk#available-methods): * `sdk.delta`: full Delta lifecycle — `getDeltaPrice`, `submitDeltaOrder`, build/sign/post split, `getDeltaOrders` (paginated), `cancelDeltaOrders`, plus approve/preSign. * `sdk.quote` exposes `getQuote`. * `sdk.swap`: rate, build, approve, balances, spender, tokens, adapters, swapTx (Market execution path for swaps). * `sdk.otcOrders` exposes the AugustusRFQ maker/taker orders used for OTC; see [OTC](/docs/sdk/products/otc). See [Swaps → Delta](/docs/sdk/products/delta) and [Swaps → Market](/docs/sdk/products/swap) for end-to-end flows. ## Sharing one caller across chains Because you own the caller, you can reuse it: ```ts theme={null} const baseConfig = { fetcher, contractCaller }; const mainnet = constructFullSDK({ ...baseConfig, chainId: 1 }); const optimism = constructFullSDK({ ...baseConfig, chainId: 10 }); ``` ## Related pages Drop unused modules entirely with `constructPartialSDK`. All four contract callers and both fetchers, with examples. The full Delta order lifecycle, including the split build/sign/post flow. Market-Swap walkthrough using the namespaced SDK. # Install @velora-dex/sdk Source: https://new-docs.velora.xyz/docs/sdk/install Install @velora-dex/sdk and fetch your first quote in under five minutes. The Velora SDK is published as [`@velora-dex/sdk`](https://www.npmjs.com/package/@velora-dex/sdk). It has no required runtime dependencies; `viem`, `ethers`, `web3`, and `axios` are all optional peers that the SDK detects at construction time. ## Install the package ```bash pnpm theme={null} pnpm add @velora-dex/sdk ``` ```bash npm theme={null} npm install @velora-dex/sdk ``` ```bash yarn theme={null} yarn add @velora-dex/sdk ``` ### Peer dependencies Pick whichever wallet library and HTTP client you already use. All of these are optional peers, so install only the ones you need. | Package | Version | When you need it | | -------- | -------------------- | --------------------------------------------------------------------------------------- | | `viem` | `^2.21.0` | If you sign and submit transactions with viem. | | `ethers` | `^5.5.0` or `^6.0.0` | If you sign and submit transactions with ethers. | | `web3` | `^4.14.0` | If you sign and submit transactions with web3.js. | | `axios` | `>=0.25.0 <2.0.0` | If you wire the SDK fetcher to axios. (Use the built-in `fetch` instead to avoid this.) | You can use the SDK in **read-only mode** without any of these. Pass `{ chainId, fetch }` (or `{ chainId, axios }`) and the SDK can call every API method (quotes, prices, order status), but it cannot sign or submit transactions. ## Your first call The smallest possible setup: quote 10,000 USDC → ETH on mainnet using native `fetch`. ```ts theme={null} import { constructSimpleSDK } from "@velora-dex/sdk"; const simpleSDK = constructSimpleSDK({ chainId: 1, fetch }); const priceRoute = await simpleSDK.swap.getRate({ srcToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC destToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", // ETH amount: "10000000000", // 10,000 USDC (6 decimals) userAddress: "0x0000000000000000000000000000000000000000", side: "SELL", options: { partner: "my-app-name" }, }); console.log(priceRoute.srcAmount, "→", priceRoute.destAmount); ``` ## Verify it works The returned `priceRoute` contains at minimum: * `srcAmount`: the input amount you passed (echoed for confirmation). * `destAmount` is the expected output amount in destination-token wei. * `bestRoute`, the resolved swap path across DEXes. * `gasCost` and `gasCostUSD`: estimated execution gas. If the call throws with `Network Error` or a 4xx response, double-check `chainId`, `partner`, and that your firewall allows outbound HTTPS to the Velora API. ## Add a wallet to send transactions Pass a `providerOptions` argument to enable `approveToken`, `submitDeltaOrder`, and `buildTx`-then-send flows. The shape varies by library; see [Configure providers](/docs/sdk/configure-providers) for the four supported stacks (viem, ethers v5, ethers v6, web3). ## Next steps Full Delta order flow: build → sign → post → poll. Wire up viem, ethers, or web3 for signing and transactions. # Monetize SDK swaps Source: https://new-docs.velora.xyz/docs/sdk/monetize Earn revenue from every swap routed through Velora using either partner fees or surplus sharing. Every quote, swap, and Delta call accepts a `partner` string and optional fee overrides. The fee is collected on-chain at settlement and routed to your partner address, with no extra integration needed. ## Quick setup If you've registered your partner key with Velora, just pass `partner` and the server resolves the fee config: ```ts theme={null} const auction = await sdk.delta.submitDeltaOrder({ route: price.route, side: price.side, owner: account, partner: "my-app-name", slippage: 50, deadline: Math.floor(Date.now() / 1000) + 60 * 60, // required, unix seconds }); ``` To override the registered defaults per call, pass the fee fields directly: ```ts theme={null} const auction = await sdk.delta.submitDeltaOrder({ route: price.route, side: price.side, owner: account, partner: "my-app-name", partnerAddress: "0xYourFeeCollector", partnerFeeBps: 25, // 0.25% partnerTakesSurplus: false, slippage: 50, deadline: Math.floor(Date.now() / 1000) + 60 * 60, // required, unix seconds }); ``` Delta sends `partner` / `partnerAddress` / `partnerFeeBps` straight to the server, which resolves and validates them in one call and encodes the fee into the on-chain order, so no local round-trip is needed. If you need to obtain the registered defaults programmatically (e.g., to show "0.25% fee" in your UI), call `getPartnerFee` directly: ```ts theme={null} const { partnerAddress, partnerFee, takeSurplus } = await sdk.delta.getPartnerFee({ partner: "my-app-name" }); ``` ## Fields | Field | Type | Description | | --------------------- | --------- | ------------------------------------------------------------------------------------------------------- | | `partner` | `string` | Your partner-key string (e.g. `"my-app-name"`). Used for attribution; required for partner features. | | `partnerAddress` | `string` | Optional. Ethereum address that receives the fee. Overrides the address registered for `partner`. | | `partnerFeeBps` | `number` | Optional. Fee in basis points. `25` = 0.25%. Max `200` (2%). | | `partnerTakesSurplus` | `boolean` | Optional. When `true`, you receive a share of swap surplus instead of a fixed fee. Defaults to `false`. | **Precedence.** If both `partnerFeeBps` and `partnerTakesSurplus` are set, `partnerFeeBps` wins. To take surplus instead, set `partnerTakesSurplus: true` and **omit** `partnerFeeBps`. ## Fee vs surplus: which to pick A fixed fee gives predictable per-trade revenue but worsens the user-facing quote; a surplus share is variable but leaves the quote untouched. For the full comparison (including how the split between partner, user, and Velora differs across Delta and Market), see [Monetization](/docs/overview/monetization). ## Where it applies * **Delta**: pass `partner` (and overrides) to `sdk.delta.getDeltaPrice`, `sdk.delta.submitDeltaOrder`, `sdk.delta.buildDeltaOrder`, and `sdk.delta.postDeltaOrder`. The server encodes the fee into the on-chain order. * **Market Swap**: pass `partner` to `sdk.swap.getRate` (inside `options: { partner }`) and `sdk.swap.buildTx` (top-level). Fee is taken from the destination token at settlement. * **Quote**: pass `partner` to `sdk.quote.getQuote`. The returned `priceRoute` / `deltaPrice` already accounts for the fee, so the `destAmount` you show users is the net amount. The fee is collected on-chain at settlement; there is no off-chain accounting step on your side. ## Production tips * **Load `partner` from an environment variable.** Different builds (staging, production, white-label) can use different keys without code changes. * **Audit `partnerAddress`.** Once a swap settles, fees pay to that address on-chain. Treat it like any treasury address. * **Don't ship per-call overrides** unless you genuinely vary fees by route or user tier. Registering defaults with Velora keeps your client code simpler and lets you adjust fees without redeploying. ## Related pages * [Pro API accounts](/docs/overview/pro-api-accounts): register a partner key and set defaults. * [Widget → Monetize](/docs/widget/monetize) — same fee mechanics for the embeddable widget. * [Swaps → Delta](/docs/sdk/products/delta) covers the full Delta order flow with partner attribution. * [Swaps → Market](/docs/sdk/products/swap), the full Market-Swap flow with partner attribution. # Velora SDK for TypeScript Source: https://new-docs.velora.xyz/docs/sdk/overview Use [@velora-dex/sdk](https://www.npmjs.com/package/@velora-dex/sdk) to integrate quotes, swaps, limit orders, and Delta intents from JavaScript or TypeScript. `@velora-dex/sdk` is a TypeScript SDK for the Velora API. It wraps the [Delta](/docs/delta/overview) and [Market](/docs/market/overview) endpoints into typed methods, leaves your wallet library (`viem`, `ethers`, or `web3`) and HTTP client (`axios` or `fetch`) up to you, and ships in three construction shapes so you only pay for what you import. ## What you get Works with [viem](/docs/sdk/configure-providers#viem), [ethers](/docs/sdk/configure-providers#ethers-v5) (v5 or v6), or [web3.js](/docs/sdk/configure-providers#web3-js). Bring whichever stack you already use. Three entry points (Simple, Full, Partial) over the same `construct*` primitives. Pick one to import only the methods you call. 10 KB gzipped for the minimal variant. Tree-shake the rest at build time. ## Quick example Fetch a Delta-or-market quote and submit the order in one flow: ```ts theme={null} import axios from "axios"; import { createWalletClient, custom } from "viem"; import { mainnet } from "viem/chains"; import { constructSimpleSDK, txParamsToViemTxParams } from "@velora-dex/sdk"; const walletClient = createWalletClient({ chain: mainnet, transport: custom(window.ethereum!), }); const [account] = await walletClient.getAddresses(); const simpleSDK = constructSimpleSDK( { chainId: 1, axios }, { viemClient: walletClient, account }, ); const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; const ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; const amount = "10000000000"; // 10,000 USDC const slippageBps = 50; // 0.5% const quote = await simpleSDK.quote.getQuote({ srcToken: USDC, destToken: ETH, amount, userAddress: account, srcDecimals: 6, destDecimals: 18, mode: "all", // try Delta first, fall back to Market side: "SELL", partner: "my-app-name", }); if ("delta" in quote) { await simpleSDK.delta.approveTokenForDelta(amount, USDC); const auction = await simpleSDK.delta.submitDeltaOrder({ route: quote.delta.route, side: quote.delta.side, owner: account, slippage: slippageBps, // SDK applies slippage for you deadline: Math.floor(Date.now() / 1000) + 60 * 60, // required, unix seconds partner: "my-app-name", }); } else { const tx = await simpleSDK.swap.buildTx({ srcToken: USDC, destToken: ETH, srcAmount: amount, slippage: slippageBps, priceRoute: quote.market, userAddress: account, partner: "my-app-name", }); const hash = await walletClient.sendTransaction({ ...txParamsToViemTxParams(tx), account, }); } ``` ## How it works All three entry points are thin orchestrators over the same per-method `construct*` factories. Pick the shape that matches how much of the SDK you actually use: ```mermaid theme={null} graph TD A["constructSimpleSDK
(namespaced: sdk.swap / sdk.delta / sdk.quote / sdk.otcOrders)"] --> C B["constructFullSDK
(namespaced, full control)"] --> C D["constructPartialSDK
(cherry-picked, tree-shaken)"] --> C C["construct* feature factories
(GetRate, BuildTx, BuildDeltaOrder, GetQuote, ...)"] C --> E["Fetcher: axios / fetch / custom"] C --> F["Contract caller: viem / ethers v5 / v6 / web3"] ``` * **Simple** auto-wires the fetcher and contract caller from a single options object. Best for quickstarts and server-side scripts. * **Full** exposes the same methods namespaced (`sdk.swap.*`, `sdk.delta.*`) but lets you construct the fetcher and caller yourself, including a custom transaction-response type. * **Partial** is the tree-shaken variant: pass in only the `construct*` functions you import, and TypeScript infers the resulting SDK shape from your selection. ## Pick your starting point Add `@velora-dex/sdk` and get the first quote in under five minutes. Simple vs Full vs Partial: bundle size, API shape, when to pick each. One constructor, sensible defaults, every method available. Wire up viem, ethers, or web3, then choose your HTTP client. ## Related pages * [Why Velora](/docs/overview/why-velora): when to reach for the SDK vs the API or widget. * [Migration from `@paraswap/sdk`](/docs/resources/migrations/paraswap-sdk-to-velora-sdk): upgrade the legacy package to `@velora-dex/sdk`. * [API reference](/docs/api-reference/introduction) — the HTTP endpoints the SDK wraps. # Partial SDK constructor Source: https://new-docs.velora.xyz/docs/sdk/partial-sdk constructPartialSDK lets bundle-size-sensitive apps import only the construct* functions they call; TypeScript infers the resulting SDK shape from the selection. `constructPartialSDK` is the tree-shaken entry point. You pick which per-method `construct*` factories you care about, and the resulting SDK has only those methods on it. TypeScript infers the return type from your selection, so calls into unused modules don't compile, and the bundler drops the unused code. ## When to pick this * You're shipping a browser bundle and every kilobyte counts. * You only use a small slice of the SDK, e.g. just `getRate` + `approveToken`, or just the Delta signing flow. * You want compile-time guarantees that your build doesn't accidentally call a method you didn't intend to ship. If you use most of the SDK or run server-side, prefer [Simple SDK](/docs/sdk/simple-sdk) or [Full SDK](/docs/sdk/full-sdk). ## Example: rates and approvals only The smallest useful Partial SDK: read rates from the API, approve tokens for swaps. ```ts theme={null} import axios from "axios"; import { createWalletClient, custom } from "viem"; import { mainnet } from "viem/chains"; import { constructPartialSDK, constructAxiosFetcher, constructViemContractCaller, constructGetRate, constructApproveToken, } from "@velora-dex/sdk"; const walletClient = createWalletClient({ chain: mainnet, transport: custom(window.ethereum!), }); const [account] = await walletClient.getAddresses(); const fetcher = constructAxiosFetcher(axios); const contractCaller = constructViemContractCaller(walletClient, account); const sdk = constructPartialSDK( { chainId: 1, fetcher, contractCaller, }, constructGetRate, constructApproveToken, ); // type is inferred from your selection; only these two methods exist const priceRoute = await sdk.getRate({ srcToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC destToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", // ETH amount: "10000000000", userAddress: account, side: "SELL", }); const hash = await sdk.approveToken( "10000000000", "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", ); ``` ## Example: Delta signing only A front-end that signs Delta orders but does no other reads or writes. The Delta constructors are exported bare from the package root: ```ts theme={null} import { constructPartialSDK, constructAxiosFetcher, constructViemContractCaller, constructGetDeltaPrice, constructBuildDeltaOrder, constructSignDeltaOrder, constructPostDeltaOrder, constructApproveTokenForDelta, } from "@velora-dex/sdk"; const fetcher = constructAxiosFetcher(axios); const contractCaller = constructViemContractCaller(walletClient, account); const deltaSDK = constructPartialSDK( { chainId: 1, fetcher, contractCaller }, constructGetDeltaPrice, constructBuildDeltaOrder, constructSignDeltaOrder, constructPostDeltaOrder, constructApproveTokenForDelta, ); const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; const ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; const amount = "10000000000"; const price = await deltaSDK.getDeltaPrice({ srcToken: USDC, destToken: ETH, amount, srcDecimals: 6, destDecimals: 18, userAddress: account, partner: "my-app-name", }); await deltaSDK.approveTokenForDelta(amount, USDC); const built = await deltaSDK.buildDeltaOrder({ route: price.route, side: price.side, owner: account, partner: "my-app-name", slippage: 50, // 0.5% in bps deadline: Math.floor(Date.now() / 1000) + 60 * 60, // required, unix seconds }); const signature = await deltaSDK.signDeltaOrder(built); const auction = await deltaSDK.postDeltaOrder({ order: built.toSign.value, signature, partner: "my-app-name", }); ``` Bundlers tree-shake whichever members you don't reference, so this example pulls in only the constructors above. ## Available constructors Pass any combination of these. Methods on the resulting SDK match the names listed in [Simple SDK → Available methods](/docs/sdk/simple-sdk#available-methods). All constructors are exported bare from the package root. | Module | Constructors | | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Delta | `constructGetDeltaPrice`, `constructBuildDeltaOrder`, `constructSignDeltaOrder`, `constructPostDeltaOrder`, `constructSubmitDeltaOrder` (orchestrator), `constructGetDeltaOrders`, `constructCancelDeltaOrder`, `constructApproveTokenForDelta`, `constructPreSignDeltaOrder`, `constructDeltaTokenModule`, `constructGetDeltaContract`, `constructGetPartnerFee`, `constructGetBridgeRoutes`, `constructIsTokenSupportedInDelta`, `constructGetAgentsList` | | TWAP | `constructBuildTWAPDeltaOrder`, `constructPostTWAPDeltaOrder`, `constructSubmitTWAPDeltaOrder`, `constructPreSignTWAPDeltaOrder` | | Swap | `constructGetRate`, `constructBuildTx`, `constructApproveToken`, `constructGetBalances`, `constructGetSpender`, `constructGetTokens`, `constructGetAdapters`, `constructSwapTx` | | Quote | `constructGetQuote` | The full list lives in [`src/index.ts`](https://github.com/VeloraDEX/sdk/blob/master/src/index.ts). Several constructors come in pairs. For example, `constructBuildDeltaOrder` + `constructSignDeltaOrder` + `constructPostDeltaOrder`, or `constructSubmitDeltaOrder` (which orchestrates all three). Use the orchestrator when you want one call; use the individual constructors when you need custom signing (hardware wallet, multisig, deferred submission). ## Related pages Side-by-side comparison of Simple, Full, and Partial. Construct the fetcher and contract caller you'll pass in. Delta order lifecycle, including the split build/sign/post flow. Market-Swap walkthrough using individual constructors. # Delta swaps with the SDK Source: https://new-docs.velora.xyz/docs/sdk/products/delta Submit, sign, and track gasless Delta intents from sdk.delta, where solvers compete to provide executable fills. A **swap** in Velora settles through one of two execution paths: **Delta** (this page) or [**Market**](/docs/sdk/products/swap). Delta wraps the [Delta API](/docs/delta/overview): gasless, MEV-protected swaps where the user signs an off-chain order, and a network of solvers (Portikus) competes to provide the best fill. The user pays no gas; settlement happens through the Delta flow. Delta is also the engine behind two other products in the SDK: [Limit orders](/docs/sdk/products/limit-orders) (a Delta order with a target price) and [TWAP](/docs/sdk/products/twap) (a Delta order split into scheduled slices). This page covers the **market** Delta order, and those pages build on the same flow. Delta orders are **server-built**: you don't compose EIP-712 typed data locally. `getDeltaPrice` returns a recommended `route` plus `alternatives`, `buildDeltaOrder` returns ready-to-sign typed data, and order history is paginated. ## When to use this * The user shouldn't pay gas, or doesn't have gas on the source chain. * You want MEV protection. Orders fill via private auction, not the public mempool. * You want one signed intent to settle crosschain. See [Crosschain Delta](/docs/delta/crosschain-delta). For swaps where the user submits the transaction themselves, see [Market](/docs/sdk/products/swap). ## How it's exposed Delta lives at two layers in the SDK: * **`sdk.delta.*`** is the pre-bound bag attached to `constructSimpleSDK` / `constructFullSDK`: `sdk.delta.getDeltaPrice`, `sdk.delta.submitDeltaOrder`, `sdk.delta.signDeltaOrder`, etc. This is what most consumers use. * **The bare `construct*` functions and types** are exported at the package root for advanced wiring (e.g., `constructPartialSDK`) and type annotations: `constructBuildDeltaOrder`, `constructSubmitDeltaOrder`, `constructAllDeltaOrdersHandlers`, and types like `DeltaPrice`, `DeltaRoute`, `BuiltDeltaOrder`, `DeltaAuction`, `BridgeRoute`. ## The flow Call `sdk.delta.getDeltaPrice` with source/destination tokens, amount, decimals, and partner. The response includes the recommended `route` plus `alternatives` and the contract `spender` to approve. Call `sdk.delta.approveTokenForDelta(amount, srcToken)`, or sign a Permit / Permit2 message with the Delta contract (returned in `price.spender`) as the verifying contract. Native tokens skip this step. Either call the one-shot orchestrator `sdk.delta.submitDeltaOrder`, or run the three steps yourself (`buildDeltaOrder` → `signDeltaOrder` → `postDeltaOrder`) when you need control over signing. Use `sdk.delta.getDeltaOrderById` (or `getDeltaOrderByHash`) on a timer until status is `COMPLETED`. ## One-call submit `submitDeltaOrder` runs build → sign → post in a single call. This is the recommended path for most flows. ```ts theme={null} const price = await sdk.delta.getDeltaPrice({ srcToken: USDC, destToken: ETH, amount: "10000000000", // 10,000 USDC srcDecimals: 6, destDecimals: 18, userAddress: account, partner: "my-app-name", }); await sdk.delta.approveTokenForDelta("10000000000", USDC); const auction = await sdk.delta.submitDeltaOrder({ route: price.route, side: price.side, owner: account, partner: "my-app-name", slippage: 50, // 0.5% in bps deadline: Math.floor(Date.now() / 1000) + 60 * 60, // required, unix seconds // beneficiary: anotherAccount, // optional, default = owner // permit: "0x...", // optional, if you signed a Permit instead of approving // partiallyFillable: true, // optional, default = fill-or-kill }); console.log("auction id:", auction.id); ``` ## Split flow Use the three-step flow when you need to customize signing: for example, a hardware wallet that prompts on each call, a multisig that signs asynchronously, or batched signing across orders. ```ts theme={null} const built = await sdk.delta.buildDeltaOrder({ route: price.route, side: price.side, owner: account, partner: "my-app-name", slippage: 50, deadline: Math.floor(Date.now() / 1000) + 60 * 60, // required, unix seconds }); const signature = await sdk.delta.signDeltaOrder(built); const auction = await sdk.delta.postDeltaOrder({ order: built.toSign.value, signature, partner: "my-app-name", }); ``` `buildDeltaOrder` returns `{ toSign, orderHash }`. The server has already composed the EIP-712 typed data, and `signDeltaOrder` wraps your contract caller's `signTypedData` to produce the signature. It's generic across order families, so the market, limit, and TWAP flows all sign through the same call. If your signer is a smart contract (e.g., a multisig or 4337 wallet) that can't produce an off-chain EIP-712 signature, use `sdk.delta.preSignDeltaOrder` to register the order hash on-chain instead. ## Poll for execution ```ts theme={null} import { OrderHelpers } from "@velora-dex/sdk"; const intervalId = setInterval(async () => { const updated = await sdk.delta.getDeltaOrderById(auction.id); if (OrderHelpers.checks.isExecutedAuction(updated)) { clearInterval(intervalId); console.log("filled"); } }, 3000); // stop polling after 5 minutes setTimeout(() => clearInterval(intervalId), 60_000 * 5); ``` `OrderHelpers.checks.isExecutedAuction` returns `true` only when same-chain orders show `status === "COMPLETED"`, and crosschain orders also have their destination-chain leg filled. ## List orders `getDeltaOrders` returns a paginated list filtered by user, chain, status, and order type: ```ts theme={null} const { data, page, limit, total } = await sdk.delta.getDeltaOrders({ userAddress: account, page: 1, limit: 100, // status: ["ACTIVE", "COMPLETED"], // optional filter // chainId: [1, 10], // omit for all chains // type: "MARKET", // 'MARKET' | 'LIMIT' }); ``` Each entry is a `DeltaAuction`, generic over `onChainOrderType`. It may report `'FillableOrder'` for a `partiallyFillable` Standard order; treat it exactly like `'Order'` (identical shape). Use `type: "LIMIT"` to filter for [limit orders](/docs/sdk/products/limit-orders). ## Partner fee Pass `partner` (and optionally `partnerAddress`, `partnerFeeBps`, `partnerTakesSurplus`) to `getDeltaPrice`, `submitDeltaOrder`, `buildDeltaOrder`, and `postDeltaOrder`. The SDK sends these directly to the server, which resolves and validates the fee in one call, so there's no local `getPartnerFee` round-trip. ```ts theme={null} const auction = await sdk.delta.submitDeltaOrder({ route: price.route, side: price.side, owner: account, partner: "my-app-name", partnerAddress: "0xYourFeeCollector", partnerFeeBps: 25, // 0.25% slippage: 50, deadline: Math.floor(Date.now() / 1000) + 60 * 60, // required, unix seconds }); ``` See [Monetize](/docs/sdk/monetize) for the full field reference and fee-vs-surplus tradeoffs. ## Cancel an order ```ts theme={null} await sdk.delta.cancelDeltaOrders({ orderIds: [auction.id] }); ``` This signs and posts a cancellation request. It only succeeds for orders that are still open in the auction. ## Crosschain Delta Pass `destChainId` to `getDeltaPrice` to settle on a different chain than the source. The returned `route` is bridge-aware; submitting the order is identical to same-chain. See [Crosschain Delta](/docs/delta/crosschain-delta) for the full design and [`getBridgeRoutes`](https://github.com/VeloraDEX/sdk/blob/master/src/methods/delta/getBridgeRoutes.ts) for advanced route inspection. ## Other Delta products Limit orders and TWAP are Delta orders too. They reuse this exact build → sign → post → poll flow with a couple of extra fields: * **[Limit orders](/docs/sdk/products/limit-orders)**: a Delta order with a target-price constraint and `type: "LIMIT"`. * **[TWAP](/docs/sdk/products/twap)** is a Delta order split into time-weighted slices, built with `buildTWAPDeltaOrder` / `submitTWAPDeltaOrder`. ## Migrate from V1 to V2 Only relevant if you're **upgrading an existing integration** from an older SDK version. New integrations can ignore this section; everything above already uses the current API. Delta V2 keeps the **same `sdk.delta.*` namespace and method names** as V1. What changes is that orders are now **server-built** (you no longer compose EIP-712 typed data locally), pricing is **route-based**, and order history is **paginated**. The on-chain contracts, approval flow, and signature format are unchanged. ### Pricing `getDeltaPrice` takes the same params, but the response shape changes: ```ts theme={null} const price = await sdk.delta.getDeltaPrice({ srcToken: USDC, destToken: ETH, amount, srcDecimals: 6, destDecimals: 18, userAddress: account, partner: "my-app-name", }); ``` V1 returned a flat `DeltaPrice { srcAmount, destAmount, partner, partnerFee, destToken, ... }`. V2 returns `DeltaPrice { route, alternatives, side, partner: { name, feePercent }, spender }`. Swap details now live under `price.route`, and `alternatives` lets users pick a different bridge. ### One-call submit ```diff theme={null} const auction = await sdk.delta.submitDeltaOrder({ - deltaPrice, - owner: account, - srcToken: USDC, - destToken: ETH, - srcAmount: amount, - destAmount, // you compute the slippage-adjusted destAmount - partner: "my-app-name", + route: price.route, // route carries src/dest tokens and amounts + side: price.side, + owner: account, + slippage: 50, // bps; the SDK applies slippage for you + partner: "my-app-name", }); ``` ### Split flow (build → sign → post) ```diff theme={null} - const signable = await sdk.delta.buildDeltaOrder({ /* ... */ }); - const signature = await sdk.delta.signDeltaOrder(signable); - const auction = await sdk.delta.postDeltaOrder({ - order: signable.data, + const built = await sdk.delta.buildDeltaOrder({ /* ... */ }); + const signature = await sdk.delta.signDeltaOrder(built); + const auction = await sdk.delta.postDeltaOrder({ + order: built.toSign.value, signature, partner: "my-app-name", }); ``` `buildDeltaOrder` now returns `{ toSign, orderHash }` from the server (V1 returned `SignableDeltaOrderData` with a locally-composed `.data`). `signDeltaOrder` is unchanged and is generic across the market, limit, and TWAP flows. ### Listing orders ```diff theme={null} - const orders = await sdk.delta.getDeltaOrders({ /* filter */ }); + const { data, total, hasMore } = await sdk.delta.getDeltaOrders({ + userAddress: account, + page: 1, + limit: 100, + }); ``` V1 returned a flat `DeltaAuction[]`. V2 returns a paginated `{ data, total, page, limit, hasMore }` envelope, and `userAddress` is required. ### Cancelling ```diff theme={null} - await sdk.delta.cancelLimitDeltaOrders({ orderIds: [orderId] }); + await sdk.delta.cancelDeltaOrders({ orderIds: [orderId] }); ``` ### Bridge inspection ```diff theme={null} - await sdk.delta.getBridgeInfo(/* ... */); + await sdk.delta.getBridgeRoutes(/* ... */); ``` `getBridgeRoutes` returns a flat `routes[]` array instead of V1's nested `srcChainId → destChainId → tokens[]` map. ### What stays the same * `sdk.delta.*` — same namespace and method names. * `approveTokenForDelta`, `getDeltaContract`, `preSignDeltaOrder`, and `getPartnerFee` are unchanged. * Type names (`DeltaPrice`, `DeltaAuction`, `BuiltDeltaOrder`) are still imported bare from the package root — only their shapes changed. * The on-chain order struct and signature format are identical, so V2 is just a different way to assemble the same on-chain payload. If you call the HTTP API directly rather than through the SDK, see [Delta V1 → V2 (HTTP API)](/docs/resources/migrations/delta-v1-to-v2). ## Related pages * [Market](/docs/sdk/products/swap) — the other swap execution path (user-submitted transactions). * [Limit orders](/docs/sdk/products/limit-orders): a Delta order with a target price. * [TWAP](/docs/sdk/products/twap), a Delta order split into scheduled slices. * [Why Delta](/docs/delta/overview). The protocol design. * [Monetize](/docs/sdk/monetize) — partner-fee fields. * [API reference → Delta](/docs/api-reference/delta/overview) covers the HTTP endpoints. # Limit orders with the SDK Source: https://new-docs.velora.xyz/docs/sdk/products/limit-orders Place gasless, MEV-protected limit orders from the SDK. In Velora, limit orders are Delta orders with a target-price constraint, built through sdk.delta. In Velora, a **limit order is a Delta order with a target-price constraint**. The user signs once, the [Portikus](/docs/delta/overview) solver network competes to fill it at or better than the limit price, and the user pays no gas. It's the same engine that settles Delta market orders, just with a price condition instead of immediate execution. You build limit orders through the same `sdk.delta` module as market Delta orders. The only difference is that you pin the output (the limit price) and mark the order `LIMIT` instead of letting it fill at the prevailing market rate. For the conceptual model (maker/taker, expiry, nonces, how a limit order differs from a swap or OTC), see [Product stack → Limit orders](/docs/overview/product-stack/limit-orders). ## When to use this * The user cares more about a target price than immediate settlement. They're willing to wait for the market to come to them. * You want the order to fill gaslessly and with MEV protection when the price condition is met. * You want a single signature, with no transaction to submit and nothing to babysit on-chain. For swaps that should fill at the current market rate, use a market Delta order or a [Market Swap](/docs/sdk/products/swap) instead. ## The flow The build → sign → post → poll flow is identical to a [market Delta order](/docs/sdk/products/delta), with two extra fields: the target output and the `LIMIT` type. Call `sdk.delta.getDeltaPrice` to discover the current route and the contract `spender` to approve. The market quote is your reference point for setting the limit. Call `sdk.delta.approveTokenForDelta(amount, srcToken)` so the Delta contract can pull the source token. Native tokens skip this step. Call `sdk.delta.submitDeltaOrder` with your target output and `type: "LIMIT"`, or run `buildDeltaOrder` → `signDeltaOrder` → `postDeltaOrder` yourself when you need control over signing. A limit order stays `ACTIVE` until a solver can satisfy the limit price. Poll `sdk.delta.getDeltaOrderById` until status is `COMPLETED`, or until your `deadline` passes. ## One-call submit ```ts theme={null} const price = await sdk.delta.getDeltaPrice({ srcToken: USDC, destToken: ETH, amount: "10000000000", // sell 10,000 USDC srcDecimals: 6, destDecimals: 18, userAddress: account, partner: "my-app-name", }); await sdk.delta.approveTokenForDelta("10000000000", USDC); const auction = await sdk.delta.submitDeltaOrder({ route: price.route, side: price.side, owner: account, partner: "my-app-name", type: "LIMIT", limitAmount: "3000000000000000000", // require at least 3 ETH, your limit price deadline: Math.floor(Date.now() / 1000) + 60 * 60 * 24, // expire in 24h // partiallyFillable: true, // optional, default = fill-or-kill }); console.log("limit order id:", auction.id); ``` Setting `limitAmount` above the quoted output is what makes this a limit order: it's the minimum destination amount you'll accept (your limit price), and the solver network only fills once it can deliver at least that much. A `deadline` is required; past it the order is unfillable. ## Split flow Use the three-step flow when you need to customize signing: a hardware wallet, an async multisig, or batched signing across several orders. ```ts theme={null} const built = await sdk.delta.buildDeltaOrder({ route: price.route, side: price.side, owner: account, partner: "my-app-name", limitAmount: "3000000000000000000", // minimum dest amount (3 ETH), your limit price deadline: Math.floor(Date.now() / 1000) + 60 * 60 * 24, }); const signature = await sdk.delta.signDeltaOrder(built); const auction = await sdk.delta.postDeltaOrder({ order: built.toSign.value, signature, partner: "my-app-name", type: "LIMIT", }); ``` In the split flow the limit price (`limitAmount`) is set at **build** time, while `type: "LIMIT"` is passed at **post** time. The one-call `submitDeltaOrder` above takes both together. If your signer is a smart contract that can't produce an off-chain EIP-712 signature, use `sdk.delta.preSignDeltaOrder` to register the order hash on-chain instead. ## Poll for the fill ```ts theme={null} import { OrderHelpers } from "@velora-dex/sdk"; const intervalId = setInterval(async () => { const updated = await sdk.delta.getDeltaOrderById(auction.id); if (OrderHelpers.checks.isExecutedAuction(updated)) { clearInterval(intervalId); console.log("limit order filled"); } }, 5000); ``` Unlike a market order, a limit order can rest `ACTIVE` for a long time, so poll on a relaxed interval (or drive your UI from the order list). ## List limit orders Filter the paginated order list by `type` to show a user's open limit orders: ```ts theme={null} const { data, total } = await sdk.delta.getDeltaOrders({ userAddress: account, page: 1, limit: 100, type: "LIMIT", // status: ["ACTIVE"], // optional, only open orders }); ``` ## Cancel a limit order ```ts theme={null} await sdk.delta.cancelDeltaOrders({ orderIds: [auction.id] }); ``` This signs and posts a cancellation. It only succeeds while the order is still open in the auction. ## Partner fee Pass `partner` (and optionally `partnerAddress`, `partnerFeeBps`, `partnerTakesSurplus`) to `getDeltaPrice`, `submitDeltaOrder`, `buildDeltaOrder`, and `postDeltaOrder`, exactly as with market Delta orders. See [Monetize](/docs/sdk/monetize) for the full field reference. ## Related pages * [Swaps → Delta](/docs/sdk/products/delta): the full Delta order flow this builds on. * [TWAP](/docs/sdk/products/twap), the other scheduled Delta-based order type. * [Product stack → Limit orders](/docs/overview/product-stack/limit-orders) — the conceptual model. * [API reference → Delta](/docs/api-reference/delta/overview) covers the HTTP endpoints behind the module. # OTC trades with the SDK Source: https://new-docs.velora.xyz/docs/sdk/products/otc Settle a direct trade between two known counterparties from the SDK. A maker signs an AugustusRFQ order naming a specific taker, and that taker fills it on-chain. **OTC** (over-the-counter) is a direct trade negotiated between two known counterparties rather than discovered through a public route. In the SDK it's a signed AugustusRFQ order, exposed under the `sdk.otcOrders` namespace: a **maker** signs the terms off-chain naming a specific **taker**, and only that taker can fill the order on-chain. Mechanically it's a signed on-chain order whose defining field is the **`taker`**: you name the counterparty's address, and only that address can fill the order: a private, fillable-by-one OTC trade (`P2P`). This is for **bilateral, counterparty-specific** trades. For open, target-price orders that any solver can fill, use [Limit orders](/docs/sdk/products/limit-orders) (Delta) instead; those are gasless and MEV-protected. For the conceptual difference, see [Product stack → OTC](/docs/overview/product-stack/otc). ## When to use this * The counterparty matters as much as the price: treasury rebalancing, partner deals, market-maker inventory moves. * You've agreed terms off-book and want a verifiable on-chain settlement restricted to the agreed counterparty. * You don't want the trade exposed as a public order before it settles. ## How it works OTC has two sides. The **maker** builds and signs the order (gasless, off-chain). The **taker** (the named counterparty) submits the fill transaction on-chain through the AugustusRFQ contract. The maker approves AugustusRFQ to pull the asset they're selling: `sdk.otcOrders.approveMakerTokenForOTCOrder(makerAmount, makerAsset)`. The maker builds an order naming the intended `taker`, signs the EIP-712 typed data, and posts it: `sdk.otcOrders.submitOTCOrder({ ...terms, taker })`. Posting stays off-chain, so the maker pays nothing. The taker approves AugustusRFQ for the asset they're paying with: `sdk.otcOrders.approveTakerTokenForOTCOrder(takerAmount, takerAsset)`. The taker submits the fill: `sdk.otcOrders.fillOTCOrder({ order, signature })`. AugustusRFQ verifies the signature and the named taker, then settles the swap. ## Maker: build, sign, and post ```ts theme={null} const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; const ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; // 1. Approve the asset the maker is selling await sdk.otcOrders.approveMakerTokenForOTCOrder( "10000000000", // 10,000 USDC USDC, ); // 2. Build, sign, and post in one call; `taker` is what makes it OTC const order = await sdk.otcOrders.submitOTCOrder({ maker: account, taker: counterparty, // the intended counterparty; only this address can fill makerAsset: USDC, takerAsset: ETH, makerAmount: "10000000000", // maker gives 10,000 USDC takerAmount: "3000000000000000000", // maker wants 3 ETH expiry: Math.floor(Date.now() / 1000) + 60 * 60 * 24, // 24h }); // `order` carries the signed terms + signature; hand it to the taker // (API, your backend, or any off-chain channel) ``` To split the steps (e.g. to sign with a hardware wallet), use `sdk.otcOrders.buildOTCOrder` → `sdk.otcOrders.signOTCOrder` → `sdk.otcOrders.postOTCOrder`. ## Taker: fill the order The taker receives the maker's signed order, approves the asset they're paying with, and fills on-chain: ```ts theme={null} // 1. Approve the asset the taker is paying with (skip for native ETH) await sdk.otcOrders.approveTakerTokenForOTCOrder( order.takerAmount, order.takerAsset, ); // 2. Fill directly against AugustusRFQ const tx = await sdk.otcOrders.fillOTCOrder({ order, // the maker's order data signature: order.signature, // the maker's signature }); ``` The fill reverts if the order is expired, already filled, or the caller isn't the named taker, so always re-check `expiry` against the current block before submitting. ## Query and cancel ```ts theme={null} // Maker: list your OTC orders const mine = await sdk.otcOrders.getOTCOrders({ maker: account }); // Taker: list orders addressed to you const forMe = await sdk.otcOrders.getOTCOrders({ taker: account }); // Maker: cancel an unfilled order on-chain await sdk.otcOrders.cancelOTCOrder(orderHash); ``` Cancellation here is an on-chain call to AugustusRFQ, so it costs gas, unlike the gasless `cancelDeltaOrders` flow for Delta orders. `sdk.otcOrders.getOTCOrdersContract()` returns the AugustusRFQ address for the active chain; see [Chains & contracts](/docs/resources/chains-and-contracts) for all deployments. ## Related pages * [Limit orders](/docs/sdk/products/limit-orders): open, gasless target-price orders (Delta). * [Product stack → OTC](/docs/overview/product-stack/otc), the conceptual model. * [API reference → AugustusRFQ](/docs/api-reference/rfq/overview) — the underlying order surface. * [Chains & contracts](/docs/resources/chains-and-contracts) for AugustusRFQ deployment addresses. # Market swaps with the SDK Source: https://new-docs.velora.xyz/docs/sdk/products/swap Build, approve, and execute Market Swaps through sdk.swap. The user submits the transaction themselves. A **swap** in Velora settles through one of two execution paths: [**Delta**](/docs/sdk/products/delta) or **Market** (this page). Market is the atomic on-chain path. It wraps the [Market API](/docs/market/overview) for rates, allowances, and transaction-building, and the **user** signs and submits the transaction themselves. For gasless swaps that settle from a signed intent, see [Delta](/docs/sdk/products/delta). This path is exposed as `sdk.swap` in code (the namespace predates the Delta/Market naming). `sdk.swap` is the Market execution path for swaps. ## When to use this * The user has gas on the source chain and is happy to submit a transaction. * You need the cheapest path across DEX aggregation (no auction, no off-chain settlement). * You want full control over slippage, gas, and recipient. * You don't need crosschain or MEV-protected settlement. See [Delta](/docs/sdk/products/delta) for that. ## The flow Call `sdk.swap.getRate` (or `sdk.quote.getQuote` with `mode: 'market'`) to choose source token, destination token, amount, and side. The response includes the routed path and expected output. Call `sdk.swap.approveToken` so the `TokenTransferProxy` can pull the source token, or sign a Permit / Permit2 message with `TokenTransferProxy` as the verifying contract. Call `sdk.swap.buildTx` with the price route, slippage (or `destAmount`), user address, and `partner`. The response is a fully-populated `TransactionRequest`. Pass the result of `buildTx` to your signer's `sendTransaction`. The SDK is no longer in the loop after this; you own the broadcast. ## Full example ```ts theme={null} import axios from "axios"; import { createWalletClient, custom } from "viem"; import { mainnet } from "viem/chains"; import { constructSimpleSDK, txParamsToViemTxParams } from "@velora-dex/sdk"; const walletClient = createWalletClient({ chain: mainnet, transport: custom(window.ethereum!), }); const [account] = await walletClient.getAddresses(); const sdk = constructSimpleSDK( { chainId: 1, axios }, { viemClient: walletClient, account } ); const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; const ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; const amount = "10000000000"; // 10,000 USDC // 1. Quote const priceRoute = await sdk.swap.getRate({ srcToken: USDC, destToken: ETH, amount, userAddress: account, side: "SELL", options: { partner: "my-app-name" }, }); // 2. Approve await sdk.swap.approveToken(amount, USDC); // 3. Build the swap transaction const tx = await sdk.swap.buildTx({ srcToken: USDC, destToken: ETH, srcAmount: amount, slippage: 50, // 0.5% in basis points priceRoute, userAddress: account, partner: "my-app-name", // receiver: "0x..." // optional, if the recipient differs from userAddress }); // 4. Send it const hash = await walletClient.sendTransaction({ ...txParamsToViemTxParams(tx), account, }); console.log("swap submitted:", hash); ``` ### Sign a Permit instead of approving If the source token supports EIP-2612 (or Permit2), skip the on-chain approval and sign a typed-data message with the `TokenTransferProxy` as the verifying contract. ```ts theme={null} const tokenTransferProxy = await sdk.swap.getSpender(); // build EIP-712 typed data with verifyingContract = tokenTransferProxy // pass the signature as `permit` to buildTx ``` See the [Build parameters for transaction](/docs/api-reference/market/transactions) endpoint for the supported permit variants. ## Other methods * `sdk.swap.getSpender()` returns the `TokenTransferProxy` address you approve. * `sdk.swap.getBalances(userAddress)`: token balances and allowances in one call. * `sdk.swap.getTokens()` lists Velora-supported tokens on the active chain. * `sdk.swap.getAdapters()` returns the DEX adapters available to the router. * `sdk.swap.swapTx(params)` is a one-call orchestrator (rate + build + send). Convenience over the four-step flow. ## Partner fee Add `partner` (and optionally `partnerAddress`, `partnerFeeBps`, `partnerTakesSurplus`) to every `getRate`, `buildTx`, and `getQuote` call to capture revenue. See [Monetize](/docs/sdk/monetize) for the full field reference. ## Related pages * [Swaps → Delta](/docs/sdk/products/delta): gasless intent-based swaps. * [Monetize](/docs/sdk/monetize) — partner-fee fields and tradeoffs. * [Configure providers](/docs/sdk/configure-providers) for wallet-library setup. * [API reference → Market](/docs/api-reference/market/overview), the underlying HTTP endpoints. # TWAP orders with the SDK Source: https://new-docs.velora.xyz/docs/sdk/products/twap Split a large trade into scheduled slices from the SDK. In Velora, a TWAP is a Delta order the user signs once and Delta settles slice-by-slice over time. 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](/docs/delta/overview) 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](/docs/overview/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](/docs/sdk/products/delta), with one wrinkle: **you quote a single slice**, not the whole order. 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. 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. Call `sdk.delta.submitTWAPDeltaOrder` with the schedule, or run `buildTWAPDeltaOrder` → `signDeltaOrder` → `postTWAPDeltaOrder` yourself when you need control over signing. 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) ```ts theme={null} 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`: ```ts theme={null} 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). ```ts theme={null} 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 ```ts theme={null} 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](/docs/sdk/monetize) for the full field reference. ## Related pages * [Swaps → Delta](/docs/sdk/products/delta) covers the market Delta order flow this builds on. * [Limit orders](/docs/sdk/products/limit-orders): the other Delta-based order type. * [Product stack → TWAP](/docs/overview/product-stack/twap) — the conceptual model. # Simple SDK constructor Source: https://new-docs.velora.xyz/docs/sdk/simple-sdk constructSimpleSDK auto-wires the fetcher and contract caller so one constructor returns a working SDK for quotes, swaps, Delta orders, and approvals. `constructSimpleSDK` is the recommended entry point for most integrators. You pass it a `chainId`, an HTTP client, and (optionally) a wallet; in return you get an SDK with every Velora method available under flat namespaces. ## When to use this * You want one import that exposes the whole API surface. * You're fine with the SDK returning transaction hashes (`string`) for write calls, instead of library-typed responses. * You don't need to share a single contract caller across multiple SDK instances. For tighter control over the transaction-response type or bundle size, use the [Full](/docs/sdk/full-sdk) or [Partial](/docs/sdk/partial-sdk) constructors instead. ## Construct it Pick your HTTP client. `fetch` keeps the bundle smaller; `axios` is convenient if you already use it. ```ts axios theme={null} import axios from "axios"; import { constructSimpleSDK } from "@velora-dex/sdk"; const simpleSDK = constructSimpleSDK({ chainId: 1, axios }); ``` ```ts fetch theme={null} import { constructSimpleSDK } from "@velora-dex/sdk"; const simpleSDK = constructSimpleSDK({ chainId: 1, fetch }); ``` Without a wallet, the SDK is **read-only** (quotes, prices, order status, supported tokens), but cannot approve, sign, or submit. ## Add a wallet Pass a second argument with your provider to enable write methods (`approveToken`, `signDeltaOrder`, `submitDeltaOrder`, `buildTx`-then-send). ```ts viem theme={null} import { createWalletClient, custom } from "viem"; import { mainnet } from "viem/chains"; const walletClient = createWalletClient({ chain: mainnet, transport: custom(window.ethereum!), }); const [account] = await walletClient.getAddresses(); const sdk = constructSimpleSDK( { chainId: 1, axios }, { viemClient: walletClient, account }, ); ``` ```ts ethers v5 theme={null} import { ethers } from "ethers"; const sdk = constructSimpleSDK( { chainId: 1, axios }, { ethersProviderOrSigner: signer, // JsonRpcProvider or Wallet EthersContract: ethers.Contract, account, }, ); ``` ```ts ethers v6 theme={null} import { ethers } from "ethers"; const sdk = constructSimpleSDK( { chainId: 1, axios }, { ethersV6ProviderOrSigner: signer, EthersV6Contract: ethers.Contract, account, }, ); ``` ```ts web3 theme={null} import Web3 from "web3"; const sdk = constructSimpleSDK( { chainId: 1, axios }, { web3: new Web3(window.ethereum), account }, ); ``` Write calls always resolve to a **transaction hash** (`string`). If you need the library-typed response object (viem's `Hex`, `ethers.ContractTransaction`, etc.), use [`constructFullSDK`](/docs/sdk/full-sdk) with the `` generic. ## Available methods The returned SDK is namespaced by feature: | Namespace | What's inside | Docs page | | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | | `sdk.delta` | `getDeltaPrice`, `buildDeltaOrder`, `signDeltaOrder`, `postDeltaOrder`, `submitDeltaOrder`, `approveTokenForDelta`, `preSignDeltaOrder`, `getDeltaContract`, `getDeltaOrderById`, `getDeltaOrderByHash`, `getDeltaOrders`, `cancelDeltaOrders`, `getBridgeRoutes`, `isTokenSupportedInDelta` | [Delta](/docs/sdk/products/delta) | | `sdk.quote` | `getQuote` — Delta price with fallback to Market | [API → /v2/quote](/docs/api-reference/market/quote) | | `sdk.swap` | `getRate`, `buildTx`, `approveToken`, `getSpender`, `getBalances`, `getTokens`, `getAdapters`, `swapTx` (Market execution path for swaps) | [Market](/docs/sdk/products/swap) | | `sdk.otcOrders` | AugustusRFQ maker/taker orders for OTC trades. For target-price limit orders, use the Delta namespace instead. | [OTC](/docs/sdk/products/otc) | ## End-to-end example Quote, approve, and submit a Delta order in one flow. (Falls back to a Market Swap if Delta isn't available for the pair.) ```ts theme={null} import axios from "axios"; import { createWalletClient, custom } from "viem"; import { mainnet } from "viem/chains"; import { constructSimpleSDK, txParamsToViemTxParams } from "@velora-dex/sdk"; const walletClient = createWalletClient({ chain: mainnet, transport: custom(window.ethereum!), }); const [account] = await walletClient.getAddresses(); const sdk = constructSimpleSDK( { chainId: 1, axios }, { viemClient: walletClient, account }, ); const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; const ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; const amount = "10000000000"; // 10,000 USDC const slippageBps = 50; // 0.5% const quote = await sdk.quote.getQuote({ srcToken: USDC, destToken: ETH, amount, userAddress: account, srcDecimals: 6, destDecimals: 18, mode: "all", side: "SELL", partner: "my-app-name", }); if ("delta" in quote) { await sdk.delta.approveTokenForDelta(amount, USDC); const auction = await sdk.delta.submitDeltaOrder({ route: quote.delta.route, // or pick from quote.delta.alternatives side: quote.delta.side, owner: account, slippage: slippageBps, // SDK applies slippage for you deadline: Math.floor(Date.now() / 1000) + 60 * 60, // required, unix seconds partner: "my-app-name", }); console.log("Delta auction id:", auction.id); } else { await sdk.swap.approveToken(amount, USDC); const tx = await sdk.swap.buildTx({ srcToken: USDC, destToken: ETH, srcAmount: amount, slippage: slippageBps, priceRoute: quote.market, userAddress: account, partner: "my-app-name", }); await walletClient.sendTransaction({ ...txParamsToViemTxParams(tx), account, }); } ``` See [Swaps → Delta](/docs/sdk/products/delta) for the split build/sign/post flow and order-status polling, and [Swaps → Market](/docs/sdk/products/swap) for the full Market-Swap walkthrough. ## Related pages * [Swaps → Delta](/docs/sdk/products/delta) * [Swaps → Market](/docs/sdk/products/swap) * [Configure providers](/docs/sdk/configure-providers) * [Monetize](/docs/sdk/monetize) # Test a Velora SDK integration Source: https://new-docs.velora.xyz/docs/sdk/testing-integration Test SDK flows without burning mainnet funds. Fork mainnet locally, mock the fetcher for unit tests, and verify partner attribution end-to-end. The SDK calls real Velora APIs and real on-chain contracts. To test integrations safely, fork mainnet for end-to-end flows and mock the fetcher for unit tests. ## When to use this * You're adding the SDK to a project for the first time and want to verify the flow before pointing it at production. * You're writing CI tests that should not depend on network connectivity or mainnet balances. * You're reproducing a bug a user reported and need a deterministic environment. ## Fork mainnet for end-to-end tests Velora's contracts (Augustus router, Delta, AugustusRFQ) deploy to production networks only; there's no testnet deployment. The standard pattern is to fork mainnet (or your target chain) and impersonate a funded account. ### Tenderly Tenderly Virtual TestNets (forks) are the most widely used option: a hosted fork with a public RPC, a block explorer, and unlimited faucet, so you don't run a node locally and your whole team can share one environment. Create a fork in the [Tenderly dashboard](https://dashboard.tenderly.co) (or via the API), then point the SDK at its RPC URL: ```ts theme={null} import { createWalletClient, http } from "viem"; import { mainnet } from "viem/chains"; import { constructSimpleSDK } from "@velora-dex/sdk"; const account = "0x1111111111111111111111111111111111111111"; // a funded address const walletClient = createWalletClient({ chain: mainnet, transport: http(process.env.TENDERLY_FORK_RPC_URL), }); const sdk = constructSimpleSDK( { chainId: 1, fetch }, { viemClient: walletClient, account }, ); // run a swap / Delta flow against the fork: real API responses, fake balances ``` Fund or impersonate any account with Tenderly's `tenderly_setBalance` / `tenderly_setErc20Balance` RPC methods (or the dashboard), so you don't need a real whale address. Because the RPC is hosted, the same fork works from CI without spinning up a node. ### Anvil (Foundry) ```bash theme={null} anvil --fork-url https://eth-mainnet.alchemyapi.io/v2/$ALCHEMY_KEY ``` Connect the SDK to the local RPC and impersonate a known USDC whale: ```ts theme={null} import { createWalletClient, createTestClient, http } from "viem"; import { mainnet } from "viem/chains"; import { constructSimpleSDK } from "@velora-dex/sdk"; const account = "0x1111111111111111111111111111111111111111"; // a funded address const testClient = createTestClient({ chain: mainnet, mode: "anvil", transport: http("http://127.0.0.1:8545"), }); await testClient.impersonateAccount({ address: account }); const walletClient = createWalletClient({ chain: mainnet, transport: http("http://127.0.0.1:8545"), }); const sdk = constructSimpleSDK( { chainId: 1, fetch }, { viemClient: walletClient, account }, ); // run a swap / Delta flow against the fork: real API responses, fake balances ``` ### Hardhat The SDK's own tests use a Hardhat fork seeded via the `PROVIDER_URL` env var. The same approach works for your integration: ```js theme={null} // hardhat.config.ts networks: { hardhat: { forking: { url: process.env.PROVIDER_URL }, }, }, ``` Run with `PROVIDER_URL=https://mainnet... npx hardhat test`. The Velora SDK exposes overrides for impersonation via your provider; see the SDK's [own hardhat config](https://github.com/VeloraDEX/sdk/blob/master/hardhat.config.ts) for a reference. Forking only spoofs the chain state. Quotes still come from the real Velora API. Account-specific endpoints (allowance lookups against the impersonated address) work because the fork's RPC returns the impersonated account's storage. ## Mock the fetcher in unit tests For unit tests that shouldn't touch the network, pass a custom `FetcherFunction` that returns canned responses. The contract caller is still real, but no HTTP request leaves your process. ```ts theme={null} import { constructSimpleSDK, type FetcherFunction } from "@velora-dex/sdk"; const fixtures: Record = { "GET /prices": { priceRoute: { srcAmount: "1000", destAmount: "999" /* ... */ }, }, }; const mockFetcher: FetcherFunction = async ({ url, method }) => { const key = `${method.toUpperCase()} ${new URL(url).pathname}`; if (key in fixtures) return fixtures[key]; throw new Error(`unexpected request: ${key}`); }; const sdk = constructSimpleSDK({ chainId: 1, fetcher: mockFetcher }); const rate = await sdk.swap.getRate({ srcToken: "0x...", destToken: "0x...", amount: "1000", userAddress: "0x...", }); expect(rate.destAmount).toBe("999"); ``` This pattern is also handy in CI: every test is deterministic and runs offline. ## Debugging tips * **Check `partner`.** A missing or unknown partner key surfaces as `400` on quote/order endpoints. Confirm it's set on every SDK call and matches the partner registered with Velora. * **Confirm `chainId` matches the connected wallet.** Mismatched chains throw on signing, because the EIP-712 domain includes `chainId`. * **Log raw fetcher calls.** Wrap your fetcher to log `{url, method, status, durationMs}` while developing. The SDK's internal retries and partner-fee resolution can issue requests you don't expect. * **Watch Delta status transitions.** A Delta order goes `OPEN` → `ACCEPTED` → `EXECUTED` (or `CANCELLED` / `EXPIRED`). If it sticks at `OPEN` for more than a minute, the auction likely returned no fill. Cancel and re-quote. * **Verify the spender.** For Delta the user approves `getDeltaContract()`. For Market Swaps the user approves `getSpender()` (`TokenTransferProxy`). Approving the wrong contract is the most common cause of `INSUFFICIENT_ALLOWANCE`. ## Related pages * [Troubleshooting](/docs/api-reference/troubleshooting): known failure modes per endpoint. * [Configure providers](/docs/sdk/configure-providers) — fetcher and caller setup. # Portikus solver network Source: https://new-docs.velora.xyz/docs/solver-network/portikus Portikus is the intent infrastructure behind Delta: an on-chain settlement layer, composable modules, and the Portikus Network of competing solvers. Velora built Delta on top of it, and other apps can build on the same rails. You sign *what you want* (sell 1,000 USDC for at least 999 USDT, on this chain, before this deadline), not *how to execute it*. That signed message is an **intent**. [Portikus](https://www.portikus.xyz) is the infrastructure that turns intents into outcomes, built by [Laita Labs](https://www.laita.xyz/). It has three parts: an on-chain settlement layer, a set of composable modules apps build on, and the **Portikus Network**, where Portikus Agents compete to fill each intent. Velora's Delta leverages Portikus for gasless, MEV-protected swaps, limit orders, TWAP, and crosschain. The same infrastructure can power other intent-based products too. A lending market or AMM, for example, could let its LPs rebalance and deploy capital through signed intents: competing agents fill each rebalance at a guaranteed price, the LP pays no gas, and nothing hits the public mempool to be front-run or sandwiched. ## One platform, many apps Apps build on Portikus by composing modules on the Portikus contract and submitting signed intents. The shared Portikus Network fills any app's intents, and settlement enforces the terms the user signed. ```mermaid theme={null} flowchart TB Delta["Delta — Velora's trading app
swaps, limit orders, TWAP, crosschain"] Other["Another app — e.g. an AMM
deploying LP liquidity, MEV-shielded"] Delta -- "composes modules" --> PC Other -- "composes modules" --> PC PC["Portikus contract
registry of agents + modules, per-app adapters"] PN["Portikus Network
sealed-bid auction + competing agents"] PC <--> PN PN --> Settle(["Settlement enforces the signed minimum"]) classDef brand fill:#FFF3EC,stroke:#FF6A1F,color:#1a1a1a classDef good fill:#E8F5E9,stroke:#2E7D32,color:#1a1a1a class PC,PN brand class Settle good ``` Delta supplies the trading modules. A different app supplies its own (an LP module, a treasury module, whatever its product needs) and inherits the same solver competition and on-chain settlement guarantees. The rest of this page describes those shared parts, using Delta as the running example. ## Following a single intent ```mermaid theme={null} flowchart TB Order([Signed intent]) --> OS[Order server] OS <--> S1[Solver A] OS <--> S2[Solver B] OS <--> S3[Solver C] OS -- "best bid wins" --> Win[Winning solver] Win --> P[Portikus settlement] P --> Check{Output ≥ signed minimum?} Check -- "yes" --> User([destToken delivered]) Check -- "no" --> Revert([Reverts, funds stay in wallet]) classDef accent fill:#FFF3EC,stroke:#FF6A1F,color:#1a1a1a classDef good fill:#E8F5E9,stroke:#2E7D32,color:#1a1a1a classDef bad fill:#FFEBEE,stroke:#C62828,color:#1a1a1a class Win accent class User good class Revert bad ``` Each intent runs through a [sealed-bid auction](/docs/solver-network/sealed-bid-auctions): solvers bid in parallel without seeing each other's offers, and the best bid wins the right to settle. ## Portikus Agents Portikus Agents are the entities authorized to execute intents. An agent reads what the user signed for, works out how to deliver it, and settles it on-chain. Agents specialize by business case, and an app runs the agents that fit its product. Delta's agents specialize in **spot trading**: they're the solvers that compete in the [sealed-bid auction](/docs/solver-network/sealed-bid-auctions) to fill a swap at the best price. An app built for LP deployment would run agents specialized in that instead, on the same infrastructure. A Delta solver commits to deliver the user's tokens, sourcing liquidity from its own inventory or on-chain routes. Most are professional DEX aggregators and market makers. Agent permissions live on-chain. Solvers are the registered Portikus Agents authorized to execute intents; every agent address sits in the Portikus registry, and the settlement functions check it before executing. An address that was never registered, or was removed for misbehaving, cannot settle an intent at all. ## On-chain settlement Whatever a solver does off-chain, the Portikus contract holds the same line on-chain: * The signature is verified against the user's address (EIP-712), and the intent's nonce is consumed so it can never settle twice. * The fill must deliver at least the `destAmount` the user signed. A fill that comes in below the minimum reverts; there is no partial-loss state. * The deadline is checked at settlement. Past it, the intent is unfillable. * Funds move only inside a successful settlement. Until the transaction lands, the user's tokens stay in their wallet. ## Order lifecycle Each app exposes its own surface for tracking an intent. Delta's is the order status you poll with `GET /v2/delta/orders/{orderId}`, which moves from submission to a terminal state like this: ```mermaid theme={null} stateDiagram-v2 classDef live fill:#FFF3EC,color:#1a1a1a,stroke:#FF6A1F classDef done fill:#E8F5E9,color:#1a1a1a,stroke:#2E7D32 [*] --> PENDING PENDING --> ACTIVE : auction starts ACTIVE --> ACTIVE : re-auctioned ACTIVE --> COMPLETED : settled ACTIVE --> BRIDGING : crosschain leg BRIDGING --> COMPLETED BRIDGING --> REFUNDING REFUNDING --> REFUNDED ACTIVE --> SUSPENDED SUSPENDED --> ACTIVE ACTIVE --> CANCELLED ACTIVE --> EXPIRED ACTIVE --> FAILED COMPLETED --> [*] REFUNDED --> [*] class ACTIVE live class COMPLETED done class REFUNDED done ``` An intent that doesn't fill in one [auction round](/docs/solver-network/sealed-bid-auctions#how-delta-runs-the-auction) simply enters the next one, until a solver fills it or the deadline expires. If the user's balance or allowance drops below what the order needs, it is suspended rather than killed; it rejoins the auction as soon as funds are back. Users can cancel any time before execution, and a crosschain order that settles on the source chain shows `BRIDGING` until the destination leg lands; if the bridge fails, the source amount is refunded. ## Why build on Portikus Solvers bid against each other for the right to fill. Your users get the best committed price, not the first one offered. Settlement gas is handled inside the Portikus flow. The user signs an off-chain message and receives tokens. A fill below the signed minimum reverts. No solver, including the winner, can deliver less. ## Related pages * [Sealed-bid auctions](/docs/solver-network/sealed-bid-auctions) — how the auction selects a winner and resists manipulation. * [How it works](/docs/delta/how-it-works) — the full Delta flow, from quote to settlement. * [Chains and contracts](/docs/resources/chains-and-contracts) — Portikus settlement addresses per chain. * [portikus.xyz](https://www.portikus.xyz) — learn more about Portikus, built by [Laita Labs](https://www.laita.xyz/). # Sealed-bid auctions for DeFi trades Source: https://new-docs.velora.xyz/docs/solver-network/sealed-bid-auctions How sealed-bid auctions work, why they suit DeFi trading, and how Delta uses them to fill orders at the best price while shutting out bid manipulation and MEV. Sealed-bid auctions are a Portikus feature: they're how the [Portikus Network](/docs/solver-network/portikus) fills intents for any app built on it, Delta included. In a sealed-bid auction, every bidder submits one private bid without seeing what anyone else offered. Every Delta order is filled through one: solvers bid blind with executable calldata, the best simulated outcome wins, and protocol settlement executes the winning calldata while enforcing the minimum the user signed. The result is a market where the only way for a solver to win is to quote its true best price. ## How a sealed-bid auction works The mechanism is old and simple; governments have sold bonds and oil leases this way for a century. The auctioneer announces what's for sale, every bidder hands in one bid in a sealed envelope, and the envelopes are opened together. Best bid wins and pays what it bid (a *first-price* sealed auction). What makes it interesting is what bidders can't do: | | Open (English) auction | Sealed-bid auction | | -------------------- | ---------------------------------------- | --------------------------------- | | What bidders see | Every competing bid, live | Nothing | | Winning strategy | Beat the runner-up by a tick | Quote your true best price | | Reacting to rivals | Core of the game | Impossible | | Manipulation surface | Shill bids, signaling, last-look sniping | One private commitment per bidder | In an open auction the winner only ever pays slightly more than the second-best bidder was willing to. In a sealed auction a bidder who shades their offer risks losing outright to someone they couldn't see, so competitive pressure pushes every bid toward the bidder's real limit. ## Why this fits DeFi trading Public blockchains leak information by default, and most trading attacks are built on that leak. A swap in the public mempool can be sandwiched before it lands. A visible quote can be undercut at the last moment by a competitor who never intended to price the trade honestly, only to beat whoever showed their hand first. A sealed-bid auction removes the channel those attacks need. The order never touches a public mempool, so there's nothing to sandwich. Bids are private, so there's nothing to undercut by a tick; a solver that wants the order has to outbid rivals it cannot observe. This is the mechanism behind the MEV protection that [Why Delta](/docs/delta/overview) promises. ## How Delta runs the auction Every Delta order is auctioned in rounds. One round looks like this: ```mermaid theme={null} flowchart TB A([Order enters round]) --> B[Query all solvers in parallel] B --> C[One sealed bid per solver] C --> D[Validate and simulate every bid] D --> F{Viable bid?} F -- "yes" --> G[Best simulated outcome wins] G --> H[Protocol executes winning calldata] H --> I{Settled?} I -- "yes" --> J([Completed]) I -. "no" .-> A F -. "no" .-> A classDef accent fill:#FFF3EC,stroke:#FF6A1F,color:#1a1a1a classDef good fill:#E8F5E9,stroke:#2E7D32,color:#1a1a1a class G accent class J good ``` Three details do most of the work: 1. **A bid is a commitment, not a quote.** Solvers don't reply with a number; they reply with the exact calldata the protocol can execute and the amount that calldata should deliver. There's no second look and no renegotiation after seeing the field. 2. **Bids are ranked by simulation, not by claim.** Before picking a winner, the order server simulates every bid against current chain state and ranks bids by what they actually produce. A solver that promises a great price but whose calldata reverts or underdelivers doesn't win. 3. **Surplus flows back.** When the winning fill beats the quoted price, the user receives the improvement; a portion is split between the integrator and the protocol. Solvers compete on execution quality, and users capture it. If no viable bid arrives, or the winning calldata fails during on-chain settlement, the order isn't stuck: it enters the next round and gets auctioned again, until it fills or its deadline expires. ## What stops a malicious solver Each layer of the auction closes a different attack: | Attack | Defense | | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Watch rivals' bids and undercut by a tick | Bids are sealed. Solvers see only the order, never each other's offers. | | Claim a great price, deliver a bad fill | Every bid is simulated before the award. The ranking uses the simulated result, not the solver's claim. | | Submit calldata that would deliver below the quote | The user's signed minimum is enforced by the settlement contract. A fill below it reverts on-chain. | | Submit fill calldata without participating honestly | Only solvers registered in the Portikus registry contract can provide executable bids. A misbehaving solver can be removed, and removal is enforced on-chain. | | Win with calldata that later reverts or becomes stale | The order re-enters the next auction round. The user's funds never moved, so the failed solver wasted only its own auction slot. | The pattern across all five: the auction never has to trust what a solver says. Bids are verified by simulation before the award, and the user's floor is verified by the contract after it. ## Related pages * [Portikus Network](/docs/solver-network/portikus) — the intent infrastructure behind these auctions. * [How it works](/docs/delta/how-it-works) — where the auction sits in the full Delta flow. * [Why Delta](/docs/delta/overview) — what the auction buys you as an integrator: gasless, MEV-protected swaps. # Velora Widget compatibility Source: https://new-docs.velora.xyz/docs/widget/compatibility Tested environments, peer-dependency ranges, SSR caveats, and performance tips for @velora-dex/widget. ## Peer dependencies | Package | Version | | ----------------------- | ---------------- | | `react` | `18.x` or `19.x` | | `react-dom` | `18.x` or `19.x` | | `@tanstack/react-query` | `^5.90` | `@tanstack/react-query` only needs to be installed. The widget manages its own query client internally. ## Tested frameworks | Framework | Status | Notes | | ---------------------- | ------------------------------ | ---------------------------------------------------------------------------------- | | Vite + React | ✅ Works out of the box | See [examples/react](/docs/widget/examples/react). | | Next.js (app router) | ✅ Works with client-only mount | Use `dynamic(... { ssr: false })`. See [examples/nextjs](/docs/widget/examples/nextjs). | | Next.js (pages router) | ✅ Works with `dynamic` | Same dynamic-import pattern as app router. | | Create React App | ✅ Works | No special setup. | ## SSR caveat The widget reads `window`, `localStorage`, and `prefers-color-scheme` on mount. It does **not** support server-side rendering. In Next.js (or any SSR/SSG framework), gate the import: ```tsx theme={null} // Next.js app router import dynamic from "next/dynamic"; const Widget = dynamic( () => import("@velora-dex/widget").then((m) => ({ default: m.Widget })), { ssr: false } ); ``` ## Tailwind v4 The widget ships compiled Tailwind v4 styles scoped under the `.velora-widget` class. You don't need Tailwind in your host app; the bundled styles are self-contained. If your host app **does** use Tailwind, the widget's scoping prevents its variables from leaking into your global stylesheet, and vice versa. See [Customize](/docs/widget/customize#css-scoping). ## Stylesheet auto-injection The compiled stylesheet is auto-injected via `vite-plugin-lib-inject-css` when you import `Widget`. No explicit `.css` import is normally needed. If your bundler strips side-effect imports aggressively (some custom Webpack / Rollup setups), force-include the stylesheet: ```tsx theme={null} import "@velora-dex/widget/styles.css"; ``` ## Error boundaries Wrap the widget in an error boundary for production. A widget crash shouldn't take down your whole page. ```tsx theme={null} import { Component, type ReactNode } from "react"; import { Widget } from "@velora-dex/widget"; class WidgetErrorBoundary extends Component<{ children: ReactNode }, { hasError: boolean }> { state = { hasError: false }; static getDerivedStateFromError() { return { hasError: true }; } render() { if (this.state.hasError) { return
The trading widget hit an error. Please refresh.
; } return this.props.children; } } export function SafeWidget() { return ( ); } ``` ## Performance tips ### Memoize non-primitive config Passing inline arrays or objects forces a re-render. Memoize them. ```tsx theme={null} import { useMemo } from "react"; import { Widget } from "@velora-dex/widget"; function MyWidget({ theme }) { const config = useMemo( () => ({ theme, tradeModes: ["swap", "limit"], partnerConfig: { partner: "my-app-name" }, }), [theme] ); return ; } ``` ### Lazy-load when offscreen If the widget isn't above the fold, defer it. ```tsx theme={null} import { lazy, Suspense } from "react"; const Widget = lazy(() => import("@velora-dex/widget").then((m) => ({ default: m.Widget })) ); export function DeferredWidget() { return ( Loading…}> ); } ``` ### Bundle size The widget is large: it ships wallet connectors, EVM tooling, and the full trading UI. Lazy-loading and route-based code splitting keep the initial bundle small. ## Known caveats * Server-side rendering is not supported (see SSR caveat above). * Strict-mode double-mount in dev triggers a brief double-fetch of price quotes, harmless and confined to development. * Sandboxed iframes without `allow-popups` and `allow-storage-access-by-user-activation` will break wallet-connection popups. ## Related pages * [Install](/docs/widget/install) — install + render. * [examples/react](/docs/widget/examples/react), [examples/nextjs](/docs/widget/examples/nextjs) — concrete setups. * [Customize](/docs/widget/customize) — CSS scoping details. # Configure the Velora Widget Source: https://new-docs.velora.xyz/docs/widget/configure Restrict chains, pick trade modes, choose a theme, and hide UI elements via the config prop. The widget accepts a `config` prop of type `WidgetConfig`. Every field is optional; omit a field to fall back to its default. ```tsx theme={null} import { Widget } from "@velora-dex/widget"; ; ``` **Memoize non-primitive config values.** Arrays and objects passed inline (like `srcChains: [1, 137]`) get a new reference on every render and force the widget to re-render its state. Move them to `useMemo` or to a module-level constant. ## Configuration options | Field | Type | Default | Purpose | | ------------------ | ------------------------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | `theme` | `"light" \| "dark"` | system preference | Color theme. See [Customize](/docs/widget/customize). | | `enableDelta` | `boolean` | `true` | Enable [Delta](/docs/delta/overview) intents (gasless, MEV-protected). | | `enableCrossChain` | `boolean` | `true` | Enable crosschain swaps. | | `srcChains` | `SupportedChainId[]` | all supported | Restrict source-chain picker. | | `destChains` | `SupportedChainId[]` | all supported | Restrict destination-chain picker. | | `tradeModes` | `TradeMode[]` | all four modes | Limit which forms appear (`"swap" \| "limit" \| "otc" \| "twap"`). | | `tokenLists` | `string[]` | curated defaults | Token-list URLs to populate token pickers. | | `excludeUI` | `WidgetElements[]` | `[]` | Hide UI chunks (`"wallet-management" \| "activities" \| "snackbars"`). | | `enableDegenMode` | `boolean` | `true` | Allow users to bypass high-price-impact warnings. | | `widgetMode` | `"standalone" \| "dapp"` | `"standalone"` | Who owns the wallet connection. See [Wallet management](/docs/widget/wallet-management). | | `debug` | `boolean` | `false` | Verbose console logging. | | `partnerConfig` | `PartnerConfig` | — | Partner fee/revenue config. See [Monetize](/docs/widget/monetize). | | `referrerConfig` | `ReferrerConfig` | — | Referrer revenue config. See [Monetize](/docs/widget/monetize). | | `privyAppId` | `string` | — | Optional. Adds Privy to the connector list in `standalone` mode. See [Wallet management](/docs/widget/wallet-management#optional-add-privy-as-a-connector). | | `privyClientId` | `string` | — | Optional. Only effective when `privyAppId` is set. | Each field is detailed below. *** ## Chains and routes ### `srcChains`, `destChains` Restrict the chain dropdowns to a subset. Useful when your integration only services specific networks. ```tsx theme={null} import { useMemo } from "react"; import { Widget, defaults } from "@velora-dex/widget"; function MyWidget() { const config = useMemo( () => ({ srcChains: [1, 137], // Ethereum + Polygon destChains: defaults.chainIds.filter((id) => id !== 1), // everywhere but Ethereum }), [] ); return ; } ``` How chain selection behaves: * An empty array or one containing only invalid chain IDs falls back to all default chains. * Invalid IDs in an otherwise valid list are dropped (with `console.warn`). * Not all source chains can bridge to all destination chains; unsupported pairs are filtered out at runtime. * Same-chain swaps (source == destination) are always allowed for any chain in `srcChains`. ### `enableCrossChain` ```tsx theme={null} ``` Disables the crosschain swap path entirely: users can only swap within a single chain. ### `enableDelta` ```tsx theme={null} ``` When `false`, hides Delta-mode swaps and Delta-only trade modes (limit, TWAP). The widget falls back to Market-API swaps only. *** ## Trade modes ### `tradeModes` ```tsx theme={null} const tradeModes = ["swap", "limit"]; ; ``` Restricts which trading forms are visible. Accepts any subset of `"swap" | "limit" | "otc" | "twap"`. Similar fallback rules apply here: * An empty array or one with only invalid modes falls back to all default modes. * If the currently selected mode becomes disabled, the widget switches to the first enabled mode. * `limit` and `twap` are Delta-only. If `enableDelta: false` (or the user disables Delta in Settings) and your `tradeModes` list contains only Delta-only modes, the widget falls back to `swap`. *** ## Theme ### `theme` ```tsx theme={null} // forced dark // forced light // follows system preference ``` See [Customize](/docs/widget/customize) for CSS scoping details. *** ## Hiding UI ### `excludeUI` Hide specific UI chunks when your host app provides its own equivalents. | Key | Hides | | --------------------- | ---------------------------------------- | | `"wallet-management"` | The wallet button in the header | | `"activities"` | The activity / transaction history panel | | `"snackbars"` | In-widget toast notifications | ```tsx theme={null} const excludeUI = ["wallet-management", "snackbars"]; ; ``` *** ## Token lists ### `tokenLists` Add custom token-list URLs. The widget merges them with curated defaults if you spread them. ```tsx theme={null} import { defaults, Widget } from "@velora-dex/widget"; const tokenLists = [ ...defaults.tokenLists, "https://example.com/my-tokens.json", ]; ; ``` If you replace defaults entirely (omit the spread), users will only see your tokens. *** ## Behavior flags ### `enableDegenMode` ```tsx theme={null} ``` When `true` (default), users can toggle Degen Mode in Trading Parameters to trade tokens with high price impact or missing USD price data. When `false`, the toggle is hidden and users can't bypass price-impact warnings. ### `debug` ```tsx theme={null} ``` Logs extra diagnostic info to the console. Don't ship enabled to production. *** ## Pre-filling the form Use the [`input` prop](/docs/widget/widget-api-reference#forminputprops) (not `config`) to pre-select tokens, amounts, and form type, for example to support deep links into a specific trade. ```tsx theme={null} ``` ## Related pages * [Customize](/docs/widget/customize) — theme details and CSS scoping. * [Wallet management](/docs/widget/wallet-management) — `widgetMode`, `provider`, optional `privyAppId`. * [Monetize](/docs/widget/monetize) — `partnerConfig` and `referrerConfig`. * [Widget API reference](/docs/widget/widget-api-reference) — full type definitions. # Customize the Velora Widget Source: https://new-docs.velora.xyz/docs/widget/customize Pick a theme, follow the user's system preference, and understand how the widget's CSS is scoped. The widget exposes a single visual control: a `theme` config field that switches between bundled light and dark themes. ## Set a theme ```tsx theme={null} // follows system preference ``` `theme` accepts the `WidgetTheme` type: `"light" | "dark"`. If you omit `theme`, the widget reads the user's OS preference via `prefers-color-scheme` and updates live when the preference changes. ## Switch themes at runtime The theme is a controlled prop. Pass a new value any time to switch. ```tsx theme={null} import { useState } from "react"; import { Widget, type WidgetTheme } from "@velora-dex/widget"; export function ThemedWidget() { const [theme, setTheme] = useState("light"); return ( <> ); } ``` ## CSS scoping The widget is built with Tailwind v4 and scopes all CSS variables under the `.velora-widget` class. That means: * The widget's styles don't leak into the rest of your app. * Your app's global styles don't bleed into the widget either. Selectors targeting bare elements (`a`, `button`, `input`) inside the widget's DOM tree will still apply, but the widget's own variables take precedence within its root. ## Stylesheet auto-injection The compiled stylesheet is auto-injected when you `import { Widget }`. No `.css` import required. ```tsx theme={null} import { Widget } from "@velora-dex/widget"; // Stylesheet injected; nothing else needed. ``` If your bundler strips side-effect imports aggressively (rare but possible with aggressive `treeshake`), force-include the stylesheet: ```tsx theme={null} import "@velora-dex/widget/styles.css"; ``` ## Related pages * [Configure](/docs/widget/configure) — every other config option. * [Compatibility](/docs/widget/compatibility) — Tailwind / bundler caveats. # Velora Widget events and callbacks Source: https://new-docs.velora.xyz/docs/widget/events-and-callbacks Listen to widget lifecycle events: wallet connections, approvals, swaps, orders, and form changes. Pass an `events` object to subscribe to widget lifecycle events. Every callback receives `{ event, state }` where `state` is a snapshot of the full widget state and `event` is a discriminated union of named sub-events. ```tsx theme={null} { if (event.name === "Swap:confirmed") { analytics.track("swap_confirmed", { txHash: event.params.txHash }); } }, }} /> ``` All callbacks are optional. Subscribe only to what you need. ## Callback summary | Callback | Fires when | | ----------------------------------------------- | ------------------------------------------------------ | | [`onConnectWallet`](#onconnectwallet) | A wallet connects (or the Connect button is clicked). | | [`onConnectWalletClick`](#onconnectwalletclick) | The Connect Wallet button is clicked (dApp-mode hook). | | [`onAllowToken`](#onallowtoken) | Token approval / permit lifecycle. | | [`onWrapETH`](#onwrapeth) | ETH → WETH wrap lifecycle (Delta pre-step). | | [`onSwap`](#onswap) | Market or Delta Swap lifecycle. | | [`onTwapOrder`](#ontwaporder) | TWAP order lifecycle. | | [`onLimitOrder`](#onlimitorder) | Delta limit-order lifecycle. | | [`onOTCOrder`](#onotcorder) | OTC order lifecycle. | | [`onCancelTx`](#oncanceltx) | User cancels a pending swap tx (replacement). | | [`onCancelOrder`](#oncancelorder) | User cancels a Delta or OTC order. | | [`onFillOTCOrder`](#onfillotcorder) | User fills an existing OTC order. | | [`onSettingsChange`](#onsettingschange) | User changes widget settings (slippage, gas, bridges). | | [`onFormInputChange`](#onforminputchange) | Any input in any trading form changes. | | [`onPriceChange`](#onpricechange) | Price quote refreshes or query state changes. | *** ## `onConnectWallet` Fires when a wallet connects to the widget, and on the click that initiates connection. **Sub-events:** * `ConnectWallet:click` — Connect Wallet button clicked. Params: `{}`. * `ConnectWallet:connect` — A wallet actually connected (explicit click, eager auto-reconnect, or embedded provider). **`ConnectWallet:connect` params:** | Param | Type | Description | | ----------------- | ------------------------------------------------ | --------------------------------------------- | | `connectorType` | `string` | Type of connector used. | | `connectorName` | `string` | Wallet name (from WalletConnect or EIP-6963). | | `connectorAction` | `"Click" \| "Eager" \| "Embedded" \| "External"` | How the connection happened. | | `provider` | `EIP1193ProviderLax` | The underlying provider. | | `account` | `Address` | Connected account address. | | `walletName` | `string \| null` | Wallet display name. | | `walletIcon` | `string \| null` | Wallet icon URL. | | `chainId` | `number` | Chain the wallet is connected to. | ```tsx theme={null} { if (event.name === "ConnectWallet:connect") { analytics.track("wallet_connected", { connector: event.params.connectorType, action: event.params.connectorAction, account: event.params.account, }); } }, }} /> ``` `ConnectWallet:click` carries no params. Check `event.name` before reading connect-specific fields. *** ## `onConnectWalletClick` Fires when the Connect Wallet button is clicked. Same payload type as `onConnectWallet`, but only emits `ConnectWallet:click`. ```tsx theme={null} { openHostAppWalletModal(); }, }} /> ``` *** ## `onAllowToken` Token approval (`approve`) or signed-permit (`permit1` / `permit2`) lifecycle. **Sub-events:** * `AllowToken:request` — Approval or permit initiated. * `AllowToken:sent` — Transaction signed and broadcast. * `AllowToken:confirmed` — Transaction confirmed on-chain, or permit signed. * `AllowToken:failed` — Transaction failed or permit rejected. **Common params:** | Param | Description | | ---------------- | ------------------------------------------------ | | `token` | Token being approved. | | `amountWei` | Approval amount, in wei. | | `spenderAddress` | The contract receiving the allowance. | | `chainId` | Chain ID. | | `tradeMode` | `"swap" \| "limit" \| "otc" \| "twap"`. | | `type` | `"approve" \| "permit"`. | | `permitType` | (if permit) `"permit1" \| "permit2"`. | | `txHash` | (if sent / confirmed / failed) Transaction hash. | | `txReceipt` | (if confirmed / failed) Transaction receipt. | | `error` | (if failed) Error object. | ```tsx theme={null} { if (event.name === "AllowToken:confirmed") { console.log("Approved", event.params.token.symbol); } else if (event.name === "AllowToken:failed") { console.error("Approval failed", event.params.error); } }, }} /> ``` *** ## `onWrapETH` Fires during ETH → WETH wrapping. Used as a pre-step for Delta Swaps that start from native ETH. **Sub-events:** `WrapETH:click`, `WrapETH:request`, `WrapETH:sent`, `WrapETH:confirmed`, `WrapETH:failed`. **Params:** `ethAmountWei`, `wethAddress`, `chainId`, `tradeMode`, `txHash` (if sent+), `txReceipt` (if confirmed/failed), `error` (if failed). ```tsx theme={null} { if (event.name === "WrapETH:confirmed") { console.log("ETH wrapped", event.params.txHash); } }, }} /> ``` *** ## `onSwap` The most common callback. Fires for both Delta and Market Swap lifecycles. **Sub-events:** * `Swap:click` — Confirmation drawer opened. * `Swap:request` — Swap initiated. * `Swap:sent` — Tx signed and broadcast (market), or Delta order submitted. * `Swap:confirmed` — Tx confirmed (market), or Delta order filled. * `Swap:failed` — Tx failed or Delta order failed. * `Swap:cancelled` — User replaced / cancelled the pending tx, or the Delta order was cancelled. **Params common to all sub-events:** | Param | Description | | ----------------------------- | ---------------------------------------- | | `swapMode` | `"market" \| "delta"`. | | `price` | Quote info (shape varies by `swapMode`). | | `tokenFrom`, `tokenTo` | Tokens involved. | | `sendAmount`, `receiveAmount` | Amounts. | | `receiverAddress` | Destination address. | | `srcChainId`, `destChainId` | Chains involved. | | `connectedAccount` | Connected wallet address. | | `side` | `"BUY" \| "SELL"`. | **Sub-event-specific:** `txHash`, `callsId`, `order` (Delta), `txReceipt`, `callsReceipt`, `error`, `cancelTxDetails`. ```tsx theme={null} { if (event.name === "Swap:confirmed") { if (event.params.swapMode === "market") { console.log("Market Swap confirmed", event.params.txHash); } else { console.log("Delta order filled", event.params.order); } } else if (event.name === "Swap:failed") { console.error("Swap failed", event.params.error); } }, }} /> ``` *** ## `onTwapOrder` TWAP (Time-Weighted Average Price) order lifecycle. TWAP splits a large trade into smaller slices executed over a duration. **Sub-events:** `TwapOrder:click`, `TwapOrder:request`, `TwapOrder:sent`, `TwapOrder:confirmed`, `TwapOrder:failed`. **Params:** Delta or bridge price, `order` (if sent+), `error` (if failed), plus form-state fields (`tokenFrom`, `tokenTo`, `sendAmount`, `receiveAmount`, `receiverAddress`, `srcChainId`, `destChainId`, `connectedAccount`, `side`). ```tsx theme={null} { if (event.name === "TwapOrder:sent") { toast.success("TWAP order placed"); } }, }} /> ``` *** ## `onLimitOrder` Delta limit-order lifecycle. **Sub-events:** `LimitOrder:click`, `LimitOrder:request`, `LimitOrder:sent`, `LimitOrder:confirmed` (rare; orders typically fill later), `LimitOrder:failed`. **Params:** Delta `price`, `order`, `error` (if failed), plus form-state fields including `limitPrice` and `orderDeadline`. ```tsx theme={null} { if (event.name === "LimitOrder:sent") { toast.success("Limit order placed"); } }, }} /> ``` *** ## `onOTCOrder` OTC (Over-The-Counter) order lifecycle. Similar to limit orders but for OTC trades. **Sub-events:** `OTCOrder:click`, `OTCOrder:request`, `OTCOrder:sent`, `OTCOrder:confirmed` (rare), `OTCOrder:failed`. **Params:** OTC `price`, `order` (if not failed), `error` (if failed), plus form-state fields including `otcPrice` and `orderDeadline`. ```tsx theme={null} { if (event.name === "OTCOrder:sent") { console.log("OTC order submitted", event.params.order); } }, }} /> ``` *** ## `onCancelTx` Fires when the user replaces a pending swap tx with a "cancel" tx (same nonce, zero value) to drop it. **Sub-events:** `CancelTx:request`, `CancelTx:sent`, `CancelTx:confirmed`, `CancelTx:failed`. **Params:** | Param | Description | | ---------------------- | ---------------------------------------------------------- | | `txType` | `"SWAP"` (only swap tx cancellations are supported today). | | `originalTxHash` | Hash of the tx being cancelled. | | `chainId` | Chain. | | `originalTx` | (if sent+) The original tx response. | | `replacementRequest` | (if sent+) The replacement (cancel) tx request. | | `replacementTxHash` | (if sent+) Hash of the cancel tx. | | `replacementTxReceipt` | (if confirmed) Receipt of the mined cancel tx. | | `error` | (if failed) Error object. | *** ## `onCancelOrder` Fires when the user cancels a Delta or OTC order. **Sub-events:** * `CancelOrder:request` — Cancel initiated (tx or typed-data signing). * `CancelOrder:sentTx` — Cancel tx signed and broadcast. Fires for OTC orders and for ETH Delta orders cancelled via `withdrawAndCancel`. Non-ETH Delta orders skip this stage (they cancel via signed typed-data). * `CancelOrder:confirmed` — Cancel tx mined, or typed-data posted. * `CancelOrder:failed` — Cancel failed. **Params:** | Param | Description | | -------------------------------- | ------------------------------------------------------------------------------------------- | | `orderType` | `"DELTA" \| "OTC"`. | | `orderSubType` | Subtype (varies by order type). | | `orderIds` | (Delta) Array of order IDs to cancel. | | `orderHash` | (OTC) Hash of the order. | | `txHash`, `chainId`, `txReceipt` | (if sent/confirmed) Required for OTC; optional for Delta (only ETH Delta orders have a tx). | | `error` | (if failed) Error object. | ```tsx theme={null} { if (event.name === "CancelOrder:confirmed") { if (event.params.orderType === "DELTA") { console.log("Delta orders cancelled", event.params.orderIds); } else { console.log("OTC order cancelled", event.params.orderHash); } } }, }} /> ``` *** ## `onFillOTCOrder` Fires when the user fills an existing OTC order (acts as the taker). **Sub-events:** `FillOTCOrder:request`, `FillOTCOrder:sent`, `FillOTCOrder:confirmed`, `FillOTCOrder:failed`. **Params:** `orderHash`, `orderType: "OTC"`, `orderSubType`, `txHash` (if sent+), `callsId` (if sendCalls), `txReceipt` (if confirmed), `callsReceipt`, `error` (if failed). *** ## `onSettingsChange` Fires when the user changes widget settings. **Sub-events:** * `Settings:switchSwapMode` — Switched between Market and Delta. Params: `{ swapMode: "market" | "delta" }`. * `Settings:saveSettings` — User saved settings. Payload is the full `SettingsState`: `slippageTolerance`, `transactionSpeed` (`"slow" | "standard" | "fast" | "custom"`), `swapMode`, `eip1559Enabled`, `degenMode`, `disabledDexes`, `bridgePreference` (`"auto" | "fastest" | "bestReturn"`), `disabledBridges`. * `Settings:changeBridgePreferences` — Bridge preferences changed independently (e.g. from Compare Quotes). Params: `bridgePreference`, `disabledBridges`. ```tsx theme={null} { if (event.name === "Settings:saveSettings") { console.log("New slippage", event.params.slippageTolerance); } }, }} /> ``` *** ## `onFormInputChange` Fires whenever any input changes in any trading form. **Sub-event:** `FormInput:change`. **Params (discriminated by `form`):** Common to all variants: | Param | Description | | --------------------------- | ----------------------------------------------------------------------- | | `form` | `"swap" \| "limit" \| "otc" \| "twap"`. | | `tokenFrom` | `MinTradeFlowToken` — source token. | | `tokenTo` | `MinTradeFlowToken` — destination token (may be absent until selected). | | `srcChainId`, `destChainId` | Chain IDs (`destChainId` may be absent). | | `receiverAddress` | Optional — defaults to connected account. | Variant-specific: * `form: "swap"` — adds `side: "SELL" | "BUY"`. When `side === "SELL"`, payload carries `sendAmount` (not `receiveAmount`); when `side === "BUY"`, `receiveAmount` (not `sendAmount`). * `form: "twap"` — adds `side`, `orderSplit` (slice count), `orderInterval` (seconds), `orderDeadline` (Unix seconds), `slippage`. * `form: "limit"` — adds `limitPrice`, `orderDeadline`. Both `sendAmount` and `receiveAmount` present. * `form: "otc"` — adds `otcPrice`, `orderDeadline`. Both `sendAmount` and `receiveAmount` present. ```tsx theme={null} { console.log("Form changed", { form: event.params.form, from: event.params.tokenFrom?.symbol, to: event.params.tokenTo?.symbol, }); }, }} /> ``` *** ## `onPriceChange` Fires when price info refreshes or the price-query state changes. **Sub-events:** * `PriceUpdate` — Price was successfully (re)fetched. * `PriceQueryUpdate` — Price-query state changed (data, isLoading, error). **Params:** | Param | Description | | ------------ | ------------------------------------------------------------------------------- | | `priceMode` | `"delta" \| "market"`. | | `price` | Price object (`DeltaPrice \| BridgePrice` for Delta, `OptimalRate` for market). | | `isLoading` | (`PriceQueryUpdate`) First-time fetch in progress. | | `isFetching` | (`PriceQueryUpdate`) Refetching. | | `isError` | (`PriceQueryUpdate`) Whether the query errored. | | `error` | (`PriceQueryUpdate`) Error or `null`. | ```tsx theme={null} { if (event.name === "PriceUpdate") { console.log("New price", event.params.priceMode, event.params.price); } }, }} /> ``` *** ## Lifecycle of a successful market swap For a wallet-connected market swap that requires token approval, events fire in this order: 1. `onConnectWallet` — `ConnectWallet:click` (user clicks), then `ConnectWallet:connect` once a wallet attaches. 2. `onFormInputChange` — `FormInput:change` for every field edit. 3. `onPriceChange` — `PriceQueryUpdate` (loading / refetching) and `PriceUpdate` (successful fetch) as quotes refresh. 4. `onAllowToken` — `AllowToken:request` → `AllowToken:sent` → `AllowToken:confirmed`. Skipped if allowance already covers the trade or the flow uses a permit signature only. 5. `onWrapETH` — for Delta Swaps with ETH as `tokenFrom`, the user is asked to wrap first: `WrapETH:click` → `WrapETH:request` → `WrapETH:sent` → `WrapETH:confirmed`. 6. `onSwap` — `Swap:click` → `Swap:request` → `Swap:sent` → `Swap:confirmed`. Replace with `Swap:failed` or `Swap:cancelled` on the unhappy path. 7. `onCancelTx` — only if the user explicitly cancels a pending market swap tx: `CancelTx:request` → `CancelTx:sent` → `CancelTx:confirmed`. Delta Swaps replace step 4/5/6 with a single Delta order submission (`Swap:sent` with `swapMode: "delta"` and an `order` param). The order is filled off-band, so `Swap:confirmed` may arrive minutes later, or be missed entirely if the user closes the widget. Limit, OTC, and TWAP flows replace step 6 with their respective callbacks (`onLimitOrder`, `onOTCOrder`, `onTwapOrder`). ## Related pages * [Wallet management](/docs/widget/wallet-management) — `onConnectWallet` and `onConnectWalletClick` patterns. * [Widget API reference](/docs/widget/widget-api-reference) — full callback type signatures. # Velora Widget Next.js example Source: https://new-docs.velora.xyz/docs/widget/examples/nextjs End-to-end widget integration for the Next.js app router, with a client-only mount and a /swap route. A Next.js 14+ app-router integration that mounts the Velora Widget at `/swap`. The widget reads `window` and `localStorage` on mount, so it must be client-only. We use `next/dynamic` with `ssr: false`. ## File tree ```text theme={null} my-app/ ├─ package.json ├─ next.config.js └─ src/app/ ├─ layout.tsx ├─ page.tsx └─ swap/ ├─ page.tsx └─ widget.tsx ``` ## Install ```bash pnpm theme={null} pnpm create next-app@latest my-app --typescript --app cd my-app pnpm add @velora-dex/widget @tanstack/react-query ``` ```bash npm theme={null} npx create-next-app@latest my-app --typescript --app cd my-app npm install @velora-dex/widget @tanstack/react-query ``` ```bash yarn theme={null} yarn create next-app my-app --typescript --app cd my-app yarn add @velora-dex/widget @tanstack/react-query ``` ## `src/app/layout.tsx` ```tsx theme={null} export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} ); } ``` ## `src/app/swap/widget.tsx` The widget itself, wrapped in `dynamic(... { ssr: false })`. ```tsx theme={null} "use client"; import dynamic from "next/dynamic"; const Widget = dynamic( () => import("@velora-dex/widget").then((m) => ({ default: m.Widget })), { ssr: false, loading: () =>
Loading widget…
} ); export default function ClientWidget() { return ( ); } ``` ## `src/app/swap/page.tsx` ```tsx theme={null} import ClientWidget from "./widget"; export default function SwapPage() { return (
); } ``` ## `.env.local` ```env theme={null} NEXT_PUBLIC_PARTNER_KEY=my-app-name ``` Restart `next dev` after creating or changing `.env.local`. ## Run it ```bash theme={null} pnpm dev ``` Visit [http://localhost:3000/swap](http://localhost:3000/swap). You should see the widget render with **Connect Wallet** in the header. ## Why `ssr: false`? The widget reads `window`, `localStorage`, and `prefers-color-scheme` on mount. None of those exist during server rendering. `dynamic(... { ssr: false })` defers the import to the browser, so the widget only ever runs client-side. If you forget `ssr: false`, you'll see a hydration-mismatch error or a `window is not defined` exception. ## With dApp-mode wallet If your app already manages the wallet (wagmi, RainbowKit, or any other host-side wallet library), switch to dApp mode and pass the provider: ```tsx theme={null} "use client"; import dynamic from "next/dynamic"; import { useConnection, useWalletClient } from "wagmi"; const Widget = dynamic( () => import("@velora-dex/widget").then((m) => ({ default: m.Widget })), { ssr: false } ); export default function ClientWidget() { const { connector } = useConnection(); const { data: walletClient } = useWalletClient(); // Hand the EIP-1193 provider to the widget once a wallet is connected. const provider = walletClient?.transport; return ( { // host-app wallet modal openConnectModal(); }, }} /> ); } ``` See [Wallet management](/docs/widget/wallet-management) for the full pattern. ## Related pages * [Install](/docs/widget/install) — package install and basic setup. * [Wallet management](/docs/widget/wallet-management) — standalone vs dApp mode. * [Compatibility](/docs/widget/compatibility) — full SSR notes. * [React example](/docs/widget/examples/react) — same widget on a Vite stack. # Velora Widget React example Source: https://new-docs.velora.xyz/docs/widget/examples/react End-to-end widget integration for a Vite + React app: full file tree, install, and mount. A minimal Vite + React app that mounts the Velora Widget. Copy each file and run `pnpm dev` (or `npm run dev`). ## File tree ```text theme={null} my-app/ ├─ index.html ├─ package.json ├─ vite.config.ts └─ src/ ├─ main.tsx └─ App.tsx ``` ## Install ```bash pnpm theme={null} pnpm create vite@latest my-app -- --template react-ts cd my-app pnpm add @velora-dex/widget @tanstack/react-query ``` ```bash npm theme={null} npm create vite@latest my-app -- --template react-ts cd my-app npm install @velora-dex/widget @tanstack/react-query ``` ```bash yarn theme={null} yarn create vite my-app --template react-ts cd my-app yarn add @velora-dex/widget @tanstack/react-query ``` ## `src/App.tsx` ```tsx theme={null} import { useMemo } from "react"; import { Widget } from "@velora-dex/widget"; export default function App() { const config = useMemo( () => ({ theme: "light" as const, partnerConfig: { partner: "my-app-name" }, }), [] ); return (
); } ``` ## `src/main.tsx` ```tsx theme={null} import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import App from "./App"; createRoot(document.getElementById("root")!).render( ); ``` ## Run it ```bash theme={null} pnpm dev ``` Open the printed `http://localhost:5173` URL. You should see the widget render with the **Connect Wallet** button and a swap form. ## Next: wire in events and a `partner` identifier ```tsx theme={null} import { Widget } from "@velora-dex/widget"; { if (event.name === "Swap:confirmed") { console.log("Swap confirmed", event.params.txHash); } }, }} />; ``` Add the `partner` identifier to `.env`: ```env theme={null} VITE_VELORA_PARTNER=my-app-name ``` ## Related pages * [Install](/docs/widget/install) — package install and the basic setup. * [Configure](/docs/widget/configure) — restrict chains, modes, hide UI. * [Monetize](/docs/widget/monetize) — partner fees and referrer. * [Events & callbacks](/docs/widget/events-and-callbacks) — every event you can subscribe to. # Install @velora-dex/widget Source: https://new-docs.velora.xyz/docs/widget/install Install @velora-dex/widget and render the swap widget in your React app. The Velora Widget is a React component published as [`@velora-dex/widget`](https://www.npmjs.com/package/@velora-dex/widget). Install it alongside `@tanstack/react-query` and render it anywhere in your component tree. ## Install the package ```bash pnpm theme={null} pnpm add @velora-dex/widget @tanstack/react-query ``` ```bash npm theme={null} npm install @velora-dex/widget @tanstack/react-query ``` ```bash yarn theme={null} yarn add @velora-dex/widget @tanstack/react-query ``` ### Peer dependencies | Package | Version | | ----------------------- | ---------------- | | `react` | `18.x` or `19.x` | | `react-dom` | `18.x` or `19.x` | | `@tanstack/react-query` | `^5.90` | ## Render the widget Drop `` anywhere in your component tree. `@tanstack/react-query` only needs to be installed; the widget manages its own query client, so no provider setup is required. ```tsx theme={null} import { Widget } from "@velora-dex/widget"; export default function App() { return ; } ``` That's it. The widget mounts with sensible defaults: system-preference theme, all supported chains, Delta enabled, and built-in wallet connectors. The widget's compiled stylesheet is auto-injected when you import `Widget`, so no extra `.css` import is required. If your bundler strips side-effect imports aggressively, you can force-include it with `import "@velora-dex/widget/styles.css"`. ## Verify it works You should see the swap form render with: * A **Connect Wallet** button in the header * Source and destination token pickers * A trade-mode toggle (Swap / Limit / OTC / TWAP) ## Next steps Restrict chains, pick trade modes, set theme, hide UI elements. Use the built-in wallet connectors or bring your own EIP-1193 provider. Collect partner fees on every swap routed through your integration. Working setups for Vite + React and Next.js app router. # Monetize Widget swaps Source: https://new-docs.velora.xyz/docs/widget/monetize Collect partner fees or surplus revenue from every swap routed through the widget. The widget supports two monetization surfaces: * `partnerConfig` — fee or surplus share on every swap that completes through your integration. * `referrerConfig` — a referrer wallet that receives a share of protocol revenue. Both are optional and independent. ## Partner fees Pass `partnerConfig` inside `config` to identify your integration and (optionally) take a cut of each swap. ```tsx theme={null} ``` ### `PartnerConfig` fields | Field | Type | Description | | --------------------- | --------- | --------------------------------------------------------------------------------------------------- | | `partner` | `string` | Your `partner` identifier (e.g. `"my-app-name"`). Used for attribution and analytics. | | `partnerAddress` | `Address` | Optional. Ethereum address that receives the fee. Overrides the address derived from `partner`. | | `partnerFeeBps` | `number` | Optional. Fee in basis points. `25` = 0.25%. Max `200` (2%). | | `partnerTakesSurplus` | `boolean` | Optional. When `true`, you receive 50% of swap surplus instead of a fixed fee. Defaults to `false`. | If both `partnerFeeBps` and `partnerTakesSurplus` are set, `partnerFeeBps` wins. To take surplus instead of a fixed fee, set `partnerTakesSurplus: true` and leave `partnerFeeBps` unset. Either `partner` or `partnerAddress` must be present for partner features to activate. ### Choosing between fee and surplus | | Fixed fee (`partnerFeeBps`) | Surplus share (`partnerTakesSurplus`) | | --------- | -------------------------------------------------- | ----------------------------------------------------------------- | | Revenue | Predictable per-trade cut | Variable; depends on routing edge | | User cost | Worse quotes (fee comes off the top) | Same quote as no-fee: surplus is the *better-than-quoted* portion | | Max | 2% (`partnerFeeBps: 200`) | 50% of surplus | | Best for | Mass-market integrations where a known cut matters | High-volume integrations that prioritize the user-facing rate | ### Example: fixed-fee integration ```tsx theme={null} import { Widget } from "@velora-dex/widget"; export function Swap() { return ( ); } ``` ### Example: surplus-share integration ```tsx theme={null} ``` ## Referrer revenue Pass a `referrerConfig` to attribute swaps to a referrer wallet that receives a share of protocol revenue. This is independent of `partnerConfig`: you can set one, both, or neither. ```tsx theme={null} ``` ### `ReferrerConfig` fields | Field | Type | Description | | ----------------- | --------- | --------------------------------------------------------------------------------------------- | | `referrerAddress` | `Address` | Ethereum address that receives the referrer share. Required to activate referrer attribution. | ## Production tips Load `partner` from an environment variable so staging, production, and white-label builds can use different identifiers without code changes. Memoize `partnerConfig` like every other non-primitive config field; a new object on every render forces the widget to re-render. And audit `partnerAddress` before shipping: once a swap is routed, fees pay to it on-chain, so treat it like any other treasury address. ## Related pages * [Configure](/docs/widget/configure) — all other config fields. * [Widget API reference](/docs/widget/widget-api-reference) — full `PartnerConfig` / `ReferrerConfig` types. # Velora swap widget Source: https://new-docs.velora.xyz/docs/widget/overview Embed the Velora swap widget in your React app with @velora-dex/widget. Multi-chain swaps, limit orders, OTC, and TWAP in a single drop-in component. The Velora Widget is a React component that gives your users a complete trading interface (swaps, limit orders, OTC, and TWAP) across every chain Velora supports. Drop `` into your app and you have a working DEX inside your product. ## Try it live Configure chains, tokens, theme, and partner fees in a live preview. Opens in a new tab. ## What you get Same-chain and crosschain across Ethereum, Polygon, BNB, Avalanche, Arbitrum, Optimism, Base, Gnosis, and Unichain. Powered by [Delta](/docs/delta/overview). Gasless and MEV-protected. Built-in wagmi connectors out of the box, or bring your own EIP-1193 provider. Take a fee or a surplus share on every trade. See [Monetize](/docs/widget/monetize). Light and dark themes with automatic system-preference detection. CSS scoped under `.velora-widget` to avoid leaking. Full TypeScript types for config, events, and form state. ## Quick example ```tsx theme={null} import { Widget } from "@velora-dex/widget"; export default function App() { return ( ); } ``` ## How it works The widget is a single React component shipped as `@velora-dex/widget`: * Quotes come from the same [Delta API](/docs/api-reference/delta/overview) and [Market API](/docs/api-reference/market/overview) you'd hit from the SDK; there's no separate widget backend. * Wallet uses either the widget's built-in wagmi connectors (default, `widgetMode: "standalone"`) or an EIP-1193 provider you pass (`widgetMode: "dapp"`). * Styles are auto-injected on import and scoped under `.velora-widget` so they don't leak into your app. * State is owned by the widget, but every important transition fires through the `events` prop so you can sync analytics or your own UI. ## Pick your starting point Add `@velora-dex/widget` and render the component. Restrict chains, pick trade modes, hide UI elements. Built-in connectors vs bring-your-own EIP-1193 provider. Take a fee or surplus share on every swap. Hook into every lifecycle event for analytics and host-app sync. A minimal Vite + React integration. # Velora Widget wallet management Source: https://new-docs.velora.xyz/docs/widget/wallet-management Use the widget's built-in wallet connectors or bring your own EIP-1193 provider from the host app. The widget supports two wallet ownership models, controlled by the `widgetMode` config field. | Mode | Who owns the wallet | When to use | | -------------------------- | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | `"standalone"` *(default)* | The widget. Uses built-in wagmi connectors (injected wallets, WalletConnect, EIP-6963 discovery). | Standalone trading pages; landing pages; embeds where the host app has no wallet flow. | | `"dapp"` | The host app. Pass an EIP-1193 `provider` and handle Connect Wallet clicks yourself. | dApps that already have a wallet connection (wagmi, RainbowKit, Web3Modal, etc.). | ## Standalone mode In `standalone` mode the widget renders its own Connect Wallet button and handles the full connector flow using built-in wagmi connectors. No extra configuration needed. ```tsx theme={null} // default; can be omitted ``` ### Optional: add Privy as a connector If you want Privy in the connector list (alongside the built-in connectors), pass `privyAppId`. Privy is **not** required; the widget works without it. ```tsx theme={null} ``` ## dApp mode: bring your own provider Set `widgetMode: "dapp"` and pass an EIP-1193 provider. Your host app is responsible for connecting the wallet. ```tsx theme={null} { // open your host app's wallet modal openConnectModal(); }, }} /> ``` ### The `provider` prop Must satisfy `EIP1193ProviderLax`. This is a looser version of viem's `EIP1193Provider`, since many third-party wallets don't satisfy viem's strict signature: ```ts theme={null} type EIP1193ProviderLax = { request: (args: { method: any; params?: any }) => Promise; on: (event: any, callback: (arg: unknown) => void) => void; removeListener: (event: any, callback: (arg: unknown) => void) => void; }; ``` Most wallet connectors (wagmi connectors, RainbowKit, raw `window.ethereum`) satisfy this shape. ### The Connect Wallet button in dApp mode In `dapp` mode the widget's internal Connect Wallet drawer is **not** rendered. Without an `onConnectWalletClick` event handler, the button is disabled. With one, the button is enabled but still won't open the widget's own drawer: you must run your host app's wallet connection flow inside the handler. ```tsx theme={null} { // host-app responsibility, e.g. open RainbowKit modal openConnectModal(); }, }} /> ``` ### Hide the wallet UI entirely If your host app shows the connected account elsewhere, hide the widget's wallet header: ```tsx theme={null} ``` ## Decision tree ```text theme={null} Does your host app already manage the user wallet? ├── No → widgetMode: "standalone" (optionally add privyAppId for Privy) └── Yes → widgetMode: "dapp" + provider + onConnectWalletClick └── Already show the connected account in the host UI? └── Yes → excludeUI: ["wallet-management"] ``` ## Connection events Both modes emit `onConnectWallet` events you can use for analytics. See [Events & callbacks](/docs/widget/events-and-callbacks#onconnectwallet) for payload details. ```tsx theme={null} { if (event.name === "ConnectWallet:connect") { analytics.track("wallet_connected", { connector: event.params.connectorType, action: event.params.connectorAction, }); } }, }} /> ``` ## Related pages * [Configure](/docs/widget/configure) — other config fields. * [Events & callbacks](/docs/widget/events-and-callbacks) — `onConnectWallet`, `onConnectWalletClick`. * [Widget API reference](/docs/widget/widget-api-reference) — full `EIP1193ProviderLax` type. # Velora Widget props and types Source: https://new-docs.velora.xyz/docs/widget/widget-api-reference Props, exports, and TypeScript types for @velora-dex/widget. This page is the type-and-prop reference for `@velora-dex/widget`. For task-oriented walkthroughs, see [Configure](/docs/widget/configure), [Wallet management](/docs/widget/wallet-management), [Monetize](/docs/widget/monetize), and [Events & callbacks](/docs/widget/events-and-callbacks). ## Public exports Everything below can be imported from `@velora-dex/widget`: | Export | Kind | Purpose | | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------ | | `Widget` | component | The main widget React component. | | `defaults` | value | `{ tokenLists, chainIds, tradeModes }` — defaults the widget uses when the corresponding config option is omitted. | | `WidgetProps` | type | Props of ``. | | `WidgetConfig` | type | Configuration object passed via the `config` prop. | | `WidgetTheme` | type | `"light" \| "dark"`. | | `WidgetElements` | type | Keys accepted by `config.excludeUI`. | | `EIP1193ProviderLax` | type | Provider shape accepted by the `provider` prop. | | `SupportedChainId` | type | Union of supported chain IDs. | | `SwapMode` | type | `"market" \| "delta"` — used in event payloads. | | `TradeMode` | type | `"swap" \| "limit" \| "otc" \| "twap"`. | | `FormInputProps` | type | Shape of the `input` prop. | | `MinTradeFlowToken` | type | Token shape used in event payload `tokenFrom` / `tokenTo`. | | `WidgetState`, `AccountState`, `SettingsState`, `SwapFormState`, `LimitOrderFormState`, `OTCOrderFormState`, `TwapFormState`, `TokenFormState` | type | Pieces of widget state passed to every event callback as `state`. | | `WidgetEventCallbacks` | type | Shape of the `events` prop. | | `OnConnectWallet`, `OnAllowToken`, `OnWrapETH`, `OnSwap`, `OnTwapOrder`, `OnLimitOrder`, `OnOTCOrder`, `OnSettingsChange`, `OnCancelOrder`, `OnCancelTx`, `OnFillOTCOrder`, `OnFormInputChange`, `OnPriceChange` | type | Individual event-callback types. | `ApiConfig` is not re-exported by name even though it's the shape of the `apiConfig` prop. Infer it via `WidgetProps["apiConfig"]` if you need a named type. ## `` props ```ts theme={null} interface WidgetProps { config?: WidgetConfig; apiConfig?: ApiConfig; provider?: EIP1193ProviderLax; events?: WidgetEventCallbacks; input?: FormInputProps; } ``` | Prop | Type | Required | Purpose | | ----------- | ---------------------- | -------- | -------------------------------------------------- | | `config` | `WidgetConfig` | No | Widget configuration. | | `apiConfig` | `ApiConfig` | No | API key and headers for backend requests. | | `provider` | `EIP1193ProviderLax` | No | EIP-1193 provider when using `widgetMode: "dapp"`. | | `events` | `WidgetEventCallbacks` | No | Event callbacks. | | `input` | `FormInputProps` | No | Initial form state (tokens, amounts, form type). | ```tsx theme={null} console.log(event.name) }} input={{ selectedForm: "swap", tokenFromAddress: "0x..." }} /> ``` ## `WidgetConfig` ```ts theme={null} interface WidgetConfig { theme?: WidgetTheme; enableDelta?: boolean; enableCrossChain?: boolean; partnerConfig?: PartnerConfig; referrerConfig?: ReferrerConfig; privyAppId?: string; privyClientId?: string; debug?: boolean; widgetMode?: "dapp" | "standalone"; enableDegenMode?: boolean; tokenLists?: string[]; srcChains?: SupportedChainId[]; destChains?: SupportedChainId[]; tradeModes?: TradeMode[]; excludeUI?: WidgetElements[]; } ``` Field-by-field documentation lives on [Configure](/docs/widget/configure). Monetization fields are documented on [Monetize](/docs/widget/monetize). Wallet-related fields on [Wallet management](/docs/widget/wallet-management). ## `ApiConfig` ```ts theme={null} interface ApiConfig { apiKey?: string; headers?: Record; } ``` Forwarded to the Velora SDK on every backend request (prices, swap construction, Delta order submission). Use when integrating against an authenticated tier or a partner-proxied endpoint. | Field | Type | Description | | --------- | ------------------------ | ------------------------------------------- | | `apiKey` | `string` | API key sent with requests. | | `headers` | `Record` | Extra HTTP headers (custom auth, metadata). | ```tsx theme={null} ``` This is client-side code. Don't embed secrets you wouldn't put in a public bundle. ## `EIP1193ProviderLax` Many wallets don't satisfy viem's strict `EIP1193Provider` signature, so the widget accepts a looser shape: ```ts theme={null} type EIP1193ProviderLax = { request: (args: { method: any; params?: any }) => Promise; on: (event: any, callback: (arg: unknown) => void) => void; removeListener: (event: any, callback: (arg: unknown) => void) => void; }; ``` Used with `widgetMode: "dapp"`. See [Wallet management](/docs/widget/wallet-management). ## `FormInputProps` Pre-populate the form on mount, useful for deep links and programmatic control. ```ts theme={null} interface FormInputProps { selectedForm?: "swap" | "limit" | "otc" | "twap"; tokenFromAddress?: Address; srcChainId?: SupportedChainId; tokenToAddress?: Address; destChainId?: SupportedChainId; sendAmount?: string; receiveAmount?: string; side?: "BUY" | "SELL"; orderDeadline?: string; } ``` ### `selectedForm` `"swap" | "limit" | "otc" | "twap"` — defaults to `"swap"`. Corresponds to `tradeMode` in events. ### `tokenFromAddress` `Address` — the source-token address to pre-select. Pair with `srcChainId`. ### `srcChainId` `SupportedChainId` — chain for the source token. Required when `tokenFromAddress` is provided. ### `tokenToAddress` `Address` — the destination-token address to pre-select. Pair with `destChainId` (or omit for same-chain). ### `destChainId` `SupportedChainId` — chain for the destination token. Only functional when `selectedForm` is `"swap"` (crosschain). For limit and OTC, it's forced to match `srcChainId`. ### `sendAmount` `string` — initial amount to send, in token units (not wei). Must parse as a number. ### `receiveAmount` `string` — initial amount to receive, in token units. Mutually exclusive with `sendAmount` for the same trade-side. ### `side` `"BUY" | "SELL"` — only for `selectedForm: "swap"` or `"twap"`. If omitted, defaults to `"SELL"` when `sendAmount` is set and `"BUY"` when `receiveAmount` is set. If both or neither amounts are present, the user's UI selection wins. ### `orderDeadline` `string` — Unix timestamp (seconds), as a numeric string. Only functional when `selectedForm` is `"limit"` or `"otc"`. For Delta Limit Orders, the minimum recommended expiry is `now + 10 minutes`. For OTC, `"0"` means no expiry. The widget doesn't reject invalid values at prop time — they surface in the trade flow. ```tsx theme={null} ``` For native ETH, pass the special address `"0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"`. ## `WidgetEventCallbacks` ```ts theme={null} interface WidgetEventCallbacks { onConnectWallet?: OnConnectWallet; onConnectWalletClick?: OnConnectWallet; onAllowToken?: OnAllowToken; onWrapETH?: OnWrapETH; onSwap?: OnSwap; onTwapOrder?: OnTwapOrder; onCancelTx?: OnCancelTx; onLimitOrder?: OnLimitOrder; onOTCOrder?: OnOTCOrder; onSettingsChange?: OnSettingsChange; onCancelOrder?: OnCancelOrder; onFillOTCOrder?: OnFillOTCOrder; onFormInputChange?: OnFormInputChange; onPriceChange?: OnPriceChange; } ``` Each callback receives `{ event, state }` where `event` is a discriminated union on `event.name` and `state` is a snapshot of the full widget state. Detailed sub-event names, params, and lifecycle ordering live on [Events & callbacks](/docs/widget/events-and-callbacks). ## `defaults` ```ts theme={null} import { defaults } from "@velora-dex/widget"; defaults.chainIds; // SupportedChainId[] defaults.tokenLists; // string[] defaults.tradeModes; // TradeMode[] ``` Use to compose custom values that include or exclude defaults: ```tsx theme={null} const srcChains = defaults.chainIds.filter((id) => id !== 1); // all except Ethereum const tokenLists = [...defaults.tokenLists, "https://example.com/my-tokens.json"]; ``` ## Related pages * [Configure](/docs/widget/configure) — `WidgetConfig` field walkthroughs. * [Wallet management](/docs/widget/wallet-management) — `widgetMode`, `provider`, optional Privy connector. * [Monetize](/docs/widget/monetize) — `partnerConfig`, `referrerConfig`. * [Events & callbacks](/docs/widget/events-and-callbacks) — per-callback sub-events and params.