agentgates.aiVerified
Confidential computers for AI swarms: sealed VMs (Intel TDX) by the hour, USDC over x402.
Finance & CryptoPayments & trading
- Passed: Handshake
- Passed: Tools listed
- Passed: Updated recently
Median latency 514 ms · Last checked
Explore
Evidence for your next connection.
Independent measurements of remote MCP servers. Every observation has a timestamp.
Read-only probesMCP server · Payments & trading
Token swaps at the best net price on 9 EVM chains and Solana. No API key, non-custodial.
3 failed · 8 not measured
Median of successful probes over 7 days
Share of countable probes over 30 days, including daily rollups. Auth challenges are excluded.
Tool definitions returned by this server
Independent monitoring
Responded
The server completed its last measured handshake. This is an observation, not a guarantee.
Last checked| Test area | Passed | Failed | Unmeasured |
|---|---|---|---|
ConnectionCan a client connect and discover tools? | 4 | 1 | 0 |
Reliability & speedDoes it respond consistently and quickly? | 0 | 0 | 4 |
Access & authenticationWhat is required to use this server? | 1 | 0 | 2 |
Tool qualityAre the tool definitions usable by an agent? | 4 | 0 | 0 |
Publisher identityCan the publisher be traced to its source? | 2 | 2 | 2 |
Unmeasured means there is not enough evidence to decide. How these checks work
Start using Vurto Swap
Choose your client, copy the configuration, then enable the server in your client’s MCP settings.
Run this command in your terminal, then restart Claude Code.
Claude Code
claude mcp add --transport http vurto-swap https://swap.vurto.cc/mcpCapabilities
Hand over the signature of destination_challenge. The server checks it is the paying wallet's signature over that exact challenge, for that receiver and chain, unexpired and unused, and then lets builds deliver to that receiver for 30 minutes. Nothing else unlocks it. Errors: signature_invalid, authorization_expired, authorization_replayed, authorization_destination_mismatch, authorization_network_mismatch.
DiscoveredDestination lock. A receiver different from the signing wallet is refused by swap_build, double_build and nn_build (403 destination_not_authorized) until the paying wallet signs an authorization for that exact address on that chain. This returns {nonce, message, expiresAt} plus, on EVM, typedData (EIP-712, the same fields) and, on Solana, proofTransaction (a memo that can never land, for Ledger). Show the user the full receiver and network and get their explicit yes; then sign: on EVM call prepare_signing with step {type: "signature", typedData} and run it; on Solana sign message (or proofTransaction) with the wallet. Then call destination_authorize. Never sign this without the user asking to send to that address. Paying an invoice to its receiver does not unlock through this, but an invoice with payerChecks asks for the same proof of the paying wallet (payer_signature_required).
DiscoveredBuilds signable/sendable plans for BOTH legs of a Double Out or Double In swap — two ordinary swap_build calls under the hood, kept together for convenience. Returns { legA, legB }, each a full SwapPlan exactly like swap_build's. The two legs are NOT atomic — there is no combined contract call, each is a transaction (or CoW signature) the wallet sends separately, same as any other swap. Execute leg A fully first (steps, signing, report_execution) and confirm it landed before starting leg B. If leg A fails or is rejected, do NOT execute leg B — proceeding would leave the wallet with only half the ratio the user asked for, which defeats the purpose of a Double swap.
DiscoveredCompares ranked routes for TWO swap legs at once — "Double Out" (one source token split into two destinations) or "Double In" (two source tokens converging on one destination). This exists because building a liquidity pool or matching a target ratio needs both legs priced against the market at the same instant, not one after another with the price moving in between. Each leg is independently quoted (two ordinary swap_quote calls under the hood) — this tool is a convenience that keeps them together, not a combined/atomic route. For mode "out": legA.tokenIn must equal legB.tokenIn (the shared source); tokenOut differs. For mode "in": legA.tokenOut must equal legB.tokenOut (the shared destination); tokenIn differs. Pass the exact amount each leg should trade — this tool does not compute percentages or splits for you. If the shared token is the chain's native asset, remember gas is paid twice (once per leg's eventual transaction) — do not quote/build a total that leaves nothing for the second leg's gas.
DiscoveredDo not use it on an invoice whose split.rule is "brackets" (created since 10/11/2026): its fee is inside the payment and already pays the analysis of both wallets, and the call is refused with analysis_included_in_fee (409). Without checks: the charge of the invoice creator, for an older invoice with payerChecks or paid checks whose analysis.status is awaiting_payment (see invoice_get). Builds ONE USDC transfer of analysis.amount (0.10 Scorechain, 0.40 Merkle Science, 0.50 both) to the Vurto fee wallet (analysis.to), signed by the invoice creator. Sign the charge transaction exactly as returned: it carries the mark that ties the payment to this charge (16 bytes after the transfer arguments on EVM, a memo on Solana). A transfer you build yourself is refused with analysis_payment_rejected, reason charge_not_tied, after the money has left; do not pay again, prove the wallet (destination_challenge with wallet = payer, receiver = details.feeWallet, chargeId = this charge and chargeTxHash = that hash, then destination_authorize) and report the same hash again. Nothing is signed or sent here. The free screening runs first on the receiving wallet and on the creator: a rejected wallet gets screening_blocked (403) and nothing is built; a screening that cannot be read gets screening_unavailable (503). payer must be the creator (the receiving wallet when the invoice was created without a session, which is always the case over MCP); any other wallet gets not_invoice_creator (403) before anything is built. plan has the same shape as invoice_pay (prepare_signing; on Solana POST the signed transaction to /v1/svm/execute), then call invoice_report_analysis_payment with the hash or signature. Paying it from another token is a swap built over the HTTP API (POST /v1/swap on EVM, POST /v1/svm/swap on Solana) from the creator wallet with tokenOut = analysis.token, receiver = analysis.to and invoiceId = this invoice, sized so the guaranteed minimum covers analysis.amountRaw; report its hash or signature to invoice_report_analysis_payment. On EVM only a swap built that way counts (the transaction must match that build); on Solana the Vurto fee wallet must be the only wallet whose USDC rises in it, and it must be the transaction we built, which carries the mark. The minimum must stay between the charge and 10% above it (charge_swap_below_amount, charge_swap_above_amount). A swap that only pays a fee to the same wallet does not count. Errors: no_paid_check, analysis_already_paid, analysis_included_in_fee, invoice_already_paid, not_invoice_creator, screening_blocked, screening_unavailable. Invoices of the new model (Solana, and EVM networks with a split contract): this is how the PAYER buys the paid analysis of the RECEIVING wallet, with their own money, before paying. Pass payer = the paying wallet and checks (["merkle-science"] 0.40, ["scorechain"] 0.10, both 0.50 USDC, the price of ONE wallet). A new purchase needs no wallet proof, the payment itself proves it; giving it up, changing the tools of an existing charge and reusing a stored analysis do (destination_challenge/destination_authorize for this invoice's receiver; without it payer_signature_required, 401). The free screening of both wallets must pass (screening_blocked 403). It returns receiverAnalysis {status: awaiting_payment, amount, to} and the USDC transfer to sign; report it with invoice_report_analysis_payment (txHash and payer). The price is the same whatever the amount, and the analysis never goes inside the payment. analysis_tool_unavailable (503) when the tool is not answering: nothing is charged. An open, unpaid analysis does not hold invoice_pay, because anyone can open one naming a wallet: pay and report it BEFORE invoice_pay if you want its verdict to count. A paid one goes stale when the receiving wallet moves, and then invoice_pay refuses with receiver_analysis_unpaid (409) until it is redone. checks: [] gives it up. The result comes back without the receiving wallet. Paying it from another token exists on Solana only: POST /v1/svm/swap from the payer with receiver = the fee wallet (receiverAnalysis.to) and invoiceId = this invoice. On EVM the payer pays with the USDC transfer.
DiscoveredCreate a payment request: who receives, which token, how much, on which network. Returns invoice.id, invoice.label (INV-XXXX-XXXX, what people copy), invoice.url (share this, after paying the analysis charge if the invoice has one; it previews with the QR on WhatsApp and Telegram) and invoice.qr (PNG). No signature or API key needed. New invoices only receive VERIFIED dollar stablecoins on the network allowlist, even without paid analysis. A new invoice without payerChecks carries no fee; with payerChecks, the analysis fee of both wallets is deducted from the amount through the split (see payerChecks). Previously created invoices keep their terms. Tokens resolve by address or symbol — an unverified token is refused because a cloned "USDC" with its own pool would let the creator sell a fake at any price. The payer can pay with ANY token on that network. Paid checks in checks are closed for new invoices (paid_check_moved): use payerChecks. the free screening of the receiving wallet must pass for the invoice to be created (receiver_blocked 403, screening_unavailable 503), and payerChecks adds the paid analysis of both wallets, paid by the fee deducted from the amount.
DiscoveredRead an invoice by id (INV-XXXX-XXXX, with or without dashes): requested amount, token, network, receiver, status (open or paid), the paying transaction once paid, and received (the raw amount measured on-chain so far). Pending payments are re-checked on-chain by the read, at most two per read and each at most every 15 seconds. checks lists the older paid screening of an invoice created before 07/11/2026 ([] for new ones), which paying runs on both wallets once analysis.status is paid; payerChecks lists the analysis of the paying wallet the receiver asked and paid for. For such an older invoice, analysis.report (Merkle Science only) carries, once the invoice is paid, the detail of both wallets; for payerChecks the result goes to the creator alone, on the site, and does not come here (over the web app, a signed session of the creator also sees the detail of the receiving wallet while it is open): score, severity, summary, main risk category, risk factors and sourceOfFunds (the largest origins of the money, up to 8, with category, entity, percentage, USD amount and direct or indirect exposure). confidential is true only on a private invoice created before 14/10/2026: its receiver reads null here, it can no longer be paid (invoice_pay answers private_invoice_paused), and its paying transaction, once paid, shows the receiver on-chain.
DiscoveredBuild the plan to pay an invoice from payer, with the token payer holds (default: the invoice token). Nothing is signed or sent here. Both wallets are screened first (payer_blocked, receiver_blocked); when the invoice has checks ["scorechain"] (see invoice_get), the creator chose and paid the Scorechain sanctions API, so this call sends the payer wallet and the receiver wallet to Scorechain, a third party (an invoice created before 22/10/2026 with the then-free Scorechain keeps running it without a charge). method "transfer": same token, a direct transfer built from the stored invoice (no fee, no gain; the receiver sees the payer as sender). method "swap": another token; amountIn is computed so the GUARANTEED minimum output covers the requested amount, the route is always the one with GAIN when there is one, and the output goes straight to the receiver (the transaction is public and signed by the payer, so the receiver can see the paying wallet on-chain). Any surplus over the requested amount goes to the receiver. plan has the same shape as a swap_build plan: on EVM sign steps[] in order with prepare_signing (approve steps first, then the transaction); on Solana pass {transaction, executionRef} to prepare_signing and POST the signed transaction to /v1/svm/execute. If simulation.status is approval_required, send the approve and call invoice_pay again. When the invoice has paid checks, the creator must have paid the analysis first (analysis_unpaid, 409). With "merkle-science" this call then sends the payer wallet and the receiver wallet to Didit/Merkle Science, and a HIGH or CRITICAL risk (score 70 or more) refuses with payer_blocked or receiver_blocked; the detail shows in invoice_get analysis.report. At most 3 different payer wallets are analysed per invoice by each paid check; a 4th gets analysis_attempts_exceeded (429). Since 23/10/2026 the payer proves the wallet BEFORE the paid analysis runs on it: over MCP that proof is the destination authorization signed by the payer for this invoice's receiver (destination_challenge with wallet = payer, receiver = the invoice receiver, chainId of the invoice, sign the message, then destination_authorize). Without it this call returns payer_signature_required (401) and no analysis slot is spent. Invoices with payerChecks and split.rule "brackets" (since 10/11/2026): nothing is paid first; the paid analysis runs HERE on BOTH wallets, the payer and the receiver, after the free screening, and the plan is the split that delivers split.receiverAmount to the receiver and split.fee to the Vurto fee wallet. Older invoices with payerChecks: the creator pays the analysis first (analysis_unpaid, 409), and it runs HERE, on the payer wallet, after its free screening passes; no field switches it off. The payer proves the wallet first (destination_challenge/destination_authorize; payer_signature_required 401). Up to 2 different payer wallets run here; after that the plan comes out with warning, and the analysis runs on the report of a confirmed payment of the whole amount, with the result going to the creator. A transaction that reaches the receiver settles the invoice: the analysis refuses nothing after the money has arrived. analysis_tool_unavailable (503) means try again in a few minutes. The plan delivers the whole amount to the receiver. An invoice that carries split keeps it (see invoice_get split): method "transfer" is then ONE payment transaction (on EVM, sign the exact approve step first, then VurtoInvoiceSplit.pay) with split.receiverAmount to the receiver and split.fee to the Vurto fee wallet, and only that transaction settles it; analysis_offer_suspended (403) applies only to those. With another token, method "swap_then_transfer": plan is a swap into the PAYER's own wallet and next is this same call again, to build the split; on Solana method "swap" does both in one transaction. A receiver analysis (invoice_analysis_pay) only counts here if it was paid and reported first: open and unpaid, it does not hold this call, and the answer carries warning and receiverAnalysis. Paid and stale gets receiver_analysis_unpaid (409), and a rejected receiver gets receiver_blocked. With method "swap", pass invoiceId to prepare_signing so it points to the invoice report. Sign the transaction as returned: it is tied to this invoice and payer, so another invoice to the same recipient cannot claim it (tx_for_another_payment). A transfer built by hand, a native transfer and a ready-made route of a provider are not, and the first report the network confirms wins. If a transaction of yours ends as tx_for_another_payment, prove the wallet (destination_challenge with chargeId = the invoice id and chargeTxHash = the hash, then destination_authorize) and report it again. Then call invoice_report_payment with the hash (EVM) or signature (Solana). Errors: price_moved (the minimum fell below the request between quote and build — call again), no_route, native_sol_only (an invoice in SOL can only be paid in SOL), invoice_already_paid, private_invoice_paused (a private invoice created before 14/10/2026, paused until the Vurto Private Contract exists). Both wallets are screened before the plan is built: the paying one (payer_blocked) and the receiving one (receiver_blocked). screening_unavailable (503) means the screening could not finish, try again in a few seconds.
DiscoveredHand the analysis payment transaction to the server once it is mined. The server reads it on-chain: a direct USDC transfer (the USDC of the invoice network) from the invoice creator to the Vurto fee wallet, of at least analysis.amount, newer than the invoice, never used for another analysis or invoice. screening_blocked (403): the free screening rejects the receiving wallet or the creator, and the payment is not registered. analysis_payment_pending (409): not mined yet, call again in a few seconds. analysis_payment_rejected (400) with details.reason (charge_not_tied, wrong_token, wrong_destination, amount_too_low, sender_not_creator, not_a_transfer, tx_reverted, tx_before_invoice): that transaction does not pay this analysis. charge_not_tied means it is not the transaction we built: do not pay again, prove the wallet (destination_challenge with receiver = details.feeWallet, chargeId = this invoice and chargeTxHash = that hash, then destination_authorize) and report the same hash again. Repeating a hash already recorded returns the status, and the stored result only with the receipt the first record returned (receiverAnalysis.receipt, sent back as receipt) or a proven wallet. tx_already_used (409): the hash already paid something else. Once paid, analysis.status is paid and the invoice can be paid. When the payer bought the analysis of the receiving wallet, pass payer too (the charge of the creator needs only txHash): the transaction must be signed by that payer and only the fee wallet may gain USDC in it (the split payment of an invoice never pays it, usdc_to_other_wallet); once paid the receiver analysis runs right away and receiverAnalysis.result comes back (verdict and the paid tools, never the receiving wallet).
DiscoveredHand the payment transaction to the server, right after sending it. The server reads the transaction on-chain and measures what reached the receiver in the invoice token; the payer must be the signer and the transaction must be newer than the invoice. The payer is screened again here (payer_blocked: a sanctioned or issuer-frozen payer does not count as paid, and once the network confirms the transaction the refusal is kept in the 10-year analysis record). With a paid analysis on the invoice and no prior proof of the payer wallet, the transaction itself is the proof: until the network confirms it the call returns payment_pending (409) and records nothing, so call again once it is mined. Pending until mined; invoice_get re-checks. An invoice holds at most 5 pending and 30 unconfirmed payments; past that, too_many_pending (429) until the network confirms the transaction, and a confirmed one is always accepted, so call again once it is mined. A hash pays each receiver once (tx_already_used once it confirmed another invoice of the same receiver and token); different receivers in one transaction are a batch payout.
DiscoveredBuilds ONE signable/sendable atomic transaction executing every leg of an N:N basket through VurtoSwapRouter. Always re-quotes the whole basket fresh from chainId/inputLegs/outputLegs — there is no quoteId handoff for N:N, pass the same fields used for nn_quote (or skip nn_quote and call this directly). No API key required: pass the wallet that will sign. A machine credential is optional and only raises your limit from the per-IP cap to the credential budget. Returns steps[]: one approve step per DISTINCT input token that still needs allowance, followed by ONE transaction step that executes every leg atomically. The approve target is the VurtoSwapRouter address (steps[].spender / the build's router), NOT each leg's underlying provider — this router pulls every input token itself inside one contract call, so approving providers individually the way swap_build does would approve the wrong address. If simulation.status is approval_required, send the approve step(s) first and call nn_build again for the executable transaction. legs[].routeSwitch, when present on a leg, means the provider the quote picked for THAT leg refused to build (it hit its request limit) and the leg was built with another provider instead: {from, to, reason}. Only that leg changed, the others are untouched, and the replacement is what will be signed: say which provider replaced it before the user signs. IMPORTANT: report_execution and swap_status do NOT support nn_build's transaction step — both key off a single quoteId, and this build has none (it is one transaction covering every leg, not one quote). After sending it, confirm success by checking the transaction receipt directly, not swap_status.
DiscoveredN:N — quotes a basket where N input tokens fund M output tokens in ONE atomic on-chain transaction. The backend runs a waterfall allocation deciding which input finances which output, then quotes the real tokenIn->tokenOut route for each resulting slice through the same provider fan-out swap_quote uses. NOT decomposable into independent swap_quote/double_quote calls — the allocation itself is the thing being computed, not just N+M separate prices for legs you already know. inputLegs[]: what you sell (tokenIn + amount or amountRaw, each). outputLegs[]: what you want back, as outputPercent — an integer percent of the TOTAL basket value, not a fixed amount, because the actual split depends on the allocation; every outputLegs[].outputPercent in the request must sum to exactly 100. Up to 10 combined input+output legs; the waterfall never produces more than inputLegs.length + outputLegs.length - 1 real on-chain legs. Returns { legs[], failures[] }. Each entry in legs[] is a real quoted tokenIn->tokenOut leg (a NormalizedQuote under .quote, plus amountIn/tokenIn/tokenOut/receiver for that slice) — this is what nn_build will execute, not a rough preview. failures[] lists any slice that found no route; a partial basket is possible and reported, never silently dropped.
DiscoveredPayroll and supplier payouts to many wallets in one batch, on Solana and on the nine EVM chains (those with loteSplit true in GET /v1/chains). EVM: up to 50 wallets, in a verified USD stablecoin (USDC, USDT, PYUSD, USDG, USD1) — the batch is ONE transaction through the Vurto IBBs split contract, and the payer pays the exact amounts PLUS a 0.1% Vurto fee on the total. Solana: up to 20 wallets, in any token the payer holds (no swap, no fee), packed into one or a few transactions. The paying wallet and every receiving wallet are screened first (OFAC SDN list and, on Solana, the issuer freeze of six stablecoins); a blocked payer refuses with payer_blocked (403), and one blocked recipient refuses the whole batch with receiver_blocked (403) and details.index of that row, before anything is created. Each recipient becomes a regular invoice (history, on-chain verification). EVM returns { invoices[], evm: { split, invoiceIds[], base, fee, batchRef, deadline, steps[] } }: sign steps IN ORDER with prepare_signing (the approve step first, then the pay transaction step), send them, and call payout_report_payment with the PAY transaction hash and evm.invoiceIds. Solana returns { invoices[], transactions[] }: sign each transactions[i].transaction (prepare_signing, then POST to /v1/svm/execute) and call payout_report_payment with that signature and its invoiceIds. checks (stablecoin token, both families) adds a PAID analysis of every destination, turning the batch into two steps. Scorechain runs on every EVM chain and Solana; Merkle Science (Didit) does not cover Gnosis, Unichain or Avalanche, so a check the chain lacks refuses with check_not_available_on_chain. With checks the response carries no transactions[]: Solana returns { invoices[], charge: { buildId, transaction, loteId, total, token, tokenDecimals, feeWallet, recipients }, reused[] } (prepare_signing with buildId and step {transaction}, POST to /v1/svm/execute); EVM returns the same charge plus charge.step, a transaction step ready for prepare_signing. Sign the charge transaction exactly as returned: it carries the mark that ties the payment to this charge (16 bytes after the transfer arguments on EVM, a memo on Solana). A transfer you build yourself is refused with analysis_payment_rejected, reason charge_not_tied, after the money has left; do not pay again, prove the wallet (destination_challenge with wallet = payer, receiver = details.feeWallet, chargeId = this charge and chargeTxHash = that hash, then destination_authorize) and report the same hash again. A Solana transaction expires in about a minute: POST /v1/payouts/charge/transaction with loteId and payer returns the same charge fresh, without another batch; if it also returns reportedTxHash, send that hash to payout_charge instead of signing, or you may pay twice. To pay the fee with another token, swap_build with tokenOut = charge.token, receiver = charge.feeWallet and loteId, with a minimum between charge.total and 10% above it. Then call payout_charge with that loteId, the charge hash/signature and the payer to analyse every destination, drop the blocked and get the approved send: Solana as transactions[] to sign, EVM as evm (the IBBs approve + pay steps of ONLY the approved, with the 0.1% fee recomputed on the approved base, with buildId, chainId and invoiceIds; if evm.deadline passed, call payout_charge again for a fresh one). Not re-charging a wallet already analysed (reused[]) needs the payer's signed session, which the API does not carry, so via MCP every destination is charged and reused[] is empty. Errors: batch_not_available_on_chain (an EVM chain without the IBBs contract), stablecoin_required (a checks batch in a non-stablecoin token), check_not_available_on_chain (a paid check the chain lacks, e.g. Merkle on Gnosis/Unichain/Avalanche), batch_duplicate_recipient (add the amounts up in one row), batch_self_payment, too_many_recipients, token_not_listed, screening_unavailable (503, try again).
DiscoveredStep 2 of a payout_batch with checks, on Solana or EVM. After signing and sending payout_batch's charge.transaction, hand its signature or hash here with the loteId and payer. The server verifies the charge on-chain, runs the paid analysis on EVERY destination, EXCLUDES any wallet that is blocked or over the payer's risk threshold (it receives nothing, its money never moved), and returns { transactions[], evm?, approved[] (each with its scan result), rejected[] (wallet, reason) }. On Solana, sign each transactions[i].transaction (prepare_signing, POST to /v1/svm/execute) and call payout_report_payment with that signature and its invoiceIds. On EVM, sign evm.steps IN ORDER (approve, then pay the IBBs contract) and call payout_report_payment with the pay transaction hash and evm.invoiceIds. Idempotent with the same charge signature (re-returns the built batch, without the wallets already paid, listed in alreadyPaid). The charge hash goes only here, never to payout_report_payment. Errors: batch_charge_not_found, invalid_tx_hash, analysis_payment_pending (409, the network has not confirmed the charge yet, send the signature again shortly), analysis_payment_rejected (the transaction does not pay this charge; details.reason charge_not_tied when it is not the transaction payout_batch built: do not pay again, prove the wallet with destination_challenge (receiver = details.feeWallet, chargeId = the loteId, chargeTxHash = that hash), then destination_authorize, and call this again), tx_already_used.
DiscoveredHand one batch transaction to the server, right after sending it, with the invoiceIds that payout_batch listed for it. Each invoice is verified on-chain like any invoice payment (what reached that receiver); call again a few seconds later if some are still pending.
DiscoveredPreview which wallets in a batch (Solana or EVM) already have a fresh paid analysis by this payer, so payout_batch would not charge for them again. This reveals a payer's own analysis history, so it needs the paying wallet's signed session; the MCP carries no session, so it always returns { paid: [] } and the batch charges every destination. Exposed for parity. Returns { paid: string[] }.
DiscoveredSynthesizes the local CLI signer invocation for one step of a swap_build plan. Does not call the Vurto backend — this only assembles the payload. You (the agent) do not need a private key and must never ask for one in chat: signing happens locally on the user's machine. RUN the command yourself as a background task (it blocks until the user approves/rejects/times out, then prints one JSON line and exits) and react to its exit — never ask the user "did you sign?". EVM supports "approve"/"transaction" steps (send tx.to/tx.data on-chain) and "signature" steps (sign step.typedData off-chain, EIP-712 — a CoW order; no gas, no transaction, no hash). expected_keys in the response tells you which result field to read: txHash for the first two, signature for the third. Solana has no steps[] and no approve: pass chainId "solana-mainnet" and step {transaction: build.transaction, executionRef: build.executionRef}. The response returns a different signer (Solana keys are not EVM keys) with the same shape, and expected_keys is signedTransaction — POST it to /v1/svm/execute, which broadcasts it and returns the signature.
DiscoveredReports a completed swap, closing the loop. EVM transaction: pass wallet + txHash + quoteId; never report an approve step as an execution. EVM CoW signature: pass wallet + chainId + quoteId + signature; the server reloads the stored build and submits the signed order, returning uid (there is no transaction hash for this path). Solana: pass buildId + signature; the server verifies the fee payer and transaction on the network. No API key required; a machine credential only raises limits.
DiscoveredBuild a signable/sendable plan for a swap. This is the tool that does the work — an agent that only knows this tool can execute a swap end to end. Quotes and builds the best route in one call when quoteId is omitted (recommended): a route with GAIN first, re-quoting up to 3 rounds total before accepting one without gain, the same rule as Invoice; pass quoteId from a prior swap_quote to build exactly that route instead. No API key required: pass the wallet that will sign. A machine credential is optional and only raises your limit from the per-IP cap to the credential budget. Four things to hold onto: 1. steps[] are ORDERED and REQUIRED. Skipping an approve step guarantees a revert. 2. If simulation.status is "approval_required", sign/send only the approve step(s), do not report them as the swap execution, then call swap_build again with quoteId set to the quote.id of that build (the approved route; without it a fresh quote may pick another provider whose spender you never approved). If it is "incomplete", do not sign anything: the transaction was never independently verified. 3. If a step has type "signature", there is no transaction and never will be one for that step — what exists afterward is the uid from report_execution, not a hash. 4. If the provider is cowswap and the token sold is the chain's native asset, the transaction only REGISTERS the order — a successful receipt is not a successful swap. Use swap_status, not the receipt, to know what actually happened. 5. routeSwitch, when present, means the route you asked for refused to build (it hit its request limit) and the plan was built with another provider instead: {from, to, reason}. The quote in the plan is the route that will actually be signed. If the user picked that route themselves, say which provider replaced it before they sign.
DiscoveredCompare ranked routes across providers for a swap, without building or spending anything. Ranked by net value after gas and platform fee, not raw output, with ONE unit price for the output token across every route, so a friendlier price feed can never put a route that delivers fewer tokens on top. Each quote also carries estimatedGas, the gas in units behind the same gasUsd, if you would rather rank against a gas price you read yourself. A quote is only usable by swap_build for about 10-12 seconds — do not hold onto a quoteId and build it later, quote again instead.
DiscoveredRe-checks a swap. EVM: pass wallet + executionId (the id from report_execution); for CoW ETH-flow this consults the orderbook and distinguishes order_expired_refundable from order_expired_refunded instead of trusting the registration receipt. Solana: pass signature; answers come directly from the network and may be confirmed, pending, failed or expired.
DiscoveredCheck any wallet (EVM 0x address or Solana base58, case-sensitive) before paying it or taking its money: OFAC SDN list on both families; on Solana also the issuer freeze of USDC and EURC (Circle), USDT (Tether), PYUSD and USDG (Paxos) and USD1 (World Liberty), the issuer freeze index, and a fund trail up to three hops back. Returns verdict passed, blocked or unavailable, with each check. Paying an invoice (invoice_pay) runs this check on the receiving wallet and refuses with receiver_blocked, so a payment through Vurto Payments never reaches a sanctioned or frozen wallet. To pay someone directly, create an invoice to their wallet (invoice_create) and pay it with invoice_pay. Plain swaps (swap_build, double_build, nn_build) do not run it. The Scorechain and Merkle Science checks are paid and run only inside an invoice whose analysis was paid; asking for them here returns paid_check_requires_invoice (400).
DiscoveredRecent measurements
| Checked | Result | Response | Tools |
|---|---|---|---|
| Connected | 87 ms | 22 |