Ми спеціалізуємося на розробці бекенду dApp на Node.js для проєктів, де on-chain логіки недостатньо. Якщо вам потрібен приватний RPC проксі, SIWE-аутентифікація, event indexer або газлесс релайер — ми створимо інфраструктуру з нуля під ключ. Без бекенду не обійтися, коли потрібні: агрегація даних з кількох джерел, кешування дорогих on-chain запитів (економія до 40% витрат на RPC, що складає близько $500 на місяць для середнього проекту), gasless транзакції (relayer), верифікація підписів. Ми використовуємо сучасний стек: Fastify, ethers.js/viem, Redis, Prisma. Наш досвід — понад 10 років у блокчейн-розробці та 50+ завершених dApp проєктів. Якщо вам потрібен надійний бекенд dApp, замовте консультацію — розрахуємо склад робіт і терміни.
Розробка бекенду dApp на Node.js: ключові компоненти
RPC abstraction layer — бекенд dapp на
Пряме звернення з фронтенду до Infura/Alchemy розкриває API ключ. Бекенд проксіює RPC виклики, додає кешування та rate limiting:
import { JsonRpcProvider, Contract } from 'ethers'; import Fastify from 'fastify'; const provider = new JsonRpcProvider(process.env.RPC_URL); const app = Fastify(); // Кэшированный endpoint для данных контракта app.get('/contract/:address/balance/:account', { config: { rateLimit: { max: 100, timeWindow: '1 minute' } } }, async (req, reply) => { const { address, account } = req.params as { address: string; account: string }; const cacheKey = `balance:${address}:${account}`; const cached = await redis.get(cacheKey); if (cached) return { balance: cached, cached: true }; const contract = new Contract(address, ERC20_ABI, provider); const balance = await contract.balanceOf(account); await redis.setex(cacheKey, 12, balance.toString()); // кэш на ~1 блок (12 сек) return { balance: balance.toString(), cached: false }; }); Як реалізувати безпечну аутентифікацію без пароля?
Sign-In With Ethereum (EIP-4361) — стандарт аутентифікації без пароля, описаний у EIP-4361. Користувач підписує SIWE-повідомлення, бекенд верифікує підпис і видає JWT:
import { SiweMessage } from 'siwe'; import jwt from 'jsonwebtoken'; app.post('/auth/verify', async (req, reply) => { const { message, signature } = req.body; const siweMessage = new SiweMessage(message); const result = await siweMessage.verify({ signature }); if (!result.success) { return reply.code(401).send({ error: 'Invalid signature' }); } const token = jwt.sign( { address: result.data.address, chainId: result.data.chainId }, process.env.JWT_SECRET!, { expiresIn: '7d' } ); return { token }; }); Nonce для захисту від replay атак: генеруємо випадковий nonce, зберігаємо в Redis з TTL 5 хвилин, верифікуємо що nonce в SIWE повідомленні збігається з виданим. Після використання — видаляємо.
Налаштування RPC проксі: покрокова інструкція
- Встановіть Fastify та ethers.js:
npm install fastify ethers - Створіть файл
server.tsта налаштуйте rate limiter (наприклад,@fastify/rate-limit) - Підключіть Redis для кешування: використовуйте бібліотеку
ioredis - Реалізуйте fallback provider: при помилці перемикайтеся на резервний RPC URL
- Додайте ендпоінти для читання даних (balance, symbol, decimals) з кешуванням
- Налаштуйте health check та логування (pino)
Як обробляти on-chain події без затримок?
On-chain події потрібні для відображення історії операцій, сповіщень, аналітики. Два підходи:
| Підхід | Затримка | Навантаження на RPC | Надійність |
|---|---|---|---|
| Polling | ~12-15 сек | Висока CUPS | Нижче (пропуск блоків) |
| WebSocket subscription | <1 сек | Низька | Вимагає reconnect логіку |
WebSocket subscription (правильний) — використовуємо на практиці:
const wsProvider = new WebSocketProvider(process.env.WSS_RPC_URL); const contract = new Contract(CONTRACT_ADDRESS, ABI, wsProvider); contract.on('Transfer', async (from, to, value, event) => { await db.transfers.insert({ from, to, value: value.toString(), blockNumber: event.log.blockNumber, txHash: event.log.transactionHash, timestamp: new Date(), }); // Уведомить подписчиков через WebSocket/SSE eventBus.emit('transfer', { from, to, value: value.toString() }); }); // Обработка разрыва соединения wsProvider.on('error', async () => { console.error('WS disconnected, reconnecting...'); setTimeout(setupSubscriptions, 5000); }); WebSocket з'єднання нестабільні — reconnect логіка обов'язкова. Альтернатива для production: Alchemy webhooks, Quicknode Streams — провайдер сам доставляє події на ваш HTTP endpoint.
Gasless транзакції (meta-transactions)
EIP-2771 + ERC-2612 дозволяють користувачеві підписувати транзакцію офф-чейн, а relayer оплачує газ. Бекенд працює як relayer, що дозволяє знизити витрати на газ для користувача на 30-50%:
app.post('/relay/transfer', authenticateJWT, async (req, reply) => { const { permit, signature } = req.body; // ERC-2612 permit // Верифицируем permit signature const tokenContract = new Contract(TOKEN_ADDRESS, ERC20_ABI, wallet); // Проверяем что permit валиден и не истёк const nonce = await tokenContract.nonces(permit.owner); if (BigInt(permit.nonce) !== nonce) { return reply.code(400).send({ error: 'Invalid nonce' }); } // Выполняем permit + transferFrom за пользователя const tx = await tokenContract.permit( permit.owner, permit.spender, permit.value, permit.deadline, permit.v, permit.r, permit.s ); await tx.wait(); return { txHash: tx.hash }; }); Для production gasless транзакцій: OpenZeppelin Defender Relayer або Biconomy — вони керують nonce, retry logic та моніторингом застряглих транзакцій.
Як забезпечити відмовостійкість RPC проксі?
Використовуємо резервні RPC-провайдери з circuit breaker. Якщо основний провайдер повертає помилки (наприклад, 429 Too Many Requests), автоматично перемикаємося на резервний. Патерн circuit breaker через бібліотеку opossum: після 5 помилок поспіль — break на 30 секунд.
Моніторинг та надійність
Типові проблеми та їх вирішення:
- Stuck transactions: транзакція з низьким gasPrice зависає в mempool. Моніторимо через polling getTransactionReceipt(). Після N хвилин — bump gas (пересилаємо з тим же nonce, gasPrice * 1.1).
- Nonce management: при паралельних транзакціях з одного гаманця потрібен атомарний nonce counter. Використовуємо Redis INCR + pending nonce tracking.
- Circuit breaker для RPC: якщо провайдер повертає помилки — перемикаємося на резервний.
Структура проекту
src/ api/ # HTTP routes (Fastify/Express) blockchain/ # Provider, contracts, event listeners services/ # Бізнес-логіка workers/ # BullMQ workers для фонових завдань db/ # Prisma schema, migrations cache/ # Redis client middleware/ # Auth, rate limiting, validation Fastify швидше Express на ~15-20% throughput і має вбудовану JSON schema валідацію. Для dApp бекенду різниця рідко критична, але fastify-plugin екосистема зручна.
Порівняння підходів до деплою
| Стратегія | Час розгортання | Відмовостійкість | Вартість |
|---|---|---|---|
| Single server | 1-2 години | Низька | Низька |
| Docker + compose | 3-4 години | Середня | Середня |
| Kubernetes | 1-2 дні | Висока | Висока |
Що входить в роботу
Ми передаємо повний пакет документації: опис API (OpenAPI/Swagger), архітектурну схему, інструкцію з деплою. Вихідний код розміщуємо в приватному репозиторії з налаштованим CI/CD (GitHub Actions). Доступи до RPC-провайдерів, Redis та бази даних передаються через менеджер паролів. Проводимо навчання команди замовника (1-2 години). Підтримка протягом 1 місяця після здачі — включена. Замовте розробку бекенду dApp — отримайте готове рішення з моніторингом та підтримкою.
Орієнтири за термінами та вартістю
Базовий бекенд (RPC proxy + SIWE auth + кешування) — 2-3 дні, вартість від $2500. Event indexer + WebSocket push + gasless relay — ще 3-4 дні, повний комплект з моніторингом, retry logic та fallback RPC — 1.5-2 тижні, вартість від $6000. Ми гарантуємо якість: кожен блок коду проходить аудит та тестування.
Зв'яжіться з нами для оцінки вашого проекту — розрахуємо терміни та склад робіт. Отримайте консультацію інженера.







