Реалізація відображення баланса токенів (ERC-20/BEP-20/SPL) у мобільному гаманці
Показати баланс ETH—один вклик eth_getBalance. Показати балансi двадцяти ERC-20 токенів одночасно—уже архітектурне питання. Послідовні RPC-запити на кожний токен дають неприйнятну затримку та навантажують ноду. Тут потрібні Multicall та грамотне кешування.
Пакетна завантаження балансів через Multicall3
Multicall3—контракт 0xcA11bde05977b3631167028862bE2a173976CA11, задеплоений у більшості EVM-мереж (Ethereum, Polygon, BNB Chain, Arbitrum, Optimism, Base). Один вклик aggregate3 повертає балансі всіх токенів за одну транзакцію читання.
// 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'ів. Нульові приховуємо за умовчанням, але даємо опцію «показати всі».
Курси токенів та фіатний еквівалент
Відображення балансу без фіатного еквіваленту—половина роботи. Для отримання курсів: CoinGecko API (/simple/price?ids=...&vs_currencies=usd) або CoinMarketCap. CoinGecko Free tier—30 запитів на хвилину, достатньо для більшості гаманців.
Ключі токенів для CoinGecko—це contract address, не тикер. Для Ethereum: https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses=0x...&vs_currencies=usd. Запит до 100 контрактів за раз—пакетуй.
Кешування та частота оновлення
| Дані | Частота оновлення | Зберігання |
|---|---|---|
| Балансі токенів | Щих 30 сек / pull-to-refresh | In-memory |
| Список токенів користувача | При кожному запуску | SQLite / UserDefaults |
| Курси токенів | Щих 60 сек | In-memory + disk cache |
| Метадані токена (ім'я, decimals) | Однократно | SQLite |
Decimals токена критично важливі: ERC-20 повертає баланс у мінімальних одиницях. USDC—6 decimals, ETH—18. Відображуваний баланс: rawBalance / 10^decimals. Помилка в decimals—баланс покаже астрономічну або нулову суму.
Сроки: 3–5 днів: Multicall3 для EVM, SPL-аккаунти для Solana, інтеграція курсів, кешування, UI списку з pull-to-refresh. Якщо потрібна мультисеть (ETH + BSC + Polygon + Solana одночасно)—5–7 днів.







