M0

M0 Orchestration API

The Orchestration (liquidity) API provides quotes for moving and converting between M0 extensions and other stablecoins, cross-chain order status and cancellation, and EIP-2612 permit building for gasless, intent-based settlement.

OpenAPI Specification

m0-orchestration-openapi-original.json Raw ↑
{"openapi":"3.0.1","info":{"title":"liquidity-api","version":"","description":"This API provides quotes for moving and converting between M extensions and other stablecoins"},"paths":{"/orders/{originChain}/{orderId}/cancel":{"post":{"description":"Build a cancel transaction for an existing limit order.\n\nThe returned `TransactionPayload` carries its own `chain` (and\n`chainId` for EVM payloads) indicating where the transaction must\nbe broadcast:\n\n  * **Same-chain orders** (origin == destination): broadcast on the\n    order's chain. The payload's `chain` matches the URL `chain`.\n  * **Cross-chain orders** (origin != destination): the cancel must\n    be initiated on the order's **destination chain**, which then\n    dispatches a CancelReport message back to the origin chain to\n    release the deposited funds. The payload's `chain` is the\n    destination chain and **differs from the URL `chain`**. The\n    payload's `value` includes the bridge fee.\n\nAlways read `payload.chain` (and `payload.chainId` for EVM) to\ndetermine the broadcast target — do not assume it matches the URL\npath parameter.\n\n**`caller`** (optional, SVM only): the base58 pubkey that will sign\nand pay for the resulting Solana transaction. Required when the\ncancel is being initiated by someone other than the original sender\n— for example, a permissionless cancel after the order's\n`fillDeadline`. If omitted, defaults to the original sender, which\nonly allows self-cancels. Ignored for EVM destinations: EVM\nunsigned-tx payloads do not bake in a signer, so any wallet can\nbroadcast the same calldata and the contract recovers `msg.sender`\nfrom the signature at submission.\n\n**Error responses**\n\nAll errors return `commons.ErrorBody` (`{ code, message, requestId }`).\nBranch on `code`, not the HTTP status — multiple errors may share a\nstatus as the API evolves. The `requestId` mirrors the per-request id\nin server logs; include it when filing a support ticket.\n\n| Status | `code`                | When                                                                          |\n| ------ | --------------------- | ----------------------------------------------------------------------------- |\n| 400    | `BadOrderRequest`     | Malformed path params: unknown chain, bad `orderId`, or unsupported `caller`. |\n| 404    | `OrderNotFound`       | No order with this id exists on-chain.                                        |\n| 409    | `OrderNotCancellable` | The order is already in a terminal state (`CANCELLED` / `COMPLETED`).         |\n| 500    | `CancelOrderError`    | Unexpected failure building the cancel transaction; may succeed on retry.     |","operationId":"order_cancelOrder","tags":["Order"],"parameters":[{"name":"originChain","in":"path","required":true,"schema":{"$ref":"#/components/schemas/Chain"}},{"name":"orderId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionPayload"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"409":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"security":[{"ApiKeyAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelOrderParams","nullable":true}}}}}},"/orders/{originChain}/{orderId}":{"get":{"description":"Get full on-chain state plus indexer enrichment for a single order.\n\n**Error responses**\n\nErrors return `commons.ErrorBody` (`{ code, message, requestId }`);\nbranch on `code`, not the HTTP status.\n\n| Status | `code`            | When                                                          |\n| ------ | ----------------- | ------------------------------------------------------------- |\n| 400    | `BadOrderRequest` | Malformed path params: unknown chain or bad `orderId`.        |\n| 404    | `OrderNotFound`   | No order with this id exists on-chain.                        |","operationId":"order_getOrder","tags":["Order"],"parameters":[{"name":"originChain","in":"path","required":true,"schema":{"$ref":"#/components/schemas/Chain"}},{"name":"orderId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"security":[{"ApiKeyAuth":[]}]}},"/orders":{"get":{"description":"List orders with optional filters","operationId":"order_getOrders","tags":["Order"],"parameters":[{"name":"sender","in":"query","required":false,"schema":{"type":"string","nullable":true}},{"name":"status","in":"query","required":false,"schema":{"$ref":"#/components/schemas/OrderStatus","nullable":true}},{"name":"originChainId","in":"query","required":false,"schema":{"type":"integer","nullable":true}},{"name":"destChainId","in":"query","required":false,"schema":{"type":"integer","nullable":true}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","nullable":true}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","nullable":true}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrdersResponse"}}}}},"security":[{"ApiKeyAuth":[]}]}},"/permit/quote":{"post":{"description":"Get quotes for the gasless-approval (EIP-2612 permit) flow.\n\nLike `/quote`, but every returned quote's approvals are satisfied by\nsigning an off-chain EIP-2612 permit instead of broadcasting a separate\n`approve` transaction — collapsing approve + action into a single\non-chain transaction. **EVM only.**\n\nEach `PermitQuote` carries one `PermitRecipe` per leg (in execution\norder); sign each recipe's `typedData`, then either POST the signed\nrecipes to `/permit/build` to receive executable payloads, or encode\nthe `*WithPermit` call locally from the recipe.\n\nOnly routes whose every leg is permit-capable are returned.\n\n**Error responses**\n\nAll errors return `commons.ErrorBody` (`{ code, message, requestId }`).\nBranch on `code`, not the HTTP status.\n\n| Status | `code`              | When                                                                    |\n| ------ | ------------------- | ----------------------------------------------------------------------- |\n| 400    | `BadPermitRequest`  | Missing/invalid fields, `source` == `destination`, or an unknown asset. |\n| 404    | `PermitNotSupported`| Structurally valid, but no permit-capable path exists for this route.   |\n| 500    | `PermitQuoteError`  | Unexpected internal failure while computing permit quotes.              |","operationId":"permit_permitQuote","tags":["Permit"],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermitQuoteResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"route":{"$ref":"#/components/schemas/Route"},"amountIn":{"type":"string"},"sender":{"type":"string"},"funder":{"type":"string","nullable":true,"description":"The account that holds the input tokens and signs the permit.\nDefaults to `sender` when omitted."},"recipient":{"type":"string","nullable":true},"maxNumQuotes":{"type":"integer","nullable":true},"providers":{"$ref":"#/components/schemas/ProvidersParams","nullable":true}},"required":["route","amountIn","sender"]}}}}}},"/permit/build":{"post":{"description":"Exchange signed permit recipes for executable transaction payloads.\n\nEcho back the `PermitRecipe`s from `/permit/quote`, each paired with\nthe user's EIP-2612 signature over its `typedData`. Returns one\n`Payload` per recipe, in order — the encoded `*WithPermit` call.\n\nThe server re-validates each recipe before encoding (permit `value`\nmatches `amountIn`, `spender` matches the operation target, `deadline`\nnot expired, and the recovered signer equals the permit `owner`).\n\n**Error responses**\n\nAll errors return `commons.ErrorBody` (`{ code, message, requestId }`).\nBranch on `code`, not the HTTP status.\n\n| Status | `code`                   | When                                                          |\n| ------ | ------------------------ | ------------------------------------------------------------- |\n| 400    | `BadPermitRequest`       | Malformed body, or a recipe that fails internal consistency.  |\n| 410    | `PermitExpired`          | A recipe's permit `deadline` has already passed.              |\n| 422    | `InvalidPermitSignature` | Signature does not recover to the permit `owner`.             |\n| 500    | `PermitBuildError`       | Unexpected internal failure while encoding the payloads.      |","operationId":"permit_permitBuild","tags":["Permit"],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermitBuildResponse"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"410":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"422":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"signedRecipes":{"type":"array","items":{"$ref":"#/components/schemas/SignedPermitRecipe"}}},"required":["signedRecipes"]}}}}}},"/quote":{"post":{"description":"Get quotes for moving or converting assets using the M Liquidity Network.\n\nReturns a non-empty array of `Quote` results ranked by best `amountOut`,\nfastest `estFillTime`, and fewest payloads (in that order). The response\nis capped at `maxNumQuotes` (default `1`); raise it to receive more than\none.\n\nLimit-order routes can contribute several quotes — one per exclusive\nsolver (each bound to its own solver on-chain, see `PayloadSolver`).\nNon-exclusive (open-fill) offers are collapsed to the single best price,\nsince they differ only in `amountOut`.\n\n**Error responses**\n\nAll errors return `commons.ErrorBody` (`{ code, message, requestId }`).\nBranch on `code`, not the HTTP status — multiple errors may share a\nstatus as the API evolves. The `requestId` mirrors the per-request id\nin server logs; include it when filing a support ticket.\n\n| Status | `code`               | When                                                                                      |\n| ------ | -------------------- | ----------------------------------------------------------------------------------------- |\n| 400    | `BadQuoteRequest`    | Missing/invalid fields, `source` == `destination`, both `include` and `exclude` set, or an unknown asset. |\n| 404    | `NoQuotesAvailable`  | Structurally valid, but no provider could quote this route + amount.                       |\n| 500    | `QuoteError`         | Unexpected internal failure while computing or simulating quotes; may succeed on retry.   |","operationId":"quote_quote","tags":["Quote"],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Quote"}}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"route":{"$ref":"#/components/schemas/Route"},"amountIn":{"type":"string"},"sender":{"type":"string"},"funder":{"type":"string","nullable":true,"description":"The account that holds the input tokens and pays for them.\nDefaults to `sender` when omitted. When supplied and different\nfrom `sender`, the funder provides `amountIn` of the input token\nwhile `sender` remains the order owner that holds\ncancel/refund rights."},"recipient":{"type":"string","nullable":true},"maxNumQuotes":{"type":"integer","nullable":true},"providers":{"$ref":"#/components/schemas/ProvidersParams","nullable":true}},"required":["route","amountIn","sender"]}}}}}},"/supported-assets":{"get":{"description":"Get all assets supported for quotes","operationId":"quote_getSupportedAssets","tags":["Quote"],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Asset"}}}}}},"security":[{"ApiKeyAuth":[]}]}},"/topology/routes":{"get":{"description":"Returns all known routes in the system. Routes are seeded from the\nstatic asset graph on startup and enriched by live quote traffic.\nThis is a read-only view of routing knowledge — not the routing\nlogic itself. Use lastUsed and totalQuoteCount to gauge confidence.\n\n**Error responses**\n\nErrors return `commons.ErrorBody` (`{ code, message, requestId }`);\nbranch on `code`, not the HTTP status.\n\n| Status | `code`               | When                                                                       |\n| ------ | -------------------- | -------------------------------------------------------------------------- |\n| 400    | `BadTopologyRequest` | Invalid query params: only one of `sourceChain` / `sourceAddress`, or an unknown asset. |","operationId":"topology_getRoutes","tags":["Topology"],"parameters":[{"name":"sourceChain","in":"query","required":false,"schema":{"$ref":"#/components/schemas/Chain","nullable":true}},{"name":"sourceAddress","in":"query","required":false,"schema":{"type":"string","nullable":true}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TopologyRoute"}}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorBody"}}}}},"security":[{"ApiKeyAuth":[]}]}},"/topology/stats":{"get":{"description":"Aggregated statistics about route usage","operationId":"topology_getRouteStats","tags":["Topology"],"parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopologyRouteStats"}}}}},"security":[{"ApiKeyAuth":[]}]}}},"components":{"schemas":{"ErrorCode":{"title":"ErrorCode","type":"string","enum":["QuoteError","BadQuoteRequest","NoQuotesAvailable","BadOrderRequest","OrderNotFound","OrderNotCancellable","CancelOrderError","BadTopologyRequest","BadPermitRequest","PermitNotSupported","PermitExpired","InvalidPermitSignature","PermitQuoteError","PermitBuildError"],"description":"Stable machine-readable identifier for an API error. Each value\ncorresponds 1:1 to an error type (and to one `responses` entry\nin the OpenAPI spec). Branch on this rather than on the HTTP status\ncode — multiple errors may share a status as the API evolves."},"ErrorBody":{"title":"ErrorBody","type":"object","description":"Standard error response body. Every error response from this API\nreturns this shape.","properties":{"code":{"$ref":"#/components/schemas/ErrorCode","description":"Stable machine-readable identifier for the failure mode."},"message":{"type":"string","description":"Human-readable description of what went wrong. Safe to surface in UI."},"requestId":{"type":"string","nullable":true,"description":"Per-request correlation id (matches the `requestId` field in\nserver logs). Include this when filing support tickets."}},"required":["code","message"]},"CancelOrderParams":{"title":"CancelOrderParams","type":"object","description":"Optional body for the cancel endpoint.","properties":{"caller":{"type":"string","nullable":true}}},"OrderSummary":{"title":"OrderSummary","type":"object","description":"Compact order shape returned by the list endpoint. Sourced from the\nindexer-fed DB, so on-chain-only fields (nonce, recipient, version) are\nnot included. Use getOrder for the full resource.","properties":{"orderId":{"type":"string"},"createdAt":{"type":"integer"},"originChainId":{"type":"integer"},"sender":{"type":"string"},"tokenIn":{"type":"string"},"amountIn":{"type":"string"},"destChainId":{"type":"integer"},"tokenOut":{"type":"string"},"amountOut":{"type":"string"},"designatedSolver":{"type":"string"},"openTx":{"type":"string"},"amountOutFilled":{"type":"string"},"fillCount":{"type":"integer"},"amountInReleased":{"type":"string"},"fillReportCount":{"type":"integer"},"amountRefunded":{"type":"string"},"status":{"$ref":"#/components/schemas/OrderStatus"},"fillDeadline":{"type":"integer"},"funder":{"type":"string"},"resolvedAt":{"type":"integer","nullable":true}},"required":["orderId","createdAt","originChainId","sender","tokenIn","amountIn","destChainId","tokenOut","amountOut","designatedSolver","openTx","amountOutFilled","fillCount","amountInReleased","fillReportCount","amountRefunded","status","fillDeadline","funder"]},"Order":{"title":"Order","type":"object","description":"Full order state returned by the detail endpoint. On-chain fields are\nauthoritative; indexer-only fields (openTx, fillCount, fillReportCount,\nresolvedAt, fills) are optional and may be absent if the indexer has not\nyet caught up or is unavailable.","properties":{"orderId":{"type":"string"},"version":{"type":"integer"},"nonce":{"type":"string"},"sender":{"type":"string"},"recipient":{"type":"string"},"originChainId":{"type":"integer"},"destChainId":{"type":"integer"},"tokenIn":{"type":"string"},"tokenOut":{"type":"string"},"amountIn":{"type":"string"},"amountOut":{"type":"string"},"designatedSolver":{"type":"string"},"createdAt":{"type":"integer"},"fillDeadline":{"type":"integer"},"status":{"$ref":"#/components/schemas/OrderStatus"},"amountOutFilled":{"type":"string"},"amountInReleased":{"type":"string"},"amountRefunded":{"type":"string"},"funder":{"type":"string"},"openTx":{"type":"string","nullable":true},"fillCount":{"type":"integer","nullable":true},"fillReportCount":{"type":"integer","nullable":true},"resolvedAt":{"type":"integer","nullable":true},"fills":{"type":"array","items":{"$ref":"#/components/schemas/Fill"},"nullable":true}},"required":["orderId","version","nonce","sender","recipient","originChainId","destChainId","tokenIn","tokenOut","amountIn","amountOut","designatedSolver","createdAt","fillDeadline","status","amountOutFilled","amountInReleased","amountRefunded","funder"]},"Fill":{"title":"Fill","type":"object","description":"A single fill event recorded by the indexer for an order. An order may\nhave multiple fills when filled by multiple solvers or in multiple\ntransactions; ordered chronologically.","properties":{"filledAt":{"type":"integer"},"chainId":{"type":"integer"},"transactionHash":{"type":"string"},"solver":{"type":"string"},"amountInToRelease":{"type":"string"},"amountOutFilled":{"type":"string"}},"required":["filledAt","chainId","transactionHash","solver","amountInToRelease","amountOutFilled"]},"OrderStatus":{"title":"OrderStatus","type":"string","enum":["CREATED","COMPLETED","CANCELLED"]},"OrdersResponse":{"title":"OrdersResponse","type":"object","properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/OrderSummary"}},"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}},"required":["orders","total","limit","offset"]},"PermitQuoteResponse":{"title":"PermitQuoteResponse","type":"object","properties":{"requestId":{"type":"string","description":"Per-request correlation id."},"quotes":{"type":"array","items":{"$ref":"#/components/schemas/PermitQuote"}},"issues":{"$ref":"#/components/schemas/PermitIssues","nullable":true,"description":"Non-fatal findings shared across all quotes (e.g. insufficient balance)."}},"required":["requestId","quotes"]},"PermitBuildResponse":{"title":"PermitBuildResponse","type":"object","properties":{"requestId":{"type":"string"},"payloads":{"type":"array","items":{"$ref":"#/components/schemas/Payload"}},"issues":{"$ref":"#/components/schemas/PermitIssues","nullable":true}},"required":["requestId","payloads"]},"PermitIssues":{"title":"PermitIssues","type":"object","description":"Soft warnings; their presence does not fail the request.","properties":{"balance":{"$ref":"#/components/schemas/BalanceIssue","nullable":true,"description":"Present when `sender` does not hold `amountIn` of the input token."}}},"BalanceIssue":{"title":"BalanceIssue","type":"object","properties":{"token":{"type":"string"},"actual":{"type":"string"},"expected":{"type":"string"}},"required":["token","actual","expected"]},"PermitQuote":{"title":"PermitQuote","type":"object","description":"A quote whose approvals are satisfied by signing permits, not `approve`.","properties":{"route":{"$ref":"#/components/schemas/Route"},"recipient":{"type":"string"},"amountIn":{"type":"string"},"amountOut":{"type":"string"},"minAmountOut":{"type":"string","description":"Floor that must be met or the transaction reverts. Equals\n`amountOut` for exact-output providers; below it for AMM legs\nper `slippageBps`."},"estFillTime":{"type":"integer"},"expiresAt":{"type":"integer","description":"Unix seconds after which this quote is no longer buildable — the\nearliest permit `deadline` across its recipes. `/permit/build`\nrejects with `PermitExpired` past this."},"recipes":{"type":"array","items":{"$ref":"#/components/schemas/PermitRecipe"},"description":"One per leg, in execution order."}},"required":["route","recipient","amountIn","amountOut","minAmountOut","estFillTime","expiresAt","recipes"]},"PermitRecipe":{"title":"PermitRecipe","type":"object","description":"Everything needed to sign one leg's permit and produce its executable\ntransaction — either by POSTing to `/permit/build` or by encoding the\n`*WithPermit` call locally (self-encoding).","properties":{"provider":{"$ref":"#/components/schemas/Providers"},"annotation":{"type":"string","description":"Human-readable label for this leg, e.g. `M0 Swap Facility wM → USD+`.\nFor display in clients."},"chain":{"$ref":"#/components/schemas/Chain"},"chainId":{"type":"integer"},"spender":{"type":"string","description":"Contract granted the permit and called in `/permit/build` (the tx `to`)."},"value":{"type":"string","description":"Native value for the final transaction. \"0\" for the permit-capable providers."},"typedData":{"$ref":"#/components/schemas/Eip2612TypedData"},"solver":{"$ref":"#/components/schemas/PayloadSolver","nullable":true,"description":"Present only on limit-order legs. Identifies the solver that produced\nthis leg, mirroring `Payload.solver` on `/quote`. For display."},"operation":{"$ref":"#/components/schemas/PermitOperation","description":"Static args the build step encodes into the `*WithPermit` call."},"functionSignature":{"type":"string","description":"Solidity signature of the `*WithPermit` call this recipe encodes to,\ne.g. `swapWithPermit(address,address,uint256,address,uint256,bytes)`.\nLets a client encode the transaction locally — from `operation` plus\nthe signature — instead of calling `/permit/build`."}},"required":["provider","annotation","chain","chainId","spender","value","typedData","operation","functionSignature"]},"Eip2612TypedData":{"title":"Eip2612TypedData","type":"object","description":"Directly signable EIP-712 payload. `types`/`primaryType` are the standard\nEIP-2612 `Permit` definition and are omitted; clients use the canonical set.","properties":{"domain":{"$ref":"#/components/schemas/Eip712Domain"},"message":{"$ref":"#/components/schemas/Eip2612Message"}},"required":["domain","message"]},"Eip712Domain":{"title":"Eip712Domain","type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"chainId":{"type":"integer"},"verifyingContract":{"type":"string","description":"The input token's address."}},"required":["name","version","chainId","verifyingContract"]},"Eip2612Message":{"title":"Eip2612Message","type":"object","properties":{"owner":{"type":"string"},"spender":{"type":"string"},"value":{"type":"string"},"nonce":{"type":"string"},"deadline":{"type":"string"}},"required":["owner","spender","value","nonce","deadline"]},"PermitOperation":{"title":"PermitOperation","oneOf":[{"type":"object","allOf":[{"type":"object","properties":{"type":{"type":"string","enum":["swap"]}}},{"$ref":"#/components/schemas/SwapPermitOp"}],"required":["type"]},{"type":"object","allOf":[{"type":"object","properties":{"type":{"type":"string","enum":["limitOrder"]}}},{"$ref":"#/components/schemas/LimitOrderPermitOp"}],"required":["type"]},{"type":"object","allOf":[{"type":"object","properties":{"type":{"type":"string","enum":["ammSwap"]}}},{"$ref":"#/components/schemas/AmmSwapPermitOp"}],"required":["type"]}],"description":"Provider-specific static args for the `*WithPermit` call, discriminated\nso the build step (or a self-encoding client) knows exactly what to build."},"SwapPermitOp":{"title":"SwapPermitOp","type":"object","description":"M Swap Facility `swap*WithPermit`.","properties":{"method":{"$ref":"#/components/schemas/SwapMethod"},"extensionIn":{"type":"string","nullable":true},"extensionOut":{"type":"string","nullable":true},"amount":{"type":"string"},"recipient":{"type":"string"},"deadline":{"type":"string"}},"required":["method","amount","recipient","deadline"]},"SwapMethod":{"title":"SwapMethod","type":"string","enum":["swap","swapInM","swapOutM"]},"LimitOrderPermitOp":{"title":"LimitOrderPermitOp","type":"object","description":"OrderBook `openOrderWithPermit`.","properties":{"destChainId":{"type":"integer"},"fillDeadline":{"type":"integer"},"tokenIn":{"type":"string"},"tokenOut":{"type":"string","description":"bytes32-encoded destination token."},"amountIn":{"type":"string"},"amountOut":{"type":"string"},"recipient":{"type":"string","description":"bytes32-encoded recipient."},"solver":{"type":"string","description":"bytes32-encoded designated solver (zero for an open fill)."},"sender":{"type":"string"},"deadline":{"type":"string"}},"required":["destChainId","fillDeadline","tokenIn","tokenOut","amountIn","amountOut","recipient","solver","sender","deadline"]},"AmmSwapPermitOp":{"title":"AmmSwapPermitOp","type":"object","description":"Uniswap V3 `multicall([selfPermit, exactInputSingle])`. Signature split to v,r,s.","properties":{"tokenIn":{"type":"string"},"tokenOut":{"type":"string"},"fee":{"type":"integer"},"recipient":{"type":"string"},"amountIn":{"type":"string"},"amountOutMinimum":{"type":"string"},"deadline":{"type":"string"}},"required":["tokenIn","tokenOut","fee","recipient","amountIn","amountOutMinimum","deadline"]},"SignedPermitRecipe":{"title":"SignedPermitRecipe","type":"object","properties":{"recipe":{"$ref":"#/components/schemas/PermitRecipe","description":"Echoed verbatim from `/permit/quote`."},"signature":{"type":"string","description":"65-byte hex EIP-2612 permit signature. Build splits to v,r,s where the contract needs it."}},"required":["recipe","signature"]},"Asset":{"title":"Asset","type":"object","properties":{"chain":{"$ref":"#/components/schemas/Chain"},"runtime":{"$ref":"#/components/schemas/ChainRuntime"},"address":{"type":"string"},"icon":{"type":"string"},"decimals":{"type":"integer"},"symbol":{"type":"string"},"name":{"type":"string"},"m0Extension":{"type":"boolean"}},"required":["chain","runtime","address","icon","decimals","symbol","name","m0Extension"]},"AssetAddress":{"title":"AssetAddress","type":"object","properties":{"chain":{"$ref":"#/components/schemas/Chain"},"address":{"type":"string"}},"required":["chain","address"]},"Quote":{"title":"Quote","type":"object","properties":{"route":{"$ref":"#/components/schemas/Route"},"recipient":{"type":"string"},"amountIn":{"type":"string"},"amountOut":{"type":"string"},"estFillTime":{"type":"integer"},"payloads":{"type":"array","items":{"$ref":"#/components/schemas/Payload"}}},"required":["route","recipient","amountIn","amountOut","estFillTime","payloads"]},"ProvidersParams":{"title":"ProvidersParams","type":"object","properties":{"include":{"type":"array","items":{"$ref":"#/components/schemas/Providers"},"nullable":true},"exclude":{"type":"array","items":{"$ref":"#/components/schemas/Providers"},"nullable":true}}},"Providers":{"title":"Providers","type":"string","enum":["m-swap-facility","m-wormhole-portal","m-hyperlane-portal","m-portal","wormhole-cctp","jupiter","raydium","mayan-swift","kyber-swap","limit-order","uniswap-v3"]},"Payload":{"title":"Payload","type":"object","properties":{"provider":{"type":"string"},"annotation":{"type":"string","nullable":true},"data":{"$ref":"#/components/schemas/TransactionPayload"},"solver":{"$ref":"#/components/schemas/PayloadSolver","nullable":true,"description":"Present only on limit-order legs. Identifies the solver that produced\nthis leg, as reported to the server over gRPC."}},"required":["provider","data"]},"PayloadSolver":{"title":"PayloadSolver","type":"object","description":"The solver behind a limit-order leg. `exclusive` means the leg is bound to\nthis solver on-chain (it becomes the order's `designatedSolver`); when\nfalse, the quote reflects this solver's price but any solver may fill.","properties":{"address":{"type":"string"},"name":{"type":"string","nullable":true},"exclusive":{"type":"boolean"},"feeBps":{"type":"integer","nullable":true}},"required":["address","exclusive"]},"TransactionPayload":{"title":"TransactionPayload","oneOf":[{"type":"object","allOf":[{"type":"object","properties":{"type":{"type":"string","enum":["evm"]}}},{"$ref":"#/components/schemas/EvmPayload"}],"required":["type"]},{"type":"object","allOf":[{"type":"object","properties":{"type":{"type":"string","enum":["svm"]}}},{"$ref":"#/components/schemas/SvmPayload"}],"required":["type"]}]},"EvmPayload":{"title":"EvmPayload","type":"object","properties":{"chain":{"$ref":"#/components/schemas/Chain"},"chainId":{"type":"integer"},"to":{"type":"string"},"data":{"type":"string"},"value":{"type":"string"}},"required":["chain","chainId","to","data","value"]},"SvmPayload":{"title":"SvmPayload","type":"object","properties":{"chain":{"$ref":"#/components/schemas/Chain"},"transaction":{"type":"string","format":"byte"}},"required":["chain","transaction"]},"Route":{"title":"Route","type":"object","properties":{"source":{"$ref":"#/components/schemas/AssetAddress"},"destination":{"$ref":"#/components/schemas/AssetAddress"}},"required":["source","destination"]},"Chain":{"title":"Chain","type":"string","enum":["Ethereum","Solana","Arbitrum","Base","Linea","Sepolia","BaseSepolia","ArbitrumSepolia","HyperEVM","BinanceSmartChain","Mantra","Plasma","SolanaDevnet","Soneium","Citrea","Fluent","Moca","Rise"]},"ChainRuntime":{"title":"ChainRuntime","type":"string","enum":["evm","svm"]},"TopologyRouteProvider":{"title":"TopologyRouteProvider","type":"object","properties":{"provider":{"$ref":"#/components/schemas/Providers"},"lastUsed":{"type":"string","format":"date-time","nullable":true},"quoteCount":{"type":"integer"}},"required":["provider","quoteCount"]},"TopologyRoute":{"title":"TopologyRoute","type":"object","properties":{"source":{"$ref":"#/components/schemas/AssetAddress"},"destination":{"$ref":"#/components/schemas/AssetAddress"},"providers":{"type":"array","items":{"$ref":"#/components/schemas/TopologyRouteProvider"}},"lastUsed":{"type":"string","format":"date-time","nullable":true},"totalQuoteCount":{"type":"integer"}},"required":["source","destination","providers","totalQuoteCount"]},"AddressFrequency":{"title":"AddressFrequency","type":"object","properties":{"address":{"type":"string"},"count":{"type":"integer"}},"required":["address","count"]},"TopologyRouteStats":{"title":"TopologyRouteStats","type":"object","properties":{"totalRoutes":{"type":"integer"},"activeRoutes":{"type":"integer"},"collect

# --- truncated at 32 KB (32 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/m0/refs/heads/main/openapi/m0-orchestration-openapi-original.json