Deposit Monitoring
Automatically detect and track incoming transactions to your customer wallet addresses across all supported networks.
Overview
The Wallet Service includes built-in deposit monitoring that watches blockchain addresses for incoming native token deposits (BNB, ETH, MATIC, TRX, SOL) and sends webhooks to your application instantly when deposits are detected.
You Control Balance Management
This is a notification-only service. We detect deposits and send webhooks - you manage your own internal balances. This architecture gives you complete control over your accounting and balance tracking.
How It Works
Key Points:
- 🔍 Automatic Monitoring - No polling needed from your side
- ⚡ 30-Second Intervals - Fast deposit detection
- 🌐 5 Networks Supported - BSC, Ethereum, Polygon, Tron, Solana
- 💰 Native Tokens Only - BNB, ETH, MATIC, TRX, SOL (not ERC-20 tokens)
- 📡 Webhook Notifications - HMAC-signed webhooks sent instantly
- 🎯 You Control Balances - We detect, you manage
Supported Networks
| Network | Native Token | Monitored | Decimals |
|---|---|---|---|
| BSC | BNB | ✅ | 18 |
| Ethereum | ETH | ✅ | 18 |
| Polygon | MATIC (POL) | ✅ | 18 |
| Tron | TRX | ✅ | 6 |
| Solana | SOL | ✅ | 9 |
Why Native Tokens Only?
Monitoring focuses on native tokens because:
- Most common for wallet deposits
- Simpler balance checking (no token contract calls)
- Lower RPC overhead
- For ERC-20 monitoring, use our Crypto Gateway product instead
Enable Monitoring on Address
When deriving an address, set the monitored flag to true:
async function deriveMonitoredAddress(customerId, network) {
const response = await axios.post(
`https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/customer/${customerId}/derive`,
{
network: network, // BTC, ETH, BSC, POL, TRX, SOL
index: 0,
monitored: true // ← Enable automatic deposit monitoring
},
{
headers: {
'X-API-Key': process.env.RACH_API_KEY,
'Content-Type': 'application/json'
}
}
);
return response.data;
}
// Create monitored addresses for common networks
const bscAddr = await deriveMonitoredAddress('user_123', 'BSC');
const ethAddr = await deriveMonitoredAddress('user_123', 'ETH');
const polAddr = await deriveMonitoredAddress('user_123', 'POL');def derive_monitored_address(customer_id, network):
"""Derive an address with monitoring enabled"""
url = f'https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/customer/{customer_id}/derive'
payload = {
'network': network,
'index': 0,
'monitored': True # ← Enable monitoring
}
headers = {
'X-API-Key': os.getenv('RACH_API_KEY'),
'Content-Type': 'application/json'
}
response = requests.post(url, json=payload, headers=headers)
response.raise_for_status()
return response.json()
# Create monitored addresses
bsc = derive_monitored_address('user_123', 'BSC')
eth = derive_monitored_address('user_123', 'ETH')
pol = derive_monitored_address('user_123', 'POL')function deriveMonitoredAddress($customerId, $network) {
$apiKey = getenv('RACH_API_KEY');
$payload = [
'network' => $network,
'index' => 0,
'monitored' => true // ← Enable monitoring
];
$url = "https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/customer/{$customerId}/derive";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: ' . $apiKey,
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
// Enable monitoring
$bscAddr = deriveMonitoredAddress('user_123', 'BSC');Configure Webhook URL
Set your webhook endpoint to receive deposit notifications:
curl -X PATCH https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/business/settings \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://yourapp.com/webhooks/deposits",
"webhook_secret": "your_secret_key_here"
}'Generate a Strong Secret
# Generate a random webhook secret
openssl rand -hex 32Save this secret securely - you'll use it to verify webhook signatures.
Webhook Event: wallet.deposit.detected
When a deposit is detected, you'll receive this webhook:
Payload Structure
{
"event": "wallet.deposit.detected",
"data": {
"customer_id": "user_123",
"network": "BSC",
"address": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"amount": "1.5",
"currency": "BNB",
"tx_hash": "pending_detection",
"confirmations": 0,
"detected_at": "2025-12-22T12:00:00Z"
}
}Field Descriptions
| Field | Type | Description |
|---|---|---|
event | string | Always "wallet.deposit.detected" |
customer_id | string | Your customer identifier |
network | string | Network where deposit occurred |
address | string | Wallet address that received funds |
amount | string | Amount receivedas decimal string |
currency | string | Native token symbol (BNB, ETH, etc.) |
tx_hash | string | Transaction hash (may be "pending_detection" initially) |
confirmations | integer | Number of confirmations (usually 0 when detected) |
detected_at | timestamp | When deposit was detected (ISO 8601) |
Handle Webhook in Your App
Create an endpoint to receive and process deposit webhooks:
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
app.post('/webhooks/deposits', async (req, res) => {
// 1. Verify HMAC signature
const signature = req.headers['x-webhook-signature'];
const secret = process.env.WEBHOOK_SECRET;
const hmac = crypto.createHmac('sha256', secret);
hmac.update(JSON.stringify(req.body));
const expectedSignature = hmac.digest('hex');
if (signature !== expectedSignature) {
return res.status(401).send('Invalid signature');
}
// 2. Extract deposit data
const { event, data } = req.body;
if (event === 'wallet.deposit.detected') {
const { customer_id, network, address, amount, currency } = data;
// 3. Update YOUR database
await db.query(`
UPDATE user_balances
SET ${currency.toLowerCase()}_balance = ${currency.toLowerCase()}_balance + $1,
updated_at = NOW()
WHERE customer_id = $2
`, [parseFloat(amount), customer_id]);
// 4. Create transaction record
await db.query(`
INSERT INTO transactions (customer_id, type, network, amount, currency, address, created_at)
VALUES ($1, 'deposit', $2, $3, $4, $5, NOW())
`, [customer_id, network, amount, currency, address]);
// 5. Notify user (optional)
await sendDepositNotification(customer_id, amount, currency);
console.log(`✅ Deposit credited: ${amount} ${currency} for ${customer_id}`);
}
// 6. Return 200 OK
res.status(200).send('Webhook processed');
});
function sendDepositNotification(customerId, amount, currency) {
// Send email/push notification to user
// "You received ${amount} ${currency}"
}from flask import Flask, request, jsonify
import hmac
import hashlib
import json
import os
from decimal import Decimal
app = Flask(__name__)
@app.route('/webhooks/deposits', methods=['POST'])
def handle_deposit_webhook():
# 1. Verify signature
signature = request.headers.get('X-Webhook-Signature')
secret = os.getenv('WEBHOOK_SECRET')
payload = request.get_json()
expected_signature = hmac.new(
secret.encode(),
json.dumps(payload).encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected_signature):
return jsonify({'error': 'Invalid signature'}), 401
# 2. Extract data
event = payload.get('event')
data = payload.get('data', {})
if event == 'wallet.deposit.detected':
customer_id = data['customer_id']
network = data['network']
address = data['address']
amount = Decimal(data['amount'])
currency = data['currency']
# 3. Update YOUR database
db.execute(f"""
UPDATE user_balances
SET {currency.lower()}_balance = {currency.lower()}_balance + %s,
updated_at = NOW()
WHERE customer_id = %s
""", (amount, customer_id))
# 4. Record transaction
db.execute("""
INSERT INTO transactions
(customer_id, type, network, amount, currency, address, created_at)
VALUES (%s, 'deposit', %s, %s, %s, %s, NOW())
""", (customer_id, network, amount, currency, address))
# 5. Notify user
send_deposit_notification(customer_id, amount, currency)
print(f"✅ Deposit credited: {amount} {currency} for {customer_id}")
return jsonify({'success': True}), 200Important: You Manage Balances
Critical Implementation Note
The monitoring service ONLY sends webhooks - it does NOT update any internal balances.
Your Responsibilities:
- ✅ Store and manage user balances in YOUR database
- ✅ Update balances when webhook received
- ✅ Handle double-spending/duplicate webhooks (idempotency)
- ✅ Maintain transaction history
- ✅ Display balances to users
Rach's Responsibilities:
- ✅ Monitor blockchain addresses
- ✅ Detect balance changes
- ✅ Send webhook notifications
- ✅ Retry failed webhooks
Why This Architecture?
This design gives you:
- 🎯 Full Control - You own the balance logic
- 🔒 Security - No external service can modify your balances
- 🔄 Flexibility - Implement custom logic (fees, bonuses, etc.)
- 📊 Compliance - Your accounting, your audit trail
Example Integration Flow
// 1. User signup - Create wallet
const wallet = await createWallet('user_123');
// 2. Derive monitored addresses
const addresses = await Promise.all([
deriveMonitoredAddress('user_123', 'BSC'),
deriveMonitoredAddress('user_123', 'ETH'),
deriveMonitoredAddress('user_123', 'POL')
]);
// 3. Save addresses to YOUR database
await db.addresses.insertMany(addresses.map(addr => ({
user_id: 'user_123',
network: addr.network,
address: addr.address,
monitored: true
})));
// 4. Initialize balances in YOUR database
await db.balances.create({
user_id: 'user_123',
bnb_balance: 0,
eth_balance: 0,
matic_balance: 0
});
// 5. Display addresses to user
// User sends crypto to any address
// 6. Webhook arrives (within 30 seconds)
// Your webhook handler updates YOUR balance
// 7. User sees updated balance in your appTesting
1. Enable Test Mode
// Derive address on testnet
const testAddr = await axios.post(
`https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/customer/user_123/derive`,
{
network: 'BSC',
index: 0,
testnet: true, // ← Use testnet
monitored: true
},
{ headers: { 'X-API-Key': process.env.RACH_TEST_API_KEY } }
);2. Send Test Deposit
Send testnet tokens to the address:
- BSC Testnet: Get free tBNB from BSC Faucet
- ETH Sepolia: Get SepoliaETH from Sepolia Faucet
- Polygon Amoy: Get MATIC from Polygon Faucet
3. Verify Webhook Delivery
Check your webhook endpoint logs within 30-60 seconds.
Monitoring Status
Check which addresses are being monitored:
curl https://payments-api-dev-966260606560.europe-west2.run.app/api/v1/wallet/customer/user_123/addresses \
-H "X-API-Key: YOUR_API_KEY"Response includes monitored flag:
{
"addresses": [
{
"network": "BSC",
"address": "0x...",
"monitored": true, // ← Monitoring enabled
"total_received": "2.5" // Total deposits received
}
]
}FAQ
Q: What tokens are monitored?
A: Only native tokens (BNB, ETH, MATIC, TRX, SOL). For ERC-20/BEP-20 tokens like USDT, use our Crypto Gateway product.
Q: How fast are deposits detected?
A: Typically within 30-60 seconds of blockchain confirmation.
Q: Do you update user balances automatically?
A: NO. We only send webhooks. You must update your own database balances.
Q: What if my webhook endpoint is down?
A: We retry up to 5 times with exponential backoff over ~8 minutes.
Q: Can I monitor multiple addresses per user?
A: Yes! Derive multiple addresses with different index values, all with monitored: true.
Q: Is there a fee for monitoring?
A: No additional fees. Monitoring is included with the Wallet Service.
Q: What about transaction confirmations?
A: Initial webhook sent at detection (0 confirmations). You can implement your own confirmation delay logic based on the network.
Best Practices
Production Recommendations
- Idempotency - Store
detected_attimestamp and ignore duplicate webhooks - Async Processing - Use a queue (Redis, RabbitMQ) to process webhooks
- Database Transactions - Use DB transactions when updating balances
- Logging - Log all webhooks for audit trail
- Alerting - Monitor for failed webhook deliveries
- Security - Always verify HMAC signatures
- Balance Reconciliation - Periodic on-chain balance checks
Next Steps
- Webhook Signatures - HMAC verification guide
- Integration Guide - Complete wallet setup
- Security - Best practices
- API Reference - Full API documentation
