Знакома ли вам эта ситуация? Вы запускаете торгового бота. Каждая миллисекунда имеет значение — каждый RPC-вызов стоит денег.
Вы платите премию высокоскоростному провайдеру RPC, чтобы выполнять транзакции немедленно. Но проблема в том, что: в ваших RPC-вызовах 90% — это чтение, а не запись. Вы запрашиваете цены, проверяете балансы, сканируете mempool — и за каждый вызов платите ту же высокую цену.
Если сохранить быстрый путь записи полностью неизменным и при этом направить весь входящий поток на одну более дешёвую небольшую по пропускной способности ветку, что получится?
Это не предположение. Такая модель называется read/write separation (разделение чтения и записи) — одна из самых эффективных архитектур для экономии затрат для любого серьёзного dApp, бота или индексатора.
Боль, которую мы все чувствуем
Честно говоря, так сегодня используют RPC большинство проектов.
while True:
price = web3.eth.call(price_feed_contract) # чтение
balance = web3.eth.get_balance(user_wallet) # чтение
# ... проверка условий ...
tx_hash = web3.eth.send_raw_transaction(signed) # запись
В типичном цикле сделок на каждые 1 транзакцию приходится 10–50 чтений. Но большинство разработчиков маршрутизируют все запросы через один RPC endpoint — обычно тот, который оптимизирован под скорость отправки транзакций, а значит и дороже.
Если вы платите за ускоряющий транзакции RPC $X, а 95% ваших вызовов — это чтение, то по сути вы тратите $0.95X на обработку запросов к данным, которые мог бы выполнять провайдер в разы дешевле.
Это не столько вопрос ценообразования, сколько архитектуры — и решение удивительно простое. Дальше я разберу всё подробно.👇
Наше решение: разделение чтения и записи
Архитектура очень простая:
Запросы на чтение (eth_call, eth_getBalance……) ➡️ BlockPI (дешево, стабильно, с архивами)
Транзакции на запись (accelerated transaction RPC) ➡️ ваш accelerated transaction RPC (низкая задержка отправки)
Достаточно оставить в коде два провайдера и умно маршрутизировать запросы — и стоимость RPC сэкономит сразу 60–80%.
Как это работает в коде
Это делается крайне просто. Ниже — практичный шаблон на Python:
from web3 import Web3
from web3.middleware import geth_poa_middleware
import os
READ_RPC_URL = os.getenv("BLOCKPI_RPC_URL")
WRITE_RPC_URL = os.getenv("TRANSACTION_ACCELERATION_RPC_URL")
w3_read = Web3(Web3.HTTPProvider(READ_RPC_URL))
w3_write = Web3(Web3.HTTPProvider(WRITE_RPC_URL))
w3_read.middleware_onion.inject(geth_poa_middleware, layer=0)
w3_write.middleware_onion.inject(geth_poa_middleware, layer=0)
def get_eth_price():
price_feed = w3_read.eth.contract(
address="0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419",
abi=[{"inputs":[],"name":"latestAnswer","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"}]
)
return price_feed.functions.latestAnswer().call()
def execute_swap(signed_tx):
return w3_write.eth.send_raw_transaction(signed_tx)
def wait_for_receipt(tx_hash):
return w3_read.eth.wait_for_transaction_receipt(tx_hash)
Или, более аккуратно, использовать Web3-обёртку, которая умеет автоматически маршрутизировать:
class SmartWeb3:
"""Web3-обёртка для маршрутизации запросов чтения и записи к разным провайдерам."""
def __init__(self, read_rpc: str, write_rpc: str):
self._read = Web3(Web3.HTTPProvider(read_rpc))
self._write = Web3(Web3.HTTPProvider(write_rpc))
@property
def eth(self):
return self._routed_eth()
def _routed_eth(self):
class RoutedEth:
def __init__(self, read, write):
self._read = read.eth
self._write = write.eth
def get_balance(self, address, block=None):
return self._read.get_balance(address, block)
def call(self, transaction, block=None):
return self._read.call(transaction, block)
def get_logs(self, filter_params):
return self._read.get_logs(filter_params)
def send_raw_transaction(self, signed_tx):
return self._write.send_raw_transaction(signed_tx)
def estimate_gas(self, transaction):
return self._write.estimate_gas(transaction)
def get_transaction_count(self, address, block=None):
return self._write.get_transaction_count(address, block)
def block_number(self):
return self._read.block_number()
def wait_for_transaction_receipt(self, tx_hash, timeout=120):
return self._read.wait_for_transaction_receipt(tx_hash, timeout)
return RoutedEth(self._read, self._write)
w3 = SmartWeb3(
read_rpc=os.getenv("BLOCKPI_RPC_URL"),
write_rpc=os.getenv("TRANSACTION_ACCELERATION_RPC_URL")
)
balance = w3.eth.get_balance("0x...")
price = w3.eth.call(tx)
tx_hash = w3.eth.send_raw_transaction(signed_tx)
Бизнес-логика не требует никаких изменений поведения — единственное отличие будет в счёте.
Почему BlockPI разработан для чтения-насыщенных сценариев
После разделения чтения и записи провайдер чтения должен обладать тремя качествами:
Надёжность на больших масштабах
Ваш бот или dApp не может позволить себе пропустить ни одного блока. Инфраструктура BlockPI построена для production-нагрузок — распределённые ноды, автоматическое переключение при сбоях и действительно эффективные буферы rate limiting.
Поддержка архивов — потому что чтение часто требует исторических данных
Многие сценарии чтения требуют исторических данных — получить логи за прошлую неделю, проверить старые позиции LP, после перезапуска воспроизвести события. BlockPI поддерживает архивный режим в Ethereum и Base (начиная с genesis), eth_getLogs поддерживает диапазоны в 5,000 блоков и позволяет делать запросы с пагинацией на любую глубину.
Реальная эффективность по стоимости
Тарифная модель BlockPI на основе RU конкурентоспособна, поэтому вы можете маршрутизировать высокообъёмное чтение без необходимости каждый раз заново «взвешивать» стоимость каждого вызова. Стоимость отдельного вызова — лишь небольшая часть того, что вы бы платили за выполнение на премиальном провайдере.
Объём вызовов Чтение через accelerated transaction RPC Чтение через BlockPI
1M вызовов/день $XX–$XXX 60–80% меньше
10M вызовов/день $XXX–$XXXX Разрыв становится шире
Кому подходит разделение чтения и записи?
Далее — как типичный MEV- или арбитраж-бот на JavaScript делает конфигурацию:
const { Web3 } = require('web3');
const web3Read = new Web3('https://base.blockpi.network/v1/rpc/{YOUR_API_KEY}');
const web3Write = new Web3(process.env.TRANSACTION_ACCELERATION_RPC_URL);
async function tradingCycle() {
// Шаг 1: сканирование возможностей (все чтения идут через BlockPI)
const currentPrice = await web3Read.eth.call({
to: '0x...',
priceFeed.encodeABI()
});
const poolReserves = await web3Read.eth.call({
to: poolAddress,
poolAbi.encodeReserves()
});
const profit = calculateProfit(currentPrice, poolReserves);
// Шаг 2: если выгодно — выполнить (быстрая запись через RPC)
if (profit \u003e threshold) {
const nonce = await web3Write.eth.getTransactionCount(wallet.address);
const gasPrice = await web3Write.eth.getGasPrice();
const tx = {
from: wallet.address,
to: routerAddress,
swapData,
gas: 300000,
gasPrice: gasPrice * 2,
nonce: nonce,
chainId: 8453
};
const signed = await wallet.signTransaction(tx);
const txHash = await web3Write.eth.sendRawTransaction(signed);
// Шаг 3: ожидание подтверждения (чтение идёт через BlockPI)
const receipt = await web3Read.eth.getTransactionReceipt(txHash);
return receipt;
}
}
Каждый блок бот выполняет сотни запросов на чтение, чтобы сканировать возможности, но когда находит шанс — отправляет всего одну-две транзакции. Без разделения чтения и записи эти расходы на сканирование накладываются на каждый eth_call и «размазывают» дорогой тариф ускоренного RPC.
BlockPI даёт разработчикам:
• Конкурентное ценообразование RU — делает чтение-насыщенные нагрузки действительно доступными
• Beacon API + blob_sidecars — для анализа данных L2
• Поддержка множества сетей — один консольный интерфейс, много цепочек, единая тарификация
• Диапазон getLogs на 5,000 блоков — можно пагинировать на любую глубину
Это означает для вашего проекта:
• Транзакционные боты — недорого сканируют mempool и данные в сети, выполняя транзакции через быстрых провайдеров
• Трекер портфеля — выполняйте сотни запросов балансов/вызовов пачками и не вздрагивайте от счетов
• Индексатор — воспроизводит исторические данные с архивной глубиной и при необходимости пересылает транзакции
• DeFi-панель — даже постоянный мониторинг ончейн-данных остаётся финансово устойчивым
🛡️ Не только для чтения — а более гибкая инфраструктура для транзакций
Разделение чтения и записи не означает, что BlockPI подходит только для чтения. Когда ваше приложение тоже отправляет транзакции через BlockPI, можно включить защиту MEV — это помогает снизить риск сэндвич-атак и других действий по «извлечению» из mempool. Чувствительные транзакции можно направлять по защищённому маршруту отправки — по умолчанию они не раскрываются в публичном mempool.
На практике многие команды держат BlockPI как основной слой чтения для high-volume eth_call, балансов, логов и запросов receipt, а путь записи выбирают в зависимости от задачи: когда приоритет — сверхнизкая задержка в отправке, используют accelerated transaction RPC; когда важнее качество и безопасность исполнения, чем первичная скорость, используют BlockPI с защитой MEV. Так разработчики получают гибкую архитектуру, а не вынуждены выбирать между провайдерами.
🔒 При включении защиты MEV BlockPI может помочь командам сохранить больше той ценности, которую они изначально хотели получать on-chain — особенно для сделок на обмен, ликвидации и других транзакций, чувствительных к цене. При этом вам не нужно отказываться от экономичной инфраструктуры для чтения. Это также помогает не дать арбитражникам перехватить ваши чувствительные транзакции.
Потренируйтесь и примените разделение чтения и записи за несколько минут
Миграция не требует существенных изменений кода:
1. Зарегистрируйтесь на https://dashboard.blockpi.io и получите endpoint
2. Настройте в коде экземпляр только для чтения Web3, направленный на BlockPI
3. Маршрутизируйте через него запросы на чтение — eth_call, eth_getBalance, eth_getLogs, eth_blockNumber, eth_getTransactionReceipt……
4. Сохраните текущего провайдера для записи — для accelerated transaction RPC. Или используйте наш MEV-сервис
Не нужно переписывать код и полностью перестраивать архитектуру — достаточно принять более умные решения по маршрутизации.
Реальное сравнение стоимости
Допустим, ваш проект делает 100,000 вызовов в день:
• Из них 95,000 — это чтение (eth_call, getBalance, getLogs, blockNumber)
• 5,000 — это запись (accelerated transaction RPC)
Способ Стоимость чтения Стоимость записи Итого
All through accelerated transaction RPC High x 95K High x 5K $$$$
Разделение чтение/запись с BlockPI Низко x 95K Высоко x 5K ~60–80% меньше
Экономия растёт пропорционально объёму чтения. Для чтения-ориентированных нагрузок — а это большинство проектов — разделение чтения и записи — не просто разумный шаг, а экономическая необходимость.
Выберите подходящий сценарий
Вашему приложению не нужно использовать один и тот же RPC-путь для каждой операции. Ключ — сопоставить каждый тип нагрузки с теми инфраструктурными характеристиками, которые ему действительно нужны:
Чтение: мощность, стабильность, глубина архивирования ➡️ BlockPI
Запись: скорость транзакций ➡️ ваш accelerated transaction RPC
Это не про замену текущих RPC, а про то, чтобы перестать платить больше за то, что вы и так делаете.
BlockPI предоставляет «читающую» часть этой формулы — цены доступны, есть архивы и инфраструктура уровня production. Это позволяет масштабировать объём чтения без синхронного роста затрат.
Выберите модель покупки, подходящую вашей нагрузке:
1️⃣ Тариф RU — покупка заранее определённого набора ресурсов RPC. Подходит для предсказуемых нагрузок: бюджет становится прозрачнее, а юнит-экономика лучше на заданных уровнях потребления.
2️⃣ Оплата по факту (PAYG) — начать можно без фиксированного пакета: платите за реальное потребление. Подходит для нагрузок с сильными колебаниями трафика, для тестов и для сценариев, которым нужна гибкая масштабируемость.
Начните использовать разделение чтения и записи прямо сейчас ➡️ https://dashboard.blockpi.io
Сфокусируйтесь на BLOCKPI:
Официальный X: https://x.com/RealBlockPI
YouTube: https://www.youtube.com/@BlockPINetwork
Telegram: @BlockPIdaily
Консоль: https://dashboard.blockpi.io/
