How do you trustlessly exchange BTC for XMR?

1 Answer 1


Originally posted on the Monero subreddit at https://www.reddit.com/r/Monero/comments/qb7t8p/how_to_atomic_swaps/, u/dEBRUYNE_1 requested I post it here too. Please excuse the mis-tagging; I apparently lack the reputation to create appropriate tags.

I flatter myself that I'm at least an above-average user of Google, a relatively competent computer user, and have an acceptable level of understanding of the mechanics of blockchains and cryptocurrencies in general, and yet I frankly found the comit atomic swap tool to be a pain in the ass to figure out. A couple of days of experiments, Googling around, and reading the Github issues page later, I feel a lot more comfortable with it. I am not part of the Comit team, just a dude who was frustrated looking for answers on Google.

This post is for people like me - people who kinda-sorta-maybe generally know what they're doing but are approaching atomic swaps for the first time - to have all the information I've gleaned in one place in a handy step-by-step guide. I am not an expert on the subject and if there are any inaccuracies in this post I'd love to be corrected by people who know more than I do.

So, without further ado:

How to swap BTC for XMR using swap (or swap.exe if you're thatway inclined)

  • Before you begin: This can be a long-ish process (you'll be waiting around for a total of 20 XMR and 4 BTC confirmations before everything's done) and for the best chance of a smooth ride, you need to maintain a connection to the provider throughout. Plan accordingly if your connectivity isn't reliable. There are ways to remedy an interrupted swap, but not in all circumstances - the issues page of the Github contains a couple of questions where XMR or BTC was apparently unrecoverable. Proceed with caution.

  • The easiest place to start your journey is https://unstoppableswap.net/ which will provide you with a list of swap providers. Some caveats with this:

    • Be aware that some are on testnet, while some are on mainnet. Be sure to look at the tags.

    • Also be aware that a provider's presence on the list is not an indicator of anything other than the provider being online. It does not guarantee that they have sufficient XMR to make swaps for the amount of BTC they claim as their maximum (or indeed for any amount), nor that their swap provider server is actually functioning correctly. More on that lower down. Choose your provider carefully.

    • It is possible to bypass unstoppableswap and get a list of providers from the swap binary if you specify a rendezvous point. I don't know enough about this to talk about it here, so I won't.

  • Choose your provider and fill in the amount of BTC you want to swap. Click Swap and fill in the form. Follow through the instructions to download swap (for *NIX) or download it manually (easier for Windows users) and then copy the command it handily generates for you.

  • The command will be something like:

    ./swap buy-xmr --receive-address $YOUR_MONERO_ADDRESS --seller $YOUR_CHOSEN_SELLER --change-address $BTC_ADDRESS_YOU_CONTROL 
  • Run it. If your provider is reachable, you will see output like the following. If your provider is not reachable, start again from the top and pick another.

    Connected to Alice at $YOUR_CHOSEN_SELLER
     Received quote price=$PRICE BTC minimum_amount=$BTC_MIN BTC maximum_amount=$BTC_MAX BTC
     [QR CODE]
     Waiting for Bitcoin deposit deposit_address=$BTC_ADDRESS max_giveable=$BTC_SPENDABLE_THISWALLET BTC minimum_amount=$BTC_MIN BTC maximum_amount=$BTC_MAX BTC
  • Confirm that you are happy to swap at the exchange rate given by $PRICE. Also now would be a good time to check on BTC transaction fees to make sure you aren't about to spend thousands of sats on a transfer.

  • If you're unhappy with tx fees, you can afford to wait a bit. There doesn't appear to be a timeout on the swap at this stage.

  • Presuming that everything is okay, you should now transfer an amount of BTC between ($BTC_MIN+$TX_FEE) and $BTC_MAX to the address indicated by $BTC_ADDRESS. You must account for the onward BTC transaction fees here, otherwise the amount that $BTC_ADDRESS can spend could be lower than $BTC_MIN. I will admit with some embarrassment that I didn't think of that at all the first time I tried a swap, so I ended up having to make two transfers into $BTC_ADDRESS, and pay two lots of transaction fees.

  • This amount does not have to be the amount you told unstoppableswap you were going to swap. As far as I can tell, unstoppableswap only asks how much you want to swap so it can validate your choice of provider.

  • When your BTC transfer is broadcast (interestingly, it doesn't appear in my experience to require confirmation, merely broadcast and acceptance into the BTC mempool), you will see output like this:

    Received Bitcoin new_balance=$XFER_AMOUNT BTC max_giveable=$BTC_SPENDABLE_THISWALLET
     Determined swap amount amount=$BTC_SPENDABLE_THISWALLET BTC fees=$FEE BTC
     Starting new swap swap_id=$SWAPID
  • Several of my swap attempts have gone wrong at this point, usually before the assignment of a $SWAPID. Some failed with cryptic error messages (see below for a table) and some with a message that the swap provider does not have sufficient XMR to fulfil the swap request.

  • If your swap errors out and drops you back at the terminal/command prompt here, DO NOT PANIC. You can initiate a transfer of your BTC with the command below. This will work to withdraw the BTC back where it came from, or you could use it to transfer to the new $BTC_ADDRESS when you retry the swap.

    ./swap withdraw-btc --address $DEST_BTC_ADDRESS
  • Assuming nothing has failed and swap is still running, however, you'll see output like this:

    Published Bitcoin transaction txid=$ONWARD_TXID kind=lock
     Waiting for Alice to lock Monero
  • Alice is waiting for two block confirmations for $ONWARD_TXID. From this point, you are no longer able to use the

    command to halt the swap. While you and Alice wait for the two block confirmations, go get a coffee or eat some soup or something. The terminal will not update until there are two block confirmations. I don't know about you, but I find it unnerving to stare at an unchanging terminal when I know for a fact there should be a process going on, so I prefer to just not look at it for a while.

  • Once $ONWARD_TXID has the two block confirmations you should receive a message confirming that Alice has locked the XMR you're going to receive, and an XMR txid. swap will keep reporting the number of confirmations until the required 10 are received. THIS IS NOT THE FINAL TRANSFER TO YOUR XMR WALLET. This is the lock transaction where Alice transfers XMR from an internal wallet to the multisig lock wallet.

    • If you lose connection to Alice during this time, the swap will be halted, but can be resumed, and depending on exact circumstances it will either complete the transfer of XMR to your wallet or refund your BTC to the $BTC_ADDRESS_YOU_CONTROL you specified at the top. To resume a halted swap, you must use
      swap resume --swap-id $SWAPID
      If you don't have the $SWAPID, you can check it with
      swap history
      which will give you the state and ID of every swap you've started. Of course the state database is persistent, so even if you had a power failure, you can resume.
  • Now that Alice's XMR lock transaction is confirmed, swap will proceed with transferring both the BTC and XMR to their final destinations. Two transactions (one XMR, one BTC) are broadcast, but swap will only tell you the txid for your XMR transfer to your wallet on the terminal, and then exit.

  • Congratulations, when you have 10 confirmations for the txid that swap gave you, you will have successfully received XMR in exchange for BTC, in a completely trustless fashion.

Stuff that has gone wrong for me, with solutions:

Error Cause/Solution
Error: Failed to complete swap 
Caused by:
0: Failed to deserialize bytes into message using CBOR
1: EOF while parsing a value
No idea why this happens. Find a new swap provider, try again. Use
swap withdraw-btc --address=<$DEST_BTC_ADDRESS>
to reclaim BTC.
Error: Failed to complete swap 
Caused by:
Seller's XMR balance is currently too low to fulfill the swap request to buy $SWAP_AMOUNT BTC, please try again later
Wait for swap provider to replenish their XMR wallet (many seem to do this manually for the moment) or try a different provider. Use
swap withdraw-btc --address=<$DEST_BTC_ADDRESS>
to reclaim BTC.
monero-wallet-rpc failed to fetch transaction, may need to be restarted txid=$XMR_TXID
Not necessarily fatal. May indicate a loss of connection. If swap exits to terminal without reporting
Successfully transferred XMR to wallet monero_receive_address=$XMR_ADDRESS
then use
swap resume --swap-id=<$SWAPID>
to complete the swap. Use
swap history
to determine $SWAPID if unknown. Swap can be resumed hours or days later, but may 'complete' by refunding BTC rather than transferring XMR.
Lost connection to Alice at $YOUR_CHOSEN_SELLER, cause: Connection error: I/O error: connection is closed
Fatal. Definitely lost connection. Use
swap resume --swap-id=<$SWAPID>
to complete the swap. Use
swap history
to determine $SWAPID if unknown. Swap can be resumed hours or days later, but may complete by refunding BTC rather than transferring XMR.

In all cases, the state db can be queried with

swap history
and will give you clues on where the XMR and BTC are (internal wallet; lock (multisig) wallet - confirmed or unconfirmed; successfully redeemed). Also, the tool maintains detailed logs to help with further diagnosis at C:\Users\$USER\AppData\Roaming\xmr-btc-swap\data\cli\mainnet\logs on Windows and I believe in ~/.xmr-btc-swap/data/cli/mainnet/logs for *NIX.

I hope this post is useful to someone, and I welcome corrections or expansion, as this is based on two days of me failing in a variety of entertaining (but apparently not uncommon) ways to complete swaps. YMMV, stay safe.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.