Розробка системи генерації унікальних адрес для криптоплатежів

Одна адреса для всіх платежів з коментарем – це працює, доки користувачі не забувають вказувати memo. Коли 5% вхідних переказів приходять без ідентифікатора і потребують ручного розбору – це стає операційною проблемою. Ми стикалися з кейсами, де у клієнта до 8% платежів губилися, і відновлення займа

Напрямки блокчейн-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1450
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1308
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1003
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1269
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    717
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1008

Одна адреса для всіх платежів з коментарем – це працює, доки користувачі не забувають вказувати memo. Коли 5% вхідних переказів приходять без ідентифікатора і потребують ручного розбору – це стає операційною проблемою. Ми стикалися з кейсами, де у клієнта до 8% платежів губилися, і відновлення займало до 3 робочих днів. Unique address per payment вирішує це завдання повністю: кожне замовлення отримує свою адресу, будь-який платіж однозначно ідентифікується. Замовте таку систему у нас – гарантуємо безпеку та прозорість. Наші спеціалісти мають 10+ років досвіду в блокчейн-розробці та реалізували 500+ проєктів.

Перевага унікальних адрес над memo

Memo – це поле коментаря в транзакції, яке користувач може не заповнити. При високому навантаженні навіть 1% втрачених платежів означає збитки та ручну працю. Унікальна адреса для кожного замовлення робить ідентифікацію автоматичною: за адресою призначення ми одразу розуміємо, до якого замовлення відноситься транзакція. Порівняємо два підходи в таблиці:

Критерій Memo-поле Унікальна адреса
Вимагає заповнення користувачем Так Ні
Ризик втрати платежу 5–8% 0%
Ручний розбір Потрібен Автоматичний
Масштабованість Обмежена Необмежена (до 2^32 адрес з одного seed)
Безпека Немає особливостей HD-деривація з ізоляцією ключів

Висновок: система унікальних адрес у 100 разів надійніша за використання memo – нульовий ризик втрати платежу.

Як працює генерація унікальних адрес?

Чому це безпечніше ніж memo?

Основа системи – ієрархічні детерміновані гаманці (BIP-32/BIP-44). З одного master seed детерміновано виводиться скільки завгодно дочірніх ключів. Адреси відтворювані, приватний ключ кожного дочірнього адресу відновлюється з seed у будь-який момент. Це стандарт BIP-44, що використовується в більшості криптогаманців.

Master Seed (128/256 біт) ↓ BIP-39 Master Mnemonic (12/24 слова) ↓ BIP-32 HMAC-SHA512 Master Extended Key (xprv) ↓ BIP-44 деривація m / purpose' / coin_type' / account' / change / index 

Для Ethereum (coin_type = 60):

m/44'/60'/0'/0/0 → перша адреса m/44'/60'/0'/0/1 → друга адреса m/44'/60'/0'/0/N → N+1-а адреса 

Важливий момент: деривація address-only не потребує приватного ключа. Extended public key (xpub) достатньо для генерації адрес. Це дозволяє рознести компоненти: сервер генерації адрес тримає лише xpub (компрометація = витік адрес, не коштів), сервер підписання транзакцій – xprv в ізольованому середовищі (HSM, offline). Такий підхід використовується в продакшені вже кілька років – ми реалізували його в десятках проєктів. Завдяки цьому мультивалютний прийом платежів стає безпечним і масштабованим.

Процес sweeping (збір коштів з дочірніх адрес)

Кошти на дочірніх адресах потрібно періодично збирати на основну адресу (холодний гаманець або multisig). Sweep має відбуватися після підтвердження платежу:

async function sweepAddress(index: number): Promise<void> { const privateKey = masterHdNode.deriveChild(index).privateKey; const wallet = new Wallet(privateKey, provider); const balance = await provider.getBalance(wallet.address); const gasEstimate = 21000n; const gasPrice = await provider.getFeeData().then(d => d.gasPrice!); const gasCost = gasEstimate * gasPrice; if (balance <= gasCost) return; await wallet.sendTransaction({ to: HOT_WALLET_ADDRESS, value: balance - gasCost, gasLimit: gasEstimate, }); } 

Для ERC-20 токенів sweep складніше: потрібно спочатку переконатися, що на адресі є ETH для gas, відправити його з основної адреси, потім забрати токени. Або використовувати паттерн з Permit/EIP-2612 – тоді газ платить не дочірня адреса. Оптимізація газу в sweep дозволяє заощадити до 30% на комісіях.

Реалізація: генерація та моніторинг транзакцій

import { HDNodeWallet, Mnemonic } from 'ethers'; class PaymentAddressGenerator { private hdNode: HDNodeWallet; private currentIndex: number; constructor(xpub: string, startIndex: number = 0) { this.hdNode = HDNodeWallet.fromExtendedKey(xpub); this.currentIndex = startIndex; } generateAddress(orderId: string): { address: string; index: number } { const index = this.currentIndex++; const childNode = this.hdNode.deriveChild(index); return { address: childNode.address.toLowerCase(), index, }; } } async function getNextIndex(db: Pool): Promise<number> { const result = await db.query( "SELECT nextval('payment_address_index_seq') AS idx" ); return parseInt(result.rows[0].idx); } 

Чому не просто інкремент в коді? При горизонтальному масштабуванні кілька інстансів сервісу можуть одночасно отримати однаковий index. PostgreSQL sequence атомарний – nextval завжди повертає унікальне значення. Ми використовуємо цю схему в проєктах з навантаженням до 10 000 адрес на день.

База даних та O(1) пошук

CREATE SEQUENCE payment_address_index_seq START 1; CREATE TABLE payment_addresses ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), address VARCHAR(42) NOT NULL UNIQUE, derivation_index INTEGER NOT NULL UNIQUE, order_id UUID NOT NULL REFERENCES orders(id), network VARCHAR(20) NOT NULL, currency VARCHAR(20) NOT NULL, expected_amount NUMERIC(36, 18), received_amount NUMERIC(36, 18) DEFAULT 0, status VARCHAR(20) NOT NULL DEFAULT 'pending', expires_at TIMESTAMPTZ NOT NULL, confirmed_tx VARCHAR(66), created_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX idx_payment_addresses_address ON payment_addresses(address); CREATE INDEX idx_payment_addresses_status ON payment_addresses(status) WHERE status = 'pending'; 

Індекс по address – критичний для O(1) lookup при отриманні транзакції з блокчейн-лістенера. Без нього перевірка кожного вхідного переказу перетворюється на повний скан таблиці. Ми гарантуємо, що моніторинг працює в реальному часі навіть при 10 000 одночасно активних адрес.

Як здійснюється моніторинг транзакцій?

Наївний підхід – підписатися на всі згенеровані адреси. При великій системі це тисячі адрес. Краще: тримати in-memory set активних (pending) адрес, який оновлюється при створенні/закритті платежів.

class PaymentAddressMonitor { private activeAddresses: Map<string, PaymentAddress> = new Map(); async loadActiveAddresses(db: Pool): Promise<void> { const result = await db.query( `SELECT address, order_id, expected_amount, currency, expires_at FROM payment_addresses WHERE status = 'pending' AND expires_at > NOW()` ); for (const row of result.rows) { this.activeAddresses.set(row.address.toLowerCase(), row); } } onTransactionDetected(toAddress: string, amount: bigint, txHash: string): void { const payment = this.activeAddresses.get(toAddress.toLowerCase()); if (!payment) return; const tolerance = payment.expectedAmount * 99n / 100n; if (amount >= tolerance) { this.confirmPayment(payment, txHash); } } } 

Multi-network: один index, різні адреси

EVM-сумісні мережі використовують один і той же приватний ключ – адреса однакова на Ethereum, BNB Chain, Polygon, Arbitrum. Це зручно: один index в таблиці можна використовувати для прийому платежів в різних мережах на одну адресу, але моніторинг потрібен окремий для кожної мережі. Такий мультивалютний прийом платежів значно спрощує інфраструктуру.

Для non-EVM (TON, Solana, Bitcoin) – окремі HD-деривації з різними master seed або різними шляхами деривації.

Безпека криптогаманця

  • Master seed – в HSM або AWS KMS. Ніколи в змінних середовища.
  • xpub для генерації адрес – окремо від xprv для підписання.
  • Signing сервіс – ізольований мікросервіс з мінімальними привілеями.
  • Аудит всіх операцій sweep – кожна транзакція логується з обґрунтуванням.
  • Gap limit – BIP-44 рекомендує не дивитися глибше 20 послідовних невикористаних адрес при відновленні гаманця.

Етапи реалізації (під ключ)

Етап Тривалість
Аналітика та проєктування 3–5 днів
Розробка модуля генерації 5–7 днів
Моніторинг та свіпінг 5–7 днів
Інтеграція з вашою системою 3–5 днів
Тестування та деплой 3–5 днів
Разом 2–3 тижні

Що входить в роботу

При замовленні розробки системи унікальних адрес ми надаємо:

  • модуль генерації та моніторингу (вихідний код під вашу ліцензію);
  • PostgreSQL схему з індексами та міграціями;
  • скрипти деплою та налаштування HSM/KMS;
  • документацію API та інструкцію з експлуатації;
  • навчання вашої команди (2–3 дні);
  • технічну підтримку на 3 місяці.
Кроки для впровадження унікальних адрес 1. Ініціалізація master seed в HSM. 2. Отримання xpub для генерації адрес. 3. Створення таблиці payment_addresses з індексами. 4. Розгортання модуля генерації адрес з PostgreSQL sequence. 5. Підключення моніторингу нових блоків. 6. Налаштування sweep-сервісу для збору коштів.

Зв'яжіться з нами для оцінки вашого проєкту – відповімо за 1–2 робочих дні. Замовте розробку та отримайте готове рішення, яке виключить втрати платежів та заощадить до 500 000 грн на рік на ручному розборі. Вартість впровадження системи – від 200 000 грн, що окупається менш ніж за півроку.

Джерело: BIP-44 специфікація на GitHub