Status: v0.1.0-preview. Looking for design-partner feedback before publishing. Field mapping verified against side-by-side responses from 9 EOA wallets across EVM multi-chain, Base, Hyperevm, MegaETH, Monad, Solana, and NFTs. Open issues are tracked in GitHub Issues.
Drop-in compatibility shim for migrating from the Dune SIM API (sunsetting) to the Zerion API.
Replace your SIM client with SimClient; the response shapes stay the same. Pagination cursors round-trip. Field names, error semantics, and the SIM-style two-call pattern (balances + defi/positions) all keep working.
-
Get a Zerion API key at dashboard.zerion.io.
-
Install the shim.
npm install @zerion/dune-sim-compat
-
Swap one import.
- import { DuneSimClient } from "@duneanalytics/sim-sdk"; - const sim = new DuneSimClient({ apiKey: process.env.SIM_API_KEY }); + import { SimClient } from "@zerion/dune-sim-compat"; + const sim = new SimClient({ apiKey: process.env.ZERION_API_KEY }); // Everything else stays the same: const balances = await sim.getBalances(addr, { exclude_spam_tokens: true }); const activity = await sim.getActivity(addr, { limit: 25 }); const defi = await sim.getDefiPositions(addr); const nfts = await sim.getCollectibles(addr);
That's it. Skim KNOWN_DIFFS.md for the handful of fields that behave differently, then deploy.
import { SimClient } from "@zerion/dune-sim-compat";
const sim = new SimClient({ apiKey: process.env.ZERION_API_KEY! });
// SIM /v1/evm/balances
const balances = await sim.getBalances("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", {
exclude_spam_tokens: true,
limit: 100,
});
console.log(balances.balances[0].symbol, balances.balances[0].value_usd);
// SIM /v1/evm/activity
const activity = await sim.getActivity("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", { limit: 25 });
// SIM /v1/evm/defi/positions
const defi = await sim.getDefiPositions("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", {
include_aggregations: true,
});
// SIM /v1/evm/collectibles
const nfts = await sim.getCollectibles("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", { limit: 50 });
// SIM /beta/svm/balances
const solBalances = await sim.getSvmBalances("6sEk1enayZBGFyNvvJMTP7qs5S3uC7KLrQWaEk38hSHH");SIM-style: pass the next_offset back as offset. The cursor is opaque (base64-encoded Zerion links.next); don't parse it.
let cursor: string | undefined;
do {
const page = await sim.getActivity(addr, { offset: cursor, limit: 25 });
// ... process page.activity
cursor = page.next_offset ?? undefined;
} while (cursor);These are the two behavioral differences most likely to surprise a SIM customer. Both are by design and documented in detail in KNOWN_DIFFS.md.
1. Smart contracts are blocked by default. Zerion blocks /transactions/ and /nft-positions/ indexing for smart contracts (CEX hot wallets, burn addresses, etc.). The shim raises a typed SimCompatSmartContractError when this happens. Balances and DeFi positions still work for contracts. Email api@zerion.io to enable indexing for specific contracts you depend on.
2. DeFi categorization is stricter. SIM treats ERC-4626 vault tokens (sUSDS, aDAI, kWBNB, UniswapV2 LP tokens) as DeFi positions. Zerion classifies them as wallet balances, since they're still ERC-20s. The same tokens show up in getBalances, just under a different conceptual label. If your code branches on "is this a DeFi position?", review it.
import {
SimClient,
SimCompatHttpError,
SimCompatSmartContractError,
SimCompatUnsupportedError,
} from "@zerion/dune-sim-compat";
try {
await sim.getActivity(addr);
} catch (e) {
if (e instanceof SimCompatSmartContractError) {
// contract address — skip, fall back, or email Zerion
} else if (e instanceof SimCompatUnsupportedError) {
// calling an endpoint with no Zerion equivalent (token holders, raw txs, ...)
} else if (e instanceof SimCompatHttpError) {
// other Zerion non-OK response. e.status is exposed for retry logic.
}
}| SIM endpoint | Shim method | Underlying Zerion |
|---|---|---|
GET /v1/evm/balances/{addr} |
getBalances |
/v1/wallets/{addr}/positions/?filter[positions]=only_simple |
GET /v1/evm/activity/{addr} |
getActivity |
/v1/wallets/{addr}/transactions/ |
GET /v1/evm/defi/positions/{addr} |
getDefiPositions |
/v1/wallets/{addr}/positions/?filter[positions]=only_complex |
GET /v1/evm/collectibles/{addr} |
getCollectibles |
/v1/wallets/{addr}/nft-positions/ |
GET /beta/svm/balances/{addr} |
getSvmBalances |
/v1/wallets/{addr}/positions/?filter[chain_ids]=solana&filter[positions]=only_simple |
- Token holders — Zerion has no equivalent
- Raw RPC-style transactions — Zerion
/transactionsis enriched, not raw - Historical prices on balances — use
/v1/fungibles/{id}/charts/{period}directly - Solana DeFi positions — Zerion doesn't support these yet
- Eclipse SVM chain — not on Zerion's supported chains list
This is a preview release. If you hit something unexpected, open a GitHub issue or email api@zerion.io.
Full Zerion field reference: developers.zerion.io/migrate-from-sim.