> For the complete documentation index, see [llms.txt](https://fgmedia.gitbook.io/articles/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://fgmedia.gitbook.io/articles/unified-apis-vs-native-json-rpc-when-normalized-on-chain-data-wins.md).

# Unified APIs vs Native JSON-RPC: When Normalized On-Chain Data Wins

Every multi-chain integration starts with an endpoint. A developer adding support for a new network — searching for a story rpc url to wire an application into Story Protocol, for instance — pastes the address into a config file, requests the latest block, and gets a valid response within a minute. The hard part begins after that handshake. Event layouts differ between chains, token metadata lives in different places, and code written against Ethereum mainnet quietly returns wrong numbers on Arbitrum or Solana. The choice between calling nodes directly over JSON-RPC — pointing an app at a [rollux json rpc](https://crypto-chief.com/rpc/rollux/) endpoint, say — and reading from a unified API with a normalized schema decides how much of that pain repeats with every network added later.

Both approaches read the same ledgers. The difference is who performs the translation. Native RPC hands over raw chain state: hex-encoded, chain-specific, unopinionated. A unified API sits on top of indexed copies of many chains and answers questions in one schema — a token transfer has the same shape whether it happened on Base, Polygon, or Solana. Each model fails in different places, and those failure modes matter more than any feature list.

### What Native JSON-RPC Actually Provides

An Ethereum node exposes a few dozen standard methods. `eth_getBlockByNumber` returns headers and transactions, `eth_getLogs` filters event logs by address and topic, `eth_call` executes contract reads without a transaction, `eth_getTransactionReceipt` reports execution results, and `debug_traceTransaction` replays a transaction opcode by opcode on nodes that enable it. Responses arrive as hex strings. A balance comes back as `0x2386f26fc10000`, and converting it to 0.01 ETH is the caller's job — as is fetching a token's `decimals()` value before displaying any ERC-20 amount.

Outside the EVM, the vocabulary changes completely. Solana clients call `getSignaturesForAddress` and `getAccountInfo`, receive base58- or base64-encoded account buffers, and decode them with Borsh according to each program's layout. Cosmos-based chains lean on gRPC and REST with protobuf messages. Bitcoin Core speaks its own RPC dialect built around UTXOs. Even inside the EVM family the standard drifts: Arbitrum receipts carry a `gasUsedForL1` field, OP Stack chains such as Base include type `0x7e` deposit transactions that have no sender signature, and Polygon's Bor client injects state-sync transactions that follow none of the usual patterns. Code assuming every transaction is signed, or that gas accounting is uniform, breaks on at least one of these networks.

What raw access buys is immediacy and precision. A node answers from its current view of the chain with no indexing pipeline in between. For pending transactions, mempool visibility, and contract simulation, nothing else is equivalent.

### What a Unified API Changes

Indexing providers — Alchemy, QuickNode, Moralis, Covalent's GoldRush, Bitquery, The Graph — run full pipelines that ingest blocks, decode logs against known ABIs, resolve token metadata, filter spam contracts, and store the result in queryable form. A single request with the semantics "all token transfers for wallet X" returns an array where each item carries the chain identifier, a human-readable timestamp, the decoded value with decimals already applied, the token symbol, the counterparty, and often a USD price at the moment of transfer.

Behind that one response sits work the caller would otherwise repeat per chain: windowed log scans, ABI resolution through proxy contracts, IPFS fetches for NFT images, reorg tracking, and cursor-based pagination. One category deserves special mention. Native ETH sent by a contract emits no event log at all; it appears only in execution traces retrieved through `trace_block` or `debug_traceBlock`, methods many hosted nodes disable. Unified transfer endpoints include these internal transfers because the indexer already ran the traces. An RPC-only integration that skips tracing will silently miss part of a wallet's history.

Pricing follows a different logic as well. Providers bill in compute units or credits, and a single indexed query replaces what would have been thousands of sequential `eth_getLogs` calls — cheaper in practice despite the per-request price looking higher.

### The Real Cost of Raw Access

Balance enumeration exposes the gap fastest. No RPC method lists which ERC-20 tokens a wallet holds. The integrator either maintains an allowlist of contracts and batches `balanceOf` reads through Multicall3 at `0xcA11bde05977b3631167028862bE2a173976CA11`, or reconstructs holdings by scanning every Transfer log where the wallet appears as sender or recipient — topic0 `0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef`. Ethereum mainnet has passed 22 million blocks, and hosted endpoints cap `eth_getLogs` at a few thousand blocks per request or roughly 10,000 matching logs. A full-history scan means thousands of sequential requests per wallet, per chain. Historical balances at a past block height add another requirement: `eth_call` against an archive node, which consumes multiple terabytes of disk to self-host or a premium tier to rent.

Decoding brings its own tax. Events are meaningless without ABIs, four-byte function selectors collide between unrelated contracts, and EIP-1967 proxies hide the implementation ABI behind a storage slot. Token contracts break assumptions individually: MKR stores its symbol as `bytes32` rather than a string, USDT's `transfer` returns no boolean and trips strict decoders, fee-on-transfer tokens log a value larger than what the recipient receives, and rebasing tokens such as stETH change every holder's balance daily without emitting a single Transfer event. Accounting built purely on logs drifts away from `balanceOf` truth within days.

Reorganizations finish the list. A block read at the head of the chain is not final. Polygon rewrote more than 150 consecutive blocks in one 2023 reorg, and shallow reorgs of one or two blocks remain routine on several networks. A raw pipeline must store block hashes, detect replaced blocks, and roll back derived state. Unified APIs absorb this behind confirmation counts and finality flags — at the price of trailing the chain head.

### Where Direct RPC Wins

None of the above makes raw access obsolete. Several workloads permit no substitute:

* **Transaction submission.** `eth_sendRawTransaction` is the only door for writes. No unified read layer signs or broadcasts anything.
* **Mempool and low-latency reads.** A websocket subscription to `newPendingTransactions` or `newHeads` delivers sub-second signal. Indexed APIs trail the head by a block or more, which disqualifies them for arbitrage, liquidations, and MEV work.
* **Simulation and debugging.** `eth_call` with state overrides, `eth_estimateGas`, and `debug_traceCall` execute against exact node state — required for previewing swaps or reproducing a failed transaction.
* **New and niche chains.** Indexing coverage lags chain launches by weeks or months. Day-one integration with a fresh L2 or an appchain runs on raw RPC or nothing.
* **Trust minimization.** Reading from a node you operate removes a third party from the data path, which matters when the number on screen moves money.

Latency numbers frame the trade. A `newHeads` subscription reflects a block within hundreds of milliseconds of propagation. Indexed endpoints typically sit one to three blocks behind, plus cache TTLs. A liquidation bot that sees prices 12 seconds late loses; a portfolio dashboard refreshed on page load never notices.

### Side-by-Side Comparison

| Dimension              | Native JSON-RPC                                | Unified API                               |
| ---------------------- | ---------------------------------------------- | ----------------------------------------- |
| Data freshness         | Chain head and mempool                         | Typically 1–3 blocks of indexing lag      |
| Historical queries     | Archive node required                          | Precomputed, included                     |
| Multi-chain effort     | New adapter per chain family                   | One schema across chains                  |
| Event decoding         | Caller supplies ABIs                           | Pre-decoded, metadata attached            |
| Internal ETH transfers | Only via trace methods                         | Present in transfer endpoints             |
| Cost shape             | Cheap per call, expensive to reconstruct state | Credit-based; one call replaces thousands |
| Write operations       | Full support                                   | Not applicable                            |
| Trust model            | Your node is the source of truth               | Provider's indexer is trusted             |

Read the table by data path rather than by product. The same application usually crosses several rows at once, and the right answer differs per row.

### Walkthrough: A Four-Chain Portfolio Tracker

Take a concrete build: a dashboard showing current balances and 90 days of transfer history for wallets on Ethereum, Base, Polygon, and Solana. The RPC-only version proceeds in these steps:

1. **Discover holdings per EVM chain.** Scan Transfer logs in both directions with windowed `eth_getLogs` calls. Base produces a block every 2 seconds, so 90 days is roughly 3.9 million blocks; at 2,000-block windows that is close to 2,000 requests per direction, per wallet, on one chain.
2. **Separate token standards.** ERC-20 and ERC-721 share the same topic0 signature. They differ in topic count: ERC-20 logs carry three topics with the value in the data field, ERC-721 logs carry four because `tokenId` is indexed. ERC-1155 uses `TransferSingle` and `TransferBatch` with different signatures entirely, so the parser needs three code paths.
3. **Resolve metadata.** Batch `symbol`, `name`, and `decimals` through Multicall3, special-case `bytes32` symbols like MKR, cache results, and filter the spam airdrop contracts that hit every active wallet by the hundred.
4. **Compute balances.** Batch `balanceOf` at the latest block and reconcile against log-derived history. For stETH and other rebasing tokens the reconciliation fails by design, so `balanceOf` becomes the source of truth and logs become a display layer.
5. **Build the Solana branch.** `getTokenAccountsByOwner` with `jsonParsed` encoding for SPL balances, a `getSignaturesForAddress` plus `getTransaction` loop for history, and Metaplex PDA derivation for token metadata. Zero code reuse from the EVM branch.
6. **Add reorg and price layers.** Track block hashes on Polygon and Base, implement rollback for replaced blocks, and join an external price feed by contract address and timestamp.

Budget three to six engineer-weeks, then permanent maintenance as chains upgrade. The unified version calls one transfers endpoint and one balances endpoint per chain, receives identical JSON shapes with prices attached and cursors for paging, and gets Solana normalized into the same schema. The build shrinks to days. What the team accepts in exchange: a monthly bill, indexing lag measured in blocks, and trust in the provider's decoding.

### Hybrid Architectures in Production

Most mature systems split the paths instead of picking a side. Reads flow from a unified API or an in-house indexer; writes and simulations go through raw RPC. A verification tier covers the gap between the two trust models: before displaying a settlement-critical value — the collateral backing a loan, the payout of a redemption — the service re-reads it with `eth_call` against a node and compares. Streaming replaces polling where freshness matters: provider webhooks or managed streams push decoded events into a queue, while a lightweight `newHeads` websocket subscription acts as a heartbeat confirming the pipeline keeps pace with the chain.

Teams with heavy query volume or custom schema needs eventually add a third option: self-hosted indexers built with Ponder, Shovel, Subsquid, or subgraphs. These sit between the extremes — your schema and your infrastructure, but an indexing pipeline you now operate and reorg-proof yourself.

| Task                                      | Better fit                         |
| ----------------------------------------- | ---------------------------------- |
| Signing and broadcasting transactions     | Native RPC                         |
| Mempool monitoring, MEV, liquidations     | Native RPC over websocket          |
| Wallet balances across five chains        | Unified API                        |
| NFT metadata and media resolution         | Unified API                        |
| Transaction simulation and gas estimation | Native RPC                         |
| 90-day transfer history with prices       | Unified API or own indexer         |
| Day-one support for a new chain           | Native RPC                         |
| Settlement-critical values                | Unified read plus RPC verification |

### FAQs

#### Is a unified API slower than calling a node directly?

For head-of-chain data, yes: expect one to three blocks of indexing lag plus caching. For historical aggregates the relationship inverts — a 90-day transfer history returns in one paginated response instead of thousands of sequential log scans, so the indexed path is faster by orders of magnitude.

#### Can normalized data be trusted for financial logic?

For display and analytics, yes. For anything that settles value, verify the specific number with `eth_call` against a node before acting on it. Providers correct decoding bugs silently, and their indexer is a dependency outside your audit scope.

#### Do unified APIs remove the need for an RPC endpoint entirely?

No. Transaction submission, gas estimation, simulation, and websocket subscriptions all require direct node access. Nearly every production application runs both layers side by side.

#### How do these services handle chain reorganizations?

Through confirmation thresholds, finality flags, and delayed indexing of the newest blocks; webhook products additionally emit removal events for logs that a reorg erased. Before committing, ask a provider exactly how it signals removed data — the answer varies, and on chains without fast finality it defines your correctness.

#### What happens when a chain my product needs is not covered?

Fall back to raw RPC or a self-hosted indexer until coverage arrives. Designing reads behind an internal adapter interface keeps that swap cheap: the application consumes your schema, and the adapter decides whether a provider or a node fills it.

#### When does running my own indexer beat both options?

At high query volume, when the schema is specific to your own contracts, or when cost predictability outweighs convenience. Protocol teams indexing their own deployments with Ponder or a subgraph get exact decoding and fixed infrastructure costs, at the price of operating the pipeline.

### Conclusion

Pick the layer per data path, not per project. Writes, mempool access, simulation, and anything sensitive to a single block of latency belong on native JSON-RPC — no indexed product substitutes for them. Cross-chain reads, transfer history, token metadata, and balance enumeration belong on normalized schemas, where a unified API collapses weeks of adapter code and edge-case handling into a handful of requests. The costs are symmetric: raw access charges in engineering time and operational risk, normalized access charges in fees, indexing lag, and provider trust. Production systems that last tend to converge on the same shape — normalize the reads, keep the writes raw, and verify with a node any number that moves money.
