HollaEx®
⚙️ DashboardStart →
  • HollaEx® — The Crypto Exchange Solution
  • ☁️Cloud Operators
    • Launching the Exchange
    • Setting Domain for Cloud Exchanges
    • Easy SMTP for Cloud Exchanges
    • SEO Settings for Cloud Exchanges
      • SEO Advanced Settings
  • ⚙️Operating Your Exchange
    • Operator Control Panel
      • General
      • Users
      • User Profile
      • Assets
      • Markets
      • Stakes
      • Sessions
      • Plugins Apps
      • Trading Fees & Account Tiers
      • Roles
      • Chat
      • Billing
    • Customize Exchange
      • Browser Tools
        • Enter Edit Mode
        • Operator Controls (Visuals)
        • Console
      • Plugins
      • Forked Repo
    • Fiat Controls
      • Initial Setup
      • Setting Up Fiat On/ Off Ramp
      • Editing Deposit & Withdrawal Fees
      • Users Making Fiat Deposit
      • Users Trading With Fiat
      • User Making Fiat Withdrawal
    • Staking
    • OTC Broker
    • P2P
      • P2P Overview
      • P2P Setup
      • P2P Troubleshooting
      • P2P Vendor Flow
    • Smart Chain Trading
    • Assets & Trading Pairs
      • Add New Assets & Trading Pairs
      • Configure Pair Parameters
    • Set up the SMTP Email
      • Set up SMTP with AWS SES
      • Set up SMTP with Mailgun
      • Set up SMTP with SendGrid
      • Test the SMTP with Gmail
    • Enabling reCAPTCHA
    • Email Customization & Audit
    • DeFi Asset Staking Process
  • 🧩Plugins
    • HollaEx Plugins
      • Announcements
      • Bank
      • AWS SNS (Text Messages - SMS)
      • KYC
      • Automatic KYC
      • Messente
      • Advanced Referral
      • CoinMarketCap
      • Guardarian
    • Install Plugins
    • Developing Plugins
      • Development Walkthrough: Hello-Plugin
        • Initialization
        • Configuration
        • Scripting
        • Web View
        • The Final Product & Installation
      • Advanced
        • Initialization
        • Config
        • Server Script
        • Plugin Libraries
        • Web View
        • Final Plugin Product
        • Advanced Tutorial: Using the user meta field
        • Advanced Tutorial: Adding a new database table column
        • Advanced Tutorial: Creating a new database table
      • Simple Wallet Example
      • Web View Development
        • Overview
        • External dependencies
        • Getting started
        • Basic Tutorial: Hello Exchange Plugin web view
        • Advanced Tutorial: KYC Plugin web views
    • Bank Integration
      • Handling Deposits
      • Handling Withdrawals
  • 👷Developers
    • API Guide
      • API Example Scripts
    • Run Dev Mode
    • Build a New Front-end Interface
  • 🧰On-Premise Operators (Advanced Only)
    • On-Premise Exchange Setup
      • Getting Started — Requirements
      • Installation
      • Server Setup
      • Web Setup
      • Production
    • CLI How-Tos
      • Start Exchange
      • Stop Exchange
      • Upgrade Exchange
        • Build and Apply the Code Changes
      • Get Exchange Logs
      • Get a Backup and Restore
      • Exchange Migration
      • Command List
    • Run Exchange on Kubernetes
    • Troubleshooting Guide
  • 🚀Advanced
    • SEO Optimization
    • Nginx
    • Rate Limits
    • Database
      • Upgrade Database
    • Dependencies
    • Contents Delivery Network
      • Cloudflare CDN for HollaEx
      • CloudFront CDN for HollaEx
    • Load Balancer
      • AWS ELB
      • DigitalOcean LB
    • Customize Kubenretes Ingress
    • Exchange Keys
      • Exchange API Keys Troubleshoot
    • HollaEx on non-Linux
      • HollaEx on Windows
      • HollaEx on macOS
    • The Network Tool Library
      • Accessing the Network Tool Library
      • Functions
        • WebSocket
      • Simple Example: Creating a User and Wallet
      • Getting More Interesting: Orders with the Tools
        • Setup: Using the transferAsset function
        • Creating and Monitoring a Sell Order
        • Settling Fees
      • Private HollaEx Network
    • Docker Content Trust (DCT)
    • Revenue Sharing
  • 📦Releases
    • Release Notes
    • Side Notes
  • ➡️External Links
  • Blogs
  • Forum
  • Videos
  • Twitter X
  • Telegram
  • Interactive Demo
  • Discord Community
  • API Documentation
  • Tools Library Documentation
  • Node Library Documentation
  • Plugins Documentation
Powered by GitBook
On this page
  • Phase 1: Receiving Deposit Request from a User
  • Phase 2: User completes deposit
  • Phase 3: Payment service notifies the server of completed deposit
  • Code Example
  1. Plugins
  2. Bank Integration

Handling Deposits

PreviousBank IntegrationNextHandling Withdrawals

Last updated 4 years ago

Phase 1: Receiving Deposit Request from a User

Step 1

The user should send the deposit request to the server. The deposit request should have the currency and amount being transferred.

// Express post endpoint to receive deposit requests
app.post(
    '/plugins/bank/deposit',
    toolsLib.security.verifyBearerTokenExpressMiddleware(['user']),
    (req, res) => {
        ...
    }
);

Step 2

The server creates a unique key (UUID) for the deposit. This UUID will ensure that this transaction occurs only once.

After creating the UUID, the deposit data (amount, currency, user ID, UUID) should be stored on Redis. We recommend setting the UUID as the key. It's also a good idea to give the data an expiry time.

const transferUuid = // generate uuid
const amount, currency = // deposit data from request
const user_id = // ID of user making request

const payload = {
    amount,
		currency,
		user_id
};

// store transfer data on redis with uuid as key
await toolsLib.database.client.setAsync(transferUuid, JSON.stringify(payload));

Step 3

After the deposit is given a UUID and is stored on Redis, the server should then forward the payment request to the payment service. The payment service should receive the amount, currency, and UUID of the requested deposit.

Step 4

Once the request from the server is received, the payment service will prompt the user to complete the payment. This can be handled by the server or by the payment service directly via a redirect.

This step will differ based on which service is used but will ultimately end up with the user being asked to complete the payment.

Phase 2: User completes deposit

Phase 3: Payment service notifies the server of completed deposit

Step 1

Once the user completes the payment, the service will notify the server of the completed payment. The way notifications are handled will depend on the payment service used. This notification should come with the amount and currency of the completed deposit. It should also provide the UUID the server created for this deposit in Phase 1.

// Express post endpoint to receive deposit notifications
// Accepts uuid as path parameter
app.post(
    '/plugins/bank/:uuid',
    (req, res) => {
        ...
    }
);

Step 2

Once the server receives the notification, it should first check Redis to make sure the UUID is valid.

If no data is found on Redis with the received UUID, the deposit should be rejected.

If data is found with the UUID, that data should be deleted from Redis. After deletion, the server should verify that the amount and currency of the deposit received from the payment service matches the ones found on Redis.

If the user paid less than the required amount or used a different currency, the deposit should be rejected.

const uuid = // uuid received in notification
const amount, currency = // deposit data from notification

// get transfer data from Redis using uuid 
const storedDepositData = await toolsLib.database.client.getAsync(uuid);

// if no data found on Redis, reject transfer
if (!storedDepositData) {
    throw err;
}

// Delete data from Redis
await toolsLib.database.client.delAsync(uuid);

// If deposit amount or currency don't match data found on redis, reject transfer
if (
    storedDepositData.amount !== amount
    || storedDepositData.currency !== currency
) {
    throw err;
}

Step 3

Once everything is validated, the server should mint the asset to the user. This completes the deposit flow.

Code Example

For this example, we will use a redirect for prompting the user to complete the payment and receive a notification of the completed payment via a callback URL. The process for both may be different for some payment services but the overall flow should remain the same.

// PHASE 1: RECEIVE DEPOSIT REQUEST FROM USER
app.post('/plugins/bank/deposit', toolsLib.security.verifyBearerTokenExpressMiddleware(['user']), (req, res) => {
	const { currency, amount } = req.body;
	const user_id = req.auth.sub.id;

	// Create UUID for this deposit
	const transactionId = uuid();
	
	// Callback url for payment notification
	const callback_url = `${toolsLib.getKitConfig().info.url}/plugins/bank/${transactionId}`;

	const payload = {
		amount,
		currency,
		callback_url,
		user_id, // user_id added for callback
		expires: moment().add(5, 'minutes') // if payment occurs 5 minutes after expires, deny transfer
	};

	// Store deposit data in Redis
	await toolsLib.database.client.setAsync(transferUuid, JSON.stringify(payload));

	// PAYMENT_SERVICE is the payment service being used
	const transferResponse = await PAYMENT_SERVICE.deposit(payment);

	// Redirect user for completing the payment
	return res.redirect(transferResponse.url);
});

// PHASE 3: RECEIVE NOTIFICATION OF COMPLETED DEPOSIT FROM PAYMENT SERVICE
app.post('/plugins/bank/:uuid', (req, res) => {
	const { uuid } = req.params;
	const { amount, currency, transaction_id } = req.body;
	
	// Get deposit data from Redis via uuid
	const storedDepositData = await toolsLib.database.client.getAsync(uuid);
	
	// If data is not found, reject deposit
	if (!storedDepositData) {
		return res.status(400).json({ message: `No deposit found with UUID ${uuid}` });
	}
	
	storedDepositData = JSON.parse(storedDepositData);
	
	// Delete data from Redis
	await toolsLib.database.client.delAsync(uuid);
	
	// If deposit occured after expiry time, reject the deposit
	if (moment().isAfter(storedDepositData.expires)) {
		return res.status(400).json({ message: 'Deposit is expired' });
	}
	
	// If deposit amount or currency don't match ones stored on Redis, reject the deposit
	if (amount !== storedDepositData.amount || currency !== storedDepositData.currency) {
		return res.status(400).json({ message: 'Incorrect amount or currency given' });
	}
	
	// All checks passed, mint the asset with the transaction ID obtained from serivce provider
	const mintResponse = await toolsLib.wallet.mintAssetByKitId(
		storedDepositData.user_id, // User kit id
		storedDepositData.currency, // currency
		storedDepositData.amount, // amount
		{
				description: 'Bank Deposit', // description
				transactionId: transaction_id // transaction id
		}
	);
	
	return res.json(mintResponse);
});
🧩