BNB Payment Acceptance Setup

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
BNB Payment Acceptance Setup
Simple
~2-3 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1215
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1043
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

BNB Payment Acceptance Setup

BNB operates in two contexts that are easy to confuse: native BNB on BNB Chain (BSC, chainId 56) and BEP-2 BNB on Binance Chain (the old chain, practically obsolete). In 99% of cases the customer wants to accept BNB on BSC — that's exactly what we'll cover.

Approach 1: Without Third-Party Providers

The most straightforward option — monitoring incoming transactions to an address via BSC node or public RPC.

Generate unique address for each order via HD wallet:

import { ethers } from "ethers";

const provider = new ethers.JsonRpcProvider("https://bsc-dataseed1.binance.org/");

// From mnemonic — for development. In production — xpub without storing seed
const masterWallet = ethers.Wallet.fromPhrase(process.env.MNEMONIC!);

function getDepositAddress(orderId: number): string {
  return masterWallet.deriveChild(orderId).address;
}

async function waitForPayment(address: string, expectedAmount: bigint): Promise<string> {
  return new Promise((resolve) => {
    provider.on({ address }, (tx) => {
      if (tx.value >= expectedAmount) {
        resolve(tx.hash);
      }
    });
  });
}

Confirmations: on BSC with 21 validators and ~3-second blocks — wait minimum 15 confirmations for amounts up to $1000, 30+ for large ones. Reorgs on BSC are rare but do happen.

Polling verification (more reliable than websocket subscriptions on public RPC):

async function checkPayment(
  depositAddress: string,
  expectedWei: bigint,
  fromBlock: number
): Promise<boolean> {
  const currentBlock = await provider.getBlockNumber();

  for (let block = fromBlock; block <= currentBlock; block++) {
    const blockData = await provider.getBlock(block, true);
    const incoming = blockData?.transactions.filter(
      (tx: any) =>
        tx.to?.toLowerCase() === depositAddress.toLowerCase() &&
        BigInt(tx.value) >= expectedWei
    );
    if (incoming && incoming.length > 0) return true;
  }
  return false;
}

Approach 2: Via BscScan API

Simpler, doesn't require your own node, but adds dependency on third-party service:

async function getIncomingBNB(address: string, startBlock: number) {
  const url = `https://api.bscscan.com/api?module=account&action=txlist` +
    `&address=${address}&startblock=${startBlock}&endblock=99999999` +
    `&sort=asc&apikey=${process.env.BSCSCAN_API_KEY}`;

  const { result } = await fetch(url).then(r => r.json());
  return result.filter((tx: any) =>
    tx.to.toLowerCase() === address.toLowerCase() &&
    tx.isError === "0"
  );
}

BscScan free plan limit: 5 requests/sec, 100k requests/day — sufficient for small volumes.

Accepting USDT/USDC on BEP-20

Often need to accept not just native BNB, but stablecoins on BSC. USDT BEP-20: 0x55d398326f99059fF775485246999027B3197955. Monitoring via Transfer events:

const USDT_BSC = "0x55d398326f99059fF775485246999027B3197955";
const transferInterface = new ethers.Interface([
  "event Transfer(address indexed from, address indexed to, uint256 value)"
]);

const filter = {
  address: USDT_BSC,
  topics: [
    ethers.id("Transfer(address,address,uint256)"),
    null,
    ethers.zeroPadValue(depositAddress, 32),
  ],
};

provider.on(filter, (log) => {
  const { from, to, value } = transferInterface.parseLog(log)!.args;
  console.log(`Received ${ethers.formatUnits(value, 18)} USDT from ${from}`);
});

Sweep and Fund Collection

After payment confirmation, the funds need to be transferred to the main cold/hot wallet. For native BNB this is a simple transaction. Keep in mind that for sweep you need to leave BNB for gas (~0.0005 BNB at 3 gwei gasPrice and 21000 gas limit).

For automatic sweep of derived wallets you need a cron worker that checks balances of deposit addresses and transfers accumulated funds.

Time Estimates

Basic setup for accepting native BNB with webhook notification: 1 day. Adding BEP-20 tokens (USDT, USDC) and auto-sweep: another 1–2 days. Integration into existing backend depends on its architecture.