Case study · Crypto trading

BlocksMaples: a P2P crypto trading platform with USDT escrow

On BlocksMaples, people who don't know each other trade emerging tokens for USDT on BNB Smart Chain. The platform holds the buyer's USDT in escrow until the seller proves delivery and the buyer confirms it. Then an admin settles the trade. We built the API, the web app, the iOS and Android app and the admin back office, in English, Korean and Chinese.

Evidence: Named client. Status: In production.See the drawing 

Visit live site: blocksmaples.com , opens in a new tabLive · checked 26 Sep 2026

Named client: client work shown by name, with the client's permission.In production: we've confirmed it's live. We show the date we checked.

Sheet
W-01 The money path
Client
BlocksMaples
Live at
blocksmaples.com
Industry
Peer-to-peer crypto trading
Engagement
Built Jun–Jul 2026
Evidence
Named client
Status
In production
Stack
BNB Smart Chain (USDT, BEP-20) · Node.js + Express · PostgreSQL + Prisma · Next.js · React Native (Expo) · ethers.js

The problem

BlocksMaples wanted a place where people trade new tokens directly with each other, settled in USDT. Strangers don't trust each other, so every trade needed escrow. Traders needed identity checks, merchant ads, referrals and live support. The people running the platform needed a full back office. All of it had to work on web and mobile, in three languages.

The technical crux was money. Deposits and withdrawals are real USDT on a public chain. A mistake in how the platform credits a deposit or pays out a withdrawal is a loss, not a bug report.

Engineer view

Custodial model: users hold balances in the platform's ledger. Each user gets an HD-derived deposit address on BNB Smart Chain. Payouts come from a hot wallet signed by a separate worker process.

Constraints

  • Real money on a public chain: USDT on BNB Smart Chain.
  • Two parties who don't trust each other, and a platform in the middle holding the funds.
  • Identity checks (KYC), reviewed by a person in the back office.
  • Three languages across web and mobile: English, Korean and Chinese.
  • API, web, mobile and admin built together, Jun–Jul 2026.

How we built it

The design rests on one goal, written into its security guide: even if someone breaks into the part of the system that faces the internet, they can't move funds.

W-01The money path

Evidence: Named client. Status: In production.Redrawn; details changed to protect the client

The money path, from a user's request to the chain.

  1. The public API can't sign anything.No private key in the API process; deposit addresses derived from a public xpub.
  2. Withdrawals wait in a queue for a separate signer.Signing request row; workers re-validate, sign, broadcast. The API never signs.
  3. Deposits count only after we check the chain ourselves.Webhook signature + on-chain receipt check; amount read from the chain; single atomic credit.
  4. Seven checks stand between a request and a payout.Validation · 24 h cap · email code · guarded debit · signer isolation · manual approval · 15 attempts/h.
  5. A stolen sign-in gets shut out.Rotating refresh tokens; reuse revokes the token family; per-device revocation.

Key decisions

Decision 1

Keep signing keys out of the public API

Decision
The internet-facing API holds no signing keys. It can only queue a withdrawal. A separate worker process, which the internet can't reach, checks the request again, signs it and sends it to the chain.
Alternative
Sign inside the API. One process, simpler to deploy.
Why
Then one break-in at the API would expose the keys. With the split, the API can ask for a payout but can't make one.
Engineer view

The API derives per-user deposit addresses from a public xpub, so it never needs a private key. Confirming a withdrawal writes a signing request to the database. The wallet workers re-validate it, sign and broadcast. The signer can run on AWS KMS, a dedicated hot-wallet key or a seed fallback, chosen by configuration.

Decision 2

Credit deposits from the chain, not from the notification

Decision
A deposit notification only starts the process. Before any balance changes, a worker reads the transaction from the chain itself and checks it.
Alternative
Trust the notification service and credit the amount it reports.
Why
A notification can be forged, replayed or wrong. The chain is the record.
Engineer view

Gate 1: the webhook signature is verified. Gate 2: the worker fetches the receipt and requires a successful transaction, a real USDT Transfer to the user's deposit address, and enough confirmations counted from the chain, not from the webhook. The credited amount is read from the chain. Credit is claimed atomically (pending → confirmed), so a deposit can't be credited twice.

Decision 3

Layer the withdrawal checks

Decision
Seven separate controls sit between a withdrawal request and a signed transaction.
Alternative
One strong check, such as a one-time code, and trust the rest of the path.
Why
Each control covers a different failure: a stolen session, two requests racing each other, an unusually large amount, a compromised API.
Engineer view

(1) input validation; (2) a rolling 24-hour cap per user; (3) a one-time code sent to the account email, which a stolen session token can't produce; (4) an atomic guarded debit, so two requests can't overdraw the balance; (5) signer isolation (Decision 1); (6) optional manual approval above a set amount; (7) a limit of 15 withdrawal attempts per hour. Withdrawals that fail before broadcast are refunded automatically.

Escrow lives in the platform's ledger. When a trade opens, the buyer's USDT is locked. The seller delivers the tokens and uploads proof, the buyer confirms receipt, and an admin approves the settlement. If the seller misses the delivery window, the buyer gets the USDT back. Sign-in tokens rotate on every refresh. If an old one is replayed, the platform treats it as stolen and ends that session.

Engineer view

Escrow is a ledger lock on the buyer's USDT balance (availableUsdt → lockedUsdt). It is released to the seller only after the buyer confirms and an admin approves the trade. An overdue delivery refunds the buyer; an overdue confirmation goes to admin review. Sessions use short-lived access tokens and rotating refresh tokens; reuse of a spent refresh token revokes its whole token family. Per-device revocation and a per-user token-version kill switch cover logout-everywhere.

Screens

The BlocksMaples landing page: “The Premier P2P Marketplace for Emerging Tokens”, with an email sign-up and the start of the live market table.
The landing page, with sign-up and the live market below.
The BlocksMaples “How it works” section: a phone showing the P2P buy screen beside three steps: complete KYC, deposit USDT (BEP-20), trade with escrow.
Three steps for a new trader: identity check, a USDT deposit, then a trade in escrow.
The BlocksMaples landing page on a phone, with the headline and the sign-up form.
The same page on a phone.

Captured from the live site on 26 Sep 2026. The words on these pages are BlocksMaples' own.

What we delivered

  • The APIAccounts, identity checks, wallets, trades, merchant ads, referrals, support, notifications and admin, on 24 data models.
  • Wallet workersIn their own process: deposit confirmation, withdrawal signing and sweeps.
  • The web app38 routes per language, 13 of them for admin.
  • The iOS and Android app35 screens, including trading, assets, identity checks, referrals, support chat, device management and biometric unlock.
  • The admin back officeUsers, per-user wallets, identity review, merchants, coins, referrals, tickets, trades, reports and an activity log.
  • Live support chatBetween users and the support team.
  • A deploy pipelineFrom GitHub Actions to AWS.
  • A security and deployment guideThe trust boundary, each control, key-management setup, a runbook and a hardening checklist. Your next engineer should be able to read the system rather than reverse-engineer it.
  • App-store preparationAn in-app account-deletion flow and a reviewer account.

Not included: an automated test suite. See “What we'd do differently”.

Result

In productionThe web platform is live at blocksmaples.com, checked 26 Sep 2026. We make no claim about app-store listings.

3apps (API, web, iOS/Android)
English, Korean and Chinese
38web routes per language, 13 of them admin
35mobile screens
24data models

No user, volume or revenue numbers. They belong to the client, and we don't publish them.

Building something similar?

A P2P or OTC venue, a wallet flow, a multilingual app? Tell us what you're planning, and we'll sketch how we'd build it on the call.

Or message us:WhatsApp, opens in a new tab

WhatsApp: