Баланс токенов ERC-20/BEP-20/SPL в мобильном кошельке
Представьте: пользователь открывает кошелёк и ждёт загрузки баланса по одному токену — секунда на каждый. При 20 токенах это 20 секунд. Пользователь закрывает приложение. Классический RPC-запрос на каждый контракт даёт задержку 2-3 секунды на токен, итого минута для портфеля из 30 активов. Мы решаем эту задачу через пакетную загрузку с Multicall3, кэширование и параллельные запросы для разных сетей. Наш опыт показывает: правильная архитектура сокращает время загрузки до 1-2 секунд, независимо от количества токенов. Экономия времени достигает 20-кратного ускорения — пользователи не уходят, а конверсия в операции растёт.
Как пакетно загрузить балансы?
Multicall3 — контракт 0xcA11bde05977b3631167028862bE2a173976CA11, задеплоенный в большинстве EVM-сетей (Ethereum, Polygon, BNB Chain, Arbitrum, Optimism, Base). Один вызов aggregate3 возвращает балансы всех токенов за одну транзакцию чтения. Сравнение методов:
| Метод | Время на 20 токенов | Нагрузка на ноду | Поддержка сетей |
|---|---|---|---|
| Последовательные RPC | 4-6 секунд | 20 вызовов | Любая EVM |
| Multicall3 | 0.3-0.6 секунды | 1 вызов | Большинство EVM |
| JSON-RPC batch | 0.5-1 секунда | 1 batch-запрос | Все EVM (без Multicall) |
Multicall3 сокращает количество RPC-вызовов в 20 раз и в 10-20 раз быстрее последовательных запросов.
Пошаговая интеграция Multicall3
- Инициализируйте Multicall3-контракт в коде кошелька. Адрес един для всех сетей —
0xcA11bde05977b3631167028862bE2a173976CA11. - Соберите массив
Call3для каждого токена: target, allowFailure: true, callData =balanceOf(address). - Вызовите
aggregate3— получите массив результатов с rawBalance и success. - Обработайте результаты: для каждого токена извлеките rawBalance, поделите на 10^decimals.
- Отобразите балансы в UI параллельно с загрузкой курсов.
// iOS — web3swift + Multicall3 let multicallAddress = EthereumAddress("0xcA11bde05977b3631167028862bE2a173976CA11")! var calls: [Multicall3.Call3] = [] for tokenAddress in tokenAddresses { let callData = ERC20.balanceOf(owner: walletAddress).encodeABI() calls.append(.init(target: tokenAddress, allowFailure: true, callData: callData)) } let results = try await multicall3.aggregate3(calls: calls) // Android — web3j + ручная сборка Multicall val multicallEncoder = Function("aggregate3", listOf(DynamicArray(calls)), listOf()) val encodedCall = FunctionEncoder.encode(multicallEncoder) val response = web3j.ethCall(Transaction.createEthCallTransaction(null, multicallAddress, encodedCall), DefaultBlockParameterName.LATEST).send() Для сетей без Multicall3 (некоторые L2 или приватные EVM-сети) — JSON-RPC batch request: массив вызовов в одном HTTP-теле. Большинство нод поддерживают до 100 запросов в batch.
Что делать с SPL-токенами на Solana?
Solana принципиально отличается: каждый SPL-токен хранится на отдельном Associated Token Account (ATA). Список ATA для кошелька получают через getTokenAccountsByOwner с программой TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA.
// iOS — SolanaSwift let tokenAccounts = try await solana.action.getTokenAccountsByOwner( pubkey: walletPublicKey, params: .init(programId: TokenProgram.publicKey), configs: nil ) for account in tokenAccounts { let mint = account.account.data.parsed.info.mint let amount = account.account.data.parsed.info.tokenAmount.uiAmount } У пользователя может быть 50+ ATA, включая нулевые балансы от старых airdrop'ов. Нулевые мы скрываем по умолчанию, но даём опцию «показать все». Это держит UI чистым, не теряя информацию.
Почему важны decimals и курсы?
Отображение баланса без фиатного эквивалента — половина работы. Для получения курсов используем CoinGecko API (/simple/price?ids=...&vs_currencies=usd) или CoinMarketCap. CoinGecko Free tier — 30 запросов в минуту, достаточно для большинства кошельков. Ключи токенов — это contract address, не тикер. Для Ethereum: https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses=0x...&vs_currencies=usd. Запрос до 100 контрактов за раз — пакетируем.
Decimals токена критически важны: согласно спецификации ERC-20, контракт возвращает баланс в минимальных единицах. USDC — 6 decimals, ETH — 18. Отображаемый баланс: rawBalance / 10^decimals. Ошибка в decimals — баланс покажет астрономическую или нулевую сумму. Мы гарантируем корректное считывание decimals из контракта при инициализации.
Типичные ошибки при работе с decimals:
- Контракт возвращает decimals = 0 для токенов, не реализующих
decimals(), — используем fallback 18. - Некоторые токены (например, USDT на Tron) имеют 6 decimals, но на EVM-версиях — 6 или 18.
- При добавлении нового токена вручную пользователь может ввести неверные decimals — перепроверяем через ончейн-данные.
Схема кэширования и частота обновления
| Данные | Частота обновления | Хранение |
|---|---|---|
| Балансы токенов | Каждые 30 сек / pull-to-refresh | In-memory |
| Список токенов пользователя | При каждом запуске | SQLite / UserDefaults |
| Курсы токенов | Каждые 60 сек | In-memory + disk cache |
| Метаданные токена (имя, decimals) | Однократно | SQLite |
Личный кейс: для одного DeFi-проекта мы интегрировали отображение балансов в 4 сетях (Ethereum, BSC, Polygon, Solana) и 30 токенах. Время загрузки сократилось с 12 секунд до 2,5 секунд благодаря пакетным запросам и кэшированию курсоров.
Что входит в работу
- Проектирование архитектуры загрузки балансов под вашу целевую аудиторию.
- Интеграция Multicall3 для EVM-сетей и
getTokenAccountsByOwnerдля Solana. - Подключение фиатных курсов с кэшированием.
- Разработка UI списка токенов с pull-to-refresh, поиском и скрытием нулевых.
- Тестирование на 10+ популярных токенах в каждой сети.
- Передача доступов к App Store Connect / Google Play Console.
- Документация по эксплуатации и поддержка в течение месяца после релиза.
Сроки ориентировочно
От 3 до 7 дней в зависимости от количества сетей и требований к UI. Для типового решения (EVM + Solana + курсы) — 5 дней. Свяжитесь с нами — мы оценим ваш проект бесплатно и назовём точные сроки. Наши инженеры имеют 5+ лет опыта в мобильной разработке и гарантируют соблюдение App Store Review Guidelines и Play Console политик.
Закажите реализацию отображения баланса токенов в вашем кошельке — получите готовое решение под ключ. Получите консультацию прямо сейчас.







