Skip to main content

Sub-wallet derivation

Use the derive API when your platform needs one unique wallet address per user. Each address is deterministically derived from your merchant xpub at a given index โ€” same index always returns the same address.

This is how platforms like exchanges, savings apps, and payment gateways give every user their own receiving address without creating separate accounts.

Xpub-based, non-custodial

HelaMesh derives addresses using your extended public key (xpub) โ€” no private keys are involved. The address is pure math (xpub + index). HelaMesh cannot sign transactions on your behalf. Sending funds from a derived address must be done by you, using your seed phrase in a wallet you control.

Idempotent by design

Calling POST /v1/wallets/derive with the same index twice returns the same TRON and BSC addresses. Nothing is stored in HelaMesh's database โ€” you own the mapping between your user IDs and HD indexes.

Authenticationโ€‹

All derive endpoints use your secret API key (x-api-key). No OTP required โ€” the API key is the authentication layer for server-to-server calls.

x-api-key: hm_live_โ€ฆ # or hm_test_โ€ฆ
Server-side only

Never expose your secret API key in client-side code. These endpoints are designed for server-to-server use only.


POST /v1/wallets/deriveโ€‹

Derive TRON and BSC addresses at a given HD index.

Bodyโ€‹

FieldTypeRequiredNotes
indexintegeryesNon-negative integer. Map your user ID to an index and store it.

Exampleโ€‹

node.js
const res = await fetch('https://api.helamesh.com/v1/wallets/derive', {
method: 'POST',
headers: {
'x-api-key': process.env.HELAMESH_API_KEY,
'content-type': 'application/json',
},
body: JSON.stringify({ index: 42 }),
});

const wallet = await res.json();
// Store wallet.tron and wallet.bsc against your user

Responseโ€‹

200 OK
{
"index": 42,
"tron": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"bsc": "0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"
}

GET /v1/wallets/derive/:index/balanceโ€‹

Get the current USDT balance at the derived address for a given network.

Query paramsโ€‹

ParamRequiredValues
networkyesTRON or BSC

Exampleโ€‹

const res = await fetch(
'https://api.helamesh.com/v1/wallets/derive/42/balance?network=TRON',
{ headers: { 'x-api-key': process.env.HELAMESH_API_KEY } },
);
const { balance } = await res.json();
console.log(`Balance: ${balance} USDT`);

Responseโ€‹

200 OK
{
"index": 42,
"address": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"network": "TRON",
"balance": "10.50"
}

1. User signs up on your platform
โ†’ POST /v1/wallets/derive { index: user.id }
โ†’ Store { userId, hdIndex, tronAddress, bscAddress } in your DB

2. User wants to deposit
โ†’ Show them their tronAddress or bscAddress (QR code is helpful)
โ†’ HelaMesh fires transfer.confirmed to your webhook when funds arrive
โ†’ Your webhook handler looks up user by hdIndex, credits their balance

3. User wants to withdraw
โ†’ Sign and broadcast the transaction yourself using your seed phrase
โ†’ Use any standard TRON/BSC library (tronweb, ethers.js)
Use webhooks, not polling

When a deposit arrives at a derived address, HelaMesh fires a transfer.confirmed webhook to your endpoint. This is the reliable way to detect deposits โ€” you get notified only after the required confirmation depth, with full deduplication and retry built in. Polling the balance endpoint works for testing but adds latency and wastes API quota in production.