
Forking xmrcheckout into wowcheckout
Wownero is a community-driven Monero fork. Same Cryptonote roots, friendlier vibe, smaller community, and — important for our purposes — a fork of Monero's wallet RPC with one quietly different constant.
Why fork xmrcheckout
We had Monero working through xmrcheckout, a small standalone service that handles wallet polling, deposit detection, and webhook delivery to Medusa. Wownero shares ~95% of Monero's RPC surface, so adding Wownero looked like a few-line copy at first.
Forking the whole service was the right call anyway, for two reasons:
1. The RPC surfaces will drift over time. Trying to keep one codebase abstracted across both forks meant constantly checking whether each upstream method was still bytewise-compatible. 2. Operationally, each currency runs as a separate Docker container with its own daemon and view-only wallet. A fork keeps the deployment topology clean and lets us version the two services independently.
So we forked xmrcheckout into wowcheckout, swapped out the daemon and wallet binaries, and started testing.
The atomic-unit gotcha
Monero uses 10^12 piconero per XMR. Wownero uses 10^11 piconero per WOW. That single-digit difference broke detection in the most subtle way possible: invoices marked as paid only when the payer happened to overpay by 10×. Underpayments looked correct on the chain but the comparison "received_atomic >= expected_atomic" silently failed.
We patched it in the wowcheckout config layer with a per-fork `atomic_units` constant, audited every callsite that did currency math, and added a unit test that asserts `expected_atomic == amount * 10^decimals` for both forks. Boring fix, but the hours we spent staring at a Wownero blockchain explorer to convince ourselves the daemon was actually receiving payments are time we'll never get back.
What else changed
Several things accumulated during the audit pass:
- Advisory locks on the deposit-detection job so two cron-style runs can't double-credit the same payment.
- Webhook retry with exponential backoff. If Medusa is down when a confirmation lands, we don't lose the event.
- Restore-height parameter on the wallet startup — without it, a fresh container has to scan from the genesis block, which on Wownero means hours of catch-up.
- Stricter confirmation counts. Wownero's block time is ~5 minutes vs Monero's ~2, so the same N confirmations means a longer wait. We surface that to the customer in the "confirming" UI.
What it looks like now
Both services run on the same `one-btcpay` server alongside the BTCPay container — a single box hosting all of our crypto infrastructure. Each fork has its own daemon, its own view-only wallet, its own webhook secret, and its own Medusa provider plugin. Adding a new fork (Haven, Salvium, etc.) is now a templated copy-and-tune rather than a rewrite.
If you run a Monero fork and want a checkout, the recipe is documented in the wowcheckout repo.