Skip to content

Fund Sweeping

Fund sweeping is the process of moving confirmed USDT from individual payment addresses to your hot wallet. PayWarden automates this entirely.

Why sweeping is needed

Each order uses a unique payment address. After confirmation, USDT sits at that address. Sweeping consolidates funds to your HOT_WALLET_ADDRESS so you can:

  • Access your revenue in one place
  • Avoid managing hundreds of individual addresses
  • Free up address indices for reuse tracking

How it works

Order confirmed


[BullMQ delayed job created]  ← 5 min delay (configurable)


Gas Manager: check TRX balance at payment address

      ├── TRX balance < threshold?
      │         │
      │         ▼
      │   Send TRX from hot wallet to cover gas
      │         │
      │         ▼
      │   Wait for TRX confirmation (~9s)


Fund Sweeper: sign USDT transfer

      ├── Derive private key for address index
      ├── Build TRC-20 transfer transaction
      ├── Sign with private key
      ├── privateKey.fill(0)  ← wipe immediately
      ├── Broadcast to TronGrid


Wait for sweep confirmation


Mark address as swept in DB
Address index retired

Gas management

TRC-20 transfers on TRON require TRX to pay for bandwidth/energy. Payment addresses receive USDT only — they have no TRX.

Before sweeping, the Gas Manager automatically:

  1. Checks the TRX balance of the payment address
  2. If below threshold, transfers enough TRX from your hot wallet
  3. Waits for the TRX transfer to confirm
  4. Then proceeds with the USDT sweep

Your hot wallet must maintain a sufficient TRX balance. The admin dashboard shows a low-balance warning when it drops below GAS_LOW_THRESHOLD.

Configuration

dotenv
HOT_WALLET_ADDRESS=TXxx...        # destination for swept funds
SWEEP_DELAY_MINUTES=5             # delay after confirmation before sweep
GAS_RESERVE_TRX=5                 # TRX to send per payment address
GAS_LOW_THRESHOLD=100             # alert when hot wallet TRX < this

Sweep modes

Mode A — TRX burn (default)

Send TRX to the payment address to cover gas, then sweep USDT. Simple and reliable, works for any address.

Typical cost: ~5–10 TRX per sweep (~$0.50–1.00 at current prices).

Mode B — Energy delegation (coming in Phase 3B)

Delegate energy from a staked TRX account to payment addresses. Reduces per-sweep gas cost by ~80%. Requires maintaining a staked TRX position.

Monitoring sweeps

The admin dashboard shows:

  • Pending sweeps (confirmed but not yet swept)
  • Sweep history with tx hashes
  • Hot wallet TRX balance
  • Failed sweeps (with error details)

Failed sweeps

If a sweep fails (network error, insufficient TRX, etc.), BullMQ retries automatically with backoff. After 5 failures, the job is marked as failed and appears in the admin dashboard for manual review.

To manually trigger a sweep:

bash
# Coming in v1.1: manual sweep command
docker compose exec app node dist/scripts/sweep.js --order-id ord_abc123

Security

Private keys exist in memory only during the signing step, for milliseconds:

typescript
const privateKey = derivePrivateKey(mnemonic, index)
const signedTx = signTransaction(tx, privateKey)
privateKey.fill(0)  // immediately overwritten with zeros
await broadcastTransaction(signedTx)

The mnemonic is decrypted from vault.enc at startup and held in memory for the lifetime of the process. If this concerns you, consider running the sweeper as a separate process with its own vault access pattern.

Released under the BSL 1.1 License.