Настройка приймання платежів у BNB
BNB працює в двох контекстах, які легко переплутати: нативний BNB на BNB Chain (BSC, chainId 56) і BEP-2 BNB на Binance Chain (стара ланцюжок, практично застаріла). У 99% випадків клієнт хоче приймати BNB на BSC — саме це і розберемо.
Підхід 1: Без сторонніх провайдерів
Найпряміший варіант — моніторинг вхідних транзакцій на адресу через BSC ноду або публічний RPC.
Генерування унікальної адреси для кожного замовлення через HD wallet:
import { ethers } from "ethers";
const provider = new ethers.JsonRpcProvider("https://bsc-dataseed1.binance.org/");
// З mnemonic — для розробки. У production — xpub без зберігання 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);
}
});
});
}
Підтвердження: на BSC з 21 валідатором і ~3-секундними блоками — чекаємо мінімум 15 підтверджень для сум до $1000, 30+ для великих. Реорги на BSC рідкісні, але трапляються.
Перевірка через polling (надійніше, ніж websocket-підписки на публічних 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;
}
Підхід 2: Через BscScan API
Простіше, не вимагає власної ноди, але додає залежність від стороннього сервісу:
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: 5 запросів/сек, 100k запросів/день — для невеликих обсягів хватає.
Приймання USDT/USDC на BEP-20
Часто потрібно приймати не тільки нативний BNB, але й stablecoin на BSC. USDT BEP-20: 0x55d398326f99059fF775485246999027B3197955. Моніторинг через 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(`Отримано ${ethers.formatUnits(value, 18)} USDT від ${from}`);
});
Sweep та збір коштів
Після підтвердження платежу кошти потрібно перевести в основний cold/hot wallet. Для нативного BNB це проста транзакція. Врахуйте, що для sweep необхідно залишити BNB на газ (~0.0005 BNB при 3 gwei gasPrice і 21000 gas limit).
Для автоматичного sweep деривованих кошельків потрібен cron-воркер, який перевіряє баланси адрес депозиту і переводить накопленне.
Орієнтири по термінах
Базова настройка приймання нативного BNB з webhook-сповіщенням: 1 день. Додавання BEP-20 токенів (USDT, USDC) і автосбір: ще 1–2 дні. Інтеграція в існуючий бекенд залежить від його архітектури.







