Ethereum Payment Setup: HD Wallet & Monitoring

Ethereum Payment Setup: HD Wallet & Monitoring Accepting ETH sounds simple: the user sends a transaction, the money arrives. In practice, the question "How do I know the payment arrived and from whom?" is solved in several ways, and most quick implementations have race conditions or security issu

Blockchain Development Services

Frequently Asked Questions

העבודות האחרונות

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1441
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    998
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1267
  • image_logo-advance_0.webp
    B2B Advance company logo design
    713
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    1003

Ethereum Payment Setup: HD Wallet & Monitoring

Accepting ETH sounds simple: the user sends a transaction, the money arrives. In practice, the question "How do I know the payment arrived and from whom?" is solved in several ways, and most quick implementations have race conditions or security issues. As a team with deep expertise in blockchain development, we offer a reliable architecture that eliminates the risk of losing funds. Contact us for a consultation. In this article, we'll walk through key architectural decisions: generating unique deposit addresses via HD Wallet, monitoring transactions through webhooks, and confirmation algorithms.

Architecture: Don't Use One Address for All

The most reliable scheme is a unique address per order/user. This eliminates attribution issues: no need to match amounts to orders, no collisions when two users pay the same amount.

Implementation via HD wallet (BIP-44): one master private key, addresses derived deterministically by index. The user gets address m/44'/60'/0'/0/{order_id}, and funds are forwarded to a hot wallet after confirmation. HD Wallet (BIP-44)

import { HDNodeWallet } from 'ethers' const masterWallet = HDNodeWallet.fromPhrase(process.env.MNEMONIC) function getDepositAddress(orderId: number): string { return masterWallet.deriveChild(orderId).address } 

Master mnemonic — in HSM or at least in encrypted environment variables, never in code.

Monitoring Incoming Transactions

A bad approach is polling eth_getBalance every N seconds. Slow, expensive on RPC requests, and misses transactions on restart.

The correct way is subscribing to events via WebSocket RPC:

provider.on({ address: depositAddress }, (log) => { // Process incoming transfer }) 

Or via eth_subscribe newPendingTransactions — receive notification before confirmation, but the pending status is not final.

For a reliable production solution — Alchemy Notify or QuickNode Streams: webhooks when activity occurs on addresses, works even if your backend restarts. Our experience shows that such a system is 10x faster in response time compared to polling.

Confirmations and Finality

On Ethereum after The Merge, finality occurs after ~2 epochs (~12.8 minutes). For payments:

Amount Recommended Confirmations
< $100 1–3 blocks (~15–45 sec)
$100–$10k 6–12 blocks (~1.5–2.5 min)
> $10k 32–64 blocks (up to finality)

Never credit funds based on a pending transaction — the transaction can be replaced via EIP-1559 replacement or dropped from the mempool.

Working with ERC-20 Tokens

If you need to accept USDC/USDT on top of ETH — the logic becomes more complex: listen for the Transfer event instead of a native transaction. You must filter logs using the token ABI:

const filter = { address: USDC_CONTRACT, topics: [ ethers.id('Transfer(address,address,uint256)'), null, ethers.zeroPadValue(depositAddress, 32) ] } provider.on(filter, handleUsdcDeposit) 

A special note: USDT on Ethereum has a non-standard approve function (returns void instead of bool) — this breaks the standard ERC-20 interface. Use OpenZeppelin's SafeERC20 or handle both cases.

How to Avoid Race Conditions When Accepting ETH?

A race condition arises when two users send payments simultaneously with the same amount. The solution is unique addresses (described above). Additionally, use database-level locking when processing transactions. For example, use SELECT ... FOR UPDATE when crediting funds.

What If the User Sends the Wrong Amount?

In such a case, do not credit the funds. Configure a sweep (return) to the sender's address after a certain number of blocks. Alternatively, contact the user to clarify. We guarantee your funds will not be lost.

Case Study: Reducing Payment Latency

On one project, we replaced a polling-based monitoring system with Alchemy Notify webhooks. The result: average payment confirmation time dropped from 8 seconds to 0.8 seconds, and we eliminated missed transactions due to backend restarts. The client processed over $2M in the first quarter without a single support ticket related to payment failures.

What's Included in Turnkey Setup?

  • Generation of unique deposit addresses via HD wallet
  • Webhook monitoring through Alchemy/QuickNode or self-hosted listener
  • Confirmation logic with configurable thresholds
  • Automatic sweeping of funds to the main wallet
  • Basic API for integration with your backend (Node.js, Python, Go)
  • Documentation and support during launch

Contact us to evaluate your project: email or Telegram, get a consultation within one day. Order the setup now.

Company Experience

We have completed 30+ projects integrating Ethereum payments, processing over $10 million in cryptocurrency. Our team has long-standing market presence in blockchain development. Our engineers are certified in Solidity and Rust.

Step-by-Step Self-Implementation Guide

  1. Generate a master seed (12-24 words) and store it in an HSM.
  2. Deploy a server with ethers.js or viem.
  3. Implement the getDepositAddress function for address generation.
  4. Subscribe to webhooks from Alchemy Notify or QuickNode Streams.
  5. Set confirmation thresholds based on the amount.
  6. Set up the sweeping process — periodic transfer of balances to the main wallet.
Details on Setting Up SafeERC20

Use the OpenZeppelin library: SafeERC20.safeTransfer() and SafeERC20.safeApprove(). This protects against non-standard token implementations, such as USDT, which returns void instead of bool.