Blockchain Centralized Wallet Development: Architecture & Implementation Insights

·

Building a blockchain-based centralized wallet is a complex yet rewarding engineering challenge—especially when aiming to bridge digital currencies with real-world usability. This article dives into the architecture and implementation details of a lightweight blockchain wallet developed in late 2016, designed to support Bitcoin and Ethereum-based token transfers with a vision of enabling seamless offline cryptocurrency payments. While some technical approaches may have evolved since then, the foundational concepts remain highly relevant for modern wallet development.

The system described here leverages Ruby on Rails 5 as the backend API layer, integrates full blockchain nodes via JSON-RPC, and uses message queues and background jobs to ensure reliability and responsiveness. Whether you're exploring blockchain wallet development, designing secure cryptocurrency transaction systems, or studying centralized wallet architecture, this guide offers practical insights grounded in real-world implementation.


System Architecture Overview

At its core, the wallet operates as a centralized service that interacts with blockchain networks through dedicated full nodes. The backend is built using Rails 5, exposing a RESTful API to mobile and web clients. This design ensures clean separation between frontend interfaces and blockchain logic.

Two primary blockchain clients are used:

Both are controlled via JSON-RPC:

To monitor on-chain activity, such as incoming deposits, the system employs RabbitMQ as a message queue. Scripts running on the node servers listen for address events and push notifications into the queue whenever funds are received. This event-driven approach decouples blockchain monitoring from business logic processing, improving scalability and fault tolerance.

👉 Discover how leading platforms securely manage blockchain interactions today.

Additionally, exchange rate data is fetched regularly from external APIs and cached in Redis. A scheduled job updates these rates every minute using Sidekiq-Cron and Active Job, ensuring fast response times for currency conversion requests within the app.

Core Keywords Identified:


Key Functional Modules

The wallet system is organized into three primary modules: user management, blockchain account handling, and transaction processing. Each plays a critical role in delivering a secure and functional experience.

User Information Module

User authentication combines Clearance for basic sign-up and login flows with Ruby-JWT (JSON Web Tokens) for stateless session management. The ApplicationController includes a before_action filter to authenticate each request:

before_action :authenticate_request!

def authenticate_request!
  begin
    fail NotAuthenticatedError unless user_id_included_in_auth_token?
    @current_user = User.find(decoded_auth_token[:user_id])
  rescue JWT::ExpiredSignature
    raise AuthenticationTimeoutError
  rescue JWT::VerificationError, JWT::DecodeError
    raise NotAuthenticatedError
  end
end

This JWT-based approach enables secure, scalable authentication across distributed services—ideal for mobile apps and microservices.

For profile management, Paperclip handles avatar uploads. User avatars are stored with hashed URLs and multiple image styles (e.g., thumb, medium), enhancing performance and security.

SMS verification is powered by an external service (originally Yunpian), abstracted through a custom sms gem. Upon registration or phone binding, the system sends a verification code and stores it securely with the user’s phone record.


Blockchain Account Module

Each user can open accounts for different cryptocurrencies—primarily Bitcoin and Ethereum-based tokens. The data model uses Single Table Inheritance (STI) in Rails:

When an account is created, an after_create callback generates a corresponding blockchain address. But instead of storing the address directly in the account table, a separate Address model is used—with STI supporting two types:

This separation allows users to register multiple withdrawal destinations while maintaining a single deposit address per currency.

👉 See how modern wallets streamline multi-address management securely.


Exchange Rate Management

Real-time fiat-to-crypto conversion is essential for usability. The system retrieves exchange rates from third-party providers (e.g., CoinMarketCap or exchange APIs) at regular intervals. To avoid latency during user requests, all rate data is cached in Redis.

The process involves two steps:

  1. Fetch raw exchange rates (e.g., BTC/USD, ETH/EUR)
  2. Normalize all values to a default fiat currency (e.g., CNY or USD)

Using Sidekiq-Cron, a background job runs every minute to refresh Redis with updated rates. Clients then query the local cache instead of external APIs, reducing load and improving speed.

A dedicated gem, currency_switcher, simplifies currency conversion logic within the application layer.


Cryptocurrency Transaction System

The transaction module forms the heart of any digital wallet. It supports three key operations:

  1. Top-up (Deposit)
  2. Withdrawal
  3. Peer-to-peer Wallet Transfers

Each follows a strict state lifecycle managed via the AASM (Acts As State Machine) gem.

State Management with AASM

Transactions progress through defined states to ensure auditability and consistency:

aasm :column => :state do
  state :canceled
  state :launch
  state :checked
  state :pending
  state :confirmed

  event :cancel do
    transitions from: :launch, to: :canceled
  end

  event :check do
    transitions from: :launch, to: :checked
  end

  event :pend do
    transitions from: [:launch, :checked], to: :pending
  end

  event :confirm do
    transitions from: [:launch, :pending], to: :confirmed
  end
end

This state machine governs both incoming and outgoing transactions.

Deposit Flow

  1. User sends crypto to their assigned deposit address.
  2. Node script detects incoming transaction via walletnotify (Bitcoin) or custom listener (Ethereum).
  3. Message is published to RabbitMQ.
  4. Wallet service consumes message, creates transaction record in launch state.
  5. TXID is stored in Redis.
  6. Background job checks confirmation count periodically.
  7. Once required confirmations are reached (e.g., 6 for Bitcoin), status updates to confirmed.

Withdrawal Flow

  1. User initiates withdrawal to a pre-registered address.
  2. Transaction starts in launch state.
  3. Admin or automated system performs check (fraud/AML screening).
  4. Approved withdrawals move to pending.
  5. Signed transaction is broadcast to the network.
  6. After sufficient confirmations, status becomes confirmed.

Unconfirmed transactions remain visible in the UI with real-time status updates.

Internal Transfers

Wallet-to-wallet transfers occur instantly within the system database—no blockchain confirmation needed. These are labeled as wallet transfers and appear immediately in both sender and receiver histories.


Best Practices & Lessons Learned

While building this system, several key lessons emerged:

Though newer tools like Web3.js, Hardhat, or dedicated wallet SDKs now simplify parts of this workflow, understanding the underlying mechanics remains crucial for debugging and security auditing.

👉 Explore secure transaction handling on advanced blockchain platforms.


Frequently Asked Questions (FAQ)

Q: Is this wallet non-custodial or custodial?
A: This is a custodial (centralized) wallet—the private keys are managed server-side, giving the service control over funds. Users rely on the platform's security and trustworthiness.

Q: How are private keys stored securely?
A: While not detailed in the original post, best practice involves encrypted storage (e.g., using KMS or HSMs), air-gapped signing environments, and strict access controls.

Q: Can this architecture support ERC-20 tokens?
A: Yes—since it uses a Go-Ethereum node, any ERC-20 token can be supported by adding token contract addresses and balance checking logic.

Q: Why use RabbitMQ instead of polling?
A: RabbitMQ enables real-time event processing without constant polling, reducing latency and server load when detecting incoming transactions.

Q: What happens if the blockchain node goes down?
A: The system would fail to process new transactions until connectivity is restored. Redundant nodes and health checks are recommended for production use.

Q: How does this compare to modern DeFi wallets?
A: Unlike non-custodial DeFi wallets (e.g., MetaMask), this solution prioritizes ease of use and centralized control—ideal for beginners but requiring greater trust in the provider.


In summary, developing a centralized blockchain wallet requires careful integration of backend APIs, blockchain nodes, real-time messaging, and financial-grade security practices. Despite being built years ago, this architecture still reflects sound engineering principles applicable to today’s crypto applications.