Skip to content

zeriontech/dune-sim-compat

Repository files navigation

@zerion/dune-sim-compat

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.

Migrate in 3 steps

  1. Get a Zerion API key at dashboard.zerion.io.

  2. Install the shim.

    npm install @zerion/dune-sim-compat
  3. 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.

Quickstart

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");

Pagination

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);

Two things to know before you ship

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.

Error handling

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.
  }
}

Supported endpoints

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

Unsupported (throws SimCompatUnsupportedError)

  • Token holders — Zerion has no equivalent
  • Raw RPC-style transactions — Zerion /transactions is 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

Feedback

This is a preview release. If you hit something unexpected, open a GitHub issue or email api@zerion.io.

Reference

Full Zerion field reference: developers.zerion.io/migrate-from-sim.

About

Drop-in TypeScript shim for migrating from the Dune SIM API to the Zerion API. Same response shapes, one import to change.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors