Ethereum ETH Exchange Wallet Development - Step 5: Generating Deposit Addresses

·

Introduction to Secure Deposit Address Management

In modern cryptocurrency exchange infrastructure, securely generating and managing deposit addresses is a critical component. This article walks you through the process of building a robust system for Ethereum (ETH) deposit address allocation, focusing on secure API design, request validation, and cryptographic signature verification. Whether you're developing a wallet backend or integrating blockchain functionality into a financial application, this guide provides actionable insights into creating a production-ready service.

The core challenge lies not only in generating valid Ethereum addresses but also in ensuring that every interaction with your system is authenticated, tamper-proof, and scalable. We’ll explore how to implement secure RESTful APIs using Go and Gin, validate incoming requests, and protect against unauthorized access using digital signatures.


Validating Incoming API Requests

Once basic wallet functionality is in place, the next step is exposing services securely via RESTful APIs. Given that these endpoints handle sensitive financial operations, request validation is essential.

We use the gin framework to build a high-performance HTTP server. Every incoming request must be authenticated and verified to prevent abuse or fraudulent address generation.

A typical request body includes the following required fields:

var req struct {
    AppName string `json:"app_name" binding:"required"`
    Nonce   string `json:"nonce" binding:"required" validate:"max=40"`
    Sign    string `json:"sign" binding:"required"`
}

👉 Discover how leading platforms secure their blockchain transactions with advanced API authentication.

To map app_name to a real application, we store credentials in a database table called t_product. This allows us to retrieve the app-specific secret key (app_sk) used during signature verification.

Database Schema: t_product

CREATE TABLE `t_product` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `app_name` varchar(128) NOT NULL DEFAULT '' COMMENT 'Application name',
  `app_sk` varchar(64) NOT NULL DEFAULT '' COMMENT 'Application secret key',
  `cb_url` varchar(512) NOT NULL COMMENT 'Callback URL',
  `whitelist_ip` varchar(1024) NOT NULL DEFAULT '' COMMENT 'Whitelisted IPs',
  PRIMARY KEY (`id`),
  UNIQUE KEY `app_name` (`app_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

This schema supports:


Signature Verification: Ensuring Request Integrity

To ensure that each API call comes from an authorized source, we implement a secure signing mechanism based on a method similar to WeChat Pay's signature algorithm. This approach guarantees data integrity and origin authenticity.

Step-by-Step Signature Generation

  1. Collect Parameters: Gather all non-empty parameters from the request (excluding the sign field itself).
  2. Sort by ASCII Key Order: Sort the parameters lexicographically by their keys.
  3. Build StringA: Concatenate the sorted key-value pairs in key=value&key2=value2 format.
  4. Append Secret Key: Append &key=app_sk to form stringSignTemp.
  5. Hash and Uppercase: Apply MD5 hashing and convert the result to uppercase — this is your final sign.
🔐 The nonce parameter ensures unpredictability. Even if an attacker intercepts a valid request, they cannot reuse it due to the one-time nature of the nonce.

Example: Generating a Valid Signature

Suppose the incoming parameters are:

Step 1: Sort and Build StringA

stringA = "app_name=wxd930ea5d5a258f4f&nonce=ibuaiVcKdpRxkhJA"

Step 2: Append Key and Hash
Assume the platform’s secret key is: 192006250b4c09247ec02edce69f6a2d

stringSignTemp = stringA + "&key=192006250b4c09247ec02edce69f6a2d"
sign = MD5(stringSignTemp).ToUpper() = "30A40459EB96131C493486D8013C5D96"

The resulting signature is sent with the request and validated server-side before any action is taken.

This method supports future extensibility — new fields can be added without breaking existing implementations, as long as they're included in the signature calculation.


Core Functionality: Fetching Deposit Addresses

Now that we’ve secured our API layer, let’s focus on the primary business logic: allocating deposit addresses to users.

Each user or application should receive a unique Ethereum address for receiving funds. To manage this efficiently, we maintain a pool of pre-generated addresses in the database.

Address Pool Structure

idaddressused_flag
10x1-1
20x20
30x30
40x40

When a valid request arrives:

  1. Begin a database transaction.
  2. Select the first available address where used_flag = 0.
  3. Update its used_flag to the requesting app’s product.id.
  4. Commit the transaction.
  5. Return the assigned address to the client.

This ensures atomicity — no race conditions occur even under high concurrency, and each address is assigned exactly once.

👉 See how top-tier exchanges handle atomic address allocation at scale.


Implementation Overview

The full implementation is open-sourced on GitHub (code reference removed per guidelines), with the main entry point located at cmd/api/main.go. It demonstrates:

While we won’t reproduce the full code here, key components include:


Frequently Asked Questions (FAQ)

Q: Why use MD5 instead of SHA-256 for signing?
A: While SHA-256 is cryptographically stronger, MD5 is still acceptable here when combined with a secret key and nonce. However, for new systems, consider upgrading to HMAC-SHA256 for better security.

Q: How do I prevent IP spoofing?
A: Use the whitelist_ip field in t_product to restrict API access by source IP. Combine this with HTTPS and rate limiting for enhanced protection.

Q: Can multiple apps share the same deposit address?
A: No. Each deposit address must be uniquely assigned to avoid fund attribution errors. Sharing addresses breaks accounting isolation.

Q: What happens if two requests arrive simultaneously?
A: Database transactions ensure serializable execution. Only one request will successfully claim an available address.

Q: How often should I rotate the app_sk (secret key)?
A: Rotate keys periodically (e.g., quarterly) or immediately if compromised. Ensure zero-downtime key rotation by supporting dual keys during transition.

Q: Is it safe to expose deposit addresses publicly?
A: Yes. Ethereum deposit addresses are designed to be public. However, never expose private keys or seed phrases.


Final Thoughts and Best Practices

Building a secure ETH exchange wallet backend requires more than just blockchain integration — it demands attention to authentication, data integrity, and operational reliability.

By implementing strong signature validation, maintaining a clean separation between available and assigned addresses, and leveraging database transactions, you create a foundation that scales securely.

As your platform grows, consider adding:

👉 Explore enterprise-grade tools for managing multi-chain deposit systems securely.

With these practices in place, your system will not only resist common attacks but also provide a reliable experience for developers and end users alike.


Core Keywords: