I needed to add cross-chain token swaps to a side project last week. Not a full DEX UI — just a backend endpoint that lets users swap ETH → USDC or USDC → XMR without me having to deal with routing logic or liquidity pools.
I'd heard of wagyu.xyz from a Discord thread about DEX aggregators. Decided to give it a shot. Here's what 20 minutes of integration looks like.
The API structure
Wagyu uses a two-step flow:
- GET a quote — tells you the rate, estimated output, and timing
- POST an order — creates a deposit address; user sends tokens, swap executes automatically
No private keys. No signing transactions on your backend. The deposit-address model is genuinely clean.
Step 1: Get a quote
const response = await fetch('https://api.wagyu.xyz/v1/quote', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': process.env.WAGYU_API_KEY,
},
body: JSON.stringify({
fromChainId: 42161, // Arbitrum
toChainId: 0, // Monero (yes, 0 = XMR)
fromToken: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // USDC on Arbitrum
toToken: 'XMR',
fromAmount: '10000000', // 10 USDC (6 decimals)
}),
});
const quote = await response.json();
console.log(quote.toAmount, quote.estimatedTime);
The response comes back in under 200ms. toAmount is the XMR you'd receive. estimatedTime was around 2 minutes in my tests.
Step 2: Create the order
const order = await fetch('https://api.wagyu.xyz/v1/order', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': process.env.WAGYU_API_KEY,
},
body: JSON.stringify({
fromChainId: 42161,
toChainId: 0,
fromToken: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',
toToken: 'XMR',
fromAmount: '10000000',
toAddress: 'YOUR_XMR_WALLET_ADDRESS',
}),
});
const { orderId, depositAddress, depositAmount, expiresAt } = await order.json();
You get back a depositAddress. Tell your user to send depositAmount there. That's it. Wagyu monitors the chain, detects the deposit, and routes the swap automatically.
Checking order status
const status = await fetch(`https://api.wagyu.xyz/v1/order/${orderId}`);
const { status: orderStatus } = await status.json();
// 'awaiting_deposit' → 'deposit_confirmed' → 'executing_swap' → 'completed'
I polled this every 15 seconds in my webhook handler. Worked fine.
What surprised me
XMR support is real. I expected it to be a checkbox feature with bad rates. It wasn't. The USDC → XMR rate was within 0.8% of what I saw on TradeOgre for the same amount. The routing goes through Hyperliquid for the EVM leg, which explains the tightness.
The chain ID for Monero is 0. Took me a minute to find this. It's in the /v1/chains endpoint response, but worth noting upfront.
Large XMR orders get TWAP'd automatically. Orders over $25k (any → XMR) get split into chunks to minimize slippage. You can configure this or let it default. Useful if you're building anything with meaningful volume.
The integrator fee system
If you register an API key, you can configure a fee percentage (0–5%) that gets deducted from deposits automatically. You specify fee addresses for EVM, Solana, and optionally Bitcoin. Genuinely useful if you're building a product on top of this — no custom smart contracts or fee accounting logic needed.
Limitations I ran into
- No price impact warning in the quote response. You have to infer this from the difference between quote and executed amount.
- Deposit address expires in ~2 hours. If a user sits on it overnight, it'll be stale. Plan accordingly.
- No webhooks (at time of writing). Polling is the only status update mechanism.
Verdict
For a backend swap integration that handles cross-chain including XMR, wagyu.xyz is the most frictionless thing I've found. The deposit-address model means I don't touch private keys at all. Setup was genuinely 20 minutes from zero to working orders.
API docs: docs.wagyu.xyz
Tested with real funds. Small amounts. Your mileage may vary on large orders — test in prod at your own risk.
Top comments (0)