diff --git a/api-reference/delta-v2/agents-list.mdx b/api-reference/delta-v2/agents-list.mdx new file mode 100644 index 0000000..337fab1 --- /dev/null +++ b/api-reference/delta-v2/agents-list.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/agents/list/{chainId}" +description: "List the active solver agents competing in the auction for a chain. Use the names to filter pricing via includeAgents / excludeAgents." +openapi: "/api-reference/specs/delta-v2.json GET /delta/v2/agents/list/{chainId}" +--- diff --git a/api-reference/delta-v2/bridge-protocols.mdx b/api-reference/delta-v2/bridge-protocols.mdx new file mode 100644 index 0000000..1cea4b7 --- /dev/null +++ b/api-reference/delta-v2/bridge-protocols.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/prices/bridge-protocols" +description: "Active bridge protocols (slug, display name, icon) for rendering a bridge picker." +openapi: "/api-reference/specs/delta-v2.json GET /delta/v2/prices/bridge-protocols" +--- diff --git a/api-reference/delta-v2/bridge-routes.mdx b/api-reference/delta-v2/bridge-routes.mdx new file mode 100644 index 0000000..9a22e99 --- /dev/null +++ b/api-reference/delta-v2/bridge-routes.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/prices/bridge-routes" +description: "Crosschain bridge-route catalogue: every supported (srcChainId, destChainId, tokens) triple." +openapi: "/api-reference/specs/delta-v2.json GET /delta/v2/prices/bridge-routes" +--- diff --git a/api-reference/delta-v2/is-token-supported.mdx b/api-reference/delta-v2/is-token-supported.mdx new file mode 100644 index 0000000..f4c7512 --- /dev/null +++ b/api-reference/delta-v2/is-token-supported.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/prices/is-token-supported" +description: "Quick yes/no check for token support on a chain." +openapi: "/api-reference/specs/delta-v2.json GET /delta/v2/prices/is-token-supported" +--- diff --git a/api-reference/delta-v2/orders-build.mdx b/api-reference/delta-v2/orders-build.mdx new file mode 100644 index 0000000..57ac38c --- /dev/null +++ b/api-reference/delta-v2/orders-build.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/orders/build" +description: "Server-built EIP-712 typed data ready to sign. Pass the route from /delta/v2/prices verbatim." +openapi: "/api-reference/specs/delta-v2.json POST /delta/v2/orders/build" +--- diff --git a/api-reference/delta-v2/orders-cancel.mdx b/api-reference/delta-v2/orders-cancel.mdx new file mode 100644 index 0000000..8b8147c --- /dev/null +++ b/api-reference/delta-v2/orders-cancel.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/orders/cancel" +description: "Cancel one or more open Delta V2 orders by ID." +openapi: "/api-reference/specs/delta-v2.json POST /delta/v2/orders/cancel" +--- diff --git a/api-reference/delta-v2/orders-fillable-balance.mdx b/api-reference/delta-v2/orders-fillable-balance.mdx new file mode 100644 index 0000000..6ed7716 --- /dev/null +++ b/api-reference/delta-v2/orders-fillable-balance.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/orders/fillablebalance/{chainId}/{userAddress}" +description: "User's source-token balance minus any amounts already committed to open limit orders. Use it when sizing a new limit order." +openapi: "/api-reference/specs/delta-v2.json GET /delta/v2/orders/fillablebalance/{chainId}/{userAddress}/{tokenAddress}" +--- diff --git a/api-reference/delta-v2/orders-get-by-hash.mdx b/api-reference/delta-v2/orders-get-by-hash.mdx new file mode 100644 index 0000000..d7950fd --- /dev/null +++ b/api-reference/delta-v2/orders-get-by-hash.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/orders/hash/{hash}" +description: "Fetch a Delta V2 order by its EIP-712 hash — useful before the order id is assigned." +openapi: "/api-reference/specs/delta-v2.json GET /delta/v2/orders/hash/{hash}" +--- diff --git a/api-reference/delta-v2/orders-get-by-id.mdx b/api-reference/delta-v2/orders-get-by-id.mdx new file mode 100644 index 0000000..0cf4292 --- /dev/null +++ b/api-reference/delta-v2/orders-get-by-id.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/orders/{orderId}" +description: "Fetch a Delta V2 order by its UUID — the id returned by POST /delta/v2/orders." +openapi: "/api-reference/specs/delta-v2.json GET /delta/v2/orders/{orderId}" +--- diff --git a/api-reference/delta-v2/orders-list.mdx b/api-reference/delta-v2/orders-list.mdx new file mode 100644 index 0000000..f363b2a --- /dev/null +++ b/api-reference/delta-v2/orders-list.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/orders" +description: "Paginated list of a user's Delta V2 orders, filterable by chain, status, type, and on-chain order type." +openapi: "/api-reference/specs/delta-v2.json GET /delta/v2/orders" +--- diff --git a/api-reference/delta-v2/orders-submit.mdx b/api-reference/delta-v2/orders-submit.mdx new file mode 100644 index 0000000..0e77ffe --- /dev/null +++ b/api-reference/delta-v2/orders-submit.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/orders" +description: "Submit a signed Delta V2 order. The relayer validates signature, balance, and allowance, then enrolls it into the sealed-bid auction." +openapi: "/api-reference/specs/delta-v2.json POST /delta/v2/orders" +--- diff --git a/api-reference/delta-v2/overview.mdx b/api-reference/delta-v2/overview.mdx new file mode 100644 index 0000000..d4b646a --- /dev/null +++ b/api-reference/delta-v2/overview.mdx @@ -0,0 +1,65 @@ +--- +title: "Delta V2 API" +description: "Server-built EIP-712 orders, route-based pricing with alternatives, paginated history, and a unified status model. Recommended path for new Delta integrations." +keywords: ["delta", "delta v2", "api-reference"] +--- + +Delta V2 is the recommended path for Delta integrations. The on-chain contracts and settlement model are identical to [Delta V1](/api-reference/delta/overview); the protocol surface changes for the better: + +- **Server-built orders.** `POST /delta/v2/orders/build` returns EIP-712 typed data ready to sign — clients don't compose `domain`, `types`, and `value` locally. +- **Route-based pricing.** `GET /delta/v2/prices` returns a recommended `route` plus `alternatives` so users can pick a different bridge or path. +- **Paginated history.** `GET /delta/v2/orders` returns `{ data, total, page, limit, hasMore }`. +- **Unified status model.** Eleven values (`PENDING`, `AWAITING_SIGNATURE`, `ACTIVE`, `SUSPENDED`, `CANCELLING`, `BRIDGING`, `COMPLETED`, `FAILED`, `EXPIRED`, `CANCELLED`, `REFUNDED`) replace the V1 split between `status` + `bridgeStatus`. +- **Server-resolved partner fee.** Pass `partner` / `partnerAddress` / `partnerFeeBps` raw — the server validates and encodes them. No client-side `getPartnerFee` round-trip. + +## Lifecycle + + + + `GET /delta/v2/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 /delta/v2/orders/build` — returns `{ toSign: { domain, types, value }, orderHash }`. + + + Sign `toSign` with `signTypedData` on the user's wallet. + + + `POST /delta/v2/orders` — passes `order: toSign.value` and `signature` to the relayer. + + + `GET /delta/v2/orders/{orderId}` until `status === "COMPLETED"` (or a terminal failure). + + + +## Endpoints + +| Method | Path | Purpose | +|---|---|---| +| `GET` | `/delta/v2/prices` | Recommended route + alternatives, same-chain or crosschain | +| `GET` | `/delta/v2/prices/bridge-routes` | Supported `(srcChainId, destChainId, tokens)` triples | +| `GET` | `/delta/v2/prices/bridge-protocols` | Active bridge protocols (slug, name, icon) | +| `GET` | `/delta/v2/prices/strategies/{chainId}` | Delta yield strategies with APR | +| `GET` | `/delta/v2/prices/is-token-supported` | Quick token-support check | +| `POST` | `/delta/v2/orders/build` | Server-built EIP-712 typed data ready to sign | +| `POST` | `/delta/v2/orders` | Submit a signed order | +| `POST` | `/delta/v2/orders/cancel` | Sign-and-post cancellation | +| `GET` | `/delta/v2/orders` | List a user's orders (paginated) | +| `GET` | `/delta/v2/orders/{orderId}` | Order by UUID | +| `GET` | `/delta/v2/orders/hash/{hash}` | Order by EIP-712 hash | +| `GET` | `/delta/v2/orders/fillablebalance/...` | Fillable balance for limit-order sizing | +| `GET` | `/delta/v2/agents/list/{chainId}` | List active auction agents | + +## SDK shortcut + +Every endpoint is wrapped by [`sdk.deltaV2.*`](/sdk/modules/delta) — the SDK handles signing, partner-fee defaults, and the build → sign → post orchestration. For a 5-minute walkthrough see [SDK → Delta module](/sdk/modules/delta). + +## Related pages + +- [Why Delta](/delta/overview) — protocol overview. +- [Order lifecycle and status codes](/delta/order-lifecycle-and-status-codes) — the V2 status model end-to-end. +- [SDK → Delta module](/sdk/modules/delta) — TypeScript examples (V2 primary, V1 below). +- [Delta V1 API](/api-reference/delta/overview) — the V1 surface, still fully supported. diff --git a/api-reference/delta-v2/prices.mdx b/api-reference/delta-v2/prices.mdx new file mode 100644 index 0000000..57d3b62 --- /dev/null +++ b/api-reference/delta-v2/prices.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/prices" +description: "Recommended route plus alternatives for a same-chain or crosschain Delta V2 swap." +openapi: "/api-reference/specs/delta-v2.json GET /delta/v2/prices" +--- diff --git a/api-reference/delta-v2/strategies.mdx b/api-reference/delta-v2/strategies.mdx new file mode 100644 index 0000000..bb130ab --- /dev/null +++ b/api-reference/delta-v2/strategies.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/v2/prices/strategies/{chainId}" +description: "Delta yield strategies (with APR) wired for ProductiveOrder swaps, keyed by underlying token." +openapi: "/api-reference/specs/delta-v2.json GET /delta/v2/prices/strategies/{chainId}" +--- diff --git a/api-reference/delta/agents-list.mdx b/api-reference/delta/agents-list.mdx new file mode 100644 index 0000000..fab3700 --- /dev/null +++ b/api-reference/delta/agents-list.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/agents/list/{chainId}" +description: "List the active solver agents competing in the V1 auction for a chain." +openapi: "/api-reference/specs/delta.json GET /delta/agents/list/{chainId}" +--- diff --git a/api-reference/delta/bridge-info.mdx b/api-reference/delta/bridge-info.mdx new file mode 100644 index 0000000..00fe638 --- /dev/null +++ b/api-reference/delta/bridge-info.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/prices/bridge-info" +description: "Supported crosschain bridge lanes grouped by srcChainId then destChainId." +openapi: "/api-reference/specs/delta.json GET /delta/prices/bridge-info" +--- diff --git a/api-reference/delta/bridge-protocols.mdx b/api-reference/delta/bridge-protocols.mdx new file mode 100644 index 0000000..cf6dba2 --- /dev/null +++ b/api-reference/delta/bridge-protocols.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/prices/bridge-protocols" +description: "Active bridge protocols (slug, display name, icon)." +openapi: "/api-reference/specs/delta.json GET /delta/prices/bridge-protocols" +--- diff --git a/api-reference/delta/is-token-supported.mdx b/api-reference/delta/is-token-supported.mdx new file mode 100644 index 0000000..12e3f08 --- /dev/null +++ b/api-reference/delta/is-token-supported.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/prices/is-token-supported" +description: "Quick yes/no check for Delta token support on a chain." +openapi: "/api-reference/specs/delta.json GET /delta/prices/is-token-supported" +--- diff --git a/api-reference/delta/orderbook.mdx b/api-reference/delta/orderbook.mdx new file mode 100644 index 0000000..032d96f --- /dev/null +++ b/api-reference/delta/orderbook.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/orders/orderbook/{chainId}/{agent}" +description: "Pending orderbook slice for a specific auction agent. Agent operators only — not intended for end-user integrations." +openapi: "/api-reference/specs/delta.json GET /delta/orders/orderbook/{chainId}/{agent}" +--- diff --git a/api-reference/delta/orders-build.mdx b/api-reference/delta/orders-build.mdx index 4214e22..d588938 100644 --- a/api-reference/delta/orders-build.mdx +++ b/api-reference/delta/orders-build.mdx @@ -1,5 +1,5 @@ --- -title: "POST /delta/orders/build" +title: "/delta/orders/build" description: "Build a signable Delta order — EIP-712 typed data — from a Delta quote." openapi: "/api-reference/specs/delta.json POST /delta/orders/build" --- diff --git a/api-reference/delta/orders-cancel.mdx b/api-reference/delta/orders-cancel.mdx new file mode 100644 index 0000000..0dfe76f --- /dev/null +++ b/api-reference/delta/orders-cancel.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/orders/cancel" +description: "Cancel one or more open Delta V1 orders by ID." +openapi: "/api-reference/specs/delta.json POST /delta/orders/cancel" +--- diff --git a/api-reference/delta/orders-fillable-balance.mdx b/api-reference/delta/orders-fillable-balance.mdx new file mode 100644 index 0000000..31a6139 --- /dev/null +++ b/api-reference/delta/orders-fillable-balance.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/orders/fillablebalance/{chainId}/{userAddress}" +description: "User's source-token balance minus amounts committed to open limit orders. Use it when sizing a new limit order." +openapi: "/api-reference/specs/delta.json GET /delta/orders/fillablebalance/{chainId}/{userAddress}/{tokenAddress}" +--- diff --git a/api-reference/delta/orders-get-by-hash.mdx b/api-reference/delta/orders-get-by-hash.mdx new file mode 100644 index 0000000..ae2d526 --- /dev/null +++ b/api-reference/delta/orders-get-by-hash.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/orders/hash/{hash}" +description: "Fetch a Delta V1 order by its EIP-712 hash — useful before the order id is assigned." +openapi: "/api-reference/specs/delta.json GET /delta/orders/hash/{hash}" +--- diff --git a/api-reference/delta/orders-get-by-id.mdx b/api-reference/delta/orders-get-by-id.mdx new file mode 100644 index 0000000..0b9c64d --- /dev/null +++ b/api-reference/delta/orders-get-by-id.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/orders/{orderId}" +description: "Fetch a Delta V1 order by its UUID — the id returned by POST /delta/orders." +openapi: "/api-reference/specs/delta.json GET /delta/orders/{orderId}" +--- diff --git a/api-reference/delta/orders-list.mdx b/api-reference/delta/orders-list.mdx new file mode 100644 index 0000000..ff8b2e4 --- /dev/null +++ b/api-reference/delta/orders-list.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/orders" +description: "List a user's Delta V1 orders. Returns a flat array — V2 wraps the response in a paginated envelope." +openapi: "/api-reference/specs/delta.json GET /delta/orders" +--- diff --git a/api-reference/delta/orders.mdx b/api-reference/delta/orders.mdx index fc211e1..0574285 100644 --- a/api-reference/delta/orders.mdx +++ b/api-reference/delta/orders.mdx @@ -1,5 +1,5 @@ --- -title: "POST /delta/orders" +title: "/delta/orders" description: "Submit a signed Delta order to the solver network." openapi: "/api-reference/specs/delta.json POST /delta/orders" --- diff --git a/api-reference/delta/overview.mdx b/api-reference/delta/overview.mdx index 0d4f611..1fa91d8 100644 --- a/api-reference/delta/overview.mdx +++ b/api-reference/delta/overview.mdx @@ -1,13 +1,48 @@ --- -title: "Delta API" -description: "OpenAPI reference for the Velora Delta intents API." -keywords: ["delta","intents","api"] +title: "Delta V1 API" +sidebarTitle: "Overview" +description: "Local EIP-712 order building, flat order lists, and the unified /quote endpoint with Market fallback. Shares on-chain contracts with Delta V2." +keywords: ["delta", "delta v1", "api-reference"] --- -This page is a stub. Content coming soon. +Delta V1 is the original Delta protocol surface. The on-chain contracts and settlement model are identical to [Delta V2](/api-reference/delta-v2/overview); V1 differs in how clients assemble and consume orders: -## Parameters +- **Locally built orders.** Clients compose EIP-712 typed data themselves from a `/delta/prices` (or `/quote`) response. `POST /delta/orders/build` returns the `data` / `domain` / `types` triple to sign. +- **Flat price.** `GET /delta/prices` returns a single `DeltaPrice` (or `BridgePrice` for crosschain) — no `route` / `alternatives` envelope. +- **Flat order list.** `GET /delta/orders` returns a plain array, paginated by `page` / `limit` query params (no `total` / `hasMore` envelope). +- **Locally resolved partner fee.** Clients call `GET /prices/partnerfee/{chainId}` themselves to look up the registered fee config (the V1 SDK caches it). +- **Unified quote.** `GET /quote` returns either a `delta` block or a `market` block (or both with `mode=ALL`) — useful when you want Delta with automatic Market fallback. V2 doesn't have an equivalent endpoint. -## Examples +[Delta V2](/api-reference/delta-v2/overview) is recommended for new integrations. V1 remains fully supported. + +## Endpoints + +| Method | Path | Purpose | +|---|---|---| +| `GET` | `/quote` | Unified Delta-with-fallback-to-Market price | +| `GET` | `/delta/prices` | Delta price (same-chain or crosschain) | +| `GET` | `/delta/prices/bridge-info` | Supported crosschain lanes (srcChainId → destChainId → tokens) | +| `GET` | `/delta/prices/bridge-protocols` | Active bridge protocols (slug, name, icon) | +| `GET` | `/delta/prices/strategies/{chainId}` | Delta yield strategies with APR | +| `GET` | `/delta/prices/is-token-supported` | Quick token-support check | +| `GET` | `/prices/partnerfee/{chainId}` | Resolve registered partner-fee config (shared with Market) | +| `POST` | `/delta/orders/build` | EIP-712 typed data ready to sign | +| `POST` | `/delta/orders` | Submit a signed order | +| `POST` | `/delta/orders/cancel` | Sign-and-post cancellation | +| `GET` | `/delta/orders` | List a user's orders (flat array) | +| `GET` | `/delta/orders/{orderId}` | Order by UUID | +| `GET` | `/delta/orders/hash/{hash}` | Order by EIP-712 hash | +| `GET` | `/delta/orders/fillablebalance/...` | Fillable balance for limit-order sizing | +| `GET` | `/delta/orders/orderbook/{chainId}/{agent}` | Agent-facing orderbook slice (operators only) | +| `GET` | `/delta/agents/list/{chainId}` | List active auction agents | + +## SDK shortcut + +The V1 surface is wrapped by [`sdk.delta.*`](/sdk/modules/delta#delta-v1) on the [Velora SDK](/sdk/overview). For a 5-minute walkthrough see [SDK → Delta module](/sdk/modules/delta). ## Related pages + +- [Why Delta](/delta/overview) — protocol overview. +- [Order lifecycle and status codes](/delta/order-lifecycle-and-status-codes) — V1 status model end-to-end. +- [Delta V2 API](/api-reference/delta-v2/overview) — the recommended surface. +- [SDK → Delta module](/sdk/modules/delta) — TypeScript examples for both V1 and V2. diff --git a/api-reference/delta/partner-fee.mdx b/api-reference/delta/partner-fee.mdx new file mode 100644 index 0000000..f9b706f --- /dev/null +++ b/api-reference/delta/partner-fee.mdx @@ -0,0 +1,5 @@ +--- +title: "/prices/partnerfee/{chainId}" +description: "Resolve the registered partner-fee config for a partner key. Shared between Market and Delta." +openapi: "/api-reference/specs/delta.json GET /prices/partnerfee/{chainId}" +--- diff --git a/api-reference/delta/prices.mdx b/api-reference/delta/prices.mdx new file mode 100644 index 0000000..f359396 --- /dev/null +++ b/api-reference/delta/prices.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/prices" +description: "Delta V1 price for a same-chain or crosschain swap. Pass the response verbatim (with hmac) to /delta/orders/build." +openapi: "/api-reference/specs/delta.json GET /delta/prices" +--- diff --git a/api-reference/delta/quote.mdx b/api-reference/delta/quote.mdx index 6e0e220..717e0e9 100644 --- a/api-reference/delta/quote.mdx +++ b/api-reference/delta/quote.mdx @@ -1,9 +1,10 @@ --- -title: "GET /quote (Delta)" +title: "/quote" description: "Retrieve a Delta price, with optional fallback to Market via mode=ALL or mode=MARKET." openapi: "/api-reference/specs/delta.json GET /quote" --- - This endpoint accepts `mode=DELTA`, `mode=MARKET`, or `mode=ALL`. See [Trading modes](/integrate/trading-modes) for guidance and fallback semantics. + This endpoint accepts `mode=DELTA`, `mode=MARKET`, or `mode=ALL`. See [Trading + modes](/integrate/trading-modes) for guidance and fallback semantics. diff --git a/api-reference/delta/strategies.mdx b/api-reference/delta/strategies.mdx new file mode 100644 index 0000000..f4e8649 --- /dev/null +++ b/api-reference/delta/strategies.mdx @@ -0,0 +1,5 @@ +--- +title: "/delta/prices/strategies/{chainId}" +description: "Delta yield strategies with APR, keyed by underlying token. Used to source the strategy address for ProductiveOrder builds." +openapi: "/api-reference/specs/delta.json GET /delta/prices/strategies/{chainId}" +--- diff --git a/api-reference/market/prices.mdx b/api-reference/market/prices.mdx index 315debe..edb7cc8 100644 --- a/api-reference/market/prices.mdx +++ b/api-reference/market/prices.mdx @@ -1,9 +1,11 @@ --- -title: "GET /prices (Market)" +title: "/prices" description: "Get a Market route from the Velora aggregator." openapi: "/api-reference/specs/market.json GET /prices" --- - Looking for a single endpoint that returns either a Market route or a Delta intent? Call [`GET /quote`](/api-reference/delta/quote) with `mode=ALL` — see [Trading modes](/integrate/trading-modes). + Looking for a single endpoint that returns either a Market route or a Delta + intent? Call [`GET /quote`](/api-reference/delta/quote) with `mode=ALL` — see + [Trading modes](/integrate/trading-modes). diff --git a/api-reference/market/transactions.mdx b/api-reference/market/transactions.mdx index 4c7a657..d5454e7 100644 --- a/api-reference/market/transactions.mdx +++ b/api-reference/market/transactions.mdx @@ -1,5 +1,5 @@ --- -title: "POST /transactions/:network (Market)" +title: "/transactions/:network" description: "Build calldata for an Augustus v6.2 swap from a Market priceRoute." openapi: "/api-reference/specs/market.json POST /transactions/{network}" --- diff --git a/api-reference/specs/delta-v2.json b/api-reference/specs/delta-v2.json new file mode 100644 index 0000000..b79b884 --- /dev/null +++ b/api-reference/specs/delta-v2.json @@ -0,0 +1,606 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Velora Delta API V2", + "version": "2.0.0", + "description": "Velora Delta API V2 — server-built EIP-712 orders, route-based pricing with alternatives, paginated order history, and a unified status model. Ships alongside Delta V1; both protocols share the same on-chain contracts." + }, + "servers": [ + { "url": "https://api.velora.xyz", "description": "Production" } + ], + "paths": { + "/delta/v2/prices": { + "get": { + "summary": "Get a Delta V2 price (same-chain or crosschain)", + "description": "Returns a recommended `route` plus `alternatives` (up to a few bridge options for crosschain). Pass the returned `route` and `side` verbatim to `POST /delta/v2/orders/build`.", + "operationId": "deltaV2Prices", + "parameters": [ + { "name": "chainId", "in": "query", "required": true, "schema": { "type": "integer", "example": 1 }, "description": "Source chain ID. Supported: 1, 10, 56, 100, 130, 137, 8453, 42161, 43114." }, + { "name": "srcToken", "in": "query", "required": true, "schema": { "type": "string", "example": "0x6B175474E89094C44Da98b954EedeAC495271d0F" } }, + { "name": "destToken", "in": "query", "required": true, "schema": { "type": "string", "example": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" }, "description": "Destination token. For crosschain quotes, the destination token on `destChainId`." }, + { "name": "amount", "in": "query", "required": true, "schema": { "type": "string", "example": "1000000000000000000" }, "description": "Source amount (SELL) or destination amount (BUY), in raw token units." }, + { "name": "srcDecimals", "in": "query", "required": true, "schema": { "type": "integer", "example": 18 } }, + { "name": "destDecimals", "in": "query", "required": true, "schema": { "type": "integer", "example": 6 } }, + { "name": "side", "in": "query", "required": false, "schema": { "type": "string", "enum": ["SELL", "BUY"], "default": "SELL" } }, + { "name": "destChainId", "in": "query", "required": false, "schema": { "type": "integer" }, "description": "Omit for same-chain. When set, response `route.bridge` is populated." }, + { "name": "userAddress", "in": "query", "required": false, "schema": { "type": "string" } }, + { "name": "beneficiary", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Address that receives the destination token. Defaults to `userAddress`." }, + { "name": "partner", "in": "query", "required": false, "schema": { "type": "string", "default": "anon", "example": "my-app-name" }, "description": "Partner key. Defaults to `anon` (1bps fee)." }, + { "name": "partnerFeeBps", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "maximum": 200 }, "description": "Override partner fee in basis points (max 200 = 2%)." }, + { "name": "maxImpact", "in": "query", "required": false, "schema": { "type": "number" }, "description": "Maximum price impact in % (default 15)." }, + { "name": "maxUSDImpact", "in": "query", "required": false, "schema": { "type": "number" }, "description": "Maximum price impact in USD." }, + { "name": "includeAgents", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated list of agent names to include." }, + { "name": "excludeAgents", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated list of agent names to exclude." }, + { "name": "includeBridges", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated bridge protocol names to include (crosschain only)." }, + { "name": "excludeBridges", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated bridge protocol names to exclude." }, + { "name": "allowBridgeAndSwap", "in": "query", "required": false, "schema": { "type": "boolean", "default": true }, "description": "Allow combining bridge + on-chain swap. Forced to `false` for BUY side." } + ], + "responses": { + "200": { + "description": "Recommended route plus alternatives.", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/PriceV2" } + } + } + }, + "400": { "description": "Invalid parameters or no route" }, + "422": { "description": "Unsupported chain or token" } + } + } + }, + "/delta/v2/prices/bridge-routes": { + "get": { + "summary": "List supported crosschain bridge routes", + "description": "Returns the set of `(srcChainId, destChainId, tokens)` triples that the relayer can quote.", + "operationId": "deltaV2BridgeRoutes", + "parameters": [ + { "name": "bridges", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated bridge protocol names (e.g., `acrossv3,stargatev2`). Omit to list every active bridge." }, + { "name": "allowBridgeAndSwap", "in": "query", "required": false, "schema": { "type": "boolean", "default": true } } + ], + "responses": { + "200": { + "description": "Flat list of supported routes.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "routes": { + "type": "array", + "items": { + "type": "object", + "properties": { + "srcChainId": { "type": "integer" }, + "destChainId": { "type": "integer" }, + "tokens": { "type": "array", "items": { "type": "string" }, "description": "Token addresses bridgeable on this lane." } + } + } + } + } + } + } + } + } + } + } + }, + "/delta/v2/prices/bridge-protocols": { + "get": { + "summary": "List active bridge protocols", + "description": "Display catalogue of every bridge protocol currently active in the relayer's `BridgeApi`. Useful for rendering a bridge picker.", + "operationId": "deltaV2BridgeProtocols", + "responses": { + "200": { + "description": "Active bridge protocols.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "bridgeProtocols": { + "type": "array", + "items": { + "type": "object", + "properties": { + "protocol": { "type": "string", "description": "Stable protocol slug. Use this for `includeBridges` / `excludeBridges` filters on `GET /delta/v2/prices`." }, + "displayName": { "type": "string" }, + "icon": { "type": "string", "description": "Absolute URL to a 1:1 SVG icon hosted on cdn.velora.xyz." } + } + } + } + } + } + } + } + } + } + } + }, + "/delta/v2/prices/strategies/{chainId}": { + "get": { + "summary": "List Delta yield strategies (with APR) for a chain", + "description": "Returns the on-chain Delta-token vaults wired for `ProductiveOrder` swaps, keyed by the underlying token address. APRs are refreshed server-side every 3 hours; `apr` is `null` when the strategy is too new to compute.", + "operationId": "deltaV2Strategies", + "parameters": [ + { "name": "chainId", "in": "path", "required": true, "schema": { "type": "integer", "example": 1 } } + ], + "responses": { + "200": { + "description": "Map of `underlyingTokenAddress → { address, strategies }`.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "type": "object", + "properties": { + "address": { "type": "string", "description": "Delta token (dToken) wrapper address." }, + "strategies": { + "type": "array", + "items": { + "type": "object", + "properties": { + "vault": { "type": "string", "description": "ERC-4626 vault address. Pass this as `strategy` to `POST /delta/v2/orders/build` for a `ProductiveOrder`." }, + "name": { "type": "string" }, + "apr": { + "type": "object", + "nullable": true, + "properties": { + "gross": { "type": "string", "description": "Gross APR as a decimal string (e.g. `\"0.052\"` = 5.2%)." }, + "net": { "type": "string", "description": "Net APR after fees, decimal string." } + } + } + } + } + } + } + } + } + } + } + }, + "400": { "description": "Unsupported chain" } + } + } + }, + "/delta/v2/prices/is-token-supported": { + "get": { + "summary": "Check whether a token is supported for Delta on a chain", + "operationId": "deltaV2IsTokenSupported", + "parameters": [ + { "name": "chainId", "in": "query", "required": true, "schema": { "type": "integer", "example": 1 } }, + { "name": "token", "in": "query", "required": true, "schema": { "type": "string", "example": "0x6B175474E89094C44Da98b954EedeAC495271d0F" } } + ], + "responses": { + "200": { + "description": "Token support flag.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { "supported": { "type": "boolean" } } + } + } + } + } + } + } + }, + "/delta/v2/orders/build": { + "post": { + "summary": "Build a signable Delta V2 order from a route", + "description": "Returns EIP-712 typed data ready to sign and the order hash. Pass the unmodified `route` from `GET /delta/v2/prices`. Use `orderType` to select Standard / External / Productive / TWAP families.", + "operationId": "deltaV2OrdersBuild", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/BuildOrderV2Request" } + } + } + }, + "responses": { + "200": { + "description": "EIP-712 typed data ready to sign.", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/BuiltOrderV2" } + } + } + }, + "400": { "description": "Invalid params (missing TWAP totals, mismatched slice amounts, etc.)" } + } + } + }, + "/delta/v2/orders": { + "post": { + "summary": "Submit a signed Delta V2 order", + "description": "Validates EIP-712 signature, nonce, balance, and allowance, then enrolls the order into the sealed-bid auction.", + "operationId": "deltaV2OrdersSubmit", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/SubmitOrderV2Request" } + } + } + }, + "responses": { + "200": { + "description": "Order accepted.", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/DeltaAuction" } + } + } + }, + "400": { "description": "Invalid signature, expired, or balance/allowance failure" } + } + }, + "get": { + "summary": "List a user's Delta V2 orders (paginated)", + "operationId": "deltaV2OrdersList", + "parameters": [ + { "name": "userAddress", "in": "query", "required": true, "schema": { "type": "string" } }, + { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 1 } }, + { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 1000, "default": 100 } }, + { "name": "chainId", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated chain IDs. Omit for all chains." }, + { "name": "type", "in": "query", "required": false, "schema": { "type": "string", "enum": ["MARKET", "LIMIT"] } }, + { "name": "status", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Comma-separated `OrderStatusV2` values. See [Order lifecycle](/delta/order-lifecycle-and-status-codes)." }, + { "name": "onChainOrderType", "in": "query", "required": false, "schema": { "type": "string", "enum": ["Order", "ProductiveOrder", "ExternalOrder", "TWAPOrder", "TWAPBuyOrder"] } } + ], + "responses": { + "200": { + "description": "Paginated envelope.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { "type": "array", "items": { "$ref": "#/components/schemas/DeltaAuction" } }, + "total": { "type": "integer" }, + "page": { "type": "integer" }, + "limit": { "type": "integer" }, + "hasMore": { "type": "boolean" } + } + } + } + } + } + } + } + }, + "/delta/v2/orders/cancel": { + "post": { + "summary": "Cancel one or more Delta V2 orders", + "description": "Sign-and-post cancellation. Only succeeds for orders still open in the auction (`PENDING`, `AWAITING_SIGNATURE`, `ACTIVE`, `SUSPENDED`).", + "operationId": "deltaV2OrdersCancel", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["orderIds", "signature"], + "properties": { + "orderIds": { "type": "array", "items": { "type": "string", "format": "uuid" }, "minItems": 1, "maxItems": 100 }, + "signature": { "type": "string", "description": "EIP-712 signature over the cancellation payload." } + } + } + } + } + }, + "responses": { + "200": { + "description": "Cancellation accepted.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "cancelled": { "type": "array", "items": { "type": "string", "format": "uuid" } } + } + } + } + } + }, + "400": { "description": "Invalid signature or order already settled" } + } + } + }, + "/delta/v2/orders/fillablebalance/{chainId}/{userAddress}/{tokenAddress}": { + "get": { + "summary": "Compute a user's fillable balance for limit orders", + "description": "Returns the user's wallet balance **minus** any source-token already committed to open limit orders on a chain. Use this when sizing a new limit order so it doesn't double-commit funds.\n\n`tokenAddress` is an optional trailing path segment — **omit it** (`/delta/v2/orders/fillablebalance/{chainId}/{userAddress}`) to get the fillable balance for every token with open commitments. With `tokenAddress` set, the response holds a single entry for that token (or `\"0\"` if the user has no open commitments on it).", + "operationId": "deltaV2OrdersFillableBalance", + "parameters": [ + { "name": "chainId", "in": "path", "required": true, "schema": { "type": "integer", "example": 1 } }, + { "name": "userAddress", "in": "path", "required": true, "schema": { "type": "string" } }, + { "name": "tokenAddress", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Source token to inspect. Omit the entire segment to get balances for every committed token." } + ], + "responses": { + "200": { + "description": "Map of `tokenAddress → fillableBalance` (raw token units as a string).", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { "type": "string" }, + "example": { + "0x6B175474E89094C44Da98b954EedeAC495271d0F": "500000000000000000" + } + } + } + } + }, + "400": { "description": "Unsupported chain" } + } + } + }, + "/delta/v2/orders/{orderId}": { + "get": { + "summary": "Get a Delta V2 order by ID", + "operationId": "deltaV2OrderById", + "parameters": [ + { "name": "orderId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } + ], + "responses": { + "200": { + "description": "Order details.", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/DeltaAuction" } + } + } + }, + "404": { "description": "Order not found" } + } + } + }, + "/delta/v2/orders/hash/{hash}": { + "get": { + "summary": "Get a Delta V2 order by EIP-712 hash", + "operationId": "deltaV2OrderByHash", + "parameters": [ + { "name": "hash", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Order hash returned by `POST /delta/v2/orders/build`." } + ], + "responses": { + "200": { + "description": "Order details.", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/DeltaAuction" } + } + } + }, + "404": { "description": "Order not found" } + } + } + }, + "/delta/v2/agents/list/{chainId}": { + "get": { + "summary": "List active agents competing in the auction for a chain", + "description": "Use the names returned here to filter pricing via the `includeAgents` / `excludeAgents` params on `GET /delta/v2/prices`.", + "operationId": "deltaV2AgentsList", + "parameters": [ + { "name": "chainId", "in": "path", "required": true, "schema": { "type": "integer", "example": 1 } } + ], + "responses": { + "200": { + "description": "Array of agent names.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { "type": "string" } + } + } + } + }, + "400": { "description": "Unsupported chain" } + } + } + } + }, + "components": { + "schemas": { + "Token": { + "type": "object", + "properties": { + "chainId": { "type": "integer" }, + "address": { "type": "string" } + } + }, + "TokenAmount": { + "type": "object", + "properties": { + "token": { "$ref": "#/components/schemas/Token" }, + "amount": { "type": "string" }, + "amountUSD": { "type": "string" } + } + }, + "RouteStep": { + "type": "object", + "properties": { + "input": { "$ref": "#/components/schemas/TokenAmount" }, + "output": { "$ref": "#/components/schemas/TokenAmount" } + } + }, + "RouteBridge": { + "type": "object", + "nullable": true, + "properties": { + "protocol": { "type": "string" }, + "estimatedTimeMs": { "type": "integer" }, + "tags": { "type": "array", "items": { "type": "string", "enum": ["recommended", "fastest", "best-return"] } }, + "contractParams": { + "type": "object", + "properties": { + "protocolSelector": { "type": "string" }, + "outputToken": { "type": "string" }, + "scalingFactor": { "type": "integer" }, + "protocolData": { "type": "string" } + } + } + } + }, + "Route": { + "type": "object", + "properties": { + "origin": { "$ref": "#/components/schemas/RouteStep" }, + "destination": { "$ref": "#/components/schemas/RouteStep" }, + "bridge": { "$ref": "#/components/schemas/RouteBridge" }, + "fees": { + "type": "object", + "properties": { + "gas": { "$ref": "#/components/schemas/TokenAmount" }, + "bridge": { "type": "array", "items": { "$ref": "#/components/schemas/TokenAmount" } } + } + } + } + }, + "PriceV2": { + "type": "object", + "properties": { + "id": { "type": "string", "description": "Request id (echo for support tickets)." }, + "side": { "type": "string", "enum": ["SELL", "BUY"] }, + "inputToken": { "$ref": "#/components/schemas/Token" }, + "outputToken": { "$ref": "#/components/schemas/Token" }, + "route": { "$ref": "#/components/schemas/Route" }, + "alternatives": { "type": "array", "items": { "$ref": "#/components/schemas/Route" }, "description": "Up to N additional routes (crosschain only)." }, + "partner": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "feePercent": { "type": "number", "description": "Resolved partner fee in percent (0.05 = 0.05%)." } + } + }, + "spender": { "type": "string", "description": "Delta contract address; approve this as ERC-20 spender." } + } + }, + "BuildOrderV2Request": { + "type": "object", + "required": ["route", "owner"], + "properties": { + "side": { "type": "string", "enum": ["SELL", "BUY"], "default": "SELL" }, + "route": { "$ref": "#/components/schemas/Route", "description": "Pass the unmodified `route` from `GET /delta/v2/prices`. The chain ID is derived from the route." }, + "owner": { "type": "string" }, + "beneficiary": { "type": "string", "description": "Defaults to `owner`." }, + "deadline": { "type": "integer", "description": "Unix seconds. Defaults to now + 1 hour." }, + "nonce": { "type": "string" }, + "permit": { "type": "string", "description": "Permit / Permit2 payload, or `0x` if approved on-chain." }, + "slippage": { "type": "integer", "minimum": 0, "maximum": 10000, "default": 100, "description": "Slippage in basis points." }, + "limitAmount": { "type": "string", "description": "Override the SDK-computed destAmount (SELL) / srcAmount (BUY)." }, + "metadata": { "type": "string", "default": "0x" }, + "partiallyFillable": { "type": "boolean", "default": false }, + "partnerAddress": { "type": "string", "description": "Defaults to zero address." }, + "partnerFeeBps": { "type": "integer", "minimum": 0, "maximum": 200, "default": 0 }, + "partnerTakesSurplus": { "type": "boolean", "default": false }, + "capSurplus": { "type": "boolean", "default": true }, + "orderType": { "type": "string", "enum": ["Order", "ProductiveOrder", "ExternalOrder", "TWAPOrder", "TWAPBuyOrder"], "default": "Order" }, + "handler": { "type": "string", "description": "Required for `ExternalOrder`." }, + "data": { "type": "string", "description": "Required for `ExternalOrder`. Handler-specific encoded bytes." }, + "strategy": { "type": "string", "description": "Required for `ProductiveOrder`." }, + "useShares": { "type": "boolean", "default": true }, + "interval": { "type": "integer", "minimum": 60, "description": "Required for TWAP. Slice interval in seconds." }, + "numSlices": { "type": "integer", "minimum": 2, "description": "Required for TWAP." }, + "totalSrcAmount": { "type": "string", "description": "Required for `TWAPOrder`. `route.origin.input.amount` must equal `floor(totalSrcAmount / numSlices)`." }, + "totalDestAmount": { "type": "string", "description": "Required for `TWAPBuyOrder`. `route.origin.output.amount` must equal `floor(totalDestAmount / numSlices)`." }, + "maxSrcAmount": { "type": "string", "description": "Required for `TWAPBuyOrder`. Maximum total source the user is willing to spend." } + } + }, + "BuiltOrderV2": { + "type": "object", + "properties": { + "toSign": { + "type": "object", + "properties": { + "domain": { + "type": "object", + "properties": { + "name": { "type": "string" }, + "version": { "type": "string" }, + "chainId": { "type": "integer" }, + "verifyingContract": { "type": "string" } + } + }, + "types": { "type": "object", "description": "EIP-712 typed-data field definitions." }, + "value": { "type": "object", "description": "The on-chain Order struct values, ready to be signed and submitted." } + } + }, + "orderHash": { "type": "string", "description": "EIP-712 hash. Use for status lookup before the order id is assigned." } + } + }, + "SubmitOrderV2Request": { + "type": "object", + "required": ["chainId", "order", "signature", "partner"], + "properties": { + "chainId": { "type": "integer" }, + "order": { "type": "object", "description": "The `toSign.value` returned by `POST /delta/v2/orders/build`, sent verbatim." }, + "signature": { "type": "string", "description": "EIP-712 signature over `order`." }, + "type": { "type": "string", "enum": ["MARKET", "LIMIT"], "default": "MARKET" }, + "partner": { "type": "string", "example": "my-app-name" }, + "referrerAddress": { "type": "string" }, + "partiallyFillable": { "type": "boolean", "default": false }, + "includeAgents": { "type": "array", "items": { "type": "string" } }, + "excludeAgents": { "type": "array", "items": { "type": "string" } } + } + }, + "DeltaAuction": { + "type": "object", + "description": "V2 order shape returned by every order endpoint (reads and posts). `input` and `output` carry the *expected* + *executed* amounts so you don't need to compute fill-percent yourself. `onChainOrderType` selects the family the `order` struct belongs to.", + "properties": { + "id": { "type": "string", "format": "uuid" }, + "status": { "type": "string", "enum": ["PENDING", "AWAITING_SIGNATURE", "ACTIVE", "SUSPENDED", "CANCELLING", "BRIDGING", "COMPLETED", "FAILED", "EXPIRED", "CANCELLED", "REFUNDED"] }, + "side": { "type": "string", "enum": ["SELL", "BUY"] }, + "type": { "type": "string", "enum": ["MARKET", "LIMIT"] }, + "onChainOrderType": { "type": "string", "enum": ["Order", "FillableOrder", "ProductiveOrder", "ExternalOrder", "TWAPOrder", "TWAPBuyOrder"] }, + "input": { + "type": "object", + "description": "Source-side token movement. SELL: `{ chainId, token, amount }`. BUY: `{ chainId, token, expectedAmount, executedAmount }`.", + "properties": { + "chainId": { "type": "integer" }, + "token": { "type": "string" }, + "amount": { "type": "string" }, + "expectedAmount": { "type": "string", "nullable": true }, + "executedAmount": { "type": "string", "nullable": true } + } + }, + "output": { + "type": "object", + "description": "Destination-side token movement. SELL: `{ chainId, token, expectedAmount, executedAmount }`. BUY: `{ chainId, token, amount }`.", + "properties": { + "chainId": { "type": "integer" }, + "token": { "type": "string" }, + "amount": { "type": "string" }, + "expectedAmount": { "type": "string", "nullable": true }, + "executedAmount": { "type": "string", "nullable": true } + } + }, + "owner": { "type": "string" }, + "beneficiary": { "type": "string" }, + "orderHash": { "type": "string" }, + "partner": { "type": "string" }, + "order": { "type": "object", "description": "The signed on-chain Order struct." }, + "transactions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "originTx": { "type": "string" }, + "destinationTx": { "type": "string", "nullable": true, "description": "Set for crosschain orders once the fill lands on `destChainId`." }, + "filledPercent": { "type": "number", "description": "0–100." }, + "spentAmount": { "type": "string", "nullable": true }, + "receivedAmount": { "type": "string", "nullable": true } + } + } + }, + "createdAt": { "type": "string", "format": "date-time" }, + "updatedAt": { "type": "string", "format": "date-time" }, + "expiresAt": { "type": "string", "format": "date-time" } + } + } + } + } +} diff --git a/api-reference/specs/delta.json b/api-reference/specs/delta.json index 815720e..f1ee8c1 100644 --- a/api-reference/specs/delta.json +++ b/api-reference/specs/delta.json @@ -1,65 +1,475 @@ { "openapi": "3.0.3", "info": { - "title": "Velora Delta API", + "title": "Velora Delta API V1", "version": "1.0.0", - "description": "Velora Delta API — intent-based quoting with optional Market fallback." - }, - "servers": [ - { "url": "https://api.velora.xyz", "description": "Production" } - ], - "externalDocs": { - "description": "Delta — how it works (quote → build → sign → submit → poll).", - "url": "https://new-docs.velora.xyz/delta/how-it-works" + "description": "Velora Delta API V1 — intent-based quoting and order lifecycle. Local EIP-712 order building; flat order list; supports the same on-chain contracts as V2." }, + "servers": [{ "url": "https://api.velora.xyz", "description": "Production" }], "paths": { "/quote": { "get": { "summary": "Retrieve a Delta price, with optional fallback to Market", "operationId": "deltaQuote", "parameters": [ - { "name": "srcToken", "in": "query", "required": true, "schema": { "$ref": "#/components/schemas/Address" }, "example": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "description": "Source token address. Example uses ETH." }, - { "name": "srcDecimals", "in": "query", "required": true, "schema": { "type": "integer" }, "example": 18, "description": "Source token decimals." }, - { "name": "destToken", "in": "query", "required": true, "schema": { "$ref": "#/components/schemas/Address" }, "example": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "description": "Destination token address. For cross-chain quotes, the destination token on the destination chain. Example uses USDC." }, - { "name": "destDecimals", "in": "query", "required": true, "schema": { "type": "integer" }, "example": 6, "description": "Destination token decimals." }, - { "name": "amount", "in": "query", "required": true, "schema": { "$ref": "#/components/schemas/TokenAmount" }, "example": "1000000000000000000", "description": "srcToken amount (SELL) or destToken amount (BUY), in WEI/raw units." }, - { "name": "side", "in": "query", "required": false, "schema": { "type": "string", "enum": ["SELL", "BUY"], "default": "SELL" } }, - { "name": "chainId", "in": "query", "required": true, "schema": { "$ref": "#/components/schemas/ChainId" }, "example": 1, "description": "Source chain ID. Supported values: 1 (Mainnet), 10 (Optimism), 56 (BSC), 137 (Polygon), 8453 (Base), 42161 (Arbitrum), 43114 (Avalanche), 100 (Gnosis)." }, - { "name": "mode", "in": "query", "required": false, "schema": { "type": "string", "enum": ["ALL", "DELTA", "MARKET"], "default": "ALL" }, "description": "Controls which execution path Velora returns. `ALL` (default) lets Velora pick the winner server-side and returns exactly one of a `delta` or `market` block — never both. `DELTA` / `MARKET` request a specific path; if no route exists for the requested mode, the API may return the other path's block as fallback. See /integrate/trading-modes for full semantics including the 400 PricingError fallback envelope." }, - { "name": "userAddress", "in": "query", "required": false, "schema": { "$ref": "#/components/schemas/Address" }, "example": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "description": "End-user wallet address." }, - { "name": "partner", "in": "query", "required": false, "schema": { "type": "string", "default": "anon" }, "example": "my-app-name", "description": "Partner string. Defaults to `anon` which charges 1bps fee for all swaps." }, - { "name": "destChainId", "in": "query", "required": false, "schema": { "$ref": "#/components/schemas/ChainId" }, "description": "Destination chain ID for cross-chain quotes. Omit for same-chain quotes." } + { + "name": "srcToken", + "in": "query", + "required": true, + "schema": { + "type": "string", + "example": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" + }, + "description": "Source token address. Example uses ETH." + }, + { + "name": "srcDecimals", + "in": "query", + "required": true, + "schema": { "type": "integer", "example": 18 }, + "description": "Source token decimals." + }, + { + "name": "destToken", + "in": "query", + "required": true, + "schema": { + "type": "string", + "example": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" + }, + "description": "Destination token address. For cross-chain quotes, the destination token on the destination chain. Example uses USDC." + }, + { + "name": "destDecimals", + "in": "query", + "required": true, + "schema": { "type": "integer", "example": 6 }, + "description": "Destination token decimals." + }, + { + "name": "amount", + "in": "query", + "required": true, + "schema": { "type": "string", "example": "1000000000000000000" }, + "description": "srcToken amount (SELL) or destToken amount (BUY), in WEI/raw units." + }, + { + "name": "side", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": ["SELL", "BUY"], + "default": "SELL" + } + }, + { + "name": "chainId", + "in": "query", + "required": true, + "schema": { "type": "integer", "example": 1 }, + "description": "Source chain ID. Supported values: 1 (Mainnet), 10 (Optimism), 56 (BSC), 137 (Polygon), 8453 (Base), 42161 (Arbitrum), 43114 (Avalanche), 100 (Gnosis)." + }, + { + "name": "mode", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": ["ALL", "DELTA", "MARKET"], + "default": "ALL" + }, + "description": "Controls which execution path Velora returns. `ALL` (default) lets Velora pick the winner server-side and returns exactly one of a `delta` or `market` block — never both. `DELTA` / `MARKET` request a specific path; if no route exists for the requested mode, the API may return the other path's block as fallback. See /integrate/trading-modes for full semantics including the 400 PricingError fallback envelope." + }, + { + "name": "userAddress", + "in": "query", + "required": false, + "schema": { + "type": "string", + "example": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" + }, + "description": "End-user wallet address." + }, + { + "name": "partner", + "in": "query", + "required": false, + "schema": { + "type": "string", + "default": "anon", + "example": "my-app-name" + }, + "description": "Partner string. Defaults to `anon` which charges 1bps fee for all swaps." + }, + { + "name": "destChainId", + "in": "query", + "required": false, + "schema": { "type": "integer" }, + "description": "Destination chain ID for cross-chain quotes. Omit for same-chain quotes." + } ], "responses": { "200": { "description": "Delta quote, optionally with a Market block depending on `mode`.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/DeltaQuoteResponse" } + "schema": { + "type": "object", + "properties": { + "delta": { + "$ref": "#/components/schemas/DeltaPriceWithHmac" + }, + "market": { + "type": "object", + "description": "Market route block. Same shape as the GET /prices `priceRoute` field. Present when `mode` is ALL or MARKET." + }, + "deltaAddress": { + "type": "string", + "description": "The Delta settlement contract address for the source chain." + }, + "fallbackReason": { + "type": "object", + "description": "Set when Delta couldn't price and the response fell back to Market.", + "properties": { + "errorType": { "type": "string" }, + "details": { "type": "string" } + } + } + } + } } } }, - "400": { - "description": "Invalid parameters. Documented examples: `InvalidInput`, `PricingError` (no route for requested mode — see /integrate/trading-modes).", + "400": { "description": "Invalid parameters" }, + "422": { "description": "Unsupported chain or token" } + } + } + }, + "/delta/prices": { + "get": { + "summary": "Get a Delta V1 price (same-chain or crosschain)", + "description": "Returns a single best route plus the Delta contract address. Same-chain quotes set `bridge` to the all-zero `DEFAULT_BRIDGE`; crosschain quotes populate `bridge` and add `bridgeInfo` / `availableBridges`.", + "operationId": "deltaPrices", + "parameters": [ + { + "name": "chainId", + "in": "query", + "required": true, + "schema": { "type": "integer", "example": 1 } + }, + { + "name": "srcToken", + "in": "query", + "required": true, + "schema": { "type": "string" } + }, + { + "name": "destToken", + "in": "query", + "required": true, + "schema": { "type": "string" }, + "description": "Destination token. For crosschain quotes, the destination token on `destChainId`." + }, + { + "name": "amount", + "in": "query", + "required": true, + "schema": { "type": "string" } + }, + { + "name": "srcDecimals", + "in": "query", + "required": true, + "schema": { "type": "integer" } + }, + { + "name": "destDecimals", + "in": "query", + "required": true, + "schema": { "type": "integer" } + }, + { + "name": "side", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": ["SELL", "BUY"], + "default": "SELL" + } + }, + { + "name": "destChainId", + "in": "query", + "required": false, + "schema": { "type": "integer" } + }, + { + "name": "userAddress", + "in": "query", + "required": false, + "schema": { "type": "string" } + }, + { + "name": "beneficiary", + "in": "query", + "required": false, + "schema": { "type": "string" } + }, + { + "name": "partner", + "in": "query", + "required": false, + "schema": { + "type": "string", + "default": "anon", + "example": "my-app-name" + } + }, + { + "name": "partnerFeeBps", + "in": "query", + "required": false, + "schema": { "type": "integer", "minimum": 0, "maximum": 200 } + }, + { + "name": "maxImpact", + "in": "query", + "required": false, + "schema": { "type": "number" } + }, + { + "name": "maxUSDImpact", + "in": "query", + "required": false, + "schema": { "type": "number" } + }, + { + "name": "includeAgents", + "in": "query", + "required": false, + "schema": { "type": "string" } + }, + { + "name": "excludeAgents", + "in": "query", + "required": false, + "schema": { "type": "string" } + }, + { + "name": "includeBridges", + "in": "query", + "required": false, + "schema": { "type": "string" } + }, + { + "name": "excludeBridges", + "in": "query", + "required": false, + "schema": { "type": "string" } + }, + { + "name": "allowBridgeAndSwap", + "in": "query", + "required": false, + "schema": { "type": "boolean", "default": true } + } + ], + "responses": { + "200": { + "description": "Delta price envelope. The `price.hmac` must be passed verbatim to `POST /delta/orders/build`.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "type": "object", + "properties": { + "price": { + "$ref": "#/components/schemas/DeltaPriceWithHmac" + }, + "deltaAddress": { "type": "string" } + } + } } } }, - "422": { - "description": "Unsupported chain or token.", + "400": { "description": "Invalid parameters or no route" }, + "422": { "description": "Unsupported chain or token" } + } + } + }, + "/delta/prices/is-token-supported": { + "get": { + "summary": "Check whether a token is supported for Delta on a chain", + "operationId": "deltaIsTokenSupported", + "parameters": [ + { + "name": "chainId", + "in": "query", + "required": true, + "schema": { "type": "integer", "example": 1 } + }, + { + "name": "token", + "in": "query", + "required": true, + "schema": { "type": "string" } + } + ], + "responses": { + "200": { + "description": "Token support flag.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "type": "object", + "properties": { "supported": { "type": "boolean" } } + } } } + } + } + } + }, + "/delta/prices/bridge-info": { + "get": { + "summary": "List the crosschain (srcChainId, destChainId, tokens) lanes", + "description": "Returns a nested map of supported bridge lanes. Useful for building a 'supported chains' picker before quoting.", + "operationId": "deltaBridgeInfo", + "parameters": [ + { + "name": "bridges", + "in": "query", + "required": false, + "schema": { "type": "string" }, + "description": "Comma-separated bridge protocol names. Omit for every active bridge." }, - "500": { - "description": "Internal server error.", + { + "name": "allowBridgeAndSwap", + "in": "query", + "required": false, + "schema": { "type": "boolean", "default": true } + } + ], + "responses": { + "200": { + "description": "Supported lanes grouped by source then destination chain.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "type": "object", + "properties": { + "supportedTokens": { + "type": "object", + "description": "`Record>`. Token addresses are on the source chain.", + "additionalProperties": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { "type": "string" } + } + } + } + } + } + } + } + } + } + } + }, + "/delta/prices/bridge-protocols": { + "get": { + "summary": "List active bridge protocols", + "description": "Display catalogue of every bridge protocol active in the relayer's `BridgeApi`. Use the `protocol` slug for `includeBridges` / `excludeBridges` filters.", + "operationId": "deltaBridgeProtocols", + "responses": { + "200": { + "description": "Active bridge protocols.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "bridgeProtocols": { + "type": "array", + "items": { "$ref": "#/components/schemas/BridgeProtocol" } + } + } + } + } + } + } + } + } + }, + "/delta/prices/strategies/{chainId}": { + "get": { + "summary": "List Delta yield strategies (with APR) for a chain", + "description": "Returns the Delta-token vaults wired for Productive orders, keyed by underlying token address. APRs are refreshed server-side every 3 hours; `apr` is `null` when the strategy is too new to compute.", + "operationId": "deltaStrategies", + "parameters": [ + { + "name": "chainId", + "in": "path", + "required": true, + "schema": { "type": "integer", "example": 1 } + } + ], + "responses": { + "200": { + "description": "Map of `underlyingTokenAddress → { address, strategies }`.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/DeltaTokenWithStrategies" + } + } + } + } + }, + "400": { "description": "Unsupported chain" } + } + } + }, + "/prices/partnerfee/{chainId}": { + "get": { + "summary": "Resolve the registered partner-fee config", + "description": "Returns the partner-fee config registered against a partner key. Shared between Market and Delta — the same key drives fees on both flows.", + "operationId": "deltaPartnerFee", + "parameters": [ + { + "name": "chainId", + "in": "path", + "required": true, + "schema": { "type": "integer", "example": 1 } + }, + { + "name": "partner", + "in": "query", + "required": true, + "schema": { "type": "string", "example": "my-app-name" } + } + ], + "responses": { + "200": { + "description": "Resolved partner-fee config.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "partnerFee": { + "type": "number", + "description": "Fee in percent (e.g. `0.12` = 0.12%)." + }, + "partnerAddress": { "type": "string" }, + "takeSurplus": { "type": "boolean" } + } + } } } } @@ -68,278 +478,684 @@ }, "/delta/orders/build": { "post": { - "summary": "Build a signable Delta order from a quote", + "summary": "Build a signable Delta V1 order from a quote", + "description": "Compose EIP-712 typed data from a `/delta/prices` (or `/quote`) response. Pass the `delta` block verbatim as `price` along with its `hmac`.", "operationId": "deltaOrdersBuild", "requestBody": { "required": true, "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/DeltaOrderBuildRequest" } + "schema": { + "type": "object", + "required": ["chainId", "owner", "price"], + "properties": { + "chainId": { "type": "integer" }, + "owner": { "type": "string" }, + "beneficiary": { + "type": "string", + "description": "Defaults to `owner`." + }, + "side": { + "type": "string", + "enum": ["SELL", "BUY"], + "default": "SELL" + }, + "onChainOrderType": { + "type": "string", + "enum": [ + "Order", + "ProductiveOrder", + "ExternalOrder", + "TWAPOrder", + "TWAPBuyOrder" + ], + "default": "Order" + }, + "price": { + "$ref": "#/components/schemas/DeltaPriceWithHmac" + }, + "deadline": { + "type": "integer", + "description": "Unix seconds. Defaults to now + 1 hour." + }, + "nonce": { "type": "string" }, + "permit": { + "type": "string", + "description": "Permit / Permit2 payload, or `0x` if approved on-chain." + }, + "slippage": { + "type": "integer", + "minimum": 0, + "maximum": 10000, + "default": 100, + "description": "Slippage in basis points." + }, + "partiallyFillable": { "type": "boolean", "default": false }, + "partnerAddress": { "type": "string" }, + "partnerFeeBps": { + "type": "integer", + "minimum": 0, + "maximum": 200, + "default": 0 + }, + "partnerTakesSurplus": { + "type": "boolean", + "default": false + }, + "capSurplus": { "type": "boolean", "default": true }, + "metadata": { "type": "string" }, + "handler": { + "type": "string", + "description": "Required for `ExternalOrder`." + }, + "data": { + "type": "string", + "description": "Required for `ExternalOrder`." + }, + "strategy": { + "type": "string", + "description": "Required for `ProductiveOrder`." + }, + "useShares": { "type": "boolean", "default": true }, + "interval": { + "type": "integer", + "minimum": 60, + "description": "TWAP slice interval in seconds." + }, + "numSlices": { + "type": "integer", + "minimum": 2, + "description": "TWAP slice count." + }, + "totalSrcAmount": { + "type": "string", + "description": "Required for `TWAPOrder`." + }, + "totalDestAmount": { + "type": "string", + "description": "Required for `TWAPBuyOrder`." + }, + "maxSrcAmount": { + "type": "string", + "description": "Required for `TWAPBuyOrder`." + } + } + } } } }, "responses": { "200": { - "description": "Order with EIP-712 typed data ready to sign.", + "description": "EIP-712 typed data ready to sign.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/DeltaOrderBuildResponse" } + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "On-chain `Order` struct values, ready to be signed and submitted." + }, + "orderHash": { "type": "string" }, + "domain": { + "type": "object", + "properties": { + "name": { "type": "string", "example": "Portikus" }, + "version": { "type": "string", "example": "2.0.0" }, + "chainId": { "type": "integer" }, + "verifyingContract": { "type": "string" } + } + }, + "types": { "type": "object" } + } + } } } }, - "400": { - "description": "Invalid input or stale price. Documented examples: `InvalidInput`, `StalePriceRoute`.", + "400": { "description": "Invalid input or stale price" } + } + } + }, + "/delta/orders": { + "post": { + "summary": "Submit a signed Delta V1 order", + "operationId": "deltaOrdersSubmit", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["chainId", "order", "signature", "partner"], + "properties": { + "chainId": { "type": "integer" }, + "order": { + "type": "object", + "description": "The `data` returned by `POST /delta/orders/build`, sent verbatim." + }, + "signature": { + "type": "string", + "description": "EIP-712 signature over `order`." + }, + "type": { + "type": "string", + "enum": ["MARKET", "LIMIT"], + "default": "MARKET" + }, + "partner": { "type": "string", "example": "my-app-name" }, + "referrerAddress": { "type": "string" }, + "partiallyFillable": { "type": "boolean", "default": false }, + "includeAgents": { + "type": "array", + "items": { "type": "string" } + }, + "excludeAgents": { + "type": "array", + "items": { "type": "string" } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Order accepted.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { "$ref": "#/components/schemas/DeltaAuction" } } } }, - "500": { - "description": "Internal server error.", + "400": { "description": "Invalid signature or order shape" } + } + }, + "get": { + "summary": "List a user's Delta V1 orders (flat array)", + "description": "Returns a flat array of orders. V1 paginates by `page` + `limit` but does NOT wrap the response in an envelope — use the array length as a soft total. For a paginated envelope, see [Delta V2 → List orders](/api-reference/delta-v2/orders-list).", + "operationId": "deltaOrdersList", + "parameters": [ + { + "name": "userAddress", + "in": "query", + "required": true, + "schema": { "type": "string" } + }, + { + "name": "page", + "in": "query", + "required": false, + "schema": { "type": "integer", "minimum": 1, "default": 1 } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "maximum": 1000, + "default": 100 + } + }, + { + "name": "chainId", + "in": "query", + "required": false, + "schema": { "type": "string" } + }, + { + "name": "type", + "in": "query", + "required": false, + "schema": { "type": "string", "enum": ["MARKET", "LIMIT"] } + }, + { + "name": "status", + "in": "query", + "required": false, + "schema": { "type": "string" }, + "description": "Comma-separated `DeltaAuctionStatus` values: `NOT_STARTED`, `AWAITING_PRE_SIGNATURE`, `RUNNING`, `EXECUTING`, `EXECUTED`, `FAILED`, `EXPIRED`, `CANCELLED`, `CANCELLING`, `SUSPENDED`, `REFUNDED`." + }, + { + "name": "onChainOrderType", + "in": "query", + "required": false, + "schema": { + "type": "string", + "enum": ["Order", "ProductiveOrder", "ExternalOrder"] + } + } + ], + "responses": { + "200": { + "description": "Flat array of orders.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "type": "array", + "items": { "$ref": "#/components/schemas/DeltaAuction" } + } } } } } } }, - "/delta/orders": { + "/delta/orders/cancel": { "post": { - "summary": "Submit a signed Delta order", - "operationId": "deltaOrdersSubmit", + "summary": "Cancel one or more Delta V1 orders", + "description": "Sign-and-post cancellation. Only succeeds for orders still open in the auction.", + "operationId": "deltaOrdersCancel", "requestBody": { "required": true, "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/DeltaOrderSubmitRequest" } + "schema": { + "type": "object", + "required": ["orderIds", "signature"], + "properties": { + "orderIds": { + "type": "array", + "items": { "type": "string", "format": "uuid" }, + "minItems": 1, + "maxItems": 100 + }, + "signature": { "type": "string" } + } + } } } }, "responses": { "200": { - "description": "Order accepted; returns order id and status URL.", + "description": "Cancellation accepted.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "cancelled": { + "type": "array", + "items": { "type": "string", "format": "uuid" } + } + } + } + } + } + }, + "400": { "description": "Invalid signature or order already settled" } + } + } + }, + "/delta/orders/{orderId}": { + "get": { + "summary": "Get a Delta V1 order by ID", + "operationId": "deltaOrderById", + "parameters": [ + { + "name": "orderId", + "in": "path", + "required": true, + "schema": { "type": "string", "format": "uuid" } + } + ], + "responses": { + "200": { + "description": "Order details.", + "content": { + "application/json": { + "schema": { "$ref": "#/components/schemas/DeltaAuction" } + } + } + }, + "404": { "description": "Order not found" } + } + } + }, + "/delta/orders/hash/{hash}": { + "get": { + "summary": "Get a Delta V1 order by EIP-712 hash", + "operationId": "deltaOrderByHash", + "parameters": [ + { + "name": "hash", + "in": "path", + "required": true, + "schema": { "type": "string" } + } + ], + "responses": { + "200": { + "description": "Order details.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/DeltaOrderSubmitResponse" } + "schema": { "$ref": "#/components/schemas/DeltaAuction" } } } }, - "400": { - "description": "Invalid signature or order shape. Documented examples: `InvalidSignature`, `InvalidInput`.", + "404": { "description": "Order not found" } + } + } + }, + "/delta/orders/fillablebalance/{chainId}/{userAddress}/{tokenAddress}": { + "get": { + "summary": "Compute a user's fillable balance for limit orders", + "description": "Returns the user's wallet balance **minus** any source-token amounts already committed to open limit orders.\n\n`tokenAddress` is an optional trailing path segment — omit it (`/delta/orders/fillablebalance/{chainId}/{userAddress}`) to get balances for every committed token.", + "operationId": "deltaFillableBalance", + "parameters": [ + { + "name": "chainId", + "in": "path", + "required": true, + "schema": { "type": "integer", "example": 1 } + }, + { + "name": "userAddress", + "in": "path", + "required": true, + "schema": { "type": "string" } + }, + { + "name": "tokenAddress", + "in": "path", + "required": true, + "schema": { "type": "string" } + } + ], + "responses": { + "200": { + "description": "Map of `tokenAddress → fillableBalance`.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "type": "object", + "additionalProperties": { "type": "string" } + } } } + } + } + } + }, + "/delta/orders/orderbook/{chainId}/{agent}": { + "get": { + "summary": "Get pending orders for a specific agent (agent operators only)", + "description": "Returns the orderbook slice the auction would feed to one agent for a given chain. **Not intended for end-user integrations** — used by agent operators to introspect their fill queue.", + "operationId": "deltaOrderbook", + "parameters": [ + { + "name": "chainId", + "in": "path", + "required": true, + "schema": { "type": "integer" } }, - "500": { - "description": "Internal server error.", + { + "name": "agent", + "in": "path", + "required": true, + "schema": { "type": "string" }, + "description": "Agent name from `GET /delta/agents/list/{chainId}`." + } + ], + "responses": { + "200": { + "description": "Pending-order slice.", "content": { "application/json": { - "schema": { "$ref": "#/components/schemas/ErrorResponse" } + "schema": { + "type": "array", + "items": { "$ref": "#/components/schemas/DeltaAuction" } + } } } } } } + }, + "/delta/agents/list/{chainId}": { + "get": { + "summary": "List active agents competing in the auction for a chain", + "operationId": "deltaAgentsList", + "parameters": [ + { + "name": "chainId", + "in": "path", + "required": true, + "schema": { "type": "integer", "example": 1 } + } + ], + "responses": { + "200": { + "description": "Array of agent names.", + "content": { + "application/json": { + "schema": { "type": "array", "items": { "type": "string" } } + } + } + }, + "400": { "description": "Unsupported chain" } + } + } } }, "components": { "schemas": { - "Address": { - "type": "string", - "description": "EVM address (20 bytes, hex-encoded with `0x` prefix). Use the mixed-case placeholder `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE` for native ETH.", - "pattern": "^0x[a-fA-F0-9]{40}$", - "example": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" - }, - "ChainId": { - "type": "integer", - "description": "EVM chain ID. Supported values today include 1 (Mainnet), 10 (Optimism), 56 (BSC), 137 (Polygon), 8453 (Base), 42161 (Arbitrum), 43114 (Avalanche), 100 (Gnosis). The set is open — call GET /chains for the live list.", - "example": 1 - }, - "TokenAmount": { - "type": "string", - "description": "Token amount in WEI / raw units (no decimal point). Serialized as a string to preserve precision for amounts that exceed JavaScript Number range.", - "example": "1000000000000000000" - }, - "ErrorCode": { - "type": "string", - "description": "Documented Velora error code (e.g. `PricingError`, `InvalidInput`, `UnsupportedChain`, `StalePriceRoute`, `InvalidSignature`). The set is open — handle codes you recognize and fall back to a generic error path for everything else. See /api-reference/troubleshooting for known codes.", - "example": "PricingError" - }, - "ErrorResponse": { + "Bridge": { "type": "object", - "description": "Standard Velora error envelope.", - "required": ["errorType"], + "description": "On-chain bridge tuple. For same-chain orders, every field is the all-zero `DEFAULT_BRIDGE`.", "properties": { - "errorType": { "$ref": "#/components/schemas/ErrorCode" }, - "details": { "type": "string", "description": "Human-readable description of the failure." } - }, - "example": { - "errorType": "PricingError", - "details": "Error getting price data" + "protocolSelector": { "type": "string", "description": "bytes4." }, + "destinationChainId": { + "type": "integer", + "description": "uint64. `0` for same-chain." + }, + "outputToken": { "type": "string" }, + "scalingFactor": { "type": "integer" }, + "protocolData": { "type": "string" } } }, - "Eip712TypedData": { + "BridgeInfo": { "type": "object", - "description": "EIP-712 typed data ready to sign. See /delta/eip-712-typed-data-reference for the Velora-specific Order primaryType.", - "required": ["domain", "types", "primaryType", "message"], "properties": { - "domain": { - "type": "object", - "properties": { - "name": { "type": "string", "example": "Velora Delta" }, - "version": { "type": "string", "example": "1.0" }, - "chainId": { "$ref": "#/components/schemas/ChainId" }, - "verifyingContract": { "$ref": "#/components/schemas/Address" } - } - }, - "types": { - "type": "object", - "description": "Type definitions keyed by struct name. Each value is an array of `{ name, type }` fields.", - "additionalProperties": { - "type": "array", - "items": { - "type": "object", - "required": ["name", "type"], - "properties": { - "name": { "type": "string" }, - "type": { "type": "string" } - } - } - } - }, - "primaryType": { "type": "string", "example": "Order" }, - "message": { - "type": "object", - "description": "Order field values matching the `primaryType` struct." - } + "protocolName": { "type": "string" }, + "destAmountAfterBridge": { "type": "string" }, + "destUSDAfterBridge": { "type": "string" }, + "estimatedTimeMs": { "type": "integer" }, + "fees": { "type": "array", "items": { "type": "object" } } } }, - "MarketPriceRoute": { + "BridgeProtocol": { "type": "object", - "description": "Market route block. Calldata-ready against Augustus v6.2 when `version=6.2`. Same shape as the `priceRoute` field returned by GET /prices on the Market API.", "properties": { - "blockNumber": { "type": "integer" }, - "network": { "$ref": "#/components/schemas/ChainId" }, - "srcToken": { "$ref": "#/components/schemas/Address" }, - "srcDecimals": { "type": "integer" }, - "srcAmount": { "$ref": "#/components/schemas/TokenAmount" }, - "destToken": { "$ref": "#/components/schemas/Address" }, - "destDecimals": { "type": "integer" }, - "destAmount": { "$ref": "#/components/schemas/TokenAmount" }, - "bestRoute": { "type": "array", "items": { "type": "object" } }, - "gasCostUSD": { "type": "string" }, - "gasCost": { "type": "string" }, - "side": { "type": "string", "enum": ["SELL", "BUY"] }, - "version": { "type": "string" }, - "contractAddress": { "$ref": "#/components/schemas/Address" }, - "tokenTransferProxy": { "$ref": "#/components/schemas/Address" }, - "contractMethod": { "type": "string" }, - "partnerFee": { "type": "number" }, - "srcUSD": { "type": "string" }, - "destUSD": { "type": "string" }, - "partner": { "type": "string" }, - "maxImpactReached": { "type": "boolean" }, - "hmac": { "type": "string" } + "protocol": { + "type": "string", + "description": "Stable slug used in `includeBridges` / `excludeBridges`." + }, + "displayName": { "type": "string" }, + "icon": { + "type": "string", + "description": "Absolute URL to a 1:1 SVG icon hosted on cdn.velora.xyz." + } } }, - "DeltaQuote": { + "DeltaPriceWithHmac": { "type": "object", - "description": "Delta intent block. Sign and submit via POST /delta/orders/build then POST /delta/orders. Pass the block verbatim — including `hmac` — on the build call.", + "description": "Flat Delta price object. Same-chain quotes return `DeltaPrice`; crosschain quotes set `bridge` and add `bridgeInfo` and `availableBridges`. Pass this object verbatim (including `hmac`) to `POST /delta/orders/build`.", "properties": { - "srcToken": { "$ref": "#/components/schemas/Address" }, - "destToken": { "$ref": "#/components/schemas/Address" }, - "srcAmount": { "$ref": "#/components/schemas/TokenAmount" }, - "destAmount": { "$ref": "#/components/schemas/TokenAmount" }, - "destAmountBeforeFee": { "$ref": "#/components/schemas/TokenAmount" }, - "gasCostUSD": { "type": "string" }, + "srcToken": { "type": "string" }, + "destToken": { "type": "string" }, + "srcAmount": { "type": "string" }, + "srcAmountBeforeFee": { + "type": "string", + "description": "BUY side only." + }, + "destAmount": { "type": "string" }, + "destAmountBeforeFee": { + "type": "string", + "description": "SELL side only." + }, + "receivedDestAmount": { "type": "string" }, + "receivedDestUSD": { "type": "string" }, "gasCost": { "type": "string" }, + "gasCostBeforeFee": { "type": "string" }, + "gasCostUSD": { "type": "string" }, + "gasCostUSDBeforeFee": { "type": "string" }, "srcUSD": { "type": "string" }, "destUSD": { "type": "string" }, "destUSDBeforeFee": { "type": "string" }, - "gasCostBeforeFee": { "type": "string" }, - "gasCostUSDBeforeFee": { "type": "string" }, "partner": { "type": "string" }, "partnerFee": { "type": "number" }, - "bridge": { - "type": "object", - "properties": { - "outputToken": { "$ref": "#/components/schemas/Address" }, - "protocolData": { "type": "string" }, - "scalingFactor": { "type": "string" }, - "destinationChainId": { "$ref": "#/components/schemas/ChainId" }, - "protocolSelector": { "type": "string" } - } + "bridge": { "$ref": "#/components/schemas/Bridge" }, + "bridgeInfo": { "$ref": "#/components/schemas/BridgeInfo" }, + "availableBridges": { + "type": "array", + "items": { "type": "object" }, + "description": "Crosschain only. Each entry mirrors a `BridgePrice` with its own `bridge` + `bridgeInfo`." }, - "bridgeInfo": { - "type": "object", - "properties": { - "protocolName": { "type": "string" }, - "destAmountAfterBridge": { "$ref": "#/components/schemas/TokenAmount" }, - "destUSDAfterBridge": { "type": "string" }, - "estimatedTimeMs": { "type": "integer" }, - "fees": { "type": "array", "items": { "type": "object" } } - } - }, - "availableBridges": { "type": "array", "items": { "type": "object" } }, - "hmac": { "type": "string", "description": "Server-signed integrity envelope; pass back verbatim on POST /delta/orders/build." } + "hmac": { + "type": "string", + "description": "Server-signed integrity tag. Must be passed verbatim to `/delta/orders/build`." + } } }, - "DeltaQuoteResponse": { + "DeltaTokenWithStrategies": { "type": "object", - "description": "GET /quote envelope. Under `mode=ALL` Velora returns exactly one of `delta` or `market`; under `mode=DELTA` or `mode=MARKET`, the other block may be present as fallback (see /integrate/trading-modes).", "properties": { - "delta": { "$ref": "#/components/schemas/DeltaQuote" }, - "market": { "$ref": "#/components/schemas/MarketPriceRoute" }, - "deltaAddress": { - "allOf": [{ "$ref": "#/components/schemas/Address" }], - "description": "The Delta settlement contract address for the source chain." - }, - "fallbackReason": { - "allOf": [{ "$ref": "#/components/schemas/ErrorResponse" }], - "description": "Set when the requested mode couldn't price and the response fell back to the other path. Same shape as a 400 PricingError envelope." + "address": { + "type": "string", + "description": "Delta token (dToken) wrapper address." + }, + "strategies": { + "type": "array", + "items": { + "type": "object", + "properties": { + "vault": { + "type": "string", + "description": "ERC-4626 vault address. Pass as `strategy` on Productive order builds." + }, + "name": { "type": "string" }, + "apr": { + "type": "object", + "nullable": true, + "properties": { + "gross": { + "type": "string", + "description": "Gross APR as a decimal string." + }, + "net": { + "type": "string", + "description": "Net APR after fees." + } + } + } + } + } } } }, - "DeltaOrderBuildRequest": { + "DeltaAuctionTransaction": { "type": "object", - "required": ["price", "hmac"], + "description": "On-chain transaction that filled (part of) the order. One entry per fill; multiple entries for `partiallyFillable` orders or per-slice TWAPs.", "properties": { - "price": { - "allOf": [{ "$ref": "#/components/schemas/DeltaQuote" }], - "description": "The `delta` block returned by GET /quote, passed verbatim — do not recompute or re-encode amounts." - }, - "hmac": { + "id": { "type": "string" }, + "hash": { "type": "string" }, + "orderId": { "type": "string" }, + "bidId": { "type": "string", "nullable": true }, + "blockNumber": { "type": "integer" }, + "blockHash": { "type": "string" }, + "blockTimestamp": { "type": "string", - "description": "The `hmac` value from the `delta` block, passed verbatim." - } + "format": "date-time", + "nullable": true + }, + "index": { "type": "integer" }, + "status": { "type": "integer" }, + "from": { "type": "string" }, + "to": { "type": "string" }, + "receivedAmount": { "type": "string" }, + "receivedAmountUSD": { "type": "number" }, + "spentAmount": { "type": "string" }, + "spentAmountUSD": { "type": "number" }, + "filledPercent": { + "type": "integer", + "description": "Basis points (10000 = 100%)." + }, + "protocolFee": { "type": "string" }, + "partnerFee": { "type": "string" }, + "agent": { "type": "string" }, + "auctionId": { "type": "string" }, + "bridgeMetadata": { "type": "object", "nullable": true }, + "bridgeStatus": { "type": "string", "nullable": true }, + "bridgeProtocol": { "type": "string", "nullable": true } } }, - "DeltaOrderBuildResponse": { + "DeltaAuction": { "type": "object", - "description": "Order with EIP-712 typed data ready to sign. See /delta/eip-712-typed-data-reference for the Order primaryType shape." - }, - "DeltaOrderSubmitRequest": { - "type": "object", - "required": ["order", "signature"], + "description": "V1 order shape returned by every order endpoint. Status uses the legacy `DeltaAuctionStatus` enum; crosschain orders set `bridgeMetadata` and `bridgeStatus`.", "properties": { - "order": { - "type": "object", - "description": "The order body returned by POST /delta/orders/build." + "id": { "type": "string", "format": "uuid" }, + "deltaVersion": { "type": "string", "description": "`1.0` for V1." }, + "user": { "type": "string" }, + "status": { + "type": "string", + "enum": [ + "NOT_STARTED", + "AWAITING_PRE_SIGNATURE", + "RUNNING", + "EXECUTING", + "EXECUTED", + "FAILED", + "EXPIRED", + "CANCELLED", + "CANCELLING", + "SUSPENDED", + "REFUNDED" + ] }, - "signature": { + "orderHash": { "type": "string", "nullable": true }, + "transactions": { + "type": "array", + "items": { "$ref": "#/components/schemas/DeltaAuctionTransaction" } + }, + "chainId": { "type": "integer" }, + "partner": { "type": "string" }, + "referrerAddress": { "type": "string", "nullable": true }, + "expiresAt": { "type": "string", "format": "date-time" }, + "createdAt": { "type": "string", "format": "date-time" }, + "updatedAt": { "type": "string", "format": "date-time" }, + "partiallyFillable": { "type": "boolean" }, + "excludeAgents": { + "type": "array", + "items": { "type": "string" }, + "nullable": true + }, + "includeAgents": { + "type": "array", + "items": { "type": "string" }, + "nullable": true + }, + "bridgeMetadata": { "type": "object", "nullable": true }, + "bridgeStatus": { "type": "string", "nullable": true }, + "type": { "type": "string", "enum": ["MARKET", "LIMIT"] }, + "onChainOrderType": { "type": "string", - "description": "EIP-712 signature of the typed data — hex-encoded with `0x` prefix." + "enum": [ + "Order", + "FillableOrder", + "ProductiveOrder", + "ExternalOrder", + "TWAPOrder", + "TWAPBuyOrder" + ], + "description": "`FillableOrder` is what the server reports for a `partiallyFillable` Standard `Order`; the `order` struct shape is identical to `Order`." + }, + "order": { + "type": "object", + "description": "The signed on-chain Order struct (shape varies by `onChainOrderType`)." } } - }, - "DeltaOrderSubmitResponse": { - "type": "object", - "description": "Order acceptance envelope. Returns an order id and status URL." } } } diff --git a/api-reference/troubleshooting.mdx b/api-reference/troubleshooting.mdx index 605ea9e..2625e47 100644 --- a/api-reference/troubleshooting.mdx +++ b/api-reference/troubleshooting.mdx @@ -17,6 +17,10 @@ import MarketTransactionsFailureModes from "/snippets/failure-modes/market-trans import DeltaQuoteFailureModes from "/snippets/failure-modes/delta-quote.mdx"; import DeltaOrdersBuildFailureModes from "/snippets/failure-modes/delta-orders-build.mdx"; import DeltaOrdersFailureModes from "/snippets/failure-modes/delta-orders.mdx"; +import DeltaV2PricesFailureModes from "/snippets/failure-modes/delta-v2-prices.mdx"; +import DeltaV2OrdersBuildFailureModes from "/snippets/failure-modes/delta-v2-orders-build.mdx"; +import DeltaV2OrdersSubmitFailureModes from "/snippets/failure-modes/delta-v2-orders-submit.mdx"; +import DeltaV2OrdersCancelFailureModes from "/snippets/failure-modes/delta-v2-orders-cancel.mdx"; Each table covers a single endpoint and is updated from support tickets at each release. Jump straight to the endpoint you're calling. @@ -34,7 +38,25 @@ Each table covers a single endpoint and is updated from support tickets at each -## Delta API +## Delta V2 API + +### GET /delta/v2/prices + + + +### POST /delta/v2/orders/build + + + +### POST /delta/v2/orders + + + +### POST /delta/v2/orders/cancel + + + +## Delta V1 API ### GET /quote diff --git a/docs.json b/docs.json index 9f5e2b7..6c468bd 100644 --- a/docs.json +++ b/docs.json @@ -86,7 +86,8 @@ "sdk/install", "sdk/choose-a-variant", "sdk/simple-sdk", - "sdk/composable-sdk", + "sdk/full-sdk", + "sdk/partial-sdk", { "group": "Modules", "pages": [ @@ -261,12 +262,44 @@ ] }, { - "group": "Delta API", + "group": "Delta API V2", + "pages": [ + "api-reference/delta-v2/overview", + "api-reference/delta-v2/prices", + "api-reference/delta-v2/bridge-routes", + "api-reference/delta-v2/bridge-protocols", + "api-reference/delta-v2/strategies", + "api-reference/delta-v2/is-token-supported", + "api-reference/delta-v2/orders-build", + "api-reference/delta-v2/orders-submit", + "api-reference/delta-v2/orders-cancel", + "api-reference/delta-v2/orders-list", + "api-reference/delta-v2/orders-get-by-id", + "api-reference/delta-v2/orders-get-by-hash", + "api-reference/delta-v2/orders-fillable-balance", + "api-reference/delta-v2/agents-list" + ] + }, + { + "group": "Delta API V1", "pages": [ "api-reference/delta/overview", "api-reference/delta/quote", + "api-reference/delta/prices", + "api-reference/delta/bridge-info", + "api-reference/delta/bridge-protocols", + "api-reference/delta/strategies", + "api-reference/delta/is-token-supported", + "api-reference/delta/partner-fee", "api-reference/delta/orders-build", - "api-reference/delta/orders" + "api-reference/delta/orders", + "api-reference/delta/orders-cancel", + "api-reference/delta/orders-list", + "api-reference/delta/orders-get-by-id", + "api-reference/delta/orders-get-by-hash", + "api-reference/delta/orders-fillable-balance", + "api-reference/delta/orderbook", + "api-reference/delta/agents-list" ] }, { @@ -310,6 +343,7 @@ "group": "Migrations", "pages": [ "resources/migrations/index", + "resources/migrations/delta-v1-to-v2", "resources/migrations/market-to-delta-parallel", "resources/migrations/market-to-delta-replace", "resources/migrations/augustus-v5-to-v6-2", diff --git a/resources/migrations/delta-v1-to-v2.mdx b/resources/migrations/delta-v1-to-v2.mdx new file mode 100644 index 0000000..0434c04 --- /dev/null +++ b/resources/migrations/delta-v1-to-v2.mdx @@ -0,0 +1,271 @@ +--- +title: "Delta V1 → V2 (HTTP API)" +description: "Endpoint-by-endpoint migration for direct HTTP integrators. Server-built orders, route-based pricing, paginated history, unified status model." +keywords: ["migration", "delta", "delta v1", "delta v2", "api"] +--- + +This page is for integrators calling the Velora Delta HTTP API directly. If you're on the [Velora SDK](/sdk/modules/delta), the SDK-level migration walks the same path with TypeScript snippets — see [SDK → Migrate from V1 to V2](/sdk/modules/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 but cleans up the protocol surface: + +- **Server-built orders.** `POST /delta/v2/orders/build` returns EIP-712 typed data ready to sign. You stop composing `domain`, `types`, and `value` on the client. +- **Route-based pricing.** `GET /delta/v2/prices` returns a recommended `route` plus `alternatives` — let users pick a different bridge, and stop juggling the `bridge` / `bridgeInfo` / `availableBridges` triple V1 returns. +- **Paginated order history.** `GET /delta/v2/orders` returns `{ data, total, page, limit, hasMore }`. V1 returns a flat array with no total. +- **Unified status model.** Eleven values (`PENDING`, `AWAITING_SIGNATURE`, `ACTIVE`, `SUSPENDED`, `CANCELLING`, `BRIDGING`, `COMPLETED`, `FAILED`, `EXPIRED`, `CANCELLED`, `REFUNDED`) collapse V1's `status` + `bridgeStatus` columns into one. +- **Server-resolved partner fee.** Pass `partner` / `partnerAddress` / `partnerFeeBps` directly on every call — the server validates and encodes them. No more separate `GET /prices/partnerfee/{chainId}` round-trip. +- **No more `hmac`.** 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 /delta/v2/prices`](/api-reference/delta-v2/prices) | Response carries `route` + `alternatives`; `price.hmac` removed | +| `GET /delta/prices/bridge-info` | [`GET /delta/v2/prices/bridge-routes`](/api-reference/delta-v2/bridge-routes) | Flat `routes[]` array instead of nested `srcChainId → destChainId → tokens[]` map | +| `GET /delta/prices/bridge-protocols` | [`GET /delta/v2/prices/bridge-protocols`](/api-reference/delta-v2/bridge-protocols) | Same shape | +| `GET /delta/prices/strategies/{chainId}` | [`GET /delta/v2/prices/strategies/{chainId}`](/api-reference/delta-v2/strategies) | Same shape | +| `GET /delta/prices/is-token-supported` | [`GET /delta/v2/prices/is-token-supported`](/api-reference/delta-v2/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 /delta/v2/orders/build`](/api-reference/delta-v2/orders-build) | Different body — pass `route` (not `price` + `hmac`); response wraps typed data in `toSign` | +| `POST /delta/orders` | [`POST /delta/v2/orders`](/api-reference/delta-v2/orders-submit) | Submit `order: built.toSign.value` instead of `data` from V1 build | +| `POST /delta/orders/cancel` | [`POST /delta/v2/orders/cancel`](/api-reference/delta-v2/orders-cancel) | Same shape | +| `GET /delta/orders` | [`GET /delta/v2/orders`](/api-reference/delta-v2/orders-list) | Wraps array in `{ data, total, page, limit, hasMore }` | +| `GET /delta/orders/{orderId}` | [`GET /delta/v2/orders/{orderId}`](/api-reference/delta-v2/orders-get-by-id) | New response shape — `input` / `output` carry expected + executed amounts | +| `GET /delta/orders/hash/{hash}` | [`GET /delta/v2/orders/hash/{hash}`](/api-reference/delta-v2/orders-get-by-hash) | Same as above | +| `GET /delta/orders/fillablebalance/...` | [`GET /delta/v2/orders/fillablebalance/...`](/api-reference/delta-v2/orders-fillable-balance) | Same shape | +| `GET /delta/agents/list/{chainId}` | [`GET /delta/v2/agents/list/{chainId}`](/api-reference/delta-v2/agents-list) | Same shape | +| `GET /quote` (mode=ALL) | _No V2 equivalent_ | If you rely on the Delta-or-Market fallback, stay on V1 `/quote` | + +## Steps + +### 1. Pricing + +V1 returns a flat price object with a server-signed `hmac`. V2 returns a structured route plus alternatives. + +```diff +- GET /delta/prices?chainId=1&srcToken=0x...&destToken=0x...&amount=...&partner=my-app-name ++ GET /delta/v2/prices?chainId=1&srcToken=0x...&destToken=0x...&amount=...&partner=my-app-name +``` + +V1 response: + +```json +{ + "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 +{ + "id": "req_...", + "side": "SELL", + "inputToken": { "chainId": 1, "address": "0x..." }, + "outputToken": { "chainId": 1, "address": "0x..." }, + "route": { + "origin": { "input": { ... }, "output": { ... } }, + "destination": { "input": { ... }, "output": { ... } }, + "bridge": null, + "fees": { "gas": { ... }, "bridge": [] } + }, + "alternatives": [], + "partner": { "name": "my-app-name", "feePercent": 0.05 }, + "spender": "0x..." +} +``` + +Three things to handle: + +- **`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 — 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. + +```diff + POST /delta/orders/build + { +- "chainId": 1, +- "owner": "0x...", +- "price": { /* the full delta price object including hmac */ }, +- "slippage": 100 ++ /* request goes to /delta/v2/orders/build instead */ + } + ++ POST /delta/v2/orders/build ++ { ++ "owner": "0x...", ++ "route": { /* the route from /delta/v2/prices, verbatim */ }, ++ "side": "SELL", ++ "slippage": 100, ++ "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 }` — `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 + // 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 +- POST /delta/orders ++ POST /delta/v2/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. Poll for status + +V1 status (`DeltaAuctionStatus`) splits into `status` + `bridgeStatus`. V2 collapses both into one `status` field. + +```diff +- GET /delta/orders/{orderId} ++ GET /delta/v2/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` | +| `CANCELLED` | `CANCELLED` | +| `REFUNDED` (or `bridgeStatus: REFUNDED`) | `REFUNDED` | + +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`. + +### 6. List orders + +```diff +- GET /delta/orders?userAddress=0x...&page=1&limit=100 ++ GET /delta/v2/orders?userAddress=0x...&page=1&limit=100 +``` + +V1 returns a plain array; V2 wraps it: + +```diff +- [ { "id": "...", "status": "...", ... }, ... ] ++ { ++ "data": [ { "id": "...", "status": "...", ... }, ... ], ++ "total": 1234, ++ "page": 1, ++ "limit": 100, ++ "hasMore": true ++ } +``` + +You now know how many pages remain — useful for "load more" UIs without falling back to "fetch until you get fewer than `limit`". + +### 7. Cancel + +No semantic change — same path under `/v2`, same request body. + +```diff +- POST /delta/orders/cancel ++ POST /delta/v2/orders/cancel + { + "orderIds": ["..."], + "signature": "0x..." + } +``` + +### 8. 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 (`/delta/v2/prices`, `/delta/v2/orders/build`, `/delta/v2/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 +- // 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 /delta/v2/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. +- **`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` shape changed.** Nested object → flat `routes[]` array. The replacement endpoint is `bridge-routes` (different name). +- **Status enum changed.** Your status-handling code needs the mapping table above. Don't rely on `EXECUTED` alone — V2 reports `COMPLETED` for executed-and-finalized orders and `BRIDGING` while the destination leg is still pending. +- **Order list response changed.** V1 returned `Order[]`; V2 returns `{ 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 /delta/v2/prices` returns a `route` and a non-empty `spender`. +2. `POST /delta/v2/orders/build` returns `{ toSign, orderHash }`. +3. The signature your wallet produces over `toSign` is accepted by `POST /delta/v2/orders` (status `200`, response carries the new order shape with `id` and `status: "PENDING"`). +4. `GET /delta/v2/orders/{id}` polls through `ACTIVE` → `COMPLETED` (or `BRIDGING` → `COMPLETED` for crosschain). +5. `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 for an order family that V2 doesn't cover for you yet). + +## Related pages + +- [Delta V2 API overview](/api-reference/delta-v2/overview) — the recommended surface. +- [Delta V1 API overview](/api-reference/delta/overview) — the surface you're migrating from. +- [SDK → Migrate from V1 to V2](/sdk/modules/delta#migrate-from-v1-to-v2) — same migration at the TypeScript SDK level. +- [Order lifecycle and status codes](/delta/order-lifecycle-and-status-codes) — full V2 status reference. diff --git a/resources/migrations/index.mdx b/resources/migrations/index.mdx index e7ed5cf..d52e2aa 100644 --- a/resources/migrations/index.mdx +++ b/resources/migrations/index.mdx @@ -9,6 +9,9 @@ These pages are for engineers already shipping on Velora. They cover the only ki ## 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. diff --git a/sdk/choose-a-variant.mdx b/sdk/choose-a-variant.mdx index b59dfee..60b0df9 100644 --- a/sdk/choose-a-variant.mdx +++ b/sdk/choose-a-variant.mdx @@ -1,15 +1,47 @@ --- title: "Choose a variant" -description: "Pick between Simple SDK (one-call entry point) and Composable SDK (tree-shakeable modules) based on bundle size and flexibility needs." -keywords: ["sdk","simple","composable"] +description: "Pick between Simple, Full, and Partial SDK constructors based on bundle size, API shape, and how much wiring you want to do." +keywords: ["sdk", "simple", "full", "partial", "tree-shaking"] --- -This page is a stub. Content coming soon. +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. -## When to use this +## At a glance -## Quickstart +| | Simple | Full | Partial | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| Constructor | `constructSimpleSDK` | `constructFullSDK` | `constructPartialSDK` | +| API shape | Flat namespaces — `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 | -## Examples +## 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** — 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](/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](/sdk/monetize). +- Same retries, errors, and `FetcherError` semantics regardless of constructor. ## Related pages + + + + `constructSimpleSDK` — one constructor, sensible defaults. + + + `constructFullSDK` — namespaced, typed transaction responses. + + + `constructPartialSDK` — cherry-pick constructors, tree-shake the rest. + + diff --git a/sdk/composable-sdk.mdx b/sdk/composable-sdk.mdx deleted file mode 100644 index db65d0d..0000000 --- a/sdk/composable-sdk.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: "Composable SDK" -description: "Use the tree-shakeable, modular SDK when bundle size matters." -keywords: ["sdk","composable","tree-shaking"] ---- - -This page is a stub. Content coming soon. - -## When to use this - -## Quickstart - -## Examples - -## Related pages diff --git a/sdk/configure-providers.mdx b/sdk/configure-providers.mdx index b31d8c0..6a9e0ef 100644 --- a/sdk/configure-providers.mdx +++ b/sdk/configure-providers.mdx @@ -1,15 +1,194 @@ --- title: "Configure providers" -description: "Wire your own RPC providers, signer, and chain config into the SDK." -keywords: ["sdk","providers","rpc"] +description: "Wire your wallet library (viem, ethers v5/v6, web3) and HTTP client (axios, fetch, custom) into the SDK." +keywords: + ["sdk", "providers", "viem", "ethers", "web3", "axios", "fetch", "wagmi"] --- -This page is a stub. Content coming soon. +The SDK separates **what** (the Velora methods) from **how it talks to the chain and the API**. You wire two things: -## When to use this +- 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. -## Quickstart +[Simple SDK](/sdk/simple-sdk) builds both for you from a single options object. [Full SDK](/sdk/full-sdk) and [Partial](/sdk/partial-sdk) SDKs take them as constructor arguments. -## Examples +## Contract callers + +### viem + +```ts +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 +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 +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 +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 +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 +const eventfulTx = await sdk.swap.approveToken(amount, DAI); +eventfulTx.once("transactionHash", (hash: string) => + console.log("tx sent:", hash), +); +``` + +## Fetchers + +### axios + +```ts +import axios from "axios"; +import { constructAxiosFetcher } from "@velora-dex/sdk"; + +const fetcher = constructAxiosFetcher(axios); +``` + +### fetch (Node 18+ and the browser) + +```ts +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 +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 +import axios from "axios"; +import { useAccount, useWalletClient } from "wagmi"; +import { + constructPartialSDK, + constructAxiosFetcher, + constructViemContractCaller, + constructGetRate, + constructBuildTx, + constructApproveToken, +} from "@velora-dex/sdk"; + +function useVeloraSDK() { + const { address } = useAccount(); + const { data: walletClient } = useWalletClient(); + + if (!walletClient || !address) return null; + + const fetcher = constructAxiosFetcher(axios); + 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](/sdk/install) — peer dependencies for each wallet library. +- [Simple SDK](/sdk/simple-sdk) — uses these callers and fetchers via a single options object. +- [Full SDK](/sdk/full-sdk) — takes the caller and fetcher you construct here. +- [Partial SDK](/sdk/partial-sdk) — same wiring, smallest bundle. diff --git a/sdk/full-sdk.mdx b/sdk/full-sdk.mdx new file mode 100644 index 0000000..4a3d6f5 --- /dev/null +++ b/sdk/full-sdk.mdx @@ -0,0 +1,112 @@ +--- +title: "Full SDK" +description: "constructFullSDK gives you every namespace (sdk.swap, sdk.delta, sdk.deltaV2, sdk.quote) over a fetcher and contract caller you construct yourself, with a typed transaction-response generic." +keywords: ["sdk", "full", "constructFullSDK"] +--- + +`constructFullSDK` returns the same namespaced API as the [Simple SDK](/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 on mainnet (`chainId: 1`) and on 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](/sdk/simple-sdk) — fewer moving parts. + +## Construct it + +```ts +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](/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 +// type Promise +const hash = await sdk.swap.approveToken("1000000000000000000", DAI); +console.log("approval submitted:", hash); +``` + +## What's available + +The namespaces are identical to [Simple SDK](/sdk/simple-sdk#available-methods): + +- `sdk.deltaV2` — **recommended.** Full Delta V2 lifecycle: `getDeltaPrice`, `submitDeltaOrder`, build/sign/post split, `getDeltaOrders` (paginated), `cancelDeltaOrders`, plus reused approve/preSign. +- `sdk.delta` — Delta V1. Same lifecycle, locally-built orders. +- `sdk.quote` — `getQuote` +- `sdk.swap` — rate, build, approve, balances, spender, tokens, adapters, swapTx +- `sdk.limitOrders` — deprecated; see [Limit orders module](/sdk/modules/limit-orders) + +See [Modules → Swap](/sdk/modules/swap) and [Modules → Delta](/sdk/modules/delta) for end-to-end flows. + +## Sharing one caller across chains + +Because you own the caller, you can reuse it: + +```ts +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. + + diff --git a/sdk/install.mdx b/sdk/install.mdx index 5c68e90..e0f498c 100644 --- a/sdk/install.mdx +++ b/sdk/install.mdx @@ -1,15 +1,101 @@ --- title: "Install & quick example" description: "Install @velora-dex/sdk and fetch your first quote in under five minutes." -keywords: ["sdk","install","quickstart"] +keywords: ["sdk", "install", "quickstart", "typescript"] --- -This page is a stub. Content coming soon. +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. -## When to use this +## Install the package -## Quickstart + -## Examples +```bash pnpm +pnpm add @velora-dex/sdk +``` -## Related pages +```bash npm +npm install @velora-dex/sdk +``` + +```bash yarn +yarn add @velora-dex/sdk +``` + + + +### Peer dependencies + +Pick whichever wallet library and HTTP client you already use. All of these are optional peers — 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 cannot sign or submit transactions. + + +## Your first call + +The smallest possible setup — quote DAI → USDC on mainnet using native `fetch`: + +```ts +import { constructSimpleSDK } from "@velora-dex/sdk"; + +const simpleSDK = constructSimpleSDK({ chainId: 1, fetch }); + +const priceRoute = await simpleSDK.swap.getRate({ + srcToken: "0x6B175474E89094C44Da98b954EedeAC495271d0F", // DAI + destToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC + amount: "1000000000000000000", // 1 DAI (18 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` — 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](/sdk/configure-providers) for the four supported stacks (viem, ethers v5, ethers v6, web3). + +## Next steps + + + + Simple vs Full vs Partial — bundle size and API shape tradeoffs. + + + The one-constructor entry point used in this page. + + + Wire up viem, ethers, or web3 for signing and transactions. + + + Full Market-swap flow: rate → approve → build → send. + + diff --git a/sdk/modules/delta.mdx b/sdk/modules/delta.mdx index 1cfe598..4c15ec6 100644 --- a/sdk/modules/delta.mdx +++ b/sdk/modules/delta.mdx @@ -1,15 +1,356 @@ --- title: "Delta module" -description: "Submit and track Delta intents from the SDK." -keywords: ["sdk","delta","intents"] +description: "Submit, sign, and track Delta intents from sdk.deltaV2 — gasless swaps where solvers execute on the user's behalf." +keywords: ["sdk", "delta", "deltaV2", "DeltaV2", "intents", "gasless", "submitDeltaOrder"] --- -This page is a stub. Content coming soon. +The Delta module wraps the [Delta API](/delta/overview) — gasless, MEV-protected swaps where the user signs an off-chain order and a network of solvers (Portikus) competes to fill it. The user pays no gas; the solver covers execution cost out of their margin. + + +**Delta V2 is recommended.** V2 is server-built (you don't compose EIP-712 typed data locally), returns richer pricing (recommended route + alternatives), and ships paginated order history. V1 remains fully supported — see [Delta V1](#delta-v1) at the bottom of this page. + ## When to use this -## Quickstart +- 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 a single signature to settle crosschain — see [Crosschain Delta](/delta/crosschain-delta). + +For swaps where the user submits the transaction themselves, see [Modules → Swap](/sdk/modules/swap). + +## How V2 is exposed + +V2 lives at two layers in the SDK: + +- **`sdk.deltaV2.*`** — the pre-bound bag attached to `constructSimpleSDK` / `constructFullSDK`. Methods on it are **unsuffixed**: `sdk.deltaV2.getDeltaPrice`, `sdk.deltaV2.submitDeltaOrder`, `sdk.deltaV2.signDeltaOrder`, etc. This is what most consumers use. +- **`DeltaV2` namespace** — re-exported at the package root. Carries the raw constructors *and* types for advanced wiring (e.g., `constructPartialSDK`) and type annotations. + +```ts +import { DeltaV2 } from "@velora-dex/sdk"; + +// values: DeltaV2.constructBuildDeltaOrder, DeltaV2.constructPostDeltaOrder, +// DeltaV2.constructSubmitDeltaOrder, DeltaV2.constructAllDeltaOrdersHandlers, ... +// types: DeltaV2.DeltaPrice, DeltaV2.DeltaRoute, DeltaV2.BuiltDeltaOrder, +// DeltaV2.DeltaAuction, DeltaV2.BridgeRoute, ... +``` + +`import type { DeltaV2 }` works the same way for type-only consumers. Types live *inside* the namespace — alias with `type DeltaPrice = DeltaV2.DeltaPrice;` if you want a short local name; you can't destructure a type at the import site. + +The same unsuffixed names exist for V1 at the top level of the package (`constructPostDeltaOrder`, `DeltaPrice`, etc.) — wrapping V2 in a namespace is what makes the two coexist without collision until V1 is deprecated. + +## The flow + + + + Call `sdk.deltaV2.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.deltaV2.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.deltaV2.submitDeltaOrder`, or run the three steps yourself (`buildDeltaOrder` → `signDeltaOrder` → `postDeltaOrder`) when you need control over signing. + + + Use `sdk.deltaV2.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 +const price = await sdk.deltaV2.getDeltaPrice({ + srcToken: DAI, + destToken: USDC, + amount: "1000000000000000000", // 1 DAI + srcDecimals: 18, + destDecimals: 6, + userAddress: account, + partner: "my-app-name", +}); + +await sdk.deltaV2.approveTokenForDelta("1000000000000000000", DAI); + +const auction = await sdk.deltaV2.submitDeltaOrder({ + route: price.route, + side: price.side, + owner: account, + partner: "my-app-name", + slippage: 50, // 0.5% in bps + // 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 +const built = await sdk.deltaV2.buildDeltaOrder({ + route: price.route, + side: price.side, + owner: account, + partner: "my-app-name", + slippage: 50, +}); + +const signature = await sdk.deltaV2.signDeltaOrder(built); + +const auction = await sdk.deltaV2.postDeltaOrder({ + order: built.toSign.value as any, + signature, + partner: "my-app-name", +}); +``` + +`buildDeltaOrder` returns `{ toSign, orderHash }` — the server has already composed the EIP-712 typed data; `signDeltaOrder` wraps your contract caller's `signTypedData` to produce the signature. + +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.deltaV2.preSignDeltaOrder` to register the order hash on-chain instead. + +## Poll for execution + +```ts +import { OrderHelpers } from "@velora-dex/sdk"; + +const intervalId = setInterval(async () => { + const updated = await sdk.deltaV2.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` works for both V2 and V1 auctions. It returns `true` only when same-chain orders show `status === "EXECUTED"` (or V2's `COMPLETED`), and crosschain orders also have their destination-chain leg filled. + +Order status codes and their meaning are documented under [Delta → Order lifecycle and status codes](/delta/order-lifecycle-and-status-codes). + +## List orders + +`getDeltaOrders` returns a paginated list filtered by user, chain, status, and order type: + +```ts +const { data, page, limit, total } = await sdk.deltaV2.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 `DeltaV2.DeltaAuction`, generic over `onChainOrderType` (the same shape as V1's `DeltaAuction`). The list may include `'ProductiveOrder'` — a family with no SDK builder; see [Productive orders](#productive-orders-read-only) below. It may also report `'FillableOrder'` for a `partiallyFillable` Standard order — treat it exactly like `'Order'` (identical shape). + +## Partner fee + +Pass `partner` (and optionally `partnerAddress`, `partnerFeeBps`, `partnerTakesSurplus`) to `getDeltaPrice`, `submitDeltaOrder`, `buildDeltaOrder`, and `postDeltaOrder`. V2 sends these directly to the server, which resolves and validates the fee — no local `getPartnerFee` round-trip needed. + +```ts +const auction = await sdk.deltaV2.submitDeltaOrder({ + route: price.route, + side: price.side, + owner: account, + partner: "my-app-name", + partnerAddress: "0xYourFeeCollector", + partnerFeeBps: 25, // 0.25% + slippage: 50, +}); +``` + +See [Monetize](/sdk/monetize) for the full field reference and fee-vs-surplus tradeoffs. + +## Cancel an order + +```ts +await sdk.deltaV2.cancelDeltaOrders({ orderIds: [auction.id] }); +``` + +This signs and posts a cancellation request. It only succeeds for orders that are still open in the auction. -## Examples +## 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](/delta/crosschain-delta) for the full design and [`getBridgeRoutes`](https://github.com/VeloraDEX/sdk/blob/master/src/methods/deltaV2/getBridgeRoutes.ts) for advanced route inspection. + +## External and TWAP orders + +The SDK supports two advanced order families on V2 that share the same build/sign/post pattern: + +- **External Delta orders** — settle through a custom handler contract. Used for Aave-style collateral/debt swaps and other DeFi compositions. Use `buildExternalDeltaOrder` / `submitExternalDeltaOrder`. See [`EXTERNAL_ORDERS.md`](https://github.com/VeloraDEX/sdk/blob/master/docs/EXTERNAL_ORDERS.md) in the SDK repo. +- **TWAP Delta orders** — split a large order into time-weighted chunks (sell-side or buy-side). Use `buildTWAPDeltaOrder` / `submitTWAPDeltaOrder`. + +Both reuse the generic `signDeltaOrder` and the V2 polling endpoints. + +## Productive orders (read-only) + +Alongside the four buildable families (`Order`, `ExternalOrder`, `TWAPOrder`, `TWAPBuyOrder`), the SDK surfaces a fifth `onChainOrderType` — **`ProductiveOrder`** — through the read endpoints (`sdk.deltaV2.getDeltaOrderById`, `sdk.deltaV2.getDeltaOrders`, etc.). Productive orders are produced and managed entirely by the server: there are **no `buildProductiveOrder`, `signProductiveOrder`, or `submitProductiveOrder` helpers** in the SDK. The shape is wired through `OnChainOrderType`, `OnChainOrderMap`, and `DeltaAuctionUnion` (also exported individually as `DeltaAuctionProductive`) so a consumer iterating over an order list can narrow on `onChainOrderType === 'ProductiveOrder'` and read the order safely. Productive orders carry no `OrderKind`, so the side is always `SELL`. + +```ts +import { OrderHelpers, type DeltaAuctionUnion } from "@velora-dex/sdk"; + +function describe(order: DeltaAuctionUnion) { + if (order.onChainOrderType === "ProductiveOrder") { + // order: DeltaAuctionProductive — read-only, no SDK builder + return `productive: ${order.order.srcToken}`; + } + // "Order" and "FillableOrder" share the same shape (DeltaAuctionFillable) + // ... handle Order / FillableOrder / ExternalOrder / TWAPOrder / TWAPBuyOrder +} +``` + +## Migrate from V1 to V2 + +The two paths share the same on-chain contracts and approval flow. What changes is where the EIP-712 typed data comes from (server in V2, local in V1) and the param shapes — V2 packages source/destination details inside a `route` object and takes `slippage` directly. + +### Pricing + +```diff +- const deltaPrice = await sdk.delta.getDeltaPrice({ ++ const price = await sdk.deltaV2.getDeltaPrice({ + srcToken: DAI, + destToken: USDC, + amount, + srcDecimals: 18, + destDecimals: 6, + userAddress: account, + partner: "my-app-name", + }); +``` + +V1 returns `DeltaPrice { destAmount, partner, partnerFee, srcAmount, destToken }`. V2 returns `DeltaV2.DeltaPrice { route, alternatives, partner: { name, feePercent }, spender, ... }` — swap details live under `price.route`, and `alternatives` lets you show users different bridges. + +### One-call submit + +```diff +- const auction = await sdk.delta.submitDeltaOrder({ +- deltaPrice, +- owner: account, +- srcToken: DAI, +- destToken: USDC, +- srcAmount: amount, +- destAmount, // you compute slippage-adjusted destAmount +- partner: "my-app-name", +- }); ++ const auction = await sdk.deltaV2.submitDeltaOrder({ ++ route: price.route, // route carries src/dest tokens and amounts ++ side: price.side, ++ owner: account, ++ partner: "my-app-name", ++ slippage: 50, // bps; SDK applies slippage for you ++ }); +``` + +### Split flow (build → sign → post) + +```diff +- const signableOrderData = await sdk.delta.buildDeltaOrder({ /* ... */ }); +- const signature = await sdk.delta.signDeltaOrder(signableOrderData); +- const auction = await sdk.delta.postDeltaOrder({ +- order: signableOrderData.data, +- signature, +- partner: "my-app-name", +- }); ++ const built = await sdk.deltaV2.buildDeltaOrder({ /* ... */ }); ++ const signature = await sdk.deltaV2.signDeltaOrder(built); ++ const auction = await sdk.deltaV2.postDeltaOrder({ ++ order: built.toSign.value as any, ++ signature, ++ partner: "my-app-name", ++ }); +``` + +V2 method names are the same as V1's at the property level (`buildDeltaOrder`, `signDeltaOrder`, `postDeltaOrder`) — what changes is the SDK namespace (`sdk.delta` → `sdk.deltaV2`) and the param/response shapes. `buildDeltaOrder` returns `{ toSign, orderHash }` from the server. `signDeltaOrder` is generic across all order families (Order, ExternalOrder, TWAPOrder, TWAPBuyOrder) — V1's separate `signExternalDeltaOrder` / `signTWAPDeltaOrder` collapse into one call. + +### Polling status + +```diff +- const updated = await sdk.delta.getDeltaOrderById(auction.id); ++ const updated = await sdk.deltaV2.getDeltaOrderById(auction.id); +``` + +`OrderHelpers.checks.isExecutedAuction(updated)` works for both. V2 introduces a richer status set (`PENDING` / `AWAITING_SIGNATURE` / `ACTIVE` / `BRIDGING` / `COMPLETED` / `FAILED` / ...). See [Order lifecycle and status codes](/delta/order-lifecycle-and-status-codes) for the V2 mapping. + +### Listing orders + +```diff +- const orders = await sdk.delta.getDeltaOrders({ /* filter */ }); ++ const { data, page, limit, total } = await sdk.deltaV2.getDeltaOrders({ ++ userAddress: account, ++ page: 1, ++ limit: 100, ++ }); +``` + +V2 returns a `PaginatedResponse` envelope. `userAddress` is required; iterate `data` and increment `page` until you've consumed `total`. + +### Cancelling + +```diff +- await sdk.delta.cancelLimitDeltaOrders([orderId]); ++ await sdk.deltaV2.cancelDeltaOrders({ orderIds: [orderId] }); +``` + +### Type imports + +```diff +- import type { DeltaPriceV2, BuiltDeltaOrderV2, DeltaOrderV2Response } from "@velora-dex/sdk"; ++ import { DeltaV2 } from "@velora-dex/sdk"; ++ // then: DeltaV2.DeltaPrice, DeltaV2.BuiltDeltaOrder, DeltaV2.DeltaAuction +``` + +V2 types live inside the `DeltaV2` namespace; the old `*V2`-suffixed bare names are no longer exported. + +### What stays the same + +- `sdk.deltaV2.approveTokenForDelta(amount, token)` — same as V1. +- `sdk.deltaV2.getDeltaContract()` — same contract address. +- `sdk.deltaV2.getPartnerFee({ partner })` — useful for showing fee info in your UI; V2 doesn't *need* this round-trip because the server resolves partner fees, but the helper is still there. +- `sdk.deltaV2.preSignDeltaOrder` — on-chain pre-signing for smart-contract wallets. +- The on-chain order struct and signature format are identical — V2 is a different way to assemble the same on-chain payload. + +## Delta V1 + +V1 is exposed at `sdk.delta.*`. The flow is similar but the order is built locally (no server `build` call) and the response shapes differ: + +```ts +const deltaPrice = await sdk.delta.getDeltaPrice({ + srcToken: DAI, + destToken: USDC, + amount, + srcDecimals: 18, + destDecimals: 6, + userAddress: account, + partner: "my-app-name", +}); + +await sdk.delta.approveTokenForDelta(amount, DAI); + +const auction = await sdk.delta.submitDeltaOrder({ + deltaPrice, + owner: account, + srcToken: DAI, + destToken: USDC, + srcAmount: amount, + destAmount: deltaPrice.destAmount, // apply your own slippage + partner: "my-app-name", +}); +``` + +Poll via `sdk.delta.getDeltaOrderById(auction.id)`. Cancel via `sdk.delta.cancelLimitDeltaOrders([auction.id])`. + +V2 is recommended for most flows — partner-fee resolution is server-side, the price response includes bridge alternatives, and order listing is paginated. V1 stays useful when you need local control over EIP-712 typed-data assembly (e.g., to inspect or modify the order before signing) or when you're already consuming the V1 `quote.getQuote` Delta-or-Market response. ## Related pages + +- [Why Delta](/delta/overview) — the protocol design. +- [Quickstart](/overview/quickstart) — Delta end-to-end via cURL. +- [Monetize](/sdk/monetize) — partner-fee fields. +- [API reference → Delta](/api-reference/delta/overview) — the HTTP endpoints. diff --git a/sdk/modules/limit-orders.mdx b/sdk/modules/limit-orders.mdx index 890de2e..ce6adff 100644 --- a/sdk/modules/limit-orders.mdx +++ b/sdk/modules/limit-orders.mdx @@ -1,15 +1,41 @@ --- title: "Limit orders module" -description: "Create, sign, and manage limit orders from the SDK." -keywords: ["sdk","limit orders"] +description: "The SDK limit-orders module is deprecated. New integrations should use Delta limit orders, which are gasless and MEV-protected." +keywords: ["sdk", "limit orders", "deprecated", "delta"] --- -This page is a stub. Content coming soon. + +**The SDK `limitOrders` module is deprecated** and will be removed in a future major version. New integrations should use **Delta limit orders** — they are gasless, MEV-protected, and use the same Portikus solver network as Delta market orders. + -## When to use this +## Migrate to Delta -## Quickstart +Limit-order behavior is now expressed through Delta with a `LIMIT` order type. You sign once and the solver network competes to fill at or better than your limit price; you pay no gas. -## Examples + + + What Delta gives you over a classic limit order — gasless, MEV-protected, crosschain. + + + Build, sign, and submit a Delta order from the SDK. + + + +## The deprecated module + +For existing integrations, the `sdk.limitOrders` namespace still exposes: + +- `buildLimitOrder` — assemble an EIP-712 typed-data payload. +- `signLimitOrder` — sign that payload with the connected wallet. +- `postLimitOrder` — submit the signed order to the API. +- `cancelLimitOrder` — sign and post a cancellation. +- `getLimitOrders` — query open and filled orders for a maker. +- `approveTokenForLimitOrder`, `getLimitOrdersContract`, `buildLimitOrderTx`, `fillOrderDirectly` — supporting on-chain methods. + +Full signatures, parameter shapes, and return types are generated from source into the [SDK typedoc reference](https://github.com/VeloraDEX/sdk/tree/master/docs/md). ## Related pages + +- [Why Delta](/delta/overview) +- [Modules → Delta](/sdk/modules/delta) +- [API reference → Delta](/api-reference/delta/overview) diff --git a/sdk/modules/swap.mdx b/sdk/modules/swap.mdx index 98d04dd..52e2a11 100644 --- a/sdk/modules/swap.mdx +++ b/sdk/modules/swap.mdx @@ -1,15 +1,118 @@ --- title: "Swap module" -description: "Build, sign, and execute swaps through the SDK swap module." -keywords: ["sdk","swap"] +description: "Build, approve, and execute Market swaps through sdk.swap — the user submits the transaction themselves." +keywords: ["sdk", "swap", "market", "buildTx", "getRate"] --- -This page is a stub. Content coming soon. +The Swap module wraps the [Market API](/market/overview) — rates, allowances, and transaction-building for swaps that the **user** signs and submits. For gasless swaps where solvers settle on the user's behalf, see [Modules → Delta](/sdk/modules/delta). ## When to use this -## Quickstart +- 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 module](/sdk/modules/delta) for that. -## Examples +## 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 +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 DAI = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; +const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; +const amount = "1000000000000000000"; // 1 DAI + +// 1. Quote +const priceRoute = await sdk.swap.getRate({ + srcToken: DAI, + destToken: USDC, + amount, + userAddress: account, + side: "SELL", + options: { partner: "my-app-name" }, +}); + +// 2. Approve +await sdk.swap.approveToken(amount, DAI); + +// 3. Build the swap transaction +const tx = await sdk.swap.buildTx({ + srcToken: DAI, + destToken: USDC, + srcAmount: amount, + slippage: 250, // 2.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 +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](/api-reference/market/transactions) endpoint for the supported permit variants. + +## Other methods + +- `sdk.swap.getSpender()` — the `TokenTransferProxy` address you approve. +- `sdk.swap.getBalances(userAddress)` — token balances and allowances in one call. +- `sdk.swap.getTokens()` — Velora-supported tokens on the active chain. +- `sdk.swap.getAdapters()` — the DEX adapters available to the router. +- `sdk.swap.swapTx(params)` — 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](/sdk/monetize) for the full field reference. ## Related pages + +- [Modules → Delta](/sdk/modules/delta) — gasless intent-based swaps. +- [Monetize](/sdk/monetize) — partner-fee fields and tradeoffs. +- [Configure providers](/sdk/configure-providers) — set up your wallet library. +- [API reference → Market](/api-reference/market/overview) — the underlying HTTP endpoints. diff --git a/sdk/monetize.mdx b/sdk/monetize.mdx index 61b42c9..d3a3b96 100644 --- a/sdk/monetize.mdx +++ b/sdk/monetize.mdx @@ -1,15 +1,91 @@ --- -title: "Monetize (fee config)" -description: "Configure partner fees on SDK calls and collect revenue per trade." -keywords: ["sdk","fees","monetization"] +title: "Monetize" +description: "Add partner fees or surplus share to every SDK call — same partner key works across Market swaps, Delta orders, and quotes." +keywords: ["sdk", "fees", "monetization", "partner", "partnerFee", "takeSurplus"] --- -This page is a stub. Content coming soon. +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 — no extra integration needed. -## When to use this +## Quick setup -## Quickstart +If you've registered your partner key with Velora, just pass `partner` and the server resolves the fee config: -## Examples +```ts +const auction = await sdk.deltaV2.submitDeltaOrder({ + route: price.route, + side: price.side, + owner: account, + partner: "my-app-name", + slippage: 50, +}); +``` + +To override the registered defaults per call, pass the fee fields directly: + +```ts +const auction = await sdk.deltaV2.submitDeltaOrder({ + route: price.route, + side: price.side, + owner: account, + partner: "my-app-name", + partnerAddress: "0xYourFeeCollector", + partnerFeeBps: 25, // 0.25% + partnerTakesSurplus: false, + slippage: 50, +}); +``` + + +**Delta V2 vs V1.** V2 sends `partner` / `partnerAddress` / `partnerFeeBps` straight to the server, which resolves and validates them — no extra round-trip. V1 calls `getPartnerFee(partner)` locally inside `buildDeltaOrder` (response is cached per partner). Either way the fee lands on-chain at settlement; the V2 path is just one fewer network call. + + +If you need to obtain the registered defaults programmatically (e.g., to show "0.25% fee" in your UI), call `getPartnerFee` directly: + +```ts +const { partnerAddress, partnerFee, takeSurplus } = + await sdk.deltaV2.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 + +| | 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 | + +## Where it applies + +- **Delta V2** (recommended) — pass `partner` (and overrides) to `sdk.deltaV2.getDeltaPrice`, `sdk.deltaV2.submitDeltaOrder`, `sdk.deltaV2.buildDeltaOrder`, and `sdk.deltaV2.postDeltaOrder`. The server encodes the fee into the on-chain order. +- **Delta V1** — pass `partner` to `sdk.delta.buildDeltaOrder` or `sdk.delta.submitDeltaOrder`. The SDK resolves the fee locally via `getPartnerFee` and encodes it into the signed order's `partnerAndFee` field. +- **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](/overview/pro-api-accounts) — register a partner key and set defaults. +- [Widget → Monetize](/widget/monetize) — same fee mechanics for the embeddable widget. +- [Modules → Delta](/sdk/modules/delta) — full Delta order flow with partner attribution. +- [Modules → Swap](/sdk/modules/swap) — full Market-swap flow with partner attribution. diff --git a/sdk/overview.mdx b/sdk/overview.mdx index 2acbff5..6e2435f 100644 --- a/sdk/overview.mdx +++ b/sdk/overview.mdx @@ -1,15 +1,138 @@ --- title: "SDK overview" -description: "Use @velora-dex/sdk to integrate quotes, swaps, limit orders, and Delta intents from JavaScript or TypeScript." -keywords: ["sdk","overview"] +description: "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." +keywords: ["sdk", "overview", "typescript", "javascript"] --- -This page is a stub. Content coming soon. +`@velora-dex/sdk` is a TypeScript SDK for the Velora API. It wraps the [Market](/market/overview) and [Delta](/delta/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. -## When to use this +## What you get + + + + Works with [viem](https://viem.sh), [ethers](https://docs.ethers.org) (v5 or + v6), or [web3.js](https://web3js.readthedocs.io) — 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 +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 DAI = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; +const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; +const amount = "1000000000000000000"; + +const quote = await simpleSDK.quote.getQuote({ + srcToken: DAI, + destToken: USDC, + amount, + userAddress: account, + srcDecimals: 18, + destDecimals: 6, + mode: "all", // try Delta first, fall back to Market + side: "SELL", + partner: "my-app-name", +}); + +if ("delta" in quote) { + await simpleSDK.delta.approveTokenForDelta(amount, DAI); + const auction = await simpleSDK.delta.submitDeltaOrder({ + deltaPrice: quote.delta, + owner: account, + srcToken: DAI, + destToken: USDC, + srcAmount: amount, + destAmount: quote.delta.destAmount, // adjust for slippage in production + partner: "my-app-name", + }); +} else { + const tx = await simpleSDK.swap.buildTx({ + srcToken: DAI, + destToken: USDC, + srcAmount: amount, + slippage: 250, + priceRoute: quote.market, + userAddress: account, + partner: "my-app-name", + }); + const hash = await walletClient.sendTransaction({ + ...txParamsToViemTxParams(tx), + account, + }); +} +``` ## How it works -## Examples +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 +graph TD + A["constructSimpleSDK
(flat: sdk.swap / sdk.delta / sdk.quote)"] --> 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 — and choose your HTTP client. + + ## Related pages + +- [Why Velora](/overview/why-velora) — when to reach for the SDK vs the API or widget. +- [Migration from `@paraswap/sdk`](/resources/migrations/paraswap-sdk-to-velora-sdk) — legacy package → `@velora-dex/sdk`. +- [API reference](/api-reference/introduction) — the HTTP endpoints the SDK wraps. diff --git a/sdk/partial-sdk.mdx b/sdk/partial-sdk.mdx new file mode 100644 index 0000000..9614365 --- /dev/null +++ b/sdk/partial-sdk.mdx @@ -0,0 +1,180 @@ +--- +title: "Partial SDK" +description: "constructPartialSDK lets bundle-size-sensitive apps import only the construct* functions they call; TypeScript infers the resulting SDK shape from the selection." +keywords: + ["sdk", "partial", "constructPartialSDK", "tree-shaking", "bundle-size"] +--- + +`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](/sdk/simple-sdk) or [Full SDK](/sdk/full-sdk). + +## Example: rates and approvals only + +The smallest useful Partial SDK — read rates from the API, approve tokens for swaps. + +```ts +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: "0x6B175474E89094C44Da98b954EedeAC495271d0F", // DAI + destToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC + amount: "1000000000000000000", + userAddress: account, + side: "SELL", +}); +const hash = await sdk.approveToken( + "1000000000000000000", + "0x6B175474E89094C44Da98b954EedeAC495271d0F", +); +``` + +## Example: Delta V2 signing only + +A front-end that signs Delta V2 orders but does no other reads or writes. V2 constructors live under the `DeltaV2` namespace at the package root: + +```ts +import { + constructPartialSDK, + constructAxiosFetcher, + constructViemContractCaller, + constructApproveTokenForDelta, + DeltaV2, +} from "@velora-dex/sdk"; + +const fetcher = constructAxiosFetcher(axios); +const contractCaller = constructViemContractCaller(walletClient, account); + +const deltaSDK = constructPartialSDK( + { chainId: 1, fetcher, contractCaller }, + DeltaV2.constructGetDeltaPrice, + DeltaV2.constructBuildDeltaOrder, + DeltaV2.constructSignDeltaOrder, + DeltaV2.constructPostDeltaOrder, + constructApproveTokenForDelta, // reused from V1 — same contract +); + +const DAI = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; +const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; +const amount = "1000000000000000000"; + +const price = await deltaSDK.getDeltaPrice({ + srcToken: DAI, + destToken: USDC, + amount, + srcDecimals: 18, + destDecimals: 6, + userAddress: account, + partner: "my-app-name", +}); + +await deltaSDK.approveTokenForDelta(amount, DAI); + +const built = await deltaSDK.buildDeltaOrder({ + route: price.route, + side: price.side, + owner: account, + partner: "my-app-name", + slippage: 50, // 0.5% in bps +}); + +const signature = await deltaSDK.signDeltaOrder(built); +const auction = await deltaSDK.postDeltaOrder({ + order: built.toSign.value as any, + signature, + partner: "my-app-name", +}); +``` + +The `DeltaV2` namespace doubles as a runtime object — bundlers tree-shake whichever members you don't reference, so this example pulls in only the four V2 constructors above. + +## Available constructors + +Pass any combination of these. Methods on the resulting SDK match the names listed in [Simple SDK → Available methods](/sdk/simple-sdk#available-methods). V2 constructors are accessed through the `DeltaV2` namespace (`DeltaV2.constructBuildDeltaOrder`, etc.); V1 constructors are exported bare from the package root. + +| Module | Constructors | +| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Delta V2** (recommended)| `DeltaV2.constructGetDeltaPrice`, `DeltaV2.constructBuildDeltaOrder`, `DeltaV2.constructSignDeltaOrder`, `DeltaV2.constructPostDeltaOrder`, `DeltaV2.constructSubmitDeltaOrder` (orchestrator), `DeltaV2.constructGetDeltaOrders`, `DeltaV2.constructCancelDeltaOrder`, `DeltaV2.constructGetBridgeRoutes`, `DeltaV2.constructIsTokenSupportedInDelta`, `DeltaV2.constructGetAgentsList`, plus reused from V1: `constructApproveTokenForDelta`, `constructPreSignDeltaOrder`, `constructDeltaTokenModule`, `constructGetDeltaContract`, `constructGetPartnerFee` | +| External Delta V2 | `DeltaV2.constructBuildExternalDeltaOrder`, `DeltaV2.constructPostExternalDeltaOrder`, `DeltaV2.constructSubmitExternalDeltaOrder` | +| TWAP Delta V2 | `DeltaV2.constructBuildTWAPDeltaOrder`, `DeltaV2.constructPostTWAPDeltaOrder`, `DeltaV2.constructSubmitTWAPDeltaOrder` | +| Delta V1 | `constructGetDeltaPrice`, `constructBuildDeltaOrder`, `constructSignDeltaOrder`, `constructPostDeltaOrder`, `constructSubmitDeltaOrder`, `constructApproveTokenForDelta`, `constructPreSignDeltaOrder`, `constructDeltaTokenModule`, `constructGetDeltaContract`, `constructGetDeltaOrders`, `constructCancelDeltaOrder`, `constructGetPartnerFee`, `constructGetBridgeInfo`, `constructIsTokenSupportedInDelta` | +| External Delta V1 | `constructBuildExternalDeltaOrder`, `constructSignExternalDeltaOrder`, `constructPostExternalDeltaOrder`, `constructPreSignExternalDeltaOrder` | +| TWAP Delta V1 | `constructBuildTWAPDeltaOrder`, `constructSignTWAPDeltaOrder`, `constructPostTWAPDeltaOrder`, `constructPreSignTWAPDeltaOrder` | +| Swap | `constructGetRate`, `constructBuildTx`, `constructApproveToken`, `constructGetBalances`, `constructGetSpender`, `constructGetTokens`, `constructGetAdapters`, `constructSwapTx` | +| Quote | `constructGetQuote` | +| Limit orders (deprecated) | `constructBuildLimitOrder`, `constructSignLimitOrder`, `constructPostLimitOrder`, `constructCancelLimitOrder`, `constructGetLimitOrders`, `constructApproveTokenForLimitOrder`, `constructGetLimitOrdersContract`, `constructBuildLimitOrderTx`, `constructFillOrderDirectly` | + +Note that V1 and V2 expose the same constructor names (`constructBuildDeltaOrder`, etc.) — V2 is just nested inside the `DeltaV2` namespace, which is what lets the two ship side-by-side without collision. 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, + `DeltaV2.constructBuildDeltaOrder` + `DeltaV2.constructSignDeltaOrder` + + `DeltaV2.constructPostDeltaOrder`, or `DeltaV2.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. + + + Market-swap walkthrough using individual constructors. + + + Delta order lifecycle, including the split build/sign/post flow. + + diff --git a/sdk/simple-sdk.mdx b/sdk/simple-sdk.mdx index 4c3dd08..8860dd2 100644 --- a/sdk/simple-sdk.mdx +++ b/sdk/simple-sdk.mdx @@ -1,15 +1,198 @@ --- title: "Simple SDK" -description: "Use the all-in-one entry point for the common quote-and-swap flow." -keywords: ["sdk","simple"] +description: "constructSimpleSDK auto-wires the fetcher and contract caller so one constructor returns a working SDK for quotes, swaps, Delta orders, and approvals." +keywords: ["sdk", "simple", "constructSimpleSDK", "quickstart"] --- -This page is a stub. Content coming soon. +`constructSimpleSDK` is the recommended entry point for most integrators. You pass it a `chainId`, an HTTP client, and (optionally) a wallet — it returns an SDK with every Velora method available under flat namespaces. ## When to use this -## Quickstart +- 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. -## Examples +For tighter control over the transaction-response type or bundle size, use the [Full](/sdk/full-sdk) or [Partial](/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 +import axios from "axios"; +import { constructSimpleSDK } from "@velora-dex/sdk"; + +const simpleSDK = constructSimpleSDK({ chainId: 1, axios }); +``` + +```ts fetch +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 +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 +import { ethers } from "ethers"; + +const sdk = constructSimpleSDK( + { chainId: 1, axios }, + { + ethersProviderOrSigner: signer, // JsonRpcProvider or Wallet + EthersContract: ethers.Contract, + account, + }, +); +``` + +```ts ethers v6 +import { ethers } from "ethers"; + +const sdk = constructSimpleSDK( + { chainId: 1, axios }, + { + ethersV6ProviderOrSigner: signer, + EthersV6Contract: ethers.Contract, + account, + }, +); +``` + +```ts web3 +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`](/sdk/full-sdk) with the `` generic. + + +## Available methods + +The returned SDK is namespaced by feature: + +| Namespace | What's inside | Module page | +| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | +| `sdk.deltaV2` | **Recommended.** `getDeltaPrice`, `buildDeltaOrder`, `signDeltaOrder`, `postDeltaOrder`, `submitDeltaOrder`, `approveTokenForDelta`, `preSignDeltaOrder`, `getDeltaContract`, `getDeltaOrderById`, `getDeltaOrderByHash`, `getDeltaOrders`, `cancelDeltaOrders`, `getBridgeRoutes`, `isTokenSupportedInDelta` | [Delta module](/sdk/modules/delta) | +| `sdk.delta` | Delta V1. Same lifecycle, locally-built orders. See [Delta V1](/sdk/modules/delta#delta-v1). | [Delta module](/sdk/modules/delta#delta-v1) | +| `sdk.quote` | `getQuote` — V1 Delta-with-fallback-to-Market price (no V2 equivalent yet) | [API → Delta /quote](/api-reference/delta/quote) | +| `sdk.swap` | `getRate`, `buildTx`, `approveToken`, `getSpender`, `getBalances`, `getTokens`, `getAdapters`, `swapTx` | [Swap module](/sdk/modules/swap) | +| `sdk.limitOrders` | Deprecated. Build/sign/post/cancel limit orders. | [Limit orders module](/sdk/modules/limit-orders) | + +## 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 +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 DAI = "0x6B175474E89094C44Da98b954EedeAC495271d0F"; +const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; +const amount = "1000000000000000000"; // 1 DAI + +const quote = await sdk.quote.getQuote({ + srcToken: DAI, + destToken: USDC, + amount, + userAddress: account, + srcDecimals: 18, + destDecimals: 6, + mode: "all", + side: "SELL", + partner: "my-app-name", +}); + +if ("delta" in quote) { + await sdk.delta.approveTokenForDelta(amount, DAI); + + const slippagePercent = 0.5; + const destAmount = BigInt( + +(+quote.delta.destAmount * (1 - slippagePercent / 100)).toFixed(0), + ).toString(10); + + const auction = await sdk.delta.submitDeltaOrder({ + deltaPrice: quote.delta, + owner: account, + srcToken: DAI, + destToken: USDC, + srcAmount: amount, + destAmount, + partner: "my-app-name", + }); + + console.log("Delta auction id:", auction.id); +} else { + await sdk.swap.approveToken(amount, DAI); + + const tx = await sdk.swap.buildTx({ + srcToken: DAI, + destToken: USDC, + srcAmount: amount, + slippage: 250, // 2.5% + priceRoute: quote.market, + userAddress: account, + partner: "my-app-name", + }); + + await walletClient.sendTransaction({ + ...txParamsToViemTxParams(tx), + account, + }); +} +``` + +See [Modules → Delta](/sdk/modules/delta) for the split build/sign/post flow and order-status polling (including the recommended Delta V2 path), and [Modules → Swap](/sdk/modules/swap) for the full Market-swap walkthrough. ## Related pages + +- [Modules → Swap](/sdk/modules/swap) +- [Modules → Delta](/sdk/modules/delta) +- [Configure providers](/sdk/configure-providers) +- [Monetize](/sdk/monetize) diff --git a/sdk/testing-integration.mdx b/sdk/testing-integration.mdx index eae687a..20e7456 100644 --- a/sdk/testing-integration.mdx +++ b/sdk/testing-integration.mdx @@ -1,15 +1,121 @@ --- -title: "Testing integration" -description: "Test your SDK integration against staging endpoints and verify expected behavior." -keywords: ["sdk","testing","staging"] +title: "Test your integration" +description: "Test SDK flows without burning mainnet funds — fork mainnet locally, mock the fetcher for unit tests, and verify partner attribution end-to-end." +keywords: ["sdk", "testing", "fork", "hardhat", "anvil", "mock", "fetcher"] --- -This page is a stub. Content coming soon. +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 -## Quickstart +- 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. -## Examples +## 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) locally and impersonate a funded account. + +### Anvil (Foundry) + +```bash +anvil --fork-url https://eth-mainnet.alchemyapi.io/v2/$ALCHEMY_KEY +``` + +Connect the SDK to the local RPC and impersonate a known DAI whale: + +```ts +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 +// 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 +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 — 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, see [Order lifecycle and status codes](/delta/order-lifecycle-and-status-codes) and [Handling stuck orders](/guides/handling-stuck-orders). +- **Verify the spender.** For Market swaps the user approves `getSpender()` (`TokenTransferProxy`). For Delta the user approves `getDeltaContract()`. Approving the wrong contract is the most common cause of `INSUFFICIENT_ALLOWANCE`. ## Related pages + +- [Troubleshooting](/api-reference/troubleshooting) — known failure modes per endpoint. +- [Debug failed transactions](/guides/debug-failed-transactions) — generic on-chain debugging. +- [Handling stuck orders](/guides/handling-stuck-orders) — Delta-specific recovery. +- [Configure providers](/sdk/configure-providers) — fetcher and caller setup. diff --git a/snippets/failure-modes/delta-v2-orders-build.mdx b/snippets/failure-modes/delta-v2-orders-build.mdx new file mode 100644 index 0000000..4acb2de --- /dev/null +++ b/snippets/failure-modes/delta-v2-orders-build.mdx @@ -0,0 +1,10 @@ +| 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 /delta/v2/prices](/api-reference/delta-v2/prices) **verbatim** — don't normalize, sort, or re-encode amounts | +| 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-05-27. diff --git a/snippets/failure-modes/delta-v2-orders-cancel.mdx b/snippets/failure-modes/delta-v2-orders-cancel.mdx new file mode 100644 index 0000000..8741acc --- /dev/null +++ b/snippets/failure-modes/delta-v2-orders-cancel.mdx @@ -0,0 +1,8 @@ +| 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 in a terminal state (`COMPLETED`, `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-05-27. diff --git a/snippets/failure-modes/delta-v2-orders-submit.mdx b/snippets/failure-modes/delta-v2-orders-submit.mdx new file mode 100644 index 0000000..1e8485c --- /dev/null +++ b/snippets/failure-modes/delta-v2-orders-submit.mdx @@ -0,0 +1,10 @@ +| Symptom | Root cause | Fix | +|---|---|---| +| 400 `Invalid signature` | Signed payload doesn't match `order` byte-for-byte | Sign `toSign` from `POST /delta/v2/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 /delta/v2/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 /delta/v2/orders/{orderId}](/api-reference/delta-v2/orders-get-by-id); cancel via [POST /delta/v2/orders/cancel](/api-reference/delta-v2/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; see [Order lifecycle](/delta/order-lifecycle-and-status-codes) | + +Updated from support tickets at each release. Last updated: 2026-05-27. diff --git a/snippets/failure-modes/delta-v2-prices.mdx b/snippets/failure-modes/delta-v2-prices.mdx new file mode 100644 index 0000000..f740fca --- /dev/null +++ b/snippets/failure-modes/delta-v2-prices.mdx @@ -0,0 +1,10 @@ +| 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 /quote](/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 /delta/v2/prices/bridge-routes](/api-reference/delta-v2/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 /delta/v2/prices/is-token-supported](/api-reference/delta-v2/is-token-supported) before quoting | + +Updated from support tickets at each release. Last updated: 2026-05-27.