TronDealer now accepts native Bitcoin on its multichain payment gateway. Receive BTC on-chain (P2WPKH bech32) and choose your settlement: automatic credit to QvaPay, peer-to-peer Zelle offer, or direct sweep to your wallet with 0.4 percent fee. BTC-to-USD conversion frozen at deposit detection, HMAC-signed webhooks, and automated settlement with no manual custody.
After months operating exclusively with stablecoins, TronDealer takes its first step toward becoming a NOWPayments-style multi-asset gateway: starting today we accept native Bitcoin on-chain. And this isn't just "another network on checkout." It's a model change: you can now charge in BTC and choose how you receive the value —QvaPay balance, P2P Zelle offer, or direct sweep to your wallet— with the amount converted to USD at the deposit-time spot.
This article explains what shipped, why it matters for your business, how it works technically under the hood, and how it fits into the payments ecosystem you already know.
bc1q...) generated per client.If you sell products or services online and want to expand the universe of customers who can pay you, not accepting Bitcoin means leaving money on the table. Three concrete reasons:
USDT and USDC are perfect for those already inside the crypto ecosystem. But for the average customer who has "some Bitcoin stored away," BTC remains the default digital asset. It's what people buy first, what appears in every news story, and what even the least technical understand. Accepting BTC opens your store to a segment of users who never touched stablecoins.
Bitcoin transfers between any address on the planet without intermediaries, without KYC, and without banking permissions. For a business selling to Cuba, Venezuela, Argentina, Colombia, or any market where the international banking rail is hostile, BTC is real financial infrastructure, not speculation.
Stablecoins are pegged to the dollar by design. Bitcoin, by contrast, has historically appreciated against USD over 4+ year horizons. If you choose the wallet payout flow, you can decide to keep part of the payment in BTC as a store of value —something you can't do with USDT/USDC without manual exchange conversion.
Charging in BTC isn't trivial. Unlike USDT on TRON or USDC on Solana —where the on-chain amount already comes in USD value (1:1)— Bitcoin has three complications any serious gateway must solve:
1. UTXO model, not account model. In Ethereum or TRON the "balance" of an address is a number in a table. In Bitcoin, the balance is the sum of "unspent transaction outputs" (UTXOs) scattered across the chain. To sweep funds you have to take each UTXO, sign it individually, and assemble a consolidating transaction.
2. No "query balance" method. Public Bitcoin Core nodes don't expose wallet RPCs (listunspent, getreceivedbyaddress). There's no direct way to ask the node "how much BTC is at this address." You have to scan the blockchain block by block and match outputs against your active addresses.
3. On-chain volatility. If a customer paid 0.001 BTC at 3pm on Tuesday when BTC was worth $75,000 (= $75 USD), but your system charges at 3:30pm when BTC is worth $76,500 (= $76.50 USD), what amount do you report to the merchant? And if BTC moves 5% between deposit and sweep?
Every minute, a cron reads the last confirmed block (getblockcount) and processes up to 6 new blocks per tick. Each block is downloaded with getblock(hash, 2) —which returns the full transaction list with outputs and addresses— and matched against an in-memory Set containing all our clients' active addresses. O(1) lookup, microsecond comparisons.
We stay 1 block behind the chain tip as cheap protection against depth-1 reorgs (orphans), which are the most common. Depth-≥2 reorgs happen approximately once a year and are handled via automatic rollback of spent state if the sweep fails with missing-inputs.
RPC-only: Bitcoin Core JSON-RPC via our own node. No Blockstream API, no Mempool.space, no BlockCypher as sources of truth. Zero third-party HTTP-API dependencies for chain data. The only exception is CoinGecko for the BTC/USD price, cached 5 minutes in memory and never affecting on-chain detection.
For a user paying $50 in BTC, 6 confirmations (~60 min) is a frustrating experience. For a $50,000 payment it's reasonable. That's why the default is 2 confirmations (~20 min in steady state) —the optimal point for most ecommerce tickets— but it's configurable per client.
Bitcoin hasn't had a substantial reorg in years; 2 confirmations cover 99.9% of cases without sacrificing UX.
This is where Bitcoin differs from stablecoins. The moment we detect your deposit —the first time it appears in a block, not when it reaches sweep— we query the BTC/USD spot price on CoinGecko and save it in the database as price_usd_at_detect. This price is what travels in the webhook to the merchant, what's used to credit QvaPay, and what appears in the Zelle P2P offer.
Why freeze it? Because the customer "paid $50" in their mind when they made the transfer. If BTC rises or falls between detection and sweep, the USD amount you report shouldn't change; otherwise you'd be reporting a different value to the merchant than what the customer tried to pay. The frozen price gives auditability: anyone can verify amount_native × price_usd = amount in the webhook payload.
{
"event": "transaction.confirmed",
"data": {
"asset": "BTC",
"amount": "50.42",
"amount_native": "0.00066667",
"price_usd": 75630.00,
"tx_hash": "abc123...",
"vout_index": 0,
"confirmations": 2,
"network": "btc"
}
}The amount field is always in USD —for BTC, USDT, USDC, every chain— so your business logic compares amount against order.total without needing a branch per asset.
What matters most for you as a merchant: once BTC arrives and confirms, you choose how you receive it. Configure it once in dashboard Settings.
If your TronDealer account has payout_method: "qvapay" and a qvapay_account configured, each confirmed BTC deposit automatically triggers an order in QvaPay that credits the USD equivalent directly to your balance. The BTC stays in TronDealer custody (operating the USDT liquidity in the backend), and you receive stablecoin USD ready to withdraw to your bank account, send to another QvaPay user, or pay services from the app.
Advantage: You never touch BTC. You receive USD-in-stablecoin, free of volatility, in the QvaPay ecosystem where you already have your banking flow.
Fee: No additional sweep commission —QvaPay applies its standard withdrawal fee you already know.
If your account has payout_method: "zelle" and a zelle_contact (Zelle email/phone), each BTC deposit ≥ $5 USD triggers a P2P offer on the Zelle Offers platform that a buyer takes to pay you directly via Zelle with dollars from their US bank account.
Advantage: You receive real USD in your US bank account without going through an exchange or intermediary. Useful for freelancers, LatAm professionals with US accounts, or anyone wanting to convert BTC → bank USD with minimal friction.
Fee: No sweep commission. The market P2P discount (~2-3%) is what you absorb vs spot price, which is the normal cost of moving Zelle.
If your account has payout_method: "wallet" and a configured sweep_wallet_btc (any BTC address: P2PKH, P2SH, P2WPKH, P2TR), each deposit is automatically swept to your address. The BTC travels directly from the client's temporary wallet to your personal wallet in a single consolidating transaction.
Advantage: Maximum control. You receive BTC at the address you manage, you can hold it as reserve, hardware wallet, whatever you want. No intermediaries.
Fee: The standard TronDealer WALLET_SWEEP_FEE applies —0.4% or $0.30 minimum (whichever is higher) for deposits under $10— automatically deducted from the swept amount. For example:
| BTC Deposit | USD Equiv. | Fee | You Receive |
|---|---|---|---|
| 0.00066 | ~$49.80 | $0.20 (0.4%) | ~0.00065736 BTC |
| 0.00013 | ~$9.80 | $0.30 (min) | ~0.00012603 BTC |
| 0.01000 | ~$755 | $3.02 (0.4%) | ~0.00996 BTC |
Plus the Bitcoin miner fee (typically $0.50-$2 per tx depending on mempool congestion), which is deducted from the gross before the TronDealer commission.
So you see exactly what happens when a customer pays:
You generate a BTC wallet from the dashboard or via API. We return a P2WPKH (bc1q...) address that is yours and unique to that client. The private key is stored encrypted in our database and never leaves the server.
The client opens their preferred wallet (Phoenix, Muun, Wallet of Satoshi for Lightning—though for now only on-chain— or any on-chain wallet) and sends BTC to the address you provided. The transaction enters the Bitcoin mempool.
On average every 10 minutes a miner assembles a block and the tx is confirmed with 1 confirmation. Your scan cron processes that block within the next minute.
We insert the row in v2_btc_transactions with status: detected, confirmations: 1, price_usd_at_detect: <spot>. If your business has a configured, we send the event with the HMAC-signed payload.
Typical total latency: 25-35 minutes from when the client signs the tx until your internal system has the balance credited. Most of it is waiting for Bitcoin blocks; our layer adds ~30-60 seconds of total overhead.
If you're already integrated with TronDealer for stablecoins, the BTC webhook contract is 100% backward-compatible. The amount field always represents the USD-equivalent value, regardless of asset.
function handleWebhook(event) {
const { asset, amount, amount_native, price_usd, tx_hash } = event.data
// Comparison with order.total — works for BTC, USDT, USDC without branching
if (parseFloat(amount) >= myOrder.total_usd) {
markOrderAsPaid(tx_hash)
}
// If you want to show the crypto amount to the user in your dashboard:
if (asset === 'BTC') {
console.log(`Paid ${amount_native} BTC ($${amount} USD @ $${price_usd})`)
}
}The X-Signature-256 signature is computed exactly the same way (HMAC-SHA256(webhook_secret, raw_body)), the expected response codes are the same, and the retry policy is identical (5 attempts with exponential backoff for transaction.confirmed; best-effort for transaction.swept; fire-and-forget with no retries for the opt-in transaction.confirmation_update).
Three design decisions worth highlighting because they seriously differentiate TronDealer from other BTC gateways:
1. No confusing custody. When you choose payout_method: "wallet", the BTC travels from the client's temporary wallet directly to your wallet. TronDealer never consolidates into an internal pool that later has to settle against you. Each deposit is traceable on-chain from the client to you.
2. No Lightning without notice. For now we only support Bitcoin on-chain (Layer 1). Lightning Network is on the roadmap but requires completely different infrastructure (dedicated LN node, channels, liquidity management) and we wouldn't promise it before having it.
3. No forced fiat conversion. If you choose payout_method: "wallet", you receive native BTC. Zero forced conversion to USDT/USDC/dollar. If you want to hold BTC, you hold it. If you want to convert, you decide when and where. If you prefer to receive directly in USD-equivalent, that's the QvaPay or Zelle option.
Bitcoin is the first step. What's coming, in order:
If you already have a TronDealer account, you don't have to do anything new in the WooCommerce plugin or your API integration. Bitcoin appears as one more option in the dashboard. The next time you generate a wallet, choose the btc network and the flow continues.
If you don't have an account yet, register free at /onboard and configure your preferred payout method. The API key you receive works for all assets —stablecoins and BTC— without differentiation.
Bitcoin is live in production but we're still polishing edges. If you find something odd, want to suggest an improvement, or your use case requires something we haven't covered, write us at [email protected] or open an issue on the WooCommerce repo.
webhook_urltransaction.incomingWhen the next block chains, the scan confirmation pass promotes the row to status: confirmed, confirmations: 2. We dispatch the transaction.confirmed event —the main one— and trigger the configured payout flow (QvaPay, Zelle, or sweep wallet).
While you wait for that second block, if you enabled notify_confirmation_updates (PATCH /api/v2/clients/me with {"notify_confirmation_updates": true}) you also receive transaction.confirmation_update events with the live count and a min_confirmations field — so your UI can show "1 of 2 confirmations" instead of a frozen pending. Bitcoin's ~10-minute blocks are exactly where this event earns its keep. It is cosmetic and fire-and-forget: no retries, and never credit balances from it.
Every 10 minutes a sweep cron sweeps wallets with confirmed deposits. We build a consolidating PSBT, sign with the temporary wallet's private key, and broadcast to the Bitcoin mempool. If you configured payout_method: wallet, the funds arrive at your address; if you configured QvaPay or Zelle, they arrive at TronDealer custody (which already credited your balance in step 5).
After the successful sweep broadcast, we send transaction.swept with the sweep's on-chain hash, the net amount, the applied commission, and the destination. Useful for accounting reconciliation.