Private Swap SOP: Hardware Wallet, Tor, No KYC
Six steps, measured end to end: four Tor exits answered 200 with no challenge, the deposit window is 601 seconds, and a 100 USDT order pays 13.9% over spot while 1,000 pays 2.7%.
What this SOP actually covers
The hard part of a private swap is not the swap. It is the four places where a machine learns both who you are and what you are moving: the browser you type in, the network that carries the request, the wallet that signs, and the address you paste. This runbook is the order I use for a cold-wallet swap, with timings and costs measured on veilswap.io at 18:00 UTC on 29 October 2026. It does not make you anonymous against a global adversary, and it does not launder anything.
Step 1: build the receiving address first, offline
Type nothing into a web form until the destination address exists and you have read it off the device screen. BTC is a 42-character bech32 string; XMR is 95 characters for a primary address or subaddress and 106 for an integrated one, and the site accepts all three shapes. If the recipient is a Monero hardware wallet, budget an extra hour for the node: the Ledger Monero app talks to a local monerod rather than a public node, and a full database measured 295,279,001,600 bytes (275.0 GiB) on 27 October.
The refund address is a separate field and it must belong to the same asset family as the leg you pay from. When we posted a 100 USDT-TRC20 order over Tor with a deliberately broken TRON string, the API answered 400 "invalid_refund_address: not a TRON address (expect T followed by 33 base58 characters)" and created nothing. Since 25 October the field is mandatory: omit it and the answer is "missing_refund_address". (Is Tor safe for swaps?)
Step 2: decide whether Tor earns its 5-10x latency (Is Tor safe for swaps?)
Measured through four different exits at 18:02-18:03 UTC - 23.128.248.168, 5.255.102.26, 171.25.193.234 and 204.8.96.166 - /exchange returned HTTP 200, 43,014 bytes, with zero challenge markers ("Just a moment", challenge-platform, cf-chl), and /api/quote returned a normal quote on all four. What you pay is time: page TTFB 1.77-3.43 s over Tor against 0.26-0.58 s direct, and the quote API 1.79-2.09 s against 0.21-0.65 s. (Is Tor safe for swaps?)
Two caveats. First, this is a snapshot: Cloudflare decides per site and per exit, and an exit that works today can be challenged tomorrow - if you get a CAPTCHA, change circuit instead of solving it. Second, DNS is the classic leak: a client that hands the hostname to the local resolver has already told your ISP which exchange you use, so the SOCKS proxy has to resolve remotely (curl --socks5-hostname, or a browser proxy with remote DNS on).
Step 3: size the order before you click
The quote is not linear, because every order carries a fixed deduction. At 18:05 UTC, 100 USDT-TRC20 bought 0.14516454 XMR, 500 bought 0.79722513, 1,000 bought 1.61121828 and 5,000 bought 8.12867363 - implied 688.9, 627.2, 620.6 and 615.1 USD per XMR against 604.55 spot. The gap is 13.9% at 100, 2.7% at 1,000 and 1.75% at 5,000. The corridor floor was 19.83547 USDT and the ceiling 176,589.173232. Below about 500 you are paying the counter, not the market. (XMR to USDT exit)
Step 4: create the order - five fields, a 601-second window
The order POST carries fromAsset, toAsset, fromAmount, toAddress and refundAddress, and nothing else: no account, no email, no signature. Our order created over Tor at 18:04:50 UTC returned id 2670192f-4119-4c46-8588-eb54d7b7f38b, deposit address TB8Ev6gKFGkPCsAS1Rcavo5DcFZseSkMbH and validUntil 18:14:51 - 601 seconds. The quote itself was good for only 120 seconds, so read the amount off the order page, never off the earlier quote. (Is Tor safe for swaps?)
One detail people miss: the order URL is the credential. /api/order/<id> answers with depositAddress, status, toAmount and validUntil to anyone holding the id, with no cookie and no login; a wrong id gives {"error":"not found"} while the page itself still returns an HTTP 200 shell. Treat that link like a password - private window, no bookmark, no screenshot into a chat.
Step 5: fund it from the hardware wallet
A deposit is a plain send, so you pay the chain, not the exchange. At 18:05 UTC the mempool held 56,866 transactions and 21.40 MvB, and all four recommended tiers sat at 1 sat/vB; a one-input, two-output P2WPKH spend is 140.25 vB (141 vB rounded up), so 141 satoshis - about $0.11 at BTC 80,741. A TRC20 transfer costs 64,285 energy (6.4285 TRX at 100 sun) plus bandwidth, roughly 6.7735 TRX or $2.24 at TRX 0.331054. A Monero send of 1,534 bytes at the 20,000 piconero/byte level is 0.00003068 XMR, about $0.019.
Send exactly the invoiced amount. Underpay and the order sits in its deposit window until it dies, and there is no RBF or CPFP rescue for an exchange deposit: the only meaningful output belongs to a receiving address you do not control, so you cannot sign a child transaction for it.
Step 6: watch it without leaking it
The order page renders client-side. The 32,808-byte HTML we pulled over Tor contained neither the deposit address nor the status; both arrived afterwards from /api/order/<id>. That is also why a script-blocked browser shows three input boxes and nothing else. On the analytics side, /order/<id> loads the aggregate counter and zero Clarity, while /exchange loads both. (Is Tor safe for swaps?)
The last leak surface is your own browser. The swap widget writes vs_active_order into localStorage with the order id, deposit address and extra id, so a shared machine still holds yesterday's deposit address after you close the tab. Use a private window or clear site data, and never leave an order tab open on a computer you do not own.
The seven traps, in the order they bite
1) Copying the address from history instead of the device. 2) Filling the refund address with an address from another chain. 3) Sending under the corridor floor (19.83547 USDT for this pair), which the API refuses and which turns a manual send into a support ticket. 4) Using a stale quote instead of the order's validUntil. 5) Paying after the window - 601 seconds here - and hoping it is credited. 6) Opening the order link on a shared browser. 7) Leaving the hardware wallet plugged into a machine with a browser open while signing: the device confirms what is on its own screen, so verify there, not on the laptop. (recovering misdirected funds)
What the whole run costs and takes
A realistic clock: five minutes to prepare addresses, one to three minutes for a Tor page load and quote, 601 seconds of deposit window, then the provider's own processing and one confirmation cycle. Cash: chain fees of roughly $0.02 to $2.24 depending on the paying chain, plus the corridor spread the quote already shows - 1.75% at 5,000 USDT, 2.7% at 1,000. Every price in this piece is from 18:0x UTC on 29 October 2026; the live page is the only current source. (Is Tor safe for swaps?)