What it is
TestnetSwap lets you swap one testnet coin for another without custody, without trusting the maker to hold your coins. It feels like a one-provider instant exchange (pick a pair, see the rate, confirm) but it is not custodial. Each Bitcoin-family swap is a cross-chain HTLC atomic swap: your funds are only ever in a contract that either completes the swap or refunds to you.
You are the taker and you run nothing but your browser. The other side of every swap is an always-on maker daemon: the default operator maker, or any maker you pick from the network. Makers fund from CypherFaucet, so there's never a wait for a second human. The maker sets the quoted rate and supplies the liquidity, but it never takes custody of your coins.
The four steps
Setup
Your browser generates a random 32-byte secret S and computes its hash H = SHA256(S). Over the relay (an untrusted message transport that never touches funds), your browser and the maker exchange H, both public keys, the amounts, and two absolute timelocks: T1 for you (longer) and T2 for the maker (shorter).
You lock
Your browser builds an HTLC on the send chain with deadline T1, funds it, and broadcasts. The contract pays the maker if it reveals S, or refunds to you after T1.
They lock
The maker waits for your funded contract to confirm, verifies it on-chain, then builds a matching HTLC on the receive chain with the shorter deadline T2, paying you if you reveal S, or refunding to the maker after T2.
You claim
Your browser verifies the maker's contract, then claims it by revealing S in the spend. You now have the receive-chain coins, and S is public on that chain. The maker reads S from your spend and uses it to claim your contract. Swap complete, atomically.
Why a maker can't take your coins
Atomicity is the whole point, and both contracts are bound to the same hash H. The maker cannot claim your contract until you reveal S by claiming the maker's contract first. Once your claim is visible on-chain, the maker can extract S and complete the other side. If the maker never posts a valid matching contract, your browser never reveals S at all.
If the maker vanishes after you lock, it never learns S, so it cannot touch your coins. After T1 your browser can build and broadcast the refund. The worst case is that you recover the principal you locked after the deadline, minus network fees.
The load-bearing rule: T1 > T2
You (who reveal the secret first) get the longer refund window. After you claim and reveal S, the maker needs time to see that spend and claim your contract before your own refund path opens. If the deadlines were inverted or too close, one side could be raced; TestnetSwap enforces a safe gap between them.
The contract
A P2WSH hash-timelock contract, identical on both chains (both are secp256k1 UTXO chains with Script):
OP_IF
OP_SIZE 0x20 OP_EQUALVERIFY # secret must be exactly 32 bytes
OP_SHA256 <secret_hash> OP_EQUALVERIFY
OP_DUP OP_HASH160 <recipient_pkh>
OP_ELSE
<locktime> OP_CHECKLOCKTIMEVERIFY OP_DROP
OP_DUP OP_HASH160 <refund_pkh>
OP_ENDIF
OP_EQUALVERIFY
OP_CHECKSIG
Redeem path (IF): reveal a 32-byte secret whose SHA256 matches, signed by the recipient. Refund path (ELSE): after the timelock (CLTV), signed by the refunder. Timelocks are time-based (wall-clock), so your browser can show a clear "refundable after HH:MM".
Monero swaps (tXMR / sXMR → tBTC or tLTC)
Monero has no on-chain scripts or timelocks, so the HTLC above can't hold it. Monero swaps use an adaptor-signature protocol instead: all the script and timelock logic lives on the settle-coin side (tBTC, or tLTC where a maker offers it) and a cross-curve (secp256k1 ↔ ed25519) proof binds the two. It runs entirely in this browser, like the HTLC swaps. The settle coin is just which Bitcoin-family chain the maker locks; the Monero side is identical either way.
Maker locks the settle coin first
You agree a quote over the relay; the maker locks its settle coin in a 2-of-2 contract with a cancel/refund path, and your browser verifies it on-chain before you move any Monero.
You deposit tXMR
Only after the settle-coin lock confirms do you send tXMR to a combined 2-of-2 lock address. Recovery material is saved before that, so a maker stall is always reclaimable.
You receive the settle coin
Your browser redeems the settle coin (tBTC or tLTC) to your address with an adaptor signature; that reveals the scalar the maker needs to claim the tXMR. Atomic: either both settle, or you reclaim your tXMR after the maker's refund.
tXMR = Monero testnet, sXMR = stagenet; the picker offers whichever network the maker runs. This page lazy-loads a ~7 MB Monero wallet engine (WASM + a Web Worker) only when you pick a Monero coin, so it runs under a slightly looser Content-Security-Policy than the rest of the site. Keys still never leave your browser.
What stays out
What Monero can't do
tXMR/sXMR settle into tBTC (or tLTC), but not back out (no tBTC/tLTC → XMR yet). The reverse would take the liveness-critical BTC-provider role off the maker and push it onto your browser, making the maker the XMR provider instead, a role reassignment we haven't taken on. And XMR ↔ XMR is impossible atomically: two scriptless chains have nothing to anchor the swap.
Custody & mainnet
No custodial mode (it would defeat the purpose) and testnet only for now. The non-custodial design would port to mainnet, but that's a separate, heavier decision.
Privacy
Non-custodial is not the same as private. The relay passes messages in plaintext and can see your IP, the amounts, the timing, and the addresses, so a swap is safe (nobody can take your coins) but not anonymous. That includes Monero swaps: moving tXMR/sXMR here does not hide it from the operator. Want network privacy? Reach the relay over Tor and treat amounts and timing as visible.