<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Envio Blog</title>
        <link>https://docs.envio.dev/blog</link>
        <description>Envio Blog</description>
        <lastBuildDate>Wed, 03 Jun 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Just-in-Time Indexing: Using Agents to Answer Onchain Questions]]></title>
            <link>https://docs.envio.dev/blog/just-in-time-indexing-agents-onchain</link>
            <guid>https://docs.envio.dev/blog/just-in-time-indexing-agents-onchain</guid>
            <pubDate>Wed, 03 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[How to use an AI agent and Envio to answer one-off onchain questions without maintaining permanent infrastructure - build the indexer on demand, query it once, and delete it.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/just-in-time-indexing-agents-onchain.png" alt="Just-in-Time Indexing: Using Agents to Answer Onchain Questions" width="100%">
<p>Just-in-time indexing is a way of using an AI agent to answer one-off questions about onchain data without maintaining permanent infrastructure or finding a pre-indexed data point. Rather than building an indexer in advance and keeping it running, the dataset is built on demand when a question comes up, read once, and deleted afterward.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-it-works">How it Works<a class="hash-link" aria-label="Direct link to How it Works" title="Direct link to How it Works" href="https://docs.envio.dev/blog/just-in-time-indexing-agents-onchain#how-it-works">​</a></h2>
<p>One user, Michael K from Curve Finance, uses it for ad hoc analysis of pool activity. The flow starts with a plain-language prompt to Claude, for example: "Use Envio to parse all the trades from this pool."</p>
<p>Claude, using Envio's tooling, generates the indexer: the config, schema, and event handlers, scoped to the specific contract and events in the question. It deploys to Envio's free development plan cloud service with <code>envio-cloud</code>, the CLI, and the indexer backfills from scratch. After 5 to 10 minutes, the data is ready to query. Once the researcher has pulled what they need, they delete the indexer.</p>
<div style="margin:2rem 0;padding:1.5rem 2rem;border-left:4px solid #f97316;background:rgba(249,115,22,0.06);border-radius:0 8px 8px 0"><p style="font-size:1.1rem;font-style:italic;margin-bottom:0.75rem">"One of the simplest ways to get large datasets of onchain data for our research purposes."</p><p style="margin:0;font-weight:600">Michael K, Researcher at Curve Finance</p></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-the-free-tier-covers-it">Why the Free Tier Covers it<a class="hash-link" aria-label="Direct link to Why the Free Tier Covers it" title="Direct link to Why the Free Tier Covers it" href="https://docs.envio.dev/blog/just-in-time-indexing-agents-onchain#why-the-free-tier-covers-it">​</a></h2>
<p>The workflow runs on Envio's free hosted cloud tier. The requests are one-off, so a single repo is enough: the agent manages it and deploys each question as a branch. A backfill of 5 to 10 minutes is acceptable for ad hoc work, where the alternative is building a pipeline by hand.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-pattern">The Pattern<a class="hash-link" aria-label="Direct link to The Pattern" title="Direct link to The Pattern" href="https://docs.envio.dev/blog/just-in-time-indexing-agents-onchain#the-pattern">​</a></h2>
<p>Traditional indexing requires deciding what data is needed, building the pipeline, and then querying it, which limits the user to questions planned for in advance. Just-in-time indexing reverses the order: the question comes first, and the dataset is built to answer it.</p>
<p>This works because backfilling takes minutes rather than days, and because an agent can stand up the indexer from a natural-language prompt without anyone writing config by hand. The same pattern applies to any agent or user asking one-off onchain questions.</p>
<div style="margin:2rem 0;padding:1.5rem 2rem;border-left:4px solid #f97316;background:rgba(249,115,22,0.06);border-radius:0 8px 8px 0"><p style="font-size:1.1rem;font-style:italic;margin-bottom:0.75rem">"We use Envio regularly to parse all kinds of data from all kinds of contracts across dozens of chains."</p><p style="margin:0;font-weight:600">Michael K, Researcher at Curve Finance</p></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/just-in-time-indexing-agents-onchain#build-with-envio">​</a></h2>
<p>Envio is a real-time multichain blockchain indexer that turns onchain events into a queryable GraphQL API. Supports any EVM chain, plus Solana and Fuel. Use <a href="https://docs.envio.dev/docs/HyperIndex/hosted-service" target="_blank" rel="noopener noreferrer">Envio Cloud</a> or self-host. If you're building onchain, come talk to us about your data needs.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a> 💌</p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>ai</category>
        </item>
        <item>
            <title><![CDATA[How to Index Sei Smart Contract Data in Minutes using Envio]]></title>
            <link>https://docs.envio.dev/blog/index-sei-smart-contracts-envio</link>
            <guid>https://docs.envio.dev/blog/index-sei-smart-contracts-envio</guid>
            <pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[A step-by-step guide to indexing a Sei ERC20 contract with Envio HyperIndex. Build a local indexer that streams Sei USDC Transfer and Approval events into Postgres and serves them through a GraphQL API.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/index-sei-smart-contracts-envio.png" alt="Envio cover banner with Sei logo and headline 'Indexing Sei Data in Minutes: A step-by-step guide'" width="100%">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>Scaffold the ERC20 template with <code>pnpx envio init template -t erc20 -d ./sei-indexer</code></li>
<li>Point <code>config.yaml</code> at Sei mainnet (chain ID <code>1329</code>, start block <code>79123881</code>) and USDC at <code>0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392</code></li>
<li>Define an <code>Account</code> and <code>Approval</code> schema, write <code>Transfer</code> and <code>Approval</code> handlers in <code>src/handlers/MyContract.ts</code></li>
<li>Run <code>pnpm codegen</code>, then <code>pnpm dev</code>, and query live Sei USDC data at <code>http://localhost:8080/v1/graphql</code></li>
</ul></div></div>
<p>This guide walks you through building a HyperIndex indexer for a smart contract on Sei. By the end, you will have a local indexer that streams Sei blockchain data into a Postgres database and serves it through a GraphQL API.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-you-will-build">What you will build<a class="hash-link" aria-label="Direct link to What you will build" title="Direct link to What you will build" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#what-you-will-build">​</a></h2>
<p>An indexer for USDC on Sei mainnet (Circle's native USDC). It tracks <code>Transfer</code> and <code>Approval</code> events, keeps a running token balance per account, and records every approval.</p>
<p>Target contract:</p>
<ul>
<li>Chain: Sei mainnet, chain ID <code>1329</code></li>
<li>Contract address: <code>0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392</code></li>
<li>Explorer: <a href="https://seitrace.com/address/0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392" target="_blank" rel="noopener noreferrer">seitrace.com</a></li>
</ul>
<p>Indexing testnet instead? See the <a href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#indexing-on-sei-testnet">Indexing on Sei testnet</a> section at the bottom of this guide for the testnet config changes.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="steps-at-a-glance">Steps at a glance<a class="hash-link" aria-label="Direct link to Steps at a glance" title="Direct link to Steps at a glance" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#steps-at-a-glance">​</a></h2>
<ol>
<li>Scaffold the indexer</li>
<li>Configure the indexer for Sei</li>
<li>Define the data schema</li>
<li>Write the event handler</li>
<li>Generate types</li>
<li>Run the indexer</li>
<li>Query your data</li>
<li>Stop the indexer</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="before-you-begin">Before you begin<a class="hash-link" aria-label="Direct link to Before you begin" title="Direct link to Before you begin" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#before-you-begin">​</a></h2>
<p>Make sure you have the following prerequisites installed. Run each check in a terminal:</p>
<ul>
<li>Node.js v22 or later. Check with <code>node -v</code>.</li>
<li>pnpm v8 or later. Check with <code>pnpm -v</code>.</li>
<li>Docker installed and running. Check with <code>docker ps</code>.</li>
<li>A free Envio API token. HyperIndex requires an API token to use HyperSync as a data source. Create one at <a href="https://envio.dev/app/api-tokens" target="_blank" rel="noopener noreferrer">envio.dev/app/api-tokens</a>.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-1-scaffold-the-indexer">Step 1: Scaffold the indexer<a class="hash-link" aria-label="Direct link to Step 1: Scaffold the indexer" title="Direct link to Step 1: Scaffold the indexer" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-1-scaffold-the-indexer">​</a></h2>
<p>Create a new HyperIndex project from the ERC20 template, then move into the project folder:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio init template </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-t</span><span class="token plain"> erc20 </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-d</span><span class="token plain"> ./sei-indexer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> sei-indexer</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>During the init flow you'll be prompted for an Envio API token. Paste an existing one or follow the prompt to create a new one at <a href="https://envio.dev/app/api-tokens" target="_blank" rel="noopener noreferrer">envio.dev/app/api-tokens</a>. The CLI writes it to <code>.env</code> for you.</p>
<p>A new <code>sei-indexer</code> folder is created with <code>config.yaml</code>, <code>schema.graphql</code>, a <code>.env</code> file, and a <code>src/handlers/</code> directory. Every file in <code>src/handlers/</code> is registered automatically, so there is no central <code>EventHandlers.ts</code> file. Generated types are written to the <code>.envio/</code> directory.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-2-configure-the-indexer-for-sei">Step 2: Configure the indexer for Sei<a class="hash-link" aria-label="Direct link to Step 2: Configure the indexer for Sei" title="Direct link to Step 2: Configure the indexer for Sei" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-2-configure-the-indexer-for-sei">​</a></h2>
<p>Replace the contents of <code>config.yaml</code> with the configuration below. This points the indexer at Sei mainnet and the USDC contract, and selects the two events to index:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># yaml-language-server: $schema=./node_modules/envio/evm.schema.json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> sei</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">indexer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Sei ERC20 indexer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> MyContract</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">events</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Transfer(address indexed from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> address indexed to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> uint256 value)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Approval(address indexed owner</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> address indexed spender</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> uint256 value)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">chains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1329</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)"># Sei mainnet (pacific-1)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">79123881</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> MyContract</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Important: <code>start_block: 79123881</code> is the first EVM block on Sei mainnet. Earlier blocks are non-EVM and have no Solidity events to index. Setting it to <code>0</code> will waste time scanning blocks that can never match. Sei is a supported HyperSync network, so the endpoint resolves automatically from the chain ID. No <code>hypersync_config</code> block is needed.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-3-define-the-data-schema">Step 3: Define the data schema<a class="hash-link" aria-label="Direct link to Step 3: Define the data schema" title="Direct link to Step 3: Define the data schema" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-3-define-the-data-schema">​</a></h2>
<p>Replace the contents of <code>schema.graphql</code> with the schema below. Each type becomes a database table and a GraphQL query:</p>
<div class="language-graphql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-graphql codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">Account</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">ID</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">balance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BigInt</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">approvals</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token class-name">Approval</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token operator">!</span><span class="token plain"> </span><span class="token directive function" style="color:rgb(80, 250, 123)">@derivedFrom</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token attr-name" style="color:rgb(241, 250, 140)">field</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"owner"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">Approval</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">ID</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">owner</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">Account</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">spender</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">String</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BigInt</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">blockNumber</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BigInt</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BigInt</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>@derivedFrom</code> directive creates a virtual reverse lookup, so each <code>Account</code> exposes its list of approvals without you storing that list explicitly.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-4-write-the-event-handler">Step 4: Write the event handler<a class="hash-link" aria-label="Direct link to Step 4: Write the event handler" title="Direct link to Step 4: Write the event handler" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-4-write-the-event-handler">​</a></h2>
<p>The ERC20 template ships a handler and a test file that both reference the template contract. Remove them first:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">rm</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-f</span><span class="token plain"> src/handlers/ERC20.ts src/indexer.test.ts</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Note: Removing <code>src/indexer.test.ts</code> matters. It imports the deleted ERC20 handler, so leaving it in place breaks <code>pnpm test</code>.</p>
<p>Now create a new handler file at <code>src/handlers/MyContract.ts</code> with the following content:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> indexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"envio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">onEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> contract</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MyContract"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> event</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Transfer"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> value </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> sender </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      id</span><span class="token operator">:</span><span class="token plain"> from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      balance</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sender</span><span class="token operator">?.</span><span class="token plain">balance </span><span class="token operator">??</span><span class="token plain"> </span><span class="token number">0n</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> receiver </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      id</span><span class="token operator">:</span><span class="token plain"> to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      balance</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">receiver</span><span class="token operator">?.</span><span class="token plain">balance </span><span class="token operator">??</span><span class="token plain"> </span><span class="token number">0n</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">+</span><span class="token plain"> value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">onEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> contract</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MyContract"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> event</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Approval"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> owner</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> spender</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> value </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> existing </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">owner</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      id</span><span class="token operator">:</span><span class="token plain"> owner</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      balance</span><span class="token operator">:</span><span class="token plain"> existing</span><span class="token operator">?.</span><span class="token plain">balance </span><span class="token operator">??</span><span class="token plain"> </span><span class="token number">0n</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Approval</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      id</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">block</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">hash</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">-</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">logIndex</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      owner_id</span><span class="token operator">:</span><span class="token plain"> owner</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      spender</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      blockNumber</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">BigInt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">number</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      timestamp</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">BigInt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Key points about the handler API:</p>
<ul>
<li>Handlers are registered with <code>indexer.onEvent</code>, imported from the <code>envio</code> package.</li>
<li>Linked entities are set with the <code>&lt;field&gt;_id</code> convention, so the <code>owner</code> relation is written as <code>owner_id</code>.</li>
<li>Event metadata is available on the <code>event</code> object, including <code>event.block</code> (<code>number</code>, <code>timestamp</code>, <code>hash</code>), <code>event.logIndex</code>, <code>event.srcAddress</code>, and more. See the <a href="https://docs.envio.dev/docs/HyperIndex/event-handlers" target="_blank" rel="noopener noreferrer">Event Handlers</a> docs for the full list.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-5-generate-types">Step 5: Generate types<a class="hash-link" aria-label="Direct link to Step 5: Generate types" title="Direct link to Step 5: Generate types" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-5-generate-types">​</a></h2>
<p>Generate the typed code from your config and schema:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> codegen</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The command reads <code>config.yaml</code> and <code>schema.graphql</code>, writes typed code into <code>.envio/</code>, and exits with no errors. Run this again any time you change the config or schema.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-6-run-the-indexer">Step 6: Run the indexer<a class="hash-link" aria-label="Direct link to Step 6: Run the indexer" title="Direct link to Step 6: Run the indexer" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-6-run-the-indexer">​</a></h2>
<p>Start the indexer in development mode:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> dev</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Envio starts Postgres and Hasura in Docker, then begins streaming Sei blocks through HyperSync. Indexed data appears within seconds. Leave this terminal running.</p>
<p>You can explore the data in the Envio Console.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-7-query-your-data">Step 7: Query your data<a class="hash-link" aria-label="Direct link to Step 7: Query your data" title="Direct link to Step 7: Query your data" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-7-query-your-data">​</a></h2>
<p>With the indexer still running, open a new terminal and query the GraphQL API. This asks for the top 3 accounts by USDC balance and the 3 most recent approvals:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">curl</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-s</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-X</span><span class="token plain"> POST http://localhost:8080/v1/graphql </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-H</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Content-Type: application/json"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-d</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'{"query":"{ Account(limit: 3, order_by: { balance: desc }) { id balance } Approval(limit: 3, order_by: { blockNumber: desc }) { id spender value blockNumber } }"}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You will get back JSON with <code>Account</code> and <code>Approval</code> rows from live Sei USDC activity. If the response is empty, wait a few seconds for the indexer to sync further and run the query again. USDC has six decimals on Sei, so a balance of <code>1000000</code> represents 1 USDC.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-8-stop-the-indexer">Step 8: Stop the indexer<a class="hash-link" aria-label="Direct link to Step 8: Stop the indexer" title="Direct link to Step 8: Stop the indexer" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-8-stop-the-indexer">​</a></h2>
<p>Stop <code>pnpm dev</code> with Ctrl+C in its terminal, then clean up the local environment:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> envio stop</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Important: This stops the Docker containers and removes the local database. Do not use <code>docker compose down</code>. HyperIndex manages its containers directly, so <code>docker compose down</code> fails.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="indexing-on-sei-testnet">Indexing on Sei testnet<a class="hash-link" aria-label="Direct link to Indexing on Sei testnet" title="Direct link to Indexing on Sei testnet" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#indexing-on-sei-testnet">​</a></h2>
<p>To target Sei testnet (atlantic-2) instead of mainnet, swap three values in the <code>chains</code> block of <code>config.yaml</code>:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token key atrule">chains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1328</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)"># Sei testnet (atlantic-2)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">186100000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> MyContract</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x4fCF1784B31630811181f670Aea7A7bEF803eaED"</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)"># Testnet USDC</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Notes for testnet:</p>
<ul>
<li>Chain ID is <code>1328</code> (vs. <code>1329</code> on mainnet).</li>
<li>Testnet USDC address: <code>0x4fCF1784B31630811181f670Aea7A7bEF803eaED</code> (verified on Seitrace).</li>
<li><code>start_block: 186100000</code> is the first EVM block on Sei testnet. Earlier blocks are non-EVM.</li>
<li>The HyperSync endpoint (<code>https://sei-testnet.hypersync.xyz</code>) auto-resolves from the chain ID.</li>
<li>To get testnet USDC, use the Circle Faucet so the contract has activity to index.</li>
</ul>
<p>Docs: <a href="https://docs.envio.dev/docs/HyperSync/hypersync-supported-networks" target="_blank" rel="noopener noreferrer">Sei Testnet on Envio</a> | <a href="https://docs.sei.io/evm/usdc-on-sei" target="_blank" rel="noopener noreferrer">USDC on Sei (Sei docs)</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="troubleshooting">Troubleshooting<a class="hash-link" aria-label="Direct link to Troubleshooting" title="Direct link to Troubleshooting" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#troubleshooting">​</a></h2>
<ul>
<li>
<p><strong>"An API token is required for using HyperSync as a data-source"</strong>: set <code>ENVIO_API_TOKEN</code> in <code>.env</code>. The init flow normally prompts for this; if you skipped it, paste a token from <a href="https://envio.dev/app/api-tokens" target="_blank" rel="noopener noreferrer">envio.dev/app/api-tokens</a> into <code>.env</code>.</p>
</li>
<li>
<p><strong>The indexer resumes but makes no progress (progress shows -1)</strong>: the database holds stale state from an earlier aborted run. Run <code>pnpm envio dev -r</code> to wipe the database and re-index from scratch.</p>
</li>
<li>
<p><strong>No events showing up on mainnet</strong>: confirm <code>start_block</code> is at least <code>79123881</code>. Blocks before that are non-EVM on Sei mainnet and contain no Solidity events. On testnet, the equivalent floor is <code>186100000</code>.</p>
</li>
<li>
<p><strong>"Failed to automatically find HyperSync endpoint for the chain 1329"</strong>: if the endpoint doesn't auto-resolve for your CLI version, set it explicitly under the chain entry in <code>config.yaml</code>:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token key atrule">chains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1329</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">79123881</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">hypersync_config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">url</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> https</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain">//sei.hypersync.xyz</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token comment" style="color:rgb(98, 114, 164)"># ...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Use <code>https://sei-testnet.hypersync.xyz</code> for testnet (chain <code>1328</code>).</p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#resources">​</a></h2>
<ul>
<li><a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">HyperIndex overview</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/sei" target="_blank" rel="noopener noreferrer">Sei on Envio</a></li>
<li><a href="https://docs.envio.dev/docs/HyperSync/hypersync-supported-networks" target="_blank" rel="noopener noreferrer">HyperSync supported networks</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/configuration-file" target="_blank" rel="noopener noreferrer">Configuration file</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/schema" target="_blank" rel="noopener noreferrer">Schema reference</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/event-handlers" target="_blank" rel="noopener noreferrer">Event handlers</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/cli-commands" target="_blank" rel="noopener noreferrer">Envio CLI reference</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/running-locally" target="_blank" rel="noopener noreferrer">Running locally</a></li>
<li><a href="https://docs.sei.io/evm/usdc-on-sei" target="_blank" rel="noopener noreferrer">USDC on Sei (Sei docs)</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#build-with-envio">​</a></h2>
<p>Envio is a real-time multichain blockchain indexer that turns onchain events into a queryable GraphQL API. Supports any EVM chain, plus Solana and Fuel. Use Envio Cloud or self-host. If you're building onchain, come talk to us about your data needs.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a></p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://x.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+kAIGElzPjApiMjI0" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>tutorials</category>
        </item>
        <item>
            <title><![CDATA[When to use HyperIndex vs HyperSync]]></title>
            <link>https://docs.envio.dev/blog/hyperindex-vs-hypersync</link>
            <guid>https://docs.envio.dev/blog/hyperindex-vs-hypersync</guid>
            <pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[A technical breakdown of HyperIndex and HyperSync, the two layers of the Envio data stack, with working v3 code and real production examples to help you choose the right one.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="Cover image for When to Use HyperIndex vs HyperSync" src="https://docs.envio.dev/assets/images/hyperindex-vs-hypersync-7bcf5bbfcd0ce6709fb14598467f2909.png" width="1920" height="1115" class="img_ev3q"></p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>HyperSync and HyperIndex are two layers of the same stack. HyperSync is the data engine, HyperIndex is the framework built on it.</li>
<li>HyperSync is a Rust data-retrieval layer that replaces JSON-RPC, up to 2000x faster, with a query, filter, and field-selection model and client libraries for TypeScript/Node.js, Python, Rust, and Go.</li>
<li>HyperIndex is a full framework that turns events into a Postgres database and GraphQL API, with a config file, schema, handlers, automatic reorg handling, factory contract support, and managed hosting.</li>
<li>Reach for HyperIndex when you need a persistent, queryable, reorg-safe dataset behind an API. Reach for HyperSync when you want raw data in your own pipeline, traces, or chain-wide scans.</li>
<li>Because HyperIndex runs on HyperSync, you can use both. Run the framework for your backend and drop to the engine for the jobs that do not fit a schema.</li>
</ul></div></div>
<p>At some point every onchain product needs the same thing. It needs to read data off a chain that was designed for sequential writes, not efficient reads. Envio ships two tools for that job at different layers of the stack, and the right choice depends on how much of the data pipeline you want to own.</p>
<p>In this blog we'll walk through what HyperSync and HyperIndex each are, the architecture that connects them, the code you actually write for each, the production systems running on them today, and a decision framework grounded in those mechanics.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-the-two-layers-relate">How the Two Layers Relate<a class="hash-link" aria-label="Direct link to How the Two Layers Relate" title="Direct link to How the Two Layers Relate" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#how-the-two-layers-relate">​</a></h2>
<p>HyperSync is the data engine. It is written in Rust and delivers up to 2000x faster data access than JSON-RPC across <!-- -->85+<!-- --> EVM chains and Fuel. You describe the logs, transactions, traces, or blocks you want, and it streams them back.</p>
<p>HyperIndex is the framework that sits on top. It uses HyperSync as its primary data source, then adds a config file, a schema, event handlers, multichain coordination, automatic reorg handling, and a GraphQL API. HyperRPC is an abstraction layer on top of HyperSync that exposes a standard JSON-RPC interface, making it a drop-in replacement for a traditional RPC endpoint in existing code.</p>
<p><img decoding="async" loading="lazy" alt="The Envio data stack: HyperIndex and HyperRPC layered on the HyperSync engine" src="https://docs.envio.dev/assets/images/hyperindex-vs-hypersync-stack-175295282008489f1777ba87aad5e142.png" width="1240" height="988" class="img_ev3q"></p>
<p>The Envio data stack. Your application can reach the chain three ways, through the HyperIndex framework, through HyperRPC's JSON-RPC interface, or by querying the HyperSync engine directly. All three sit on the same HyperSync engine, which does the actual work of retrieving data from the blockchain.</p>
<p>The practical consequence of this layering is that raw retrieval speed is not the axis you choose on. All three paths pull data through the same engine. What changes is how much of the pipeline, storage, and API you build yourself.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="hypersync-the-data-engine">HyperSync: The Data Engine<a class="hash-link" aria-label="Direct link to HyperSync: The Data Engine" title="Direct link to HyperSync: The Data Engine" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#hypersync-the-data-engine">​</a></h2>
<p><a href="https://docs.envio.dev/docs/HyperSync/overview" target="_blank" rel="noopener noreferrer">HyperSync</a> gives you the data and nothing else. There is no database, no schema, no API layer, and no hosting. There is a query interface, a fast stream of results, and whatever you build downstream.</p>
<p>You work with a small set of primitives. A query is a single object describing a block range, a filter section, and a field selection. Filters narrow results across logs, transactions, traces, and blocks. Field selection returns only the columns you ask for, which keeps responses small and credit usage low. Output modes decide how you consume results, with <code>client.stream()</code> for in-memory processing, <code>client.collect_json()</code> for small datasets, and <code>client.collect_parquet()</code> for analytical workloads.</p>
<p>A useful way to see what the engine unlocks is native ETH transfers. They do not emit event logs, so the only way to track them is by reading execution traces, which is slow and awkward over RPC. HyperSync exposes trace filtering directly. The example below streams call traces on Ethereum using the trace-enabled endpoint, taken from the <a href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync" target="_blank" rel="noopener noreferrer">native ETH transfers tutorial</a>.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">TraceField</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@envio-dev/hypersync-client"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> client </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  url</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://eth-traces.hypersync.xyz"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  apiToken</span><span class="token operator">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">ENVIO_API_TOKEN</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">let</span><span class="token plain"> query </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  fromBlock</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">22000000</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  traces</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> callType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"call"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  fieldSelection</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    trace</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"From"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"To"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Value"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"CallType"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"BlockNumber"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> TraceField</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> stream </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">stream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">while</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> res </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> stream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">recv</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">res </span><span class="token operator">===</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">break</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">data</span><span class="token operator">?.</span><span class="token plain">traces</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">Got </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">res</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">data</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">traces</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">length</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)"> traces</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">nextBlock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">fromBlock </span><span class="token operator">=</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">nextBlock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Two mechanics in that loop are worth calling out. Filtering on <code>callType</code> rather than trace <code>kind</code> lets the engine skip irrelevant trace types upfront. Feeding <code>res.nextBlock</code> back into the query is the standard way to page through a large range, since a single request has a processing window and returns where it stopped. Trace endpoints are available on a growing set of chains, so check the <a href="https://docs.envio.dev/docs/HyperSync/hypersync-supported-networks" target="_blank" rel="noopener noreferrer">supported networks page</a> for the current list.</p>
<p>Switching chains is a one-line change to the URL, and the same client works against any supported network. Client libraries ship for TypeScript/Node.js, Python, Rust, and Go, plus a curl interface for quick testing.</p>
<p>In production, HyperSync is the layer behind tools that would be impractical on RPC. <a href="https://chaindensity.xyz/" target="_blank" rel="noopener noreferrer">ChainDensity.xyz</a> scans entire chains to render transaction and event density for any address in seconds. <a href="https://scope.sh/" target="_blank" rel="noopener noreferrer">Scope.sh</a> is an Account Abstraction block explorer that leans on HyperSync for fast historical retrieval. LogTUI is a zero-install terminal event viewer you can try right now with <code>pnpx logtui aave arbitrum</code>. The open-source <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">Polymarket reference indexer</a> used HyperSync to sync 4 billion events in 6 days.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="hyperindex-the-framework">HyperIndex: The Framework<a class="hash-link" aria-label="Direct link to HyperIndex: The Framework" title="Direct link to HyperIndex: The Framework" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#hyperindex-the-framework">​</a></h2>
<p><a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">HyperIndex</a> turns onchain events into a structured, queryable database. You declare what to index in a <code>config.yaml</code>, define your data model in a <code>schema.graphql</code>, and write handlers that map events onto entities. The framework owns the rest, including fetching data through HyperSync, persisting to Postgres, serving GraphQL, and rolling back on reorgs.</p>
<p>The config file is the first step to indexing. This one tracks <code>Approval</code> and <code>Transfer</code> on the UNI token across two chains at once, straight from the <a href="https://docs.envio.dev/docs/HyperIndex/configuration-file" target="_blank" rel="noopener noreferrer">configuration docs</a>.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># yaml-language-server: $schema=./node_modules/envio/evm.schema.json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> erc20</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">indexer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ERC</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">20 Indexer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ERC20</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">events</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Approval(address indexed owner, address indexed spender, uint256 value)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Transfer(address indexed from, address indexed to, uint256 value)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">chains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)"># Ethereum Mainnet</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ERC20</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)"># UNI</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">100</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)"># Gnosis Mainnet</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ERC20</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x4537e328Bf7e4eFA29D05CAeA260D7fE26af9D74"</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)"># UNI</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Notice there is no RPC URL. For chains supported by HyperSync, it is the primary data source out of the box, and you can add an RPC entry purely as a fallback. Setting <code>start_block</code> to <code>0</code> is safe because HyperSync fast-forwards to the first block that holds data for your contracts.</p>
<p>The schema defines the entities you query.</p>
<div class="language-graphql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-graphql codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">Transfer</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">ID</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">String</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">String</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BigInt</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The handler maps each event onto those entities. This is the full v3 mental model, where you describe what an event means for your data and the framework keeps the database current.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> indexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"envio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">onEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> contract</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ERC20"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> event</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Transfer"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Transfer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      id</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">chainId</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">_</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">block</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation builtin" style="color:rgb(189, 147, 249)">number</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">_</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">logIndex</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      from</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      to</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      value</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Three framework features do real work here that you would otherwise build by hand.</p>
<p>Factory contracts are handled with a <code>contractRegister</code> handler. When a factory emits a creation event, you register the new contract address and the framework starts indexing it, including events in the same block as the creation. This is how Envio indexes data from over 1M dynamically registered contracts.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> indexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"envio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">contractRegister</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> contract</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"NftFactory"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> event</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"SimpleNftCreated"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">chain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">SimpleNft</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">contractAddress</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>External calls run through the Effect API, which batches and memoizes requests so a network call inside a handler does not become a per-event bottleneck. You define an effect once with optional caching and rate limiting, then call it from any handler.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> createEffect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">S</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"envio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> getMetadata </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">createEffect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"getMetadata"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    input</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">S</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    output</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> description</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">S</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> value</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">S</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">bigint </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    cache</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    rateLimit</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> calls</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">5</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> per</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"second"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> input </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> response </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">fetch</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">https://api.example.com/metadata/</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">input</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> data </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> response</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">json</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> description</span><span class="token operator">:</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">description</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> value</span><span class="token operator">:</span><span class="token plain"> data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Reorg handling is automatic. <code>rollback_on_reorg</code> defaults to <code>true</code>, so the indexer detects reorganisations and rolls affected entities back without you writing recovery logic. You can also keep the indexer a few blocks behind the head with <code>block_lag</code> if you want extra safety, or store entities in ClickHouse alongside Postgres for analytics workloads.</p>
<p>On performance, HyperIndex is the fastest indexer in independent testing. In Sentio's May 2025 benchmark of the Uniswap V2 Factory case, it finished in 8 seconds, 15x faster than the nearest competitor (Subsquid) at 2 minutes, 142x faster than The Graph at 19 minutes, and 157x faster than Ponder at 21 minutes. Historical backfills run at 30,000+ events per second. The full table is on the <a href="https://docs.envio.dev/docs/HyperIndex/benchmarks" target="_blank" rel="noopener noreferrer">benchmarks page</a>, and the <a href="https://github.com/enviodev/open-indexer-benchmark" target="_blank" rel="noopener noreferrer">open-indexer-benchmark repo</a> lets you reproduce it.</p>
<p>In production, the framework shows up wherever a team needs a backend rather than a script. <a href="https://docs.envio.dev/blog/case-study-sablier" target="_blank" rel="noopener noreferrer">Sablier</a> replaced 12 separate indexer deployments with one multichain indexer now spanning 27 chains. The <a href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study" target="_blank" rel="noopener noreferrer">Polymarket case study</a> consolidated 8 subgraphs into a single indexer on Polygon. <a href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex" target="_blank" rel="noopener noreferrer">Revert Finance</a> synced a PancakeSwap V3 dataset on BNB Smart Chain that had been stuck at 70% on The Graph for over two years, reaching 100% in 10 days across 1.7 billion events.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-decision-by-mechanics">The Decision, by Mechanics<a class="hash-link" aria-label="Direct link to The Decision, by Mechanics" title="Direct link to The Decision, by Mechanics" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#the-decision-by-mechanics">​</a></h2>
<p>The choice follows from the architecture. HyperIndex gives you a persistent, structured store and an API in exchange for working within a schema and handler model. HyperSync gives you raw data and total control in exchange for building storage and any API yourself. The table maps concrete needs onto the layer that serves them.</p>
<table><thead><tr><th>If your need is...</th><th>Use</th><th>Why, mechanically</th></tr></thead><tbody><tr><td>A queryable backend or dashboard API</td><td>HyperIndex</td><td>You get Postgres plus a GraphQL endpoint without building either</td></tr><tr><td>One config, one API across many chains</td><td>HyperIndex</td><td>Multichain indexing from a single <code>config.yaml</code> and one GraphQL endpoint</td></tr><tr><td>Reorg-safe state at the head of the chain</td><td>HyperIndex</td><td><code>rollback_on_reorg</code> and real-time indexing are built in</td></tr><tr><td>Indexing factory-deployed contracts</td><td>HyperIndex</td><td><code>contractRegister</code> discovers and tracks new addresses automatically</td></tr><tr><td>No infrastructure to run</td><td>HyperIndex</td><td>Deploy to Envio Cloud, or self-host with Docker</td></tr><tr><td>A one-off scan or research script</td><td>HyperSync</td><td>Query and stream, with no schema or database to set up</td></tr><tr><td>ETL into a data warehouse</td><td>HyperSync</td><td><code>collect_parquet</code> writes analytical output directly</td></tr><tr><td>Trace data</td><td>HyperSync</td><td>Trace filtering on trace-enabled endpoints, outside the event-log model</td></tr><tr><td>A custom monitor with your own storage</td><td>HyperSync</td><td>The thinnest layer between you and the data, in any supported language</td></tr><tr><td>Speeding up existing RPC calls, no rewrite</td><td>HyperRPC</td><td>Drop-in JSON-RPC, up to 5x faster on data-heavy reads</td></tr></tbody></table>
<p>A shorter version of the same logic. If you would otherwise stand up a database, a GraphQL server, and reorg handling, use HyperIndex, because it already did that work. If you would otherwise fight a framework to get at raw data, use HyperSync, because that is all it returns.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="using-hyperindex--hypersync-together">Using HyperIndex &amp; HyperSync Together<a class="hash-link" aria-label="Direct link to Using HyperIndex &amp; HyperSync Together" title="Direct link to Using HyperIndex &amp; HyperSync Together" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#using-hyperindex--hypersync-together">​</a></h2>
<p>The layering means these are not exclusive choices, and many teams run both. A common split is HyperIndex for the application backend that powers the product and HyperSync directly for a side workload, such as a nightly Parquet export or an internal analytics dashboard. The product gets a managed API, the data team gets raw access, and both ride the same engine.</p>
<p>The other common path is to start with HyperIndex and reach for HyperSync only when a specific need appears, like a one-off backfill or a monitoring script that does not belong in your indexer. Because HyperIndex already runs on HyperSync, dropping to the raw engine for one job is a natural step rather than a migration.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="where-hyperrpc-fits">Where HyperRPC Fits<a class="hash-link" aria-label="Direct link to Where HyperRPC Fits" title="Direct link to Where HyperRPC Fits" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#where-hyperrpc-fits">​</a></h2>
<p>HyperRPC is the option for existing RPC-based code you do not want to rewrite. It is an abstraction over HyperSync that exposes a standard JSON-RPC interface, supporting methods like <code>eth_getLogs</code>, <code>eth_getBlockByNumber</code>, and <code>eth_getTransactionReceipt</code>, with early benchmarks showing up to 5x improvement over traditional nodes like geth, erigon, and reth on data-heavy reads.</p>
<p>Use it when you need a drop-in speed boost for tooling that expects standard JSON-RPC. For new projects where you design the data layer, the docs recommend HyperSync, because it is faster and far more flexible. Neither HyperRPC nor HyperSync can send transactions; both are read paths, and you still need a standard RPC for writes.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-to-try-each">How to Try Each<a class="hash-link" aria-label="Direct link to How to Try Each" title="Direct link to How to Try Each" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#how-to-try-each">​</a></h2>
<p>To feel HyperSync with zero install, run the LogTUI event viewer.</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx logtui aave arbitrum</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To scaffold a full indexer with config, schema, handlers, and a GraphQL API, initialise a HyperIndex project.</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio init</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Both paths use HyperSync, which requires an API token. Indexers deployed to Envio Cloud have special access and do not need a custom token.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="i-already-run-a-hyperindex-indexer-when-would-i-ever-query-hypersync-directly">I already run a HyperIndex indexer. When would I ever query HyperSync directly?<a class="hash-link" aria-label="Direct link to I already run a HyperIndex indexer. When would I ever query HyperSync directly?" title="Direct link to I already run a HyperIndex indexer. When would I ever query HyperSync directly?" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#i-already-run-a-hyperindex-indexer-when-would-i-ever-query-hypersync-directly">​</a></h3>
<p>When you have a data job that does not belong in your indexer. HyperIndex keeps a structured, reorg-safe dataset in sync for your application, but a one-off Parquet export, a chain-wide scan for sparse data, or a standalone monitoring script with custom logic are all lighter on raw HyperSync. Since HyperIndex already uses HyperSync as its data source, you are reaching one layer down for a specific task rather than replacing anything.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="is-hyperindex-slower-than-querying-hypersync-directly">Is HyperIndex slower than querying HyperSync directly?<a class="hash-link" aria-label="Direct link to Is HyperIndex slower than querying HyperSync directly?" title="Direct link to Is HyperIndex slower than querying HyperSync directly?" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#is-hyperindex-slower-than-querying-hypersync-directly">​</a></h3>
<p>For backfilling and serving structured data, no. HyperIndex uses HyperSync as its primary data source and adds preload optimization on top, so the framework layer manages schema, storage, reorgs, and the API rather than slowing retrieval. Raw HyperSync only feels faster on narrow tasks where you deliberately skip building a database and API, such as a streaming script.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="do-i-have-to-run-my-own-database-with-hypersync">Do I have to run my own database with HyperSync?<a class="hash-link" aria-label="Direct link to Do I have to run my own database with HyperSync?" title="Direct link to Do I have to run my own database with HyperSync?" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#do-i-have-to-run-my-own-database-with-hypersync">​</a></h3>
<p>If you want to persist what you pull, yes. HyperSync streams data to you and stores nothing on your behalf, so you bring your own storage, whether that is Postgres, a Parquet file, or a warehouse. HyperIndex is the layer that gives you a managed Postgres database and GraphQL API without setting one up.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="which-layer-handles-factory-contracts-and-dynamic-addresses">Which layer handles factory contracts and dynamic addresses?<a class="hash-link" aria-label="Direct link to Which layer handles factory contracts and dynamic addresses?" title="Direct link to Which layer handles factory contracts and dynamic addresses?" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#which-layer-handles-factory-contracts-and-dynamic-addresses">​</a></h3>
<p>HyperIndex, through the <code>contractRegister</code> handler. You register a contract type without an address in <code>config.yaml</code>, then call <code>context.chain.&lt;Contract&gt;.add(address)</code> when a factory event fires, and the framework indexes every instance, including events in the creation block. Doing the equivalent on raw HyperSync means tracking the address set and filtering queries yourself.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-track-native-eth-transfers-which-do-not-emit-logs">How do I track native ETH transfers, which do not emit logs?<a class="hash-link" aria-label="Direct link to How do I track native ETH transfers, which do not emit logs?" title="Direct link to How do I track native ETH transfers, which do not emit logs?" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#how-do-i-track-native-eth-transfers-which-do-not-emit-logs">​</a></h3>
<p>Query traces on HyperSync. Native transfers only appear in execution traces, so you filter on <code>callType: ["call"]</code> against a trace-enabled endpoint like <code>https://eth-traces.hypersync.xyz</code> and stream the results. Check the <a href="https://docs.envio.dev/docs/HyperSync/hypersync-supported-networks" target="_blank" rel="noopener noreferrer">supported networks page</a> for the current list.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="can-i-start-with-hyperindex-and-move-a-workload-to-hypersync-later">Can I start with HyperIndex and move a workload to HyperSync later?<a class="hash-link" aria-label="Direct link to Can I start with HyperIndex and move a workload to HyperSync later?" title="Direct link to Can I start with HyperIndex and move a workload to HyperSync later?" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#can-i-start-with-hyperindex-and-move-a-workload-to-hypersync-later">​</a></h3>
<p>Yes. Starting with HyperIndex gets a working backend up quickly, and because it runs on HyperSync, moving a specific workload to the raw engine later is straightforward. Most teams end up using each where it fits rather than committing to one for everything.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="does-hyperindex-handle-reorgs-or-do-i-build-that-myself">Does HyperIndex handle reorgs, or do I build that myself?<a class="hash-link" aria-label="Direct link to Does HyperIndex handle reorgs, or do I build that myself?" title="Direct link to Does HyperIndex handle reorgs, or do I build that myself?" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#does-hyperindex-handle-reorgs-or-do-i-build-that-myself">​</a></h3>
<p>HyperIndex handles them automatically. <code>rollback_on_reorg</code> defaults to <code>true</code>, so the indexer detects a reorganisation and rolls affected entities back without recovery code. On raw HyperSync, you would design reorg handling yourself, which is one of the main reasons to use the framework for stateful backends.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/hyperindex-vs-hypersync#build-with-envio">​</a></h2>
<p>Envio is a real-time multichain blockchain indexer that turns onchain events into a queryable GraphQL API. Supports any EVM chain, plus Solana and Fuel. Use Envio Cloud or self-host. If you're building onchain, come talk to us about your data needs.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a></p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>tutorials</category>
        </item>
        <item>
            <title><![CDATA[Envio Developer Update May 2026]]></title>
            <link>https://docs.envio.dev/blog/envio-developer-update-may-2026</link>
            <guid>https://docs.envio.dev/blog/envio-developer-update-may-2026</guid>
            <pubDate>Fri, 29 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[HyperIndex V3 officially shipped, Envio went live on Katana, and we published four large-scale case studies (Polymarket, Revert Finance, Privacy Pools, and Katana's SushiSwap migration), alongside deep dives on HyperSync, production reliability, and AI agents.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026.png" alt="Cover Image Envio Developer Update May 2026" width="100%">
<p>May was our biggest month yet. After five months of alpha and release candidates, HyperIndex V3 officially shipped, production-ready, faster, and the foundation for everything we build next. Alongside it we went live on Katana, published four large-scale case studies (Polymarket, Revert Finance, Privacy Pools, and Katana's SushiSwap migration off The Graph), and shipped a stack of deep-dive guides on HyperSync, production reliability, and building onchain with AI.</p>
<p>We also joined Monad's Devrel livestream to talk HyperIndex, started rolling out HyperSync rate limits ahead of paid plans, and confirmed our ETHConf New York sponsorship in June.</p>
<p>Let's dive in!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="hyperindex-v3-is-here">HyperIndex V3 Is Here<a class="hash-link" aria-label="Direct link to HyperIndex V3 Is Here" title="Direct link to HyperIndex V3 Is Here" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#hyperindex-v3-is-here">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-1.png" alt="HyperIndex V3 Is Here" width="100%">
<p>After five months of alpha, HyperIndex V3 officially shipped. This is the biggest release in the framework's history, a full modernisation that bundles five months of work into a stable, production-ready release. A unified handlers API, ESM with top-level await, a purpose-built testing framework, 3x faster historical sync, Solana support, ClickHouse as a second storage backend, and a much smaller package. With V3 we are back to following SemVer and set up for the next year of features.</p>
<p>To upgrade an existing project, follow the <a href="https://docs.envio.dev/docs/HyperIndex/migrate-to-v3" target="_blank" rel="noopener noreferrer">Migrate to V3</a> guide. For the complete rundown, see <a href="https://docs.envio.dev/docs/HyperIndex/whats-new-in-v3" target="_blank" rel="noopener noreferrer">What's New in V3</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="unified-handlers-api">Unified Handlers API<a class="hash-link" aria-label="Direct link to Unified Handlers API" title="Direct link to Unified Handlers API" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#unified-handlers-api">​</a></h3>
<p>All handler registrations now flow through a single indexer value. Contract-specific exports are replaced by <code>indexer.onEvent</code>, <code>indexer.contractRegister</code>, and <code>indexer.onBlock</code>.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> indexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"envio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">onEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    contract</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ERC20"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    event</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Transfer"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    wildcard</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function-variable function" style="color:rgb(80, 250, 123)">where</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> chain </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      params</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> from</span><span class="token operator">:</span><span class="token plain"> chain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Safe</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">addresses </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> to</span><span class="token operator">:</span><span class="token plain"> chain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Safe</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">addresses </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// Handler logic</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="3x-faster-historical-backfill">3x Faster Historical Backfill<a class="hash-link" aria-label="Direct link to 3x Faster Historical Backfill" title="Direct link to 3x Faster Historical Backfill" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#3x-faster-historical-backfill">​</a></h3>
<p>We added chunking logic to request events across multiple ranges at once, removed overfetching for contracts with a much later start block, and sped up dynamic contract registration.</p>
<p><strong>25k events per second is now standard.</strong></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="a-purpose-built-testing-framework">A Purpose-Built Testing Framework<a class="hash-link" aria-label="Direct link to A Purpose-Built Testing Framework" title="Direct link to A Purpose-Built Testing Framework" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#a-purpose-built-testing-framework">​</a></h3>
<p>HyperIndex now ships its own testing framework powered by <code>createTestIndexer()</code>. You write tests against the same indexer that runs in production, with no database, no Docker, and no manual mock wiring. It integrates with Vitest, includes snapshot testing out of the box, and gives you three ways to feed events (auto-exit, explicit block range, or simulate).</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> describe</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> it </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"vitest"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> createTestIndexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"envio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">describe</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"ERC20 indexer"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">it</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"processes the first block with events"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> indexer </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">createTestIndexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> result </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> chains</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token number">1</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// Auto-filled by Vitest on first run -- just review and commit</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toMatchInlineSnapshot</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">      {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">        "changes": [</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">          {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            "Transfer": {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">              "sets": [</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                  "blockNumber": 10861674,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                  "from": "0x0000000000000000000000000000000000000000",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                  "id": "1-10861674-23",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                  "to": "0x41653c7d61609D856f29355E404F310Ec4142Cfb",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                  "transactionHash": "0x4b37d2f343608457ca...",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                  "value": 1000000000000000000000000000n,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">              ],</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            "block": 10861674,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            "chainId": 1,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            "eventsProcessed": 1,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">          },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">        ],</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">      }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">    </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="esm-and-top-level-await">ESM and Top-Level Await<a class="hash-link" aria-label="Direct link to ESM and Top-Level Await" title="Direct link to ESM and Top-Level Await" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#esm-and-top-level-await">​</a></h3>
<p>We migrated HyperIndex from CommonJS to ESM. That unlocks the latest versions of libraries that dropped CommonJS long ago, and lets you use <code>await</code> directly at the top of your handler files.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="solana-support-experimental">Solana Support (Experimental)<a class="hash-link" aria-label="Direct link to Solana Support (Experimental)" title="Direct link to Solana Support (Experimental)" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#solana-support-experimental">​</a></h3>
<p>HyperIndex now supports Solana with RPC as a source. Spin up a Solana project with <code>pnpx envio init svm</code>. Solana exposes its block-stream handler as <code>indexer.onSlot</code> rather than <code>onBlock</code>, matching Solana's slot-based model.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="clickhouse-as-an-additional-storage-backend-experimental">ClickHouse as an Additional Storage Backend (Experimental)<a class="hash-link" aria-label="Direct link to ClickHouse as an Additional Storage Backend (Experimental)" title="Direct link to ClickHouse as an Additional Storage Backend (Experimental)" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#clickhouse-as-an-additional-storage-backend-experimental">​</a></h3>
<p>HyperIndex can now run with multiple storage backends side by side. Postgres remains the primary database, and entities can additionally be written to a ClickHouse database that is restart and reorg resistant. Enable it in <code>config.yaml</code> and route each entity via the <code>@storage</code> directive in <code>schema.graphql</code>.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token key atrule">storage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">postgres</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean important">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">clickhouse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean important">true</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Envio Cloud supports ClickHouse on the Dedicated Plan.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="a-much-smaller-package-and-bun-support">A Much Smaller Package and Bun Support<a class="hash-link" aria-label="Direct link to A Much Smaller Package and Bun Support" title="Direct link to A Much Smaller Package and Bun Support" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#a-much-smaller-package-and-bun-support">​</a></h3>
<p>You can run HyperIndex on Bun with <code>bun --bun envio dev</code>, and we removed the runtime ReScript compiler from the published package by eliminating dynamically generated ReScript code.</p>
<p><strong>The envio npm package shrank from 141MB to 53MB.</strong></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="agentic-mode-in-envio-init">Agentic Mode in envio init<a class="hash-link" aria-label="Direct link to Agentic Mode in envio init" title="Direct link to Agentic Mode in envio init" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#agentic-mode-in-envio-init">​</a></h3>
<p><code>envio init</code> now ships an agentic mode. When an AI coding assistant runs the command, it produces an AI-readable guiding prompt instead of a TTY error, so the agent knows exactly how to scaffold an indexer end to end.</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Welcome to Envio Indexer! Let's set up an indexer that will become a reliable blockchain backend you trust, love, and own.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Leave the rest to your favorite agent:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  1. Prompt the user for the project intent if it is missing from context (what should the indexer track and surface?).</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  2. Determine the chain, contract, and addresses needed to produce that result. Use web search or block-explorer tool calls when the user hasn't supplied them.</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  3. To continue, call:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">       pnpx envio init contract-import explorer \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         -n ${indexer-name} \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         -c ${address} \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         -b ${chainId} \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         --single-contract \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         --all-events \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         -d ${directory}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Then `cd ${directory}` and run `pnpm test`. Don't hand the project off yet -- keep iterating on the indexer with a TDD loop (extend tests, run them, fix handlers) until the user's goal is met.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>See the full <a href="https://github.com/enviodev/hyperindex/releases" target="_blank" rel="noopener noreferrer">release notes</a></p>
<p>Star us on <a href="https://github.com/enviodev/hyperindex" target="_blank" rel="noopener noreferrer">GitHub</a> ⭐</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="envio-is-live-on-katana">Envio is Live on Katana<a class="hash-link" aria-label="Direct link to Envio is Live on Katana" title="Direct link to Envio is Live on Katana" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#envio-is-live-on-katana">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-2.gif" alt="Envio is Live on Katana" width="100%">
<p>We launched production-grade indexing on Katana, the DeFi-first chain built where liquidity concentrates and real yield flows back to users. Developers can now access real-time and historical onchain data on Katana, up to 2000x faster than RPC.</p>
<p>Easy, fast, and fully customisable.</p>
<p>Original post on X: <a href="https://x.com/katana/status/2056389958303441051" target="_blank" rel="noopener noreferrer">https://x.com/katana/status/2056389958303441051</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="indexing-4-billion-polymarket-events">Indexing 4 Billion Polymarket Events<a class="hash-link" aria-label="Direct link to Indexing 4 Billion Polymarket Events" title="Direct link to Indexing 4 Billion Polymarket Events" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#indexing-4-billion-polymarket-events">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-3.png" alt="Indexing 4 Billion Polymarket Events" width="100%">
<p>We replaced Polymarket's eight production subgraphs, four years of fragmentation across separate AssemblyScript codebases on The Graph, with a single HyperIndex indexer written in TypeScript. Over 4 billion events synced in 6 days on Polygon.</p>
<p>The unlock is handler merging. A shared contract event like <code>ConditionalTokens.PositionSplit</code> previously fired across three or four separate subgraphs. In the unified indexer, one handler fires once and updates open interest, activity, and PnL together. That is 25+ entity types behind a single GraphQL endpoint, and one deployment to maintain instead of eight. The full indexer is open source as a reference for any team migrating from The Graph.</p>
<p>Read the case study: <a href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/polymarket-hyperindex-case-study</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="revert-finance-fixed-2-years-of-unsynced-pancakeswap-v3-data">Revert Finance Fixed 2 Years of Unsynced PancakeSwap V3 Data<a class="hash-link" aria-label="Direct link to Revert Finance Fixed 2 Years of Unsynced PancakeSwap V3 Data" title="Direct link to Revert Finance Fixed 2 Years of Unsynced PancakeSwap V3 Data" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#revert-finance-fixed-2-years-of-unsynced-pancakeswap-v3-data">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-4.png" alt="Revert Finance Fixed 2 Years of Unsynced PancakeSwap V3 Data" width="100%">
<p>Revert Finance builds analytics and management tools for AMM liquidity providers. Their PancakeSwap V3 subgraph on BNB Smart Chain had been stuck at 70% sync for over two years, unable to reach chain head, because the chain's throughput outpaced what RPC-based indexing could sustain.</p>
<p>We built a HyperIndex indexer covering the full PancakeSwap V3 contract surface on BNB Smart Chain. 1,711,569,200 events synced to 100% in 10 days.</p>
<p>Read the case study: <a href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="privacy-in-public-indexing-privacy-pools">Privacy in Public, Indexing Privacy Pools<a class="hash-link" aria-label="Direct link to Privacy in Public, Indexing Privacy Pools" title="Direct link to Privacy in Public, Indexing Privacy Pools" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#privacy-in-public-indexing-privacy-pools">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-5.png" alt="Privacy in Public, Indexing Privacy Pools" width="100%">
<p>Privacy Pools is a privacy primitive co-authored by Vitalik Buterin that pairs a zero-knowledge proof of pool membership with an off-chain compliance layer. We indexed every deposit, withdrawal, ragequit, ASP root update, and relayer fee across all 21 live pools on four chains (Ethereum, Optimism, BSC, and Arbitrum) with a single HyperIndex indexer using dual Postgres and ClickHouse storage.</p>
<p>Full multichain sync to head in roughly 30 seconds, and 91% of withdrawals use the privacy-preserving relayed path. The full stack, including the indexer, the analytics queries, and the BI report generator, is open source under MIT license. It is a great example of multichain coverage and an analytics-grade columnar store as first-class features.</p>
<p>Read the case study: <a href="https://docs.envio.dev/blog/privacy-in-public-case-study" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/privacy-in-public-case-study</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="katana-migrates-sushiswap-off-the-graph">Katana Migrates SushiSwap Off The Graph<a class="hash-link" aria-label="Direct link to Katana Migrates SushiSwap Off The Graph" title="Direct link to Katana Migrates SushiSwap Off The Graph" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#katana-migrates-sushiswap-off-the-graph">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-6.png" alt="Katana Migrates SushiSwap Off The Graph" width="100%">
<p>Katana migrated two production subgraphs, SushiSwap V3 and the Sushi staker, from The Graph to Envio HyperIndex without disrupting the app surfacing the data. Katana's existing subgraph-style queries kept working through Envio's subgraph-compatible endpoint, and for the full GraphQL feature set its app needed, Katana moved onto Envio's native endpoint, with our team supporting the move directly.</p>
<p>SushiSwap V3 synced 11,473,382 events in about two hours, and the Sushi staker synced 68,201 events in under 20 seconds.</p>
<p>Read the case study: <a href="https://docs.envio.dev/blog/case-study-katana-sushiswap" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/case-study-katana-sushiswap</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-hypersync">What is HyperSync?<a class="hash-link" aria-label="Direct link to What is HyperSync?" title="Direct link to What is HyperSync?" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#what-is-hypersync">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-7.png" alt="What is HyperSync?" width="100%">
<p>Reading onchain data over standard JSON-RPC breaks down the moment you need fast, filtered, or multichain historical data. HyperSync is our high-performance data retrieval layer built to fix exactly that. It is written in Rust, uses optimised binary encoding and parallel fetching, and exposes a single query interface across every supported chain.</p>
<p>Scanning Arbitrum for sparse log data takes 2 seconds with HyperSync, up to 2000x faster than RPC. HyperSync is the engine behind HyperIndex. Client libraries are available for TypeScript, Python, Rust, and Go. This blog covers what it is, how it works, and how to use it in your own application.</p>
<p>Learn more here: <a href="https://docs.envio.dev/blog/what-is-hypersync" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/what-is-hypersync</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="production-indexer-reliability-with-hyperindex">Production Indexer Reliability with HyperIndex<a class="hash-link" aria-label="Direct link to Production Indexer Reliability with HyperIndex" title="Direct link to Production Indexer Reliability with HyperIndex" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#production-indexer-reliability-with-hyperindex">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-8.png" alt="Production Indexer Reliability with HyperIndex" width="100%">
<p>Speed wins benchmarks, but reliability is what keeps an indexer running for years. This post walks through the four reliability guarantees HyperIndex provides at the framework level, so any indexer built on it inherits them without writing operational code. Those guarantees are built-in reorg handling with automatic rollback, restart-resistant operation, HyperSync data validation, and multi data-source recovery.</p>
<p>Reorgs are handled automatically by tracking entity state history for every unfinalized block and rolling back without any custom handler logic. Multi data-source recovery fails over to a fallback within seconds and recovers to the primary 60 seconds later. Observability comes through a semver-stable Prometheus endpoint.</p>
<p>More here: <a href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/production-indexer-reliability-hyperindex</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-ai-agents-acting-onchain-need-an-indexer">Why AI Agents Acting Onchain Need an Indexer<a class="hash-link" aria-label="Direct link to Why AI Agents Acting Onchain Need an Indexer" title="Direct link to Why AI Agents Acting Onchain Need an Indexer" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#why-ai-agents-acting-onchain-need-an-indexer">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-9.png" alt="Why AI Agents Acting Onchain Need an Indexer" width="100%">
<p>SQL warehouses let agents ask. Indexers let them act. An agent reading raw RPC hits four walls quickly, namely reorgs, no schema, low throughput, and per-chain quirks at multichain scale. A SQL warehouse fronted by an LLM solves the read side, but an agent acting onchain needs to build, deploy, and own new data pipelines mid-session, not just query existing ones.</p>
<p>This post makes the case for a programmable indexer over a query layer, backed by the docs MCP server, the auto-discovered <code>.claude/skills/</code> directory, and the GitHub-native deploy flow.</p>
<p><strong>One prompt, roughly 20 seconds, 400,000 events indexed on Monad.</strong></p>
<p>Read the full breakdown: <a href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="ai-assisted-subgraph-migration-to-hyperindex-with-claude">AI-Assisted Subgraph Migration to HyperIndex with Claude<a class="hash-link" aria-label="Direct link to AI-Assisted Subgraph Migration to HyperIndex with Claude" title="Direct link to AI-Assisted Subgraph Migration to HyperIndex with Claude" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#ai-assisted-subgraph-migration-to-hyperindex-with-claude">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-10.png" alt="AI-Assisted Subgraph Migration to HyperIndex with Claude" width="100%">
<p>The hardest part of moving off The Graph has always been the AssemblyScript rewrite. With the docs MCP server and the dedicated migrate-from-subgraph skill shipped in every HyperIndex project, Claude can handle the AssemblyScript-to-TypeScript translation end to end while a developer reviews the diff, runs the tests, and ships the indexer.</p>
<p>This guide walks the full workflow on a real surface area, anchored to the open-source Polymarket reference. A migration that used to take weeks becomes a one or two day exercise.</p>
<p>Read the full tutorial: <a href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-an-ai-powered-onchain-app-with-hyperindex-and-claude">Build an AI-Powered Onchain App with HyperIndex and Claude<a class="hash-link" aria-label="Direct link to Build an AI-Powered Onchain App with HyperIndex and Claude" title="Direct link to Build an AI-Powered Onchain App with HyperIndex and Claude" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#build-an-ai-powered-onchain-app-with-hyperindex-and-claude">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-11.png" alt="Build an AI-Powered Onchain App with HyperIndex and Claude" width="100%">
<p>A practical, end-to-end walkthrough of building a multichain HyperIndex indexer with Claude as a pair programmer. It covers wiring up the docs MCP server, scaffolding the project, making it multichain, writing the schema and handlers, running locally, and deploying to Envio Cloud through the GitHub-native flow.</p>
<p>Every command is reproducible against the current release, and the patterns come straight from the public Polymarket reference indexer. With Claude driving, you can go from a blank project to a deployed, queryable indexer in minutes.</p>
<p>More here: <a href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="migrating-from-ponder-to-envio">Migrating from Ponder to Envio<a class="hash-link" aria-label="Direct link to Migrating from Ponder to Envio" title="Direct link to Migrating from Ponder to Envio" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#migrating-from-ponder-to-envio">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-12.png" alt="Migrating from Ponder to Envio" width="100%">
<p>Both Ponder and HyperIndex are TypeScript-first and expose a GraphQL API, so migration is mostly mechanical translation. Three things change. <code>ponder.config.ts</code> becomes <code>config.yaml</code>, <code>ponder.schema.ts</code> becomes <code>schema.graphql</code>, and event handlers adapt to the HyperIndex entity API. This guide walks all three steps end to end, with every code block taken from the official migration reference.</p>
<p>Up to 157x faster historical sync via HyperSync, with multichain support by default.</p>
<p>For teams looking for a clear path forward, our team supports the migration end to end, from planning the rewrite to getting the indexer live on Envio Cloud.</p>
<p>Read the full tutorial: <a href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/migrate-from-ponder-to-envio</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="hypersync-rate-limits">HyperSync Rate Limits<a class="hash-link" aria-label="Direct link to HyperSync Rate Limits" title="Direct link to HyperSync Rate Limits" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#hypersync-rate-limits">​</a></h2>
<p>Throughout May we have been rolling out HyperSync rate limits more aggressively. Limits ratchet down gradually so you get the smoothest possible transition to paid plans without disruption to your services. Keep an eye out for 429 rate limit exceeded errors.</p>
<p>If you are already on a paid HyperSync plan, your normal plan limits apply and no action is needed. If you are not on a paid plan yet, get sorted as soon as possible by opening a Discord ticket to arrange one with the team, or by picking a plan directly.</p>
<p>This affects all HyperSync users and anyone self-hosting HyperIndex with a HyperSync token. Envio Cloud deployments are not affected.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="polymarkets-top-traders-run-on-indexed-data">Polymarket's Top Traders Run on Indexed Data<a class="hash-link" aria-label="Direct link to Polymarket's Top Traders Run on Indexed Data" title="Direct link to Polymarket's Top Traders Run on Indexed Data" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#polymarkets-top-traders-run-on-indexed-data">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-14.png" alt="Banner reading 'The Top Hundred Polymarket Traders, Day 1: Bids on Everything'" width="100%">
<p>Co-founder Jonjon Clark published a data-driven series profiling the top 100 Polymarket traders by realised PnL, and the deeper he digs, the clearer it becomes that these operations live or die on fast, real-time access to onchain data, exactly the workload HyperIndex and HyperSync are built for. Here are a few that stand out.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-95-win-rate-trader">The 95% Win Rate Trader<a class="hash-link" aria-label="Direct link to The 95% Win Rate Trader" title="Direct link to The 95% Win Rate Trader" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#the-95-win-rate-trader">​</a></h3>
<p>$23.6M in realised PnL and a 95.4% win rate. It runs a live NBA model that prices games faster than the order book, pre-positions on the cheap side before tip-off, and rides the eventual winner to oracle redemption.</p>
<p><a href="https://x.com/jonjonclark" target="_blank" rel="noopener noreferrer">Read the thread</a></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-15-minute-bitcoin-loop-trader">The 15-Minute Bitcoin Loop Trader<a class="hash-link" aria-label="Direct link to The 15-Minute Bitcoin Loop Trader" title="Direct link to The 15-Minute Bitcoin Loop Trader" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#the-15-minute-bitcoin-loop-trader">​</a></h3>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-16.png" alt="Scatter chart of buy and sell fills on a 15-minute Polymarket BTC binary, resolving UP redeems $1 and DOWN $0 at 03:15 UTC" width="100%">
<p>7.6 million fills across 32,021 markets in 111 days, about one fill per second, netting $2.38M. It posts resting bids on both sides of Polymarket's 15-minute BTC binaries and captures the spread off retail flow, completely indifferent to which way Bitcoin moves.</p>
<p><a href="https://x.com/jonjonclark" target="_blank" rel="noopener noreferrer">Read the thread</a></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-uma-gap-trader">The UMA Gap Trader<a class="hash-link" aria-label="Direct link to The UMA Gap Trader" title="Direct link to The UMA Gap Trader" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#the-uma-gap-trader">​</a></h3>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-17.png" alt="Histogram of every BUY by Polymarket wallet 0x8dcd…4eae showing 92% of buys land at $0.97 or above" width="100%">
<p>Number 26 on the leaderboard with $8M in lifetime realised PnL. Its cleanest mechanism is the settlement sweep, buying near-par winning tokens in the gap between when a result is known and when the UMA oracle finalises payout, for a 98.2% win rate across more than 4,000 positions.</p>
<p><a href="https://x.com/jonjonclark" target="_blank" rel="noopener noreferrer">Read the thread</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="envio-x-monads-devrel-livestream">Envio x Monad's Devrel Livestream<a class="hash-link" aria-label="Direct link to Envio x Monad's Devrel Livestream" title="Direct link to Envio x Monad's Devrel Livestream" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#envio-x-monads-devrel-livestream">​</a></h2>
<p><a href="https://x.com/i/broadcasts/1qxvvkjpedaxB" target="_blank" rel="noopener noreferrer"><img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-19.png" alt="Denham on Monad's Devrel Livestream" width="100%"></a></p>
<p>Co-founder Denham joined Monad's Devrel Livestream to chat HyperIndex on Monad, Monskills, and how to vibecode your way to a production indexer.</p>
<p>Missed it live? Catch the full recording on <a href="https://x.com/i/broadcasts/1qxvvkjpedaxB" target="_blank" rel="noopener noreferrer">X</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="current--upcoming-events--hackathons">Current &amp; Upcoming Events &amp; Hackathons<a class="hash-link" aria-label="Direct link to Current &amp; Upcoming Events &amp; Hackathons" title="Direct link to Current &amp; Upcoming Events &amp; Hackathons" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#current--upcoming-events--hackathons">​</a></h2>
<ul>
<li><a href="https://ethconf.com/" target="_blank" rel="noopener noreferrer">ETHConf - New York</a>: June 8th -&gt; 10th (sponsoring)</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="playlist-of-the-month">Playlist of the Month<a class="hash-link" aria-label="Direct link to Playlist of the Month" title="Direct link to Playlist of the Month" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#playlist-of-the-month">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-may-2026-18.png" alt="Playlist of the month" width="100%">
<p>▶ <a href="https://open.spotify.com/playlist/3XgXvqbIgrCTLzxqJRehxC?si=5d1949361dfb49a4" target="_blank" rel="noopener noreferrer">Open Spotify</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/envio-developer-update-may-2026#build-with-envio">​</a></h2>
<p>Envio is a multichain EVM blockchain indexer for querying real-time and historical data. If you're working on a Web3 project and want a smoother development process, Envio's got your back(end). Check out our docs, join the community, and let's talk about your data needs.</p>
<p>Stay tuned for more monthly updates by subscribing to our newsletter, following us on X, or hopping into our Discord for more up-to-date information.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a> 💌</p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>product-updates</category>
        </item>
        <item>
            <title><![CDATA[How Katana Migrated SushiSwap Data from The Graph to Envio]]></title>
            <link>https://docs.envio.dev/blog/case-study-katana-sushiswap</link>
            <guid>https://docs.envio.dev/blog/case-study-katana-sushiswap</guid>
            <pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Katana moved two production SushiSwap subgraphs from The Graph to Envio HyperIndex. The data model carried over entity-for-entity, and Katana's app now runs on Envio's native GraphQL endpoint.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/katana-sushiswap-case-study.png" alt="Envio case study cover for Katana, headline reads Migrating SushiSwap Data Off The Graph" width="100%">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>Katana migrated two production subgraphs, SushiSwap V3 and the Sushi staker, from The Graph to Envio HyperIndex while keeping its existing data model intact.</li>
<li>Katana's existing subgraph-style queries ran against Envio's subgraph-compatible endpoint, and for the full GraphQL feature set its app needed, Katana moved its queries onto Envio's native endpoint. The data model itself carried over unchanged.</li>
<li>Katana forked the indexer and deployed it on Envio Cloud, and the Envio team assisted with the backend configuration, the subgraph-compatible endpoint, and the cache.</li>
</ul></div></div>
<p>Migrating your data infrastructure from one provider to another is rarely simple, mostly because of everything that has to change around it. Katana is a DeFi network, and its app surfaces SushiSwap data such as V3 pools, swaps, fees, positions, and staking to its users. That data was served by two production subgraphs running on The Graph. Katana wanted to move this data layer to Envio HyperIndex without disrupting the apps that depend on it.</p>
<p>Because this was a live production system rather than a greenfield build, the priority was continuity. The existing queries had to keep working and the data had to stay correct. This case study walks through how the migration came together, from the subgraph-compatible endpoint that kept Katana's queries running to the hands-on support that handled the rest.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-challenge-moving-a-production-data-layer-without-disrupting-it">The Challenge: Moving a Production Data Layer Without Disrupting It<a class="hash-link" aria-label="Direct link to The Challenge: Moving a Production Data Layer Without Disrupting It" title="Direct link to The Challenge: Moving a Production Data Layer Without Disrupting It" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#the-challenge-moving-a-production-data-layer-without-disrupting-it">​</a></h2>
<p>Katana's existing subgraph queries were wired into production and had to keep working. Data quality and expected behaviour had to be preserved. And it had to be efficient, a swap, not a multi-week infrastructure project. For DeFi data, correctness and uptime were non-negotiable, because their application and users depended on it.</p>
<p>During development, the team also noticed the existing subgraph data often running around three blocks behind the chain head. For user-facing DeFi data, that kind of freshness gap matters.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-solution-a-subgraph-compatible-path-off-the-graph">The Solution: A Subgraph-Compatible Path off The Graph<a class="hash-link" aria-label="Direct link to The Solution: A Subgraph-Compatible Path off The Graph" title="Direct link to The Solution: A Subgraph-Compatible Path off The Graph" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#the-solution-a-subgraph-compatible-path-off-the-graph">​</a></h2>
<p>The migration came down to two things. Envio's tooling fit the setup Katana already had, and the support was there at every step.</p>
<p>The foundation was schema parity. The HyperIndex deployment reproduces the original Sushi V3 subgraph entity-for-entity, all 23 entity types, tracking the Uniswap V3 factory, the position manager, and every pool it deploys. Same entities, same shape, so Katana did not have to redesign its data or rebuild against a new model.</p>
<p>Envio exposes two GraphQL endpoints, a subgraph-compatible one that runs existing subgraph-style queries as a drop-in, and a native one with the full query feature set. Katana's standard queries ran against the compatible endpoint, and for the full feature set its app needed, Katana standardised on the native endpoint, with the Envio team working through the move alongside them.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="contracts-indexed">Contracts Indexed<a class="hash-link" aria-label="Direct link to Contracts Indexed" title="Direct link to Contracts Indexed" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#contracts-indexed">​</a></h3>
<p>The SushiSwap V3 indexer runs on Katana mainnet:</p>
<table><thead><tr><th>Contract</th><th>Address</th><th>Start block</th></tr></thead><tbody><tr><td>UniswapV3Factory</td><td><code>0x203e8740894c8955cb8950759876d7e7e45e04c1</code></td><td>1,858,972</td></tr><tr><td>NonfungiblePositionManager</td><td><code>0x2659c6085d26144117d904c46b48b6d180393d27</code></td><td>1,860,127</td></tr><tr><td>UniswapV3Pool</td><td>Dynamic, registered by the factory</td><td>When each pool is deployed</td></tr></tbody></table>
<p>The process was a fork-and-deploy flow. Katana forked the indexer, connected it to Envio Cloud, and deployed, while the Envio team handled the backend configuration, set up the subgraph-compatible endpoint, and managed the caching for the deployment. The team could also validate on a fast instance first. With the most RPC-heavy fields turned off, backfill ran about ten times faster, so they could confirm everything looked right before running the full indexer with every field populated.</p>
<p>The Envio team set up the endpoints, configured the caching, and worked through the query migration directly with Katana's engineers.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-results">The Results<a class="hash-link" aria-label="Direct link to The Results" title="Direct link to The Results" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#the-results">​</a></h2>
<p>Katana migrated both production subgraphs, SushiSwap V3 and the Sushi staker, from The Graph to Envio. Its existing queries kept working through the subgraph-compatible endpoint, so the app did not need a rewrite. A third subgraph, a pre-staking one with deprecation already planned, was left as-is by design.</p>
<p><em>The SushiSwap V3 indexer on Envio, fully synced (11,473,382 events) in about two hours.</em></p>
<img src="https://docs.envio.dev/blog-assets/katana-sushiswap-case-study-1.png" alt="Katana SushiSwap V3 indexer synced to 100% on Envio in about two hours, processing 11,473,382 events" width="100%">
<p><em>The Sushi staker subgraph, fully synced (68,201 events) in under 20 seconds on Envio.</em></p>
<img src="https://docs.envio.dev/blog-assets/katana-sushiswap-case-study-2.png" alt="Katana Sushi staker indexer synced to 100% on Envio in under 20 seconds, processing 68,201 events" width="100%">
<p>With the migration complete, both SushiSwap indexers run on Envio Cloud, serving Katana's app through the same queries it used before. Where the original subgraph had drifted a few blocks behind, the new indexer indexes in real time at the chain head.</p>
<div style="margin:2rem 0;padding:1.5rem 2rem;border-left:4px solid #f97316;background:rgba(249,115,22,0.06);border-radius:0 8px 8px 0"><p style="font-size:1.1rem;font-style:italic;margin-bottom:0.75rem">"The comprehensive resources and proactive support provided by the Envio team made our migration from The Graph remarkably smooth and efficient."</p><p style="margin:0;font-weight:600">Kirienzo, Senior Software Engineer, Katana</p></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="before-and-after-the-migration">Before and After the Migration<a class="hash-link" aria-label="Direct link to Before and After the Migration" title="Direct link to Before and After the Migration" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#before-and-after-the-migration">​</a></h2>
<table><thead><tr><th></th><th>The Graph</th><th>Envio</th></tr></thead><tbody><tr><td>GraphQL queries</td><td>Subgraph</td><td>Run against Envio's native GraphQL endpoint</td></tr><tr><td>Entity schema</td><td>Sushi V3 subgraph schema</td><td>Reproduced entity-for-entity, 23 types</td></tr><tr><td>Handler language</td><td>AssemblyScript</td><td>TypeScript</td></tr><tr><td>Hosting</td><td>The Graph</td><td>Envio Cloud (managed)</td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-carries-over-when-you-move-off-the-graph">What Carries Over When You Move Off The Graph<a class="hash-link" aria-label="Direct link to What Carries Over When You Move Off The Graph" title="Direct link to What Carries Over When You Move Off The Graph" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#what-carries-over-when-you-move-off-the-graph">​</a></h2>
<p>A subgraph rarely sits on its own. Queries, dashboards, and app code are all built against its schema, which is what makes moving it feel risky. The part that carries over cleanly is the data model. Because the HyperIndex indexer reproduced the Sushi V3 subgraph entity-for-entity, Katana did not have to redesign its data or rebuild against a new model. On the query side, Envio gives you a subgraph-compatible endpoint for a drop-in start and a native GraphQL endpoint for the full feature set, and Katana's app runs on the native one.</p>
<p>For a team considering a migration off The Graph, Envio's subgraph-compatible endpoint is what makes it a swap rather than a multi-week rebuild.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="relevant-resources">Relevant Resources<a class="hash-link" aria-label="Direct link to Relevant Resources" title="Direct link to Relevant Resources" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#relevant-resources">​</a></h2>
<ul>
<li><a href="https://github.com/katana-network/katana-sushi-v3-subgraph" target="_blank" rel="noopener noreferrer">Katana SushiSwap V3 indexer (GitHub)</a></li>
<li><a href="https://thegraph.com/explorer/subgraphs/2hnbrb3a4zWmQDkAbvDmYsBLGMWSaH6vAYcJnUJcLe1B?view=Query&amp;chain=arbitrum-one" target="_blank" rel="noopener noreferrer">Original Sushi staker subgraph on The Graph</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/katana" target="_blank" rel="noopener noreferrer">Indexing Katana Data with Envio</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/migration-guide" target="_blank" rel="noopener noreferrer">Migrating from The Graph</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/contract-import" target="_blank" rel="noopener noreferrer">HyperIndex Quickstart</a></li>
<li><a href="https://docs.envio.dev/docs/HyperSync/overview" target="_blank" rel="noopener noreferrer">HyperSync</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/hosted-service" target="_blank" rel="noopener noreferrer">Envio Cloud</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-katana">What is Katana?<a class="hash-link" aria-label="Direct link to What is Katana?" title="Direct link to What is Katana?" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#what-is-katana">​</a></h3>
<p>Katana is a DeFi-focused blockchain, designed to concentrate liquidity into a small set of core applications instead of spreading it thin across many. SushiSwap V3 is its spot exchange, which is why the Katana app surfaces SushiSwap data such as pools, swaps, fees, and staking to its users.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-sushiswap">What is SushiSwap?<a class="hash-link" aria-label="Direct link to What is SushiSwap?" title="Direct link to What is SushiSwap?" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#what-is-sushiswap">​</a></h3>
<p>SushiSwap is a decentralised exchange (DEX). Its V3 deployment, the concentrated-liquidity version, is Katana's spot trading venue, and it generates the pools, positions, swaps, and fees that the migrated subgraphs index.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-did-katana-migrate">What did Katana migrate?<a class="hash-link" aria-label="Direct link to What did Katana migrate?" title="Direct link to What did Katana migrate?" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#what-did-katana-migrate">​</a></h3>
<p>Two production subgraphs, the SushiSwap V3 subgraph and the Sushi staker subgraph, both from The Graph to Envio HyperIndex. A third, pre-staking subgraph scheduled for deprecation was not migrated.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-did-katana-have-to-change-to-migrate">What did Katana have to change to migrate?<a class="hash-link" aria-label="Direct link to What did Katana have to change to migrate?" title="Direct link to What did Katana have to change to migrate?" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#what-did-katana-have-to-change-to-migrate">​</a></h3>
<p>The data model carried over entity-for-entity, so there was no schema rebuild. Katana's existing queries ran against Envio's subgraph-compatible endpoint, and for the full GraphQL feature set its app needed, Katana moved its queries onto Envio's native endpoint, with the Envio team supporting the move.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-the-subgraph-compatible-endpoint">What is the subgraph-compatible endpoint?<a class="hash-link" aria-label="Direct link to What is the subgraph-compatible endpoint?" title="Direct link to What is the subgraph-compatible endpoint?" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#what-is-the-subgraph-compatible-endpoint">​</a></h3>
<p>It is an Envio feature that runs existing The Graph subgraph-style GraphQL queries against a HyperIndex deployment, a drop-in path for standard subgraph queries. For the full GraphQL feature set, Envio also exposes a native endpoint, which is what Katana's app runs on.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-migrate-from-the-graph-to-hyperindex">How do I migrate from The Graph to HyperIndex?<a class="hash-link" aria-label="Direct link to How do I migrate from The Graph to HyperIndex?" title="Direct link to How do I migrate from The Graph to HyperIndex?" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#how-do-i-migrate-from-the-graph-to-hyperindex">​</a></h3>
<p>HyperIndex handlers are written in TypeScript, and AssemblyScript is a subset of TypeScript, so most handler logic carries across directly. Envio provides a <a href="https://docs.envio.dev/docs/HyperIndex/migration-guide" target="_blank" rel="noopener noreferrer">migration guide</a>, a subgraph-compatible endpoint that preserves existing queries, and hands-on migration support.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/case-study-katana-sushiswap#build-with-envio">​</a></h2>
<p>Envio is a real-time multichain blockchain indexer that turns onchain events into a queryable GraphQL API. Supports any EVM chain, plus Solana and Fuel. Use Envio Cloud or self-host. If you're building onchain, come talk to us about your data needs.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a></p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://x.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+kAIGElzPjApiMjI0" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>case-studies</category>
        </item>
        <item>
            <title><![CDATA[Migrate from Ponder to Envio HyperIndex]]></title>
            <link>https://docs.envio.dev/blog/migrate-from-ponder-to-envio</link>
            <guid>https://docs.envio.dev/blog/migrate-from-ponder-to-envio</guid>
            <pubDate>Thu, 21 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Migrate from Ponder to HyperIndex in three steps. Up to 157x faster sync. Same TypeScript, multichain by default. Real before-and-after code.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/migrate-from-ponder-to-envio.png" alt="Migrating from Ponder to Envio HyperIndex" width="100%">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>Migrating from Ponder to HyperIndex is straightforward. Both frameworks use TypeScript, index EVM events, and expose a GraphQL API.</li>
<li>Three things change: <code>ponder.config.ts</code> becomes <code>config.yaml</code>, <code>ponder.schema.ts</code> becomes <code>schema.graphql</code>, and event handlers adapt to the HyperIndex entity API.</li>
<li>Up to 157x faster historical sync via HyperSync (Sentio Uniswap V2 Factory benchmark).</li>
<li>Multichain by default. One config, any number of chains.</li>
<li>Full migration reference at <a href="https://docs.envio.dev/docs/HyperIndex/migrate-from-ponder" target="_blank" rel="noopener noreferrer">docs.envio.dev/docs/HyperIndex/migrate-from-ponder</a>. AI-assisted migration docs also available for Cursor and Claude Code.</li>
</ul></div></div>
<p>If you are running a Ponder indexer in production, you already know two things. The framework is TypeScript end-to-end, and historical backfills using RPC are the bottleneck. Envio HyperIndex keeps the TypeScript and removes the bottleneck. Up to 157x faster sync via HyperSync, same GraphQL API on top.</p>
<p>This blog walks the three-step migration end to end. Every code block is taken directly from the official migration reference in our docs.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="ai-assisted-migration">AI-Assisted Migration<a class="hash-link" aria-label="Direct link to AI-Assisted Migration" title="Direct link to AI-Assisted Migration" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#ai-assisted-migration">​</a></h2>
<p>If you prefer not to do the rewrite by hand, HyperIndex ships with built-in Claude skills that guide AI coding assistants through the migration. See our <a href="https://docs.envio.dev/docs/HyperIndex/quickstart-with-ai" target="_blank" rel="noopener noreferrer">Quickstart with AI</a> guide that walks you through the full setup.</p>
<p>Combined with the Envio docs <a href="https://docs.envio.dev/docs/HyperIndex/mcp-server" target="_blank" rel="noopener noreferrer">MCP server</a>, an agent can read your Ponder config, schema, and handlers, and produce the HyperIndex equivalents while you review the diff. Learn more about general AI-assisted migration in our <a href="https://docs.envio.dev/blog" target="_blank" rel="noopener noreferrer">blog</a>. The same flow applies to Ponder migration.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="migration-overview">Migration Overview<a class="hash-link" aria-label="Direct link to Migration Overview" title="Direct link to Migration Overview" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#migration-overview">​</a></h2>
<p>Three steps plus a bootstrap:</p>
<ol>
<li><code>ponder.config.ts</code> becomes <code>config.yaml</code></li>
<li><code>ponder.schema.ts</code> becomes <code>schema.graphql</code></li>
<li>Event handlers adapt syntax and entity operations</li>
</ol>
<p>At any point during the migration, run:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> envio codegen   </span><span class="token comment" style="color:rgb(98, 114, 164)"># validate config + schema, regenerate types</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> dev             </span><span class="token comment" style="color:rgb(98, 114, 164)"># run the indexer locally</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If you are new to HyperIndex, see the <a href="https://docs.envio.dev/docs/HyperIndex/getting-started" target="_blank" rel="noopener noreferrer">Getting Started</a> guide.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-0-bootstrap-the-project">Step 0: Bootstrap the Project<a class="hash-link" aria-label="Direct link to Step 0: Bootstrap the Project" title="Direct link to Step 0: Bootstrap the Project" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#step-0-bootstrap-the-project">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio init</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Follow the prompts, using your Ponder project as the source of truth for contract addresses, ABIs, and events. This generates a boilerplate indexer you can use as a base to edit.</p>
<p>Convert your ABIs first. Ponder exports ABIs as TypeScript (<code>as const</code>). For each contract, strip the <code>export const ... =</code> wrapper and the <code>as const</code>, and save it as a plain <code>.json</code> file in <code>abis/</code>. Have these ready before running <code>envio init</code>, because the local ABI import asks for the path to each contract's JSON ABI file. If a contract is verified on a block explorer, <code>envio init</code> can fetch the ABI for you instead.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-1-ponderconfigts-to-configyaml">Step 1: <code>ponder.config.ts</code> to <code>config.yaml</code><a class="hash-link" aria-label="Direct link to step-1-ponderconfigts-to-configyaml" title="Direct link to step-1-ponderconfigts-to-configyaml" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#step-1-ponderconfigts-to-configyaml">​</a></h2>
<p>Here is the same indexer configured in both frameworks, taken from the migration docs.</p>
<p><strong>Ponder:</strong></p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> createConfig </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ponder"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">default</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">createConfig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  chains</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    mainnet</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> id</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">1</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> rpc</span><span class="token operator">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">PONDER_RPC_URL_1</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  contracts</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    MyToken</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      abi</span><span class="token operator">:</span><span class="token plain"> myTokenAbi</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      chain</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"mainnet"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      address</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0xabc..."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      startBlock</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">18000000</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>HyperIndex:</strong></p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># yaml-language-server: $schema=./node_modules/envio/evm.schema.json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">indexer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> MyToken</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">abi_file_path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ./abis/MyToken.json</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">events</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Transfer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Approval</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">chains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> MyToken</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> 0xabc</span><span class="token punctuation" style="color:rgb(248, 248, 242)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">18000000</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Key differences:</strong></p>
<table><thead><tr><th>Concept</th><th>Ponder</th><th>HyperIndex</th></tr></thead><tbody><tr><td>Config format</td><td><code>ponder.config.ts</code> (TypeScript)</td><td><code>config.yaml</code> (YAML)</td></tr><tr><td>Chain reference</td><td>Named + viem object</td><td>Numeric chain ID</td></tr><tr><td>RPC URL</td><td>In config</td><td><code>RPC_URL_&lt;chainId&gt;</code> env var</td></tr><tr><td>ABI source</td><td>TypeScript import</td><td>JSON file (<code>abi_file_path</code>)</td></tr><tr><td>Events to index</td><td>Inferred from handlers</td><td>Explicit <code>events:</code> list</td></tr><tr><td>Handler file</td><td>Inferred</td><td>Auto-discovered from <code>src/handlers/</code></td></tr></tbody></table>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="field-selection-for-transaction-and-block-fields">Field selection for transaction and block fields<a class="hash-link" aria-label="Direct link to Field selection for transaction and block fields" title="Direct link to Field selection for transaction and block fields" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#field-selection-for-transaction-and-block-fields">​</a></h3>
<p>By default, only a minimal set of fields is available on <code>event.transaction</code> and <code>event.block</code>. Fields like <code>event.transaction.hash</code> are undefined unless explicitly requested.</p>
<p>Per-event:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token key atrule">events</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Transfer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">field_selection</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token key atrule">transaction_fields</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> hash</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Or declared once at the top level to apply to all events:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> my</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">indexer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">field_selection</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">transaction_fields</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> hash</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># ...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>See full list of available fields in <a href="https://docs.envio.dev/docs/HyperIndex/configuration-file" target="_blank" rel="noopener noreferrer">our docs</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-2-ponderschemats-to-schemagraphql">Step 2: <code>ponder.schema.ts</code> to <code>schema.graphql</code><a class="hash-link" aria-label="Direct link to step-2-ponderschemats-to-schemagraphql" title="Direct link to step-2-ponderschemats-to-schemagraphql" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#step-2-ponderschemats-to-schemagraphql">​</a></h2>
<p><strong>Ponder:</strong></p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> onchainTable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> primaryKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> index </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ponder"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> token </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">onchainTable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"token"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  address</span><span class="token operator">:</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">primaryKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token builtin" style="color:rgb(189, 147, 249)">symbol</span><span class="token operator">:</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">notNull</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  balance</span><span class="token operator">:</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">bigint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">notNull</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> transferEvent </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">onchainTable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"transfer_event"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    id</span><span class="token operator">:</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">text</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">primaryKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    from</span><span class="token operator">:</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">notNull</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    to</span><span class="token operator">:</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">hex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">notNull</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    amount</span><span class="token operator">:</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">bigint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">notNull</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    timestamp</span><span class="token operator">:</span><span class="token plain"> t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">integer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">notNull</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">table</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    fromIdx</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">index</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">table</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>HyperIndex:</strong></p>
<div class="language-graphql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-graphql codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">Token</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">ID</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">symbol</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">String</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">balance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BigInt</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">TransferEvent</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">ID</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">String</span><span class="token operator">!</span><span class="token plain"> </span><span class="token directive function" style="color:rgb(80, 250, 123)">@index</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">String</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">amount</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BigInt</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">Int</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Type mapping, taken from the migration docs:</strong></p>
<table><thead><tr><th>Ponder</th><th>HyperIndex GraphQL</th></tr></thead><tbody><tr><td><code>t.hex()</code></td><td><code>String!</code></td></tr><tr><td><code>t.text()</code></td><td><code>String!</code></td></tr><tr><td><code>t.bigint()</code></td><td><code>BigInt!</code></td></tr><tr><td><code>t.integer()</code></td><td><code>Int!</code></td></tr><tr><td><code>t.boolean()</code></td><td><code>Boolean!</code></td></tr><tr><td><code>t.real()</code> / <code>t.doublePrecision()</code></td><td><code>Float!</code></td></tr><tr><td><code>t.hex().array()</code></td><td><code>Json!</code></td></tr></tbody></table>
<p>Three more conversion rules.</p>
<p><strong>Primary keys.</strong> HyperIndex requires a single <code>id: ID!</code> string field on every entity. For composite primary keys (e.g. owner + spender), construct the ID string manually: <code>${owner}_${spender}</code>.</p>
<p><strong>Indexes.</strong> Replace Ponder's <code>index().on(column)</code> with an <code>@index</code> directive on the field.</p>
<p><strong>Relations.</strong> Replace Ponder's <code>relations()</code> call with <code>@derivedFrom</code> on the parent entity:</p>
<div class="language-graphql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-graphql codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">NftCollection</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">ID</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">contractAddress</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">Bytes</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">String</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">symbol</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">String</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">maxSupply</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BigInt</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">currentSupply</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">Int</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">tokens</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token class-name">Token</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token operator">!</span><span class="token plain"> </span><span class="token directive function" style="color:rgb(80, 250, 123)">@derivedFrom</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token attr-name" style="color:rgb(241, 250, 140)">field</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"collection"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">Token</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">ID</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">tokenId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BigInt</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">collection</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">NftCollection</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">owner</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">User</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Full schema reference at <a href="https://docs.envio.dev/docs/HyperIndex/schema" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperIndex/schema</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-3-event-handlers">Step 3: Event Handlers<a class="hash-link" aria-label="Direct link to Step 3: Event Handlers" title="Direct link to Step 3: Event Handlers" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#step-3-event-handlers">​</a></h2>
<p>Handler registration changes shape.</p>
<p><strong>Ponder:</strong></p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> ponder </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ponder:registry"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ponder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MyToken:Transfer"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>HyperIndex (v3):</strong></p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> indexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"envio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">onEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> contract</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MyToken"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> event</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Transfer"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="event-data-access">Event data access<a class="hash-link" aria-label="Direct link to Event data access" title="Direct link to Event data access" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#event-data-access">​</a></h3>
<p>The accessors are slightly different. Here is the full mapping from the migration docs:</p>
<table><thead><tr><th>Data</th><th>Ponder</th><th>HyperIndex</th></tr></thead><tbody><tr><td>Event parameters</td><td><code>event.args.name</code></td><td><code>event.params.name</code></td></tr><tr><td>Contract address</td><td><code>event.log.address</code></td><td><code>event.srcAddress</code></td></tr><tr><td>Chain ID</td><td><code>context.chain.id</code></td><td><code>event.chainId</code></td></tr><tr><td>Block number</td><td><code>event.block.number</code></td><td><code>event.block.number</code></td></tr><tr><td>Block timestamp</td><td><code>event.block.timestamp</code> (bigint)</td><td><code>event.block.timestamp</code> (number)</td></tr><tr><td>Tx hash</td><td><code>event.transaction.hash</code></td><td><code>event.transaction.hash</code> (needs <code>field_selection</code>)</td></tr></tbody></table>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="entity-operations">Entity operations<a class="hash-link" aria-label="Direct link to Entity operations" title="Direct link to Entity operations" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#entity-operations">​</a></h3>
<p>This is the part that takes the most rewriting. The Ponder drizzle-style API maps to a different shape in HyperIndex.</p>
<table><thead><tr><th>Intent</th><th>Ponder</th><th>HyperIndex</th></tr></thead><tbody><tr><td>Insert</td><td><code>context.db.insert(t).values({...})</code></td><td><code>context.Entity.set({ id, ...fields })</code></td></tr><tr><td>Update</td><td><code>context.db.update(t, pk).set({...})</code></td><td><code>get</code> → spread → <code>context.Entity.set({ ...existing, ...changes })</code></td></tr><tr><td>Upsert</td><td><code>.insert().values().onConflictDoUpdate()</code></td><td><code>context.Entity.getOrCreate({ id, ...defaults })</code> → <code>set</code></td></tr><tr><td>Read (nullable)</td><td><code>context.db.find(table, pk)</code></td><td><code>context.Entity.get(id)</code></td></tr><tr><td>Read (throws)</td><td>manual null check</td><td><code>context.Entity.getOrThrow(id)</code></td></tr></tbody></table>
<p><strong>Full handler example</strong></p>
<p><strong>Ponder:</strong></p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">ponder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">on</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"MyToken:Transfer"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">db</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">insert</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">transferEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">values</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    id</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    from</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">args</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    to</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">args</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    amount</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">args</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">amount</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    timestamp</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">Number</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">db</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">update</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">token</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> address</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">args</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">row</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> balance</span><span class="token operator">:</span><span class="token plain"> row</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">balance </span><span class="token operator">+</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">args</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">amount </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>HyperIndex (v3):</strong></p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> indexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"envio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">onEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> contract</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MyToken"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> event</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Transfer"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">TransferEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    id</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">transaction</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">hash</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">_</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">logIndex</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    from</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    to</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    amount</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">amount</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    timestamp</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> token </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Token</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getOrThrow</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Token</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">...</span><span class="token plain">token</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    balance</span><span class="token operator">:</span><span class="token plain"> token</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">balance </span><span class="token operator">+</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">amount</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Heads up.</strong> The ID above uses <code>event.transaction.hash</code>, which is not available by default. Add <code>transaction_fields: [hash]</code> under <code>field_selection</code> in <code>config.yaml</code> as shown in Step 1, or build the ID from fields that are always available (e.g. <code>${event.chainId}_${event.block.number}_${event.logIndex}</code>).</p>
<p><strong>One rule that catches every team.</strong> Entity objects from <code>context.Entity.get()</code> are read-only. Always spread (<code>...existing</code>) and set new fields. Never mutate directly.</p>
<p>Full event handlers reference at <a href="https://docs.envio.dev/docs/HyperIndex/event-handlers" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperIndex/event-handlers</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="factory-contracts-dynamic-registration">Factory Contracts (Dynamic Registration)<a class="hash-link" aria-label="Direct link to Factory Contracts (Dynamic Registration)" title="Direct link to Factory Contracts (Dynamic Registration)" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#factory-contracts-dynamic-registration">​</a></h2>
<p>Ponder uses a <code>factory()</code> helper in the config. HyperIndex uses a <code>contractRegister</code> handler.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> indexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"envio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">contractRegister</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> contract</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"MyFactory"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> event</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"ContractCreated"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">chain</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">MyContract</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">contractAddress</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In <code>config.yaml</code>, omit the <code>address</code> field for the dynamically registered contract.</p>
<p>The Polymarket reference indexer uses dynamic contract registration for FPMM pools created by FPMMFactory. See <a href="https://github.com/enviodev/polymarket-indexer/blob/main/src/handlers/FPMMFactory.ts" target="_blank" rel="noopener noreferrer">https://github.com/enviodev/polymarket-indexer/blob/main/src/handlers/FPMMFactory.ts</a> for the production example (note: Polymarket is still on v2 syntax, the v3 equivalent is shown above).</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="external-calls-effect-api">External Calls (Effect API)<a class="hash-link" aria-label="Direct link to External Calls (Effect API)" title="Direct link to External Calls (Effect API)" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#external-calls-effect-api">​</a></h2>
<p>Replace <code>context.client.readContract(...)</code> with the Effect API. This isolates external calls (fetch, RPC, async I/O) from the sync path safely.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> createEffect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">S</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"envio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> getSymbol </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">createEffect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"getSymbol"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    input</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">S</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    output</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">S</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    cache</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    rateLimit</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> calls</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">5</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> per</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"second"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> input </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// implementation: fetch the symbol from RPC for the given address</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Per the <a href="https://docs.envio.dev/docs/HyperIndex/effect-api" target="_blank" rel="noopener noreferrer">Effect API guide</a>, external calls (fetch, RPC, async I/O) should be wrapped in <code>createEffect</code> and invoked via <code>context.effect</code>, which provides automatic batching, memoization, deduplication, and rate-limiting.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-carries-across-what-changes">What Carries Across, What Changes<a class="hash-link" aria-label="Direct link to What Carries Across, What Changes" title="Direct link to What Carries Across, What Changes" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#what-carries-across-what-changes">​</a></h2>
<p>A condensed summary.</p>
<p><strong>Carries across without change:</strong></p>
<ul>
<li>TypeScript handler logic (entity writes, math, conditionals)</li>
<li>GraphQL API (your frontend queries do not change)</li>
<li>ABI bytes (just re-serialised as JSON)</li>
<li>Indexed entities (data model)</li>
</ul>
<p><strong>Changes during migration:</strong></p>
<ul>
<li>Config file format (<code>.ts</code> to <code>.yaml</code>)</li>
<li>Schema file format (drizzle table builder to GraphQL SDL)</li>
<li>Entity operation API (<code>db.insert</code>/<code>update</code> to <code>context.Entity.set</code>)</li>
<li>External calls (use Effect API)</li>
<li>Factory contract pattern (config <code>factory()</code> to handler <code>indexer.contractRegister</code>)</li>
<li>Event parameter access (<code>event.args</code> to <code>event.params</code>)</li>
<li>Transaction field access (needs explicit <code>field_selection</code>)</li>
</ul>
<p>For most projects, the body of the work is mechanical translation. Claude with the built-in HyperIndex skills can handle most of it under developer review.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-migrate">Why Migrate<a class="hash-link" aria-label="Direct link to Why Migrate" title="Direct link to Why Migrate" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#why-migrate">​</a></h2>
<p>From the Sentio Uniswap V2 Factory benchmark:</p>
<table><thead><tr><th>Indexer</th><th>Time</th></tr></thead><tbody><tr><td>Envio HyperIndex</td><td>8 seconds</td></tr><tr><td>Ponder</td><td>~21 minutes</td></tr></tbody></table>
<p>HyperIndex completed the workload 157x faster.</p>
<p>Three concrete reasons to migrate.</p>
<p><strong>Speed.</strong> Up to 157x faster historical sync via HyperSync. For Ponder users running backfills against RPC, that is hours into minutes.</p>
<p><strong>Multichain by default.</strong> One config covers any number of chains. Ponder's per-chain configuration is replaced by a single <code>chains:</code> array.</p>
<p><strong>Same language.</strong> TypeScript handlers transfer directly. The migration is syntax adjustment, not a language rewrite.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#get-started">​</a></h2>
<ul>
<li>Full Ponder migration reference: <a href="https://docs.envio.dev/docs/HyperIndex/migrate-from-ponder" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperIndex/migrate-from-ponder</a></li>
<li>Getting Started: <a href="https://docs.envio.dev/docs/HyperIndex/getting-started" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperIndex/getting-started</a></li>
<li>Quickstart with AI: <a href="https://docs.envio.dev/docs/HyperIndex/quickstart-with-ai" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperIndex/quickstart-with-ai</a></li>
<li>Configuration reference: <a href="https://docs.envio.dev/docs/HyperIndex/configuration-file" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperIndex/configuration-file</a></li>
<li>Schema reference: <a href="https://docs.envio.dev/docs/HyperIndex/schema" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperIndex/schema</a></li>
<li>Event handlers reference: <a href="https://docs.envio.dev/docs/HyperIndex/event-handlers" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperIndex/event-handlers</a></li>
<li>Polymarket production reference: <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">https://github.com/enviodev/polymarket-indexer</a></li>
<li>GitHub releases (current versions): <a href="https://github.com/enviodev/hyperindex/releases" target="_blank" rel="noopener noreferrer">https://github.com/enviodev/hyperindex/releases</a></li>
</ul>
<p>For teams affected by the Ponder acquisition looking for a clear path forward, the Envio team supports the migration end-to-end, from planning the rewrite to reviewing the diff to getting the indexer live on Envio Cloud. Reach out on Discord and we will help you scope it.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-long-does-a-ponder-to-hyperindex-migration-take">How long does a Ponder-to-HyperIndex migration take?<a class="hash-link" aria-label="Direct link to How long does a Ponder-to-HyperIndex migration take?" title="Direct link to How long does a Ponder-to-HyperIndex migration take?" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#how-long-does-a-ponder-to-hyperindex-migration-take">​</a></h3>
<p>For a small project (one or two contracts, single chain), a manual migration is typically a few hours. With the AI-assisted flow, faster. Larger projects with multiple contracts, factory patterns, and external calls take longer, but the bulk of the work is mechanical translation that Claude can often complete in a few hours to a day, with a developer reviewing the output.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="is-hyperindex-faster-than-ponder-in-production">Is HyperIndex faster than Ponder in production?<a class="hash-link" aria-label="Direct link to Is HyperIndex faster than Ponder in production?" title="Direct link to Is HyperIndex faster than Ponder in production?" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#is-hyperindex-faster-than-ponder-in-production">​</a></h3>
<p>Yes. In the Sentio Uniswap V2 Factory benchmark, HyperIndex completed in 8 seconds. Ponder completed in approximately 21 minutes. HyperIndex was 157x faster on that workload. See <a href="https://docs.envio.dev/docs/HyperIndex/benchmarks" target="_blank" rel="noopener noreferrer">benchmark comparison</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="does-hyperindex-support-typescript-like-ponder">Does HyperIndex support TypeScript like Ponder?<a class="hash-link" aria-label="Direct link to Does HyperIndex support TypeScript like Ponder?" title="Direct link to Does HyperIndex support TypeScript like Ponder?" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#does-hyperindex-support-typescript-like-ponder">​</a></h3>
<p>Yes. HyperIndex handlers are standard TypeScript. Both frameworks share the same language and same general shape of code. The differences are the entity operation API, the config format, and the data engine underneath.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="can-i-run-multiple-chains-in-one-hyperindex-indexer">Can I run multiple chains in one HyperIndex indexer?<a class="hash-link" aria-label="Direct link to Can I run multiple chains in one HyperIndex indexer?" title="Direct link to Can I run multiple chains in one HyperIndex indexer?" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#can-i-run-multiple-chains-in-one-hyperindex-indexer">​</a></h3>
<p>Yes. A single <code>config.yaml</code> declares all chains under a <code>chains:</code> array. Multichain is the default. Ponder configures chains separately per setup.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-does-hypersync-replace-in-a-ponder-setup">What does HyperSync replace in a Ponder setup?<a class="hash-link" aria-label="Direct link to What does HyperSync replace in a Ponder setup?" title="Direct link to What does HyperSync replace in a Ponder setup?" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#what-does-hypersync-replace-in-a-ponder-setup">​</a></h3>
<p>Ponder pulls historical data through standard RPC, which is the bottleneck for backfills against high-event contracts. HyperSync replaces that RPC fetch with a purpose-built data lake, delivering up to 2,000x faster data access than RPC. <!-- -->85+<!-- --> EVM chains have native HyperSync coverage, so most Ponder workloads can migrate without changing data-source configuration.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-handle-reorgs-in-hyperindex">How do I handle reorgs in HyperIndex?<a class="hash-link" aria-label="Direct link to How do I handle reorgs in HyperIndex?" title="Direct link to How do I handle reorgs in HyperIndex?" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#how-do-i-handle-reorgs-in-hyperindex">​</a></h3>
<p>At the framework level. HyperIndex tracks entity state history for every unfinalized block and rolls back automatically on reorg. No handler code is required.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="can-i-use-hyperindex-with-cursor-or-claude-code">Can I use HyperIndex with Cursor or Claude Code?<a class="hash-link" aria-label="Direct link to Can I use HyperIndex with Cursor or Claude Code?" title="Direct link to Can I use HyperIndex with Cursor or Claude Code?" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#can-i-use-hyperindex-with-cursor-or-claude-code">​</a></h3>
<p>Yes. HyperIndex v3 ships with built-in Claude skills that guide AI coding assistants through building with HyperIndex, plus a docs MCP server for live access to the documentation.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="where-is-the-production-reference-for-a-hyperindex-indexer">Where is the production reference for a HyperIndex indexer?<a class="hash-link" aria-label="Direct link to Where is the production reference for a HyperIndex indexer?" title="Direct link to Where is the production reference for a HyperIndex indexer?" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#where-is-the-production-reference-for-a-hyperindex-indexer">​</a></h3>
<p>The Polymarket reference indexer. It syncs 4,000,000,000 events on Polygon in 6 days, replacing 8 separate subgraphs on The Graph.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/migrate-from-ponder-to-envio#build-with-envio">​</a></h2>
<p>Envio is the fastest independently benchmarked EVM blockchain indexer for querying real-time and historical data. If you are building onchain and need indexing that keeps up with your chain, check out the docs, run the benchmarks yourself, and come talk to us about your data needs.</p>
<p>Stay tuned for more updates by subscribing to our newsletter, following us on X, or hopping into our Discord.</p>
<p>Subscribe to our newsletter</p>
<p>Website | X | Discord | Telegram | GitHub | YouTube | Reddit</p>]]></content:encoded>
            <category>tutorial</category>
        </item>
        <item>
            <title><![CDATA[Why AI Agents Acting Onchain Need an Indexer]]></title>
            <link>https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer</link>
            <guid>https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer</guid>
            <pubDate>Thu, 14 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[AI agents that act onchain need reorg-safe, queryable data they can act on. HyperIndex delivers it. Real MCP server, real Claude skills, 400k events in 20 seconds.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/ai-agents-acting-onchain-indexer.png" alt="Envio blog cover: 'Why AI Agents Need an Indexer' with subtitle 'The data layer for onchain agents'" width="100%">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>HyperIndex is Envio's multichain blockchain indexing framework for EVM chains. It is the right data layer for AI agents acting onchain because it ships reorg-safe data, structured GraphQL output, an MCP server that exposes the docs to any agent, and a <code>.claude/skills/</code> directory that auto-discovers for Cursor, Claude Code, and Codex.</li>
<li>The published <a href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex" target="_blank" rel="noopener noreferrer">agentic demo</a> documents an end-to-end flow where an agent scaffolded, configured, pushed to GitHub, and deployed a wstETH indexer on Monad Mainnet from a single prompt. 400,000 events indexed in approximately 20 seconds.</li>
<li>The Envio docs MCP server exposes two tools (<code>docs_search</code> and <code>docs_fetch</code>) over Streamable HTTP at <code>https://docs.envio.dev/mcp</code>. Configured into Claude Code, Cursor, or VS Code with one command.</li>
<li>HyperIndex projects scaffold a <code>.claude/skills/</code> directory pre-populated with 14 skills covering config, schema, handler syntax, factory patterns, filters, multichain, performance, traces, transactions, wildcard, blocks, external calls (the Effect API), testing, and subgraph migration.</li>
</ul></div></div>
<p>The agentic-onchain conversation in 2026 has settled into two camps. One says agents need a reconciled SQL warehouse to make sense of raw blockchain data. The other says agents need a programmable indexer that lets them act, not just analyse. Both are right about the diagnosis. Raw RPC is unworkable for an agent. The disagreement is about what replaces it.</p>
<p>This blog is the case for indexers, not warehouses. A SQL warehouse lets an agent ask questions. An indexing framework lets an agent build, deploy, and own new data pipelines mid-session. The first is a query tool, the second is infrastructure. Agents acting onchain need the second. HyperIndex ships it today.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-raw-blockchain-data-breaks-agents">Why Raw Blockchain Data Breaks Agents<a class="hash-link" aria-label="Direct link to Why Raw Blockchain Data Breaks Agents" title="Direct link to Why Raw Blockchain Data Breaks Agents" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#why-raw-blockchain-data-breaks-agents">​</a></h2>
<p>An agent reading from RPC directly hits four problems within minutes.</p>
<p><strong>1. Reorgs.</strong> A recent block can be reorged. An agent that wrote a record based on an unfinalized block has to either lag the chain head (and miss real-time signals) or roll its own rollback logic (and get it wrong on the next edge case). Neither is acceptable for an agent running in a production environment.</p>
<p><strong>2. Schema.</strong> RPC returns logs and transactions. It does not return entities, relationships, or aggregations. The agent has to assemble the schema in memory on every query. Cross-contract state, factory pattern instances, and anything time-windowed have to be rebuilt from scratch.</p>
<p><strong>3. Throughput.</strong> An agent that wants to know the last 1,000 trades on a market has to issue 1,000 <code>eth_getLogs</code> calls or hand-tune a paginated request. A historical sweep across a year of activity can take hours to query from RPC.</p>
<p><strong>4. Multichain.</strong> Most agents that matter operate across at least two chains. Each chain is a separate RPC, separate quirks, separate rate limits. The application code that joins those RPCs is exactly the indexing code an indexer would write for you.</p>
<p>The standard response to "raw RPC is unworkable for agents" is to put a SQL warehouse in front of it. That works for read-only analytical queries. It does not work for an agent that needs to spin up a new product on top of the data within a session.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-hyperindex-provides-instead">What HyperIndex Provides Instead<a class="hash-link" aria-label="Direct link to What HyperIndex Provides Instead" title="Direct link to What HyperIndex Provides Instead" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#what-hyperindex-provides-instead">​</a></h2>
<p>HyperIndex addresses all four problems by being a blockchain indexing framework rather than a query layer.</p>
<ul>
<li><strong>Reorg safety at the framework level.</strong> Entity state history, automatic rollback, no reorg logic required in handlers. Learn more in <a href="https://docs.envio.dev/blog/indexing-and-reorgs" target="_blank" rel="noopener noreferrer">Indexing and Reorgs</a>.</li>
<li><strong>Structured GraphQL output.</strong> Entities, relationships, aggregations, time-windowed views, all queryable from one endpoint. Agents read GraphQL, not raw logs.</li>
<li><strong>HyperSync historical throughput.</strong> Up to 2,000x faster than RPC. The Polymarket reference indexer synced its first 4,000,000,000 events in 6 days and has indexed over 6,500,000,000 to date.</li>
<li><strong>Multichain in one config.</strong> <!-- -->85+<!-- --> have native HyperSync coverage, any EVM chain accessible via standard RPC, all in a single <code>config.yaml</code>.</li>
</ul>
<p>That is the read side. The act side is what makes HyperIndex an agent's infrastructure, not just an agent's data layer.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-three-things-that-make-it-programmable-for-agents">The Three Things That Make It Programmable for Agents<a class="hash-link" aria-label="Direct link to The Three Things That Make It Programmable for Agents" title="Direct link to The Three Things That Make It Programmable for Agents" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#the-three-things-that-make-it-programmable-for-agents">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="1-the-envio-docs-mcp-server">1. The Envio Docs MCP Server<a class="hash-link" aria-label="Direct link to 1. The Envio Docs MCP Server" title="Direct link to 1. The Envio Docs MCP Server" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#1-the-envio-docs-mcp-server">​</a></h3>
<p>The <a href="https://docs.envio.dev/docs/HyperIndex/mcp-server" target="_blank" rel="noopener noreferrer">docs MCP server</a> exposes the entire Envio docs site as two MCP tools:</p>
<ul>
<li><code>docs_search</code> for semantic search across the docs</li>
<li><code>docs_fetch</code> to retrieve a docs page by ID</li>
</ul>
<p>Endpoint: <code>https://docs.envio.dev/mcp</code>. Transport: Streamable HTTP.</p>
<p>Setup is one command for Claude Code:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">claude mcp </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--transport</span><span class="token plain"> http envio-docs https://docs.envio.dev/mcp</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Cursor and VS Code use the JSON config form on the same page. Once added, every agent session in that workspace grounds its answers about HyperIndex in the live docs rather than stale training data.</p>
<p>This matters because agents writing indexer code typically hallucinate APIs that do not exist. The MCP server gives the agent a fresh source of truth on every request, so it cites real HyperIndex syntax instead of guessing.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="2-auto-discovered-skills-in-claudeskills">2. Auto-Discovered Skills in <code>.claude/skills/</code><a class="hash-link" aria-label="Direct link to 2-auto-discovered-skills-in-claudeskills" title="Direct link to 2-auto-discovered-skills-in-claudeskills" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#2-auto-discovered-skills-in-claudeskills">​</a></h3>
<p>When a HyperIndex project is initialised, it scaffolds a <code>.claude/skills/</code> directory pre-populated with skill definitions. Cursor, Claude Code, and Codex all auto-discover skills from this directory at session start. The descriptions load up front, full skill content loads on demand. Confirmed in the public Polymarket reference repo's <code>CLAUDE.md</code>:</p>
<blockquote>
<p>Skills in <code>.claude/skills/</code> are auto-discovered — descriptions load at startup, full content on demand.</p>
</blockquote>
<p>HyperIndex projects scaffolded with v3 rc ship 14 skill definitions:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">.claude/skills/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-blocks/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-configuration/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-external-calls/   # Effect API for fetch / RPC / async I/O</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-factory/          # Dynamic contract registration</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-filters/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-handlers/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-multichain/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-performance/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-schema/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-testing/          # Vitest patterns for handler tests</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-traces/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-transactions/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer-wildcard/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  migrate-from-subgraph/    # AssemblyScript-to-TypeScript conversion</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The canonical skill set lives at <a href="https://github.com/enviodev/hyperindex/tree/main/packages/cli/templates/static/shared/.claude/skills" target="_blank" rel="noopener noreferrer">github.com/enviodev/hyperindex/tree/main/packages/cli/templates/static/shared/.claude/skills</a> and ships into every new HyperIndex project.</p>
<p>These skills encode the patterns that make a HyperIndex project work. A developer running Claude Code, Cursor, or Codex in a HyperIndex project does not need to teach the agent what HyperIndex is. The skills do that, scoped to the actual conventions the framework expects.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="3-the-envio-cloud-cli">3. The envio-cloud CLI<a class="hash-link" aria-label="Direct link to 3. The envio-cloud CLI" title="Direct link to 3. The envio-cloud CLI" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#3-the-envio-cloud-cli">​</a></h3>
<p>The <code>envio-cloud</code> CLI is the GitHub-native deploy surface for HyperIndex indexers running on Envio Cloud. The three core agent-facing commands are:</p>
<ul>
<li><code>envio-cloud login</code> to authenticate via GitHub</li>
<li><code>envio-cloud indexer add</code> to register a new indexer</li>
<li><code>envio-cloud deployment status</code> to check sync state</li>
</ul>
<p>Every command supports <code>-o json</code> for parseable output. Install with <code>npm install -g envio-cloud</code>.</p>
<p>The full <a href="https://docs.envio.dev/docs/HyperIndex/envio-cloud-cli" target="_blank" rel="noopener noreferrer">CLI reference</a> is in the docs.</p>
<p>The deploy model is GitHub-native. An agent commits the indexer code to a GitHub repo, pushes to the <code>envio</code> branch (the default deploy branch), and registers the indexer with <code>envio-cloud indexer add</code>. The Envio GitHub App handles deployments from there. No deploy button, no dashboard step.</p>
<p>The published agentic demo did exactly that for a wstETH indexer on Monad Mainnet. 400,000 events indexed in approximately 20 seconds. The agent reads the contract, scaffolds the project from the ERC20 template, configures <code>config.yaml</code> for Monad, runs codegen and a type check, pushes to GitHub, and registers the indexer. End to end, no human in the loop after the first prompt. <a href="https://www.loom.com/share/09cdac43b18f4143ad78b18c8c8a492b" target="_blank" rel="noopener noreferrer">Loom walkthrough</a>. <a href="https://envio.dev/app/denhampreen/wsteth-monad-indexer-demo/5d55d35" target="_blank" rel="noopener noreferrer">Live deployment</a>.</p>
<p>That is the <em>act</em> in "programmable infrastructure for agents that need to act, not just query."</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="a-concrete-example-the-published-wsteth-on-monad-demo">A Concrete Example: The Published wstETH-on-Monad Demo<a class="hash-link" aria-label="Direct link to A Concrete Example: The Published wstETH-on-Monad Demo" title="Direct link to A Concrete Example: The Published wstETH-on-Monad Demo" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#a-concrete-example-the-published-wsteth-on-monad-demo">​</a></h2>
<p>The <a href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex" target="_blank" rel="noopener noreferrer">agentic indexing blog</a> documents the full end-to-end flow an agent ran from scaffold to live deployment. This is not a hypothetical. The <a href="https://envio.dev/app/denhampreen/wsteth-monad-indexer-demo/5d55d35" target="_blank" rel="noopener noreferrer">live deployment</a> and the <a href="https://www.loom.com/share/09cdac43b18f4143ad78b18c8c8a492b" target="_blank" rel="noopener noreferrer">Loom walkthrough</a> are both public.</p>
<p>The commands the agent ran (from the published blog):</p>
<p><strong>Step 1: Scaffold from the ERC20 template</strong></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio@3.0.0-rc.0 init template </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-t</span><span class="token plain"> erc20 </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-l</span><span class="token plain"> typescript </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-d</span><span class="token plain"> ./my-indexer --api-token </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>--api-token ""</code> makes the init non-interactive. No token is needed at scaffold time; auth is handled at deploy.</p>
<p><strong>Step 2: Configure for the target chain</strong></p>
<p>The agent edits <code>config.yaml</code> to target the wstETH contract on Monad Mainnet. From the published blog: chain ID 143, contract <code>0x10Aeaf63194db8d453d4D85a06E5eFE1dd0b5417</code>, <code>start_block: 0</code>.</p>
<p>Then runs codegen and a type check:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> codegen</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> tsc </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--noEmit</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Step 3: Push to GitHub on the deploy branch</strong></p>
<p>Envio Cloud deploys from the <code>envio</code> branch by default:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">gh repo create wsteth-monad-indexer-demo </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--public</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> init </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">.</span><span class="token plain"> </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> commit </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-m</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"init"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> push </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-u</span><span class="token plain"> origin main</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> checkout </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-b</span><span class="token plain"> envio </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> push </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-u</span><span class="token plain"> origin envio</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Step 4: Connect the Envio GitHub App to the repo</strong></p>
<p>A one-time install at <a href="https://github.com/apps/envio-deployments/installations/select_target" target="_blank" rel="noopener noreferrer">github.com/apps/envio-deployments</a>. The app handles the actual deployment when commits land on the <code>envio</code> branch.</p>
<p><strong>Step 5: Register and deploy</strong></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio-cloud login</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio-cloud indexer </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--name</span><span class="token plain"> wsteth-monad-indexer-demo </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--repo</span><span class="token plain"> wsteth-monad-indexer-demo </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--description</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"wstETH ERC20 indexer on Monad"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--branch</span><span class="token plain"> envio </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --skip-repo-check </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--yes</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><strong>Step 6: Verify</strong></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio-cloud indexer get wsteth-monad-indexer-demo </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">org</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio-cloud deployment status wsteth-monad-indexer-demo </span><span class="token operator">&lt;</span><span class="token plain">commit-hash</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">org</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Once synced, the indexer is at <code>https://envio.dev/app/{org}/{indexer-name}/{commit-hash}</code>.</p>
<p><strong>Result: 400,000 events indexed in ~20 seconds.</strong></p>
<p>Every command above is taken directly from the published blog. Every flag exists. The flow is what this whole blog is arguing for, an agent that scaffolds, configures, deploys, and verifies an indexer end to end, with no human stepping in. The <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">Polymarket reference indexer</a> is the production-scale reference for what this stack produces at full scale. The wstETH demo is the documented one-prompt run.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-this-beats-a-sql-warehouse-for-agentic-workflows">Why This Beats a SQL Warehouse for Agentic Workflows<a class="hash-link" aria-label="Direct link to Why This Beats a SQL Warehouse for Agentic Workflows" title="Direct link to Why This Beats a SQL Warehouse for Agentic Workflows" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#why-this-beats-a-sql-warehouse-for-agentic-workflows">​</a></h2>
<p>A SQL warehouse fronted by an LLM is excellent for analysts. The agent reads a question, writes SQL, returns a number. The agent does not change the warehouse, does not deploy new ingestion, does not branch the schema.</p>
<p>An agent acting onchain needs the opposite. It needs to:</p>
<ul>
<li>Add a new contract to its data ingestion mid-session</li>
<li>Branch the schema to add a new entity type for a workflow it is exploring</li>
<li>Spin up a brand-new indexer for an opportunity it just discovered</li>
<li>Deploy to a hosted runtime and stream results back</li>
</ul>
<p>HyperIndex gives the agent that ability. The indexer is a project the agent owns, not a warehouse it queries. The same agent can have ten indexers running at any time, each tracking a different market. None of that is possible if the only interface is read-only SQL.</p>
<p>For analysts: SQL warehouses are the right tool. For agents acting on the data: an indexing framework is the right tool. Both can coexist. The case here is for the agent side, which is the side under-served by the current SQL-warehouse-plus-LLM consensus.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#get-started">​</a></h2>
<ul>
<li><a href="https://docs.envio.dev/docs/HyperIndex/quickstart-with-ai" target="_blank" rel="noopener noreferrer">HyperIndex Quickstart with AI</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/mcp-server" target="_blank" rel="noopener noreferrer">Envio docs MCP server</a></li>
<li><a href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex" target="_blank" rel="noopener noreferrer">Agentic indexing case (400k events, 20s)</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/envio-cloud-cli" target="_blank" rel="noopener noreferrer">envio-cloud CLI reference</a></li>
<li><a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">Polymarket production reference</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="why-do-ai-agents-acting-onchain-need-an-indexer-at-all">Why do AI agents acting onchain need an indexer at all?<a class="hash-link" aria-label="Direct link to Why do AI agents acting onchain need an indexer at all?" title="Direct link to Why do AI agents acting onchain need an indexer at all?" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#why-do-ai-agents-acting-onchain-need-an-indexer-at-all">​</a></h3>
<p>Raw RPC has four problems for an agent: reorgs, no schema, low throughput, and per-chain quirks at multichain scale. An indexer addresses all four. HyperIndex addresses them at the framework level, with reorg-safe storage, structured GraphQL output, <a href="https://docs.envio.dev/docs/HyperSync/overview">HyperSync</a> throughput, and a single multichain config.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-the-envio-docs-mcp-server">What is the Envio docs MCP server?<a class="hash-link" aria-label="Direct link to What is the Envio docs MCP server?" title="Direct link to What is the Envio docs MCP server?" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#what-is-the-envio-docs-mcp-server">​</a></h3>
<p>A Model Context Protocol server at <code>https://docs.envio.dev/mcp</code> that exposes the Envio docs as two tools, <code>docs_search</code> and <code>docs_fetch</code>. Configured into Claude Code, Cursor, or VS Code with one setup command. Announcement blog: <a href="https://docs.envio.dev/blog/envio-docs-mcp-server" target="_blank" rel="noopener noreferrer">Introducing the Envio Docs MCP Server</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-fast-can-an-ai-agent-deploy-a-hyperindex-indexer">How fast can an AI agent deploy a HyperIndex indexer?<a class="hash-link" aria-label="Direct link to How fast can an AI agent deploy a HyperIndex indexer?" title="Direct link to How fast can an AI agent deploy a HyperIndex indexer?" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#how-fast-can-an-ai-agent-deploy-a-hyperindex-indexer">​</a></h3>
<p>The <a href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex" target="_blank" rel="noopener noreferrer">agentic indexing blog</a> documents a single-prompt flow that scaffolds, deploys, and runs an indexer covering 400,000 events on Monad in roughly 20 seconds.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="does-the-envio-cloud-cli-support-agent-driven-deploys">Does the envio-cloud CLI support agent-driven deploys?<a class="hash-link" aria-label="Direct link to Does the envio-cloud CLI support agent-driven deploys?" title="Direct link to Does the envio-cloud CLI support agent-driven deploys?" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#does-the-envio-cloud-cli-support-agent-driven-deploys">​</a></h3>
<p>Yes. The CLI surface includes <code>envio-cloud login</code>, <code>envio-cloud indexer add</code>, <code>envio-cloud deployment status</code>, <code>envio-cloud deployment metrics</code>, <code>envio-cloud deployment promote</code>, with <code>-o json</code> on any command for parseable output. Deployments are GitHub-native: an agent commits to the <code>envio</code> branch and the registered indexer deploys automatically.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-does-hyperindex-differ-from-a-sql-warehouse-for-agents">How does HyperIndex differ from a SQL warehouse for agents?<a class="hash-link" aria-label="Direct link to How does HyperIndex differ from a SQL warehouse for agents?" title="Direct link to How does HyperIndex differ from a SQL warehouse for agents?" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#how-does-hyperindex-differ-from-a-sql-warehouse-for-agents">​</a></h3>
<p>A SQL warehouse is a read-only query layer. HyperIndex is a programmable indexer the agent can own, branch, and deploy. Both have a place. SQL warehouses suit analytical workflows. Indexers suit agents that need to act, not just query.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="can-an-agent-register-a-new-contract-mid-session-without-a-redeploy">Can an agent register a new contract mid-session without a redeploy?<a class="hash-link" aria-label="Direct link to Can an agent register a new contract mid-session without a redeploy?" title="Direct link to Can an agent register a new contract mid-session without a redeploy?" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#can-an-agent-register-a-new-contract-mid-session-without-a-redeploy">​</a></h3>
<p>Yes, when the contract is created by a factory the agent has already configured. HyperIndex's dynamic contract registration is a first-class feature, and the <code>indexer-factory</code> skill in <code>.claude/skills/</code> is the canonical reference for the pattern. Adding a brand-new chain or an unrelated contract still requires a config change and a redeploy, which the agent can run from the <code>envio-cloud</code> CLI in one command.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="where-can-i-watch-an-agent-run-this-end-to-end">Where can I watch an agent run this end-to-end?<a class="hash-link" aria-label="Direct link to Where can I watch an agent run this end-to-end?" title="Direct link to Where can I watch an agent run this end-to-end?" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#where-can-i-watch-an-agent-run-this-end-to-end">​</a></h3>
<p>The published <a href="https://www.loom.com/share/09cdac43b18f4143ad78b18c8c8a492b" target="_blank" rel="noopener noreferrer">Loom walkthrough</a> shows the full wstETH-on-Monad demo, scaffold to live deployment. The <a href="https://envio.dev/app/denhampreen/wsteth-monad-indexer-demo/5d55d35" target="_blank" rel="noopener noreferrer">live indexer</a> is public.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#build-with-envio">​</a></h2>
<p>Envio is the fastest independently benchmarked EVM blockchain indexer for querying real-time and historical data. If you are building onchain and need indexing that keeps up with your chain, check out the <a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">docs</a>, run the benchmarks yourself, and come talk to us about your data needs.</p>
<p>Stay tuned for more updates by subscribing to our newsletter, following us on X, or hopping into our Discord.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a></p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.com/invite/gt7yEUZKeB" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>ai</category>
        </item>
        <item>
            <title><![CDATA[Build an AI-Powered App with HyperIndex and Claude]]></title>
            <link>https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude</link>
            <guid>https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude</guid>
            <pubDate>Thu, 14 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[End-to-end tutorial: scaffold, deploy, and run a multichain HyperIndex indexer with Claude. Real config, real handlers, real CLI, real GraphQL.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/ai-onchain-app-hyperindex-claude.png" alt="Build an AI-Powered App with HyperIndex and Claude" width="100%">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>HyperIndex is Envio's multichain blockchain indexing framework for EVM chains. With Claude Code pointed at a HyperIndex project, the agent has the docs (via the docs MCP server) and the patterns (via the auto-discovered <code>.claude/skills/</code> directory shipped with every v3 rc project) to scaffold, code, deploy, and run an indexer end to end.</li>
<li>The CLI surface is <code>pnpx envio init</code> for scaffold, <code>TUI_OFF=true pnpm dev</code> for local, and the GitHub-native <code>envio-cloud indexer add</code> flow for hosted deployments. Every command is scriptable and agent-friendly.</li>
<li>The Polymarket reference at <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">github.com/enviodev/polymarket-indexer</a> is the public production example. 8 subgraphs replaced with 1; the first 4,000,000,000 events synced in 6 days, over 6,500,000,000 indexed to date.</li>
<li>Anything in this blog is reproducible today against the current HyperIndex release tracked at <a href="https://github.com/enviodev/hyperindex/releases" target="_blank" rel="noopener noreferrer">github.com/enviodev/hyperindex/releases</a>.</li>
</ul></div></div>
<p>This is a practical, end-to-end walkthrough of building a HyperIndex indexer with Claude as a pair programmer. Every command is from the published Envio docs. Every code shape is taken directly from the public Polymarket reference indexer. The aim is to show the shortest reliable path from a blank project to a deployed multichain indexer that an engineer (or an agent) can actually run today.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-youre-building">What You're Building<a class="hash-link" aria-label="Direct link to What You're Building" title="Direct link to What You're Building" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#what-youre-building">​</a></h2>
<p>A multichain HyperIndex indexer that tracks ERC20 transfers across two chains (Ethereum and Base) and exposes the data through a GraphQL endpoint. Two contracts, one schema, one config, deployed to <a href="https://docs.envio.dev/docs/HyperIndex/hosted-service" target="_blank" rel="noopener noreferrer">Envio Cloud</a> and queryable in roughly 30 minutes if you are reading along, or roughly 5 minutes if Claude is driving.</p>
<p>The structure of the project will be three files plus generated TypeScript:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">my-erc20-indexer/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  config.yaml          # Networks, contracts, events</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  schema.graphql       # Entity model</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  src/EventHandlers.ts # The handler logic</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Source for the three-file structure: <a href="https://docs.envio.dev/docs/HyperIndex/quickstart-with-ai" target="_blank" rel="noopener noreferrer">docs.envio.dev/docs/HyperIndex/quickstart-with-ai</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-0-wire-up-claude">Step 0: Wire Up Claude<a class="hash-link" aria-label="Direct link to Step 0: Wire Up Claude" title="Direct link to Step 0: Wire Up Claude" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#step-0-wire-up-claude">​</a></h2>
<p>Once. Then never again. The Envio <a href="https://docs.envio.dev/docs/HyperIndex/mcp-server" target="_blank" rel="noopener noreferrer">docs MCP server</a> exposes the live docs to any MCP-capable agent. From the docs MCP server reference, the setup commands are:</p>
<p>For Claude Code:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">claude mcp </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--transport</span><span class="token plain"> http envio-docs https://docs.envio.dev/mcp</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>For Cursor or VS Code, drop this into the MCP config:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"mcpServers"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"envio-docs"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"url"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://docs.envio.dev/mcp"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"transport"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"http"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>After this, Claude has two tools available in any session: <code>docs_search</code> (semantic search) and <code>docs_fetch</code> (retrieve a page). The agent uses these instead of guessing at API surface from training data.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-1-scaffold-the-project">Step 1: Scaffold the Project<a class="hash-link" aria-label="Direct link to Step 1: Scaffold the Project" title="Direct link to Step 1: Scaffold the Project" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#step-1-scaffold-the-project">​</a></h2>
<p>Use the template flow to scaffold an ERC20 indexer in one non-interactive command.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio@3.0.0-rc.0 init template </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-t</span><span class="token plain"> erc20 </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-l</span><span class="token plain"> typescript </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-d</span><span class="token plain"> ./my-indexer --api-token </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This pulls the current HyperIndex v3 release candidate, which ships with the V3 testing framework, the built-in <code>.claude/skills/</code> directory, and the current CLI flags. The current release is tracked at <a href="https://github.com/enviodev/hyperindex/releases" target="_blank" rel="noopener noreferrer">github.com/enviodev/hyperindex/releases</a>.</p>
<p>The <code>--api-token ""</code> flag tells the init to run non-interactively, with no prompt for an Etherscan-style API token. If an agent is driving, every interactive prompt is a failure mode.</p>
<p>The init produces the three files plus a <code>package.json</code>, <code>tsconfig.json</code>, an <code>AGENTS.md</code> and <code>CLAUDE.md</code> documenting the conventions, and an auto-discovered <code>.claude/skills/</code> directory. Every project scaffolded with v3 rc ships these skills out of the box, encoding the indexing patterns Claude needs to write idiomatic HyperIndex code without improvising.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-2-make-it-multichain">Step 2: Make It Multichain<a class="hash-link" aria-label="Direct link to Step 2: Make It Multichain" title="Direct link to Step 2: Make It Multichain" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#step-2-make-it-multichain">​</a></h2>
<p>The init scaffolds for one chain. Adding a second is a config edit, not a fresh project. Open <code>config.yaml</code> and add a second chain entry. The shape mirrors the public <a href="https://github.com/enviodev/polymarket-indexer/blob/main/config.yaml" target="_blank" rel="noopener noreferrer">Polymarket config</a>. HyperIndex uses two-tier declaration. Top-level <code>contracts:</code> for global event signatures, then a <code>chains:</code> array for per-chain addresses and start blocks.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># Pattern from: https://github.com/enviodev/polymarket-indexer/blob/main/config.yaml</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># yaml-language-server: $schema=./node_modules/envio/evm.schema.json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> erc20</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">multichain</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> USDC</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">events</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Transfer(address indexed from, address indexed to, uint256 value)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">field_selection</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">transaction_fields</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> hash</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> from</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> to</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">chains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">17000000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> USDC</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">8453</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">2000000</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> USDC</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Three things to call out:</p>
<ul>
<li><code>chains:</code> is the keyword, not <code>networks:</code>. Per the AGENTS.md generated into every HyperIndex project: "Uses chains (not networks)." If your editor or an AI agent suggests <code>networks:</code>, the schema validation will fail.</li>
<li>The <code>handler:</code> field is optional. Handlers auto-register from <code>src/handlers/</code>. Same AGENTS.md.</li>
<li><code>field_selection</code> controls which transaction fields HyperSync ships down. Asking for fewer fields is faster and uses less memory.</li>
</ul>
<p>For the current set of supported config options including per-contract <code>start_block</code> and environment variable interpolation, the full <a href="https://docs.envio.dev/docs/HyperIndex/configuration-file" target="_blank" rel="noopener noreferrer">configuration reference</a> lives in the docs.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-3-the-schema">Step 3: The Schema<a class="hash-link" aria-label="Direct link to Step 3: The Schema" title="Direct link to Step 3: The Schema" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#step-3-the-schema">​</a></h2>
<p>Edit <code>schema.graphql</code> to model entities the application will query. The shape uses a <code>chainId</code>-first pattern (per-chain entities plus aggregated entities) for clean cross-chain queries:</p>
<div class="language-graphql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-graphql codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># Pattern from: https://github.com/enviodev/polymarket-indexer/blob/main/schema.graphql</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">Transfer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive function" style="color:rgb(80, 250, 123)">@index</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token attr-name" style="color:rgb(241, 250, 140)">fields</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"from"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"timestamp"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"DESC"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token directive function" style="color:rgb(80, 250, 123)">@index</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token attr-name" style="color:rgb(241, 250, 140)">fields</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"to"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"timestamp"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"DESC"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">ID</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">String</span><span class="token operator">!</span><span class="token plain"> </span><span class="token directive function" style="color:rgb(80, 250, 123)">@index</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">String</span><span class="token operator">!</span><span class="token plain"> </span><span class="token directive function" style="color:rgb(80, 250, 123)">@index</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BigInt</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">chainId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">Int</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">blockNumber</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">Int</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">Int</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">AccountBalance</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">ID</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">String</span><span class="token operator">!</span><span class="token plain"> </span><span class="token directive function" style="color:rgb(80, 250, 123)">@index</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">chainId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">Int</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">balance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BigInt</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">lastUpdated</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">Int</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">AggregateBalance</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">ID</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">String</span><span class="token operator">!</span><span class="token plain"> </span><span class="token directive function" style="color:rgb(80, 250, 123)">@index</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">totalAcrossChains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token class-name">BigInt</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token attr-name" style="color:rgb(241, 250, 140)">lastUpdated</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token scalar">Int</span><span class="token operator">!</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Two HyperIndex-specific things worth noting in this schema:</p>
<ul>
<li>No <code>@entity</code> decorator. From the project's <code>AGENTS.md</code>: "Unlike TheGraph, schema types have no decorators." Subgraphs put <code>@entity</code> on every type. HyperIndex does not.</li>
<li><code>@index</code> is composable. The <a href="https://github.com/enviodev/polymarket-indexer/blob/main/schema.graphql" target="_blank" rel="noopener noreferrer">Polymarket schema</a> uses both per-field <code>@index</code> and per-type composite indexes like <code>@index(fields: ["from", ["timestamp", "DESC"]])</code> to drive the queries the application needs.</li>
</ul>
<p><code>Transfer</code> carries every transfer event with <code>chainId</code> first-class. <code>AccountBalance</code> is per-chain. <code>AggregateBalance</code> is the cross-chain rollup. The same indexer writes to all three.</p>
<p>After editing the schema, run <code>pnpm codegen</code> to regenerate the typed bindings. The project's <code>AGENTS.md</code> is explicit that codegen is required after any schema or config change. Types go stale otherwise.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-4-the-handler">Step 4: The Handler<a class="hash-link" aria-label="Direct link to Step 4: The Handler" title="Direct link to Step 4: The Handler" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#step-4-the-handler">​</a></h2>
<p>In v3 rc, types come from the <code>envio</code> package directly. The handler imports <code>indexer</code> plus any entity types it needs, then registers handlers as <code>indexer.onEvent({ contract: "CONTRACT_NAME", event: "EVENT_NAME" }, handler)</code>.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">Transfer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">AccountBalance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">AggregateBalance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"envio"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">onEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> contract</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"USDC"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> event</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Transfer"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> transferId </span><span class="token operator">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">chainId</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">_</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">block</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation builtin" style="color:rgb(189, 147, 249)">number</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">_</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">logIndex</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> transfer</span><span class="token operator">:</span><span class="token plain"> Transfer </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      id</span><span class="token operator">:</span><span class="token plain"> transferId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      from</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      to</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      value</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      chainId</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">chainId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      blockNumber</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token builtin" style="color:rgb(189, 147, 249)">number</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      timestamp</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Transfer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">transfer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> fromKey </span><span class="token operator">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">chainId</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">_</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">params</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">from</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> toKey </span><span class="token operator">=</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">chainId</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">_</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">params</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">to</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> fromBal</span><span class="token operator">:</span><span class="token plain"> AccountBalance </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">AccountBalance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">fromKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      id</span><span class="token operator">:</span><span class="token plain"> fromKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      account</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      chainId</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">chainId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      balance</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0n</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      lastUpdated</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">AccountBalance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token operator">...</span><span class="token plain">fromBal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      balance</span><span class="token operator">:</span><span class="token plain"> fromBal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">balance </span><span class="token operator">-</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      lastUpdated</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> toBal</span><span class="token operator">:</span><span class="token plain"> AccountBalance </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">AccountBalance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">toKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      id</span><span class="token operator">:</span><span class="token plain"> toKey</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      account</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      chainId</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">chainId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      balance</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0n</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      lastUpdated</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">AccountBalance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token operator">...</span><span class="token plain">toBal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      balance</span><span class="token operator">:</span><span class="token plain"> toBal</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">balance </span><span class="token operator">+</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      lastUpdated</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> fromAgg</span><span class="token operator">:</span><span class="token plain"> AggregateBalance </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">AggregateBalance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      id</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      account</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      totalAcrossChains</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0n</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      lastUpdated</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">AggregateBalance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token operator">...</span><span class="token plain">fromAgg</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      totalAcrossChains</span><span class="token operator">:</span><span class="token plain"> fromAgg</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">totalAcrossChains </span><span class="token operator">-</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      lastUpdated</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> toAgg</span><span class="token operator">:</span><span class="token plain"> AggregateBalance </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">AggregateBalance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      id</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      account</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      totalAcrossChains</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0n</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      lastUpdated</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">AggregateBalance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token operator">...</span><span class="token plain">toAgg</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      totalAcrossChains</span><span class="token operator">:</span><span class="token plain"> toAgg</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">totalAcrossChains </span><span class="token operator">+</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      lastUpdated</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Three project-enforced conventions visible in this snippet, all spelled out in the <code>AGENTS.md</code> generated into every HyperIndex project:</p>
<ul>
<li><strong>Spread operator for updates.</strong> Entities returned by <code>context.Entity.get()</code> are read-only. Always spread: <code>context.Entity.set({ ...existing, field: newValue })</code>. Direct mutation throws.</li>
<li><strong>Composite IDs for cross-chain uniqueness.</strong> <code>${event.chainId}_${event.block.number}_${event.logIndex}</code> is the Polymarket pattern. Without <code>chainId</code> in the ID, two chains writing the same <code>(block, logIndex)</code> collide.</li>
<li><strong>Effect API for any external call.</strong> If the handler needs to fetch Gamma metadata, call an RPC, or hit any other async I/O, use <code>createEffect</code> plus <code>context.effect()</code>. Never call external services directly. The Polymarket <code>TokenRegistered</code> handler shows the pattern with <code>context.effect(getMarketMetadata, token0Str)</code>.</li>
</ul>
<p>This is the structure an agent with the <code>indexer-handlers</code> and <code>indexer-external-calls</code> skills produces when asked to "write the Transfer handler that updates per-chain and aggregate balances." The skills encode these conventions so the agent does not improvise them wrongly.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-5-run-it-locally">Step 5: Run It Locally<a class="hash-link" aria-label="Direct link to Step 5: Run It Locally" title="Direct link to Step 5: Run It Locally" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#step-5-run-it-locally">​</a></h2>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> codegen          </span><span class="token comment" style="color:rgb(98, 114, 164)"># regenerate types from schema + config</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> tsc </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--noEmit</span><span class="token plain">     </span><span class="token comment" style="color:rgb(98, 114, 164)"># type-check without emitting</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">TUI_OFF</span><span class="token operator">=</span><span class="token plain">true </span><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> dev </span><span class="token comment" style="color:rgb(98, 114, 164)"># run indexer (TUI_OFF gives AI-friendly stdout)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Source for these exact commands: <a href="https://github.com/enviodev/polymarket-indexer/blob/main/AGENTS.md" target="_blank" rel="noopener noreferrer">polymarket-indexer/AGENTS.md</a>.</p>
<p>The local dev environment spins up a Postgres and a Hasura GraphQL instance. The indexer starts pulling events from both chains via HyperSync. Sync rates of 25,000 events per second on historical backfill are standard. The <a href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study" target="_blank" rel="noopener noreferrer">Polymarket case study</a> documents 4,000,000,000 events synced in 6 days on Polygon; the indexer has since indexed over 6,500,000,000 in total.</p>
<p>The Hasura GraphQL endpoint is available locally. Once the indexer is at chain head, queries like:</p>
<div class="language-graphql codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-graphql codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">query</span><span class="token plain"> </span><span class="token definition-query function" style="color:rgb(80, 250, 123)">AggregateBalanceForAccount</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property-query">AggregateBalance</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token attr-name" style="color:rgb(241, 250, 140)">where</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token attr-name" style="color:rgb(241, 250, 140)">account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token attr-name" style="color:rgb(241, 250, 140)">_eq</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0xabc..."</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">account</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">totalAcrossChains</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">lastUpdated</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>return live data.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-6-deploy-to-envio-cloud">Step 6: Deploy to Envio Cloud<a class="hash-link" aria-label="Direct link to Step 6: Deploy to Envio Cloud" title="Direct link to Step 6: Deploy to Envio Cloud" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#step-6-deploy-to-envio-cloud">​</a></h2>
<p>Envio Cloud uses a GitHub-native deploy model. An agent commits the indexer to a GitHub repo, pushes to the <code>envio</code> branch (the default deploy branch), and registers the indexer with <code>envio-cloud indexer add</code>. The Envio GitHub App handles deployments from there. No deploy button, no dashboard step.</p>
<p>Install the CLI and authenticate:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-g</span><span class="token plain"> envio-cloud</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">envio-cloud login</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Push the project to GitHub on the <code>envio</code> branch:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">gh repo create my-erc20-indexer </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--public</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> init </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">.</span><span class="token plain"> </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> commit </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-m</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"init"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> push </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-u</span><span class="token plain"> origin main</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> checkout </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-b</span><span class="token plain"> envio </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> push </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-u</span><span class="token plain"> origin envio</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Connect the Envio GitHub App to the repo (one-time install at <a href="https://github.com/apps/envio-deployments/installations/select_target" target="_blank" rel="noopener noreferrer">github.com/apps/envio-deployments</a>), then register the indexer:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">envio-cloud indexer </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--name</span><span class="token plain"> my-erc20-indexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--repo</span><span class="token plain"> my-erc20-indexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--description</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Multichain ERC20 indexer"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--branch</span><span class="token plain"> envio </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --skip-repo-check </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--yes</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The verified CLI surface (from the <a href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex" target="_blank" rel="noopener noreferrer">agentic indexing blog</a>) includes:</p>
<ul>
<li><code>envio-cloud login</code> authenticates via GitHub</li>
<li><code>envio-cloud indexer add</code> registers a new indexer pointing at a GitHub repo and branch</li>
<li><code>envio-cloud indexer get</code> fetches indexer details</li>
<li><code>envio-cloud deployment status</code> returns the current sync state of a deployment</li>
<li><code>envio-cloud deployment metrics</code> returns runtime metrics</li>
<li><code>envio-cloud deployment promote</code> promotes a deployment to production</li>
<li><code>-o json</code> on any command for parseable output</li>
</ul>
<p>Track sync progress with <code>envio-cloud deployment status</code> and <code>envio-cloud deployment metrics</code>. Full reference at <a href="https://docs.envio.dev/docs/HyperIndex/envio-cloud-cli" target="_blank" rel="noopener noreferrer">docs.envio.dev/docs/HyperIndex/envio-cloud-cli</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-7-test-it">Step 7: Test It<a class="hash-link" aria-label="Direct link to Step 7: Test It" title="Direct link to Step 7: Test It" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#step-7-test-it">​</a></h2>
<p><code>pnpm test</code> runs the project's Vitest suite. In v3 rc, tests import <code>createTestIndexer</code> and <code>TestHelpers</code> from the <code>envio</code> package directly, so tests use the same types as handlers. The <code>indexer-testing</code> skill in <code>.claude/skills/</code> encodes the current API surface (mock event factories, test indexer setup, assertion patterns) and the <a href="https://docs.envio.dev/docs/HyperIndex/testing" target="_blank" rel="noopener noreferrer">testing reference docs</a> cover it end to end.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-the-stack-looks-like-end-to-end">What the Stack Looks Like End to End<a class="hash-link" aria-label="Direct link to What the Stack Looks Like End to End" title="Direct link to What the Stack Looks Like End to End" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#what-the-stack-looks-like-end-to-end">​</a></h2>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">[Claude Code or Cursor]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         | (reads docs via MCP server, applies built-in Claude skills)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         v</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">[HyperIndex Project (config.yaml + schema.graphql + handlers)]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         | (pnpm dev locally, or push to GitHub envio branch)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         v</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">[HyperIndex Runtime + HyperSync]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         | (live indexes EVM chains natively, any EVM via RPC)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         v</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">[Postgres + Hasura GraphQL endpoint]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         | (queried by application, dashboard, agent, or downstream service)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">         v</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">[Your AI-Powered Onchain App]</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Each layer is a piece you have full control over. None of them require black-box assumptions about how an indexer behaves under reorgs, source outages, or scale. The <a href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex" target="_blank" rel="noopener noreferrer">reliability blog</a> covers what HyperIndex provides at the framework level.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#get-started">​</a></h2>
<ul>
<li><a href="https://docs.envio.dev/docs/HyperIndex/quickstart-with-ai" target="_blank" rel="noopener noreferrer">HyperIndex Quickstart with AI</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/mcp-server" target="_blank" rel="noopener noreferrer">Envio docs MCP server</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/envio-cloud-cli" target="_blank" rel="noopener noreferrer">envio-cloud CLI reference</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/configuration-file" target="_blank" rel="noopener noreferrer">config.yaml reference</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/testing" target="_blank" rel="noopener noreferrer">Testing docs (V3 framework)</a></li>
<li><a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">Polymarket production reference</a></li>
<li><a href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude" target="_blank" rel="noopener noreferrer">Companion: AI-assisted subgraph migration</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-does-an-ai-powered-onchain-app-stack-look-like">What does an AI-powered onchain app stack look like?<a class="hash-link" aria-label="Direct link to What does an AI-powered onchain app stack look like?" title="Direct link to What does an AI-powered onchain app stack look like?" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#what-does-an-ai-powered-onchain-app-stack-look-like">​</a></h3>
<p>The stack is: Claude Code (or another MCP-aware editor) as the development surface, a HyperIndex project with an auto-discovered <code>.claude/skills/</code> directory shipped by v3 rc, the HyperIndex runtime with <a href="https://docs.envio.dev/docs/HyperSync/overview">HyperSync</a> as the data engine, Postgres plus Hasura for GraphQL, and the application or agent on top. Every layer is real and shipping today.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-deploy-a-hyperindex-indexer-programmatically">How do I deploy a HyperIndex indexer programmatically?<a class="hash-link" aria-label="Direct link to How do I deploy a HyperIndex indexer programmatically?" title="Direct link to How do I deploy a HyperIndex indexer programmatically?" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#how-do-i-deploy-a-hyperindex-indexer-programmatically">​</a></h3>
<p>Install the envio-cloud CLI with <code>npm install -g envio-cloud</code> and authenticate with <code>envio-cloud login</code>. Push the indexer code to a GitHub repo on the <code>envio</code> branch, connect the Envio GitHub App to the repo, then register with <code>envio-cloud indexer add</code>. Track sync state with <code>envio-cloud deployment status</code> and <code>envio-cloud deployment metrics</code>. Every command supports <code>-o json</code> for parseable output. Full reference at <a href="https://docs.envio.dev/docs/HyperIndex/envio-cloud-cli" target="_blank" rel="noopener noreferrer">docs.envio.dev/docs/HyperIndex/envio-cloud-cli</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="can-i-add-a-chain-to-a-hyperindex-indexer-without-redeploying">Can I add a chain to a HyperIndex indexer without redeploying?<a class="hash-link" aria-label="Direct link to Can I add a chain to a HyperIndex indexer without redeploying?" title="Direct link to Can I add a chain to a HyperIndex indexer without redeploying?" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#can-i-add-a-chain-to-a-hyperindex-indexer-without-redeploying">​</a></h3>
<p>Adding a chain requires a config change and a redeploy because the indexer needs to start a new HyperSync stream. The redeploy itself is one CLI command. Adding a contract on an existing chain that uses the factory pattern can be done dynamically without a redeploy. See the <code>indexer-factory</code> skill in the project.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-does-hyperindex-compare-to-subgraphs-for-an-ai-workflow">How does HyperIndex compare to subgraphs for an AI workflow?<a class="hash-link" aria-label="Direct link to How does HyperIndex compare to subgraphs for an AI workflow?" title="Direct link to How does HyperIndex compare to subgraphs for an AI workflow?" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#how-does-hyperindex-compare-to-subgraphs-for-an-ai-workflow">​</a></h3>
<p>Subgraphs use AssemblyScript handlers, single-chain config per subgraph, and matchstick for testing. HyperIndex uses TypeScript handlers, multichain config in one file, and Vitest for testing. The TypeScript surface is what makes Claude's involvement straightforward. The migration story is covered in <a href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude" target="_blank" rel="noopener noreferrer">AI-assisted subgraph migration</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="is-hyperindex-faster-than-other-indexers-in-benchmarks">Is HyperIndex faster than other indexers in benchmarks?<a class="hash-link" aria-label="Direct link to Is HyperIndex faster than other indexers in benchmarks?" title="Direct link to Is HyperIndex faster than other indexers in benchmarks?" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#is-hyperindex-faster-than-other-indexers-in-benchmarks">​</a></h3>
<p>In Sentio's independent Uniswap V2 Factory benchmark, HyperIndex completed in 8 seconds, 142x faster than The Graph and 15x faster than the nearest competitor.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="where-can-i-see-a-public-production-reference">Where can I see a public production reference?<a class="hash-link" aria-label="Direct link to Where can I see a public production reference?" title="Direct link to Where can I see a public production reference?" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#where-can-i-see-a-public-production-reference">​</a></h3>
<p>The <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">Polymarket reference indexer</a>. Synced its first 4,000,000,000 events from block 3,764,531 in 6 days, replacing 8 separate subgraphs, and has indexed over 6,500,000,000 to date. Live at <a href="https://envio.dev/app/moose-code/polymarket-indexer/7cad3ad" target="_blank" rel="noopener noreferrer">envio.dev/app/moose-code/polymarket-indexer/7cad3ad</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#build-with-envio">​</a></h2>
<p>Envio is the fastest independently benchmarked EVM blockchain indexer for querying real-time and historical data. If you are building onchain and need indexing that keeps up with your chain, check out the <a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">docs</a>, run the benchmarks yourself, and come talk to us about your data needs.</p>
<p>Stay tuned for more updates by subscribing to our newsletter, following us on X, or hopping into our Discord.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a></p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.com/invite/gt7yEUZKeB" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>ai</category>
        </item>
        <item>
            <title><![CDATA[AI-Assisted Subgraph Migration to HyperIndex with Claude]]></title>
            <link>https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude</link>
            <guid>https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude</guid>
            <pubDate>Thu, 14 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Migrate a subgraph from The Graph to Envio HyperIndex with Claude doing the AssemblyScript-to-TypeScript rewrite. Real config, real handlers, real repo.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/ai-subgraph-migration-hyperindex-claude.png" alt="AI-Assisted Subgraph Migration to HyperIndex with Claude" width="100%">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>HyperIndex is Envio's multichain blockchain indexing framework for EVM chains. It accepts subgraph YAML and ABIs as input, scaffolds a HyperIndex project, and ships a TypeScript handler skeleton that AssemblyScript handler logic can be ported into.</li>
<li>Claude (running with the Envio docs MCP server and the auto-discovered <code>.claude/skills/</code> directory, including the dedicated <code>migrate-from-subgraph</code> skill) handles the AssemblyScript-to-TypeScript rewrite end to end. Skills auto-discover for Cursor, Claude Code, and Codex.</li>
<li>The Polymarket reference indexer is the public production-scale example: 8 subgraphs' worth of logic consolidated into one TypeScript indexer that synced its first 4,000,000,000 events in 6 days on Polygon and has indexed over 6,500,000,000 to date.</li>
</ul></div></div>
<p>The hardest part of migrating off The Graph to HyperIndex has always been the AssemblyScript rewrite. Subgraphs run handler code in WebAssembly, which means handlers are written in AssemblyScript, a stricter subset of TypeScript with its own constraints, its own tooling, and its own foot-guns. Teams who otherwise live in TypeScript every day end up maintaining one codebase in a language they touch only when their indexer breaks.</p>
<p>The HyperIndex reference indexer for Polymarket demonstrates the consolidation pattern at scale, 8 subgraphs' worth of logic rewritten as a single TypeScript indexer. The full reference is public on <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">GitHub</a> and is documented in our <a href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study" target="_blank" rel="noopener noreferrer">Polymarket case study</a>.</p>
<p>This blog is about how you can leverage Claude (or any coding agent) to migrate your subgraphs to HyperIndex. The agent does the AssemblyScript-to-TypeScript rewrite; a developer reviews the diff, runs the tests, and ships the indexer.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-hyperindex-is-and-why-the-migration-story-changed">What HyperIndex Is and Why the Migration Story Changed<a class="hash-link" aria-label="Direct link to What HyperIndex Is and Why the Migration Story Changed" title="Direct link to What HyperIndex Is and Why the Migration Story Changed" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#what-hyperindex-is-and-why-the-migration-story-changed">​</a></h2>
<p>HyperIndex is Envio's multichain blockchain indexing framework for EVM chains. HyperIndex handlers are written in regular TypeScript. Unlike AssemblyScript, which restricts which npm packages handlers can use, HyperIndex lets you bring in any npm package you want. Since handlers are TypeScript, there is no WebAssembly compilation step and no AssemblyScript-specific syntax to learn, you write handlers in the language you already use every day.</p>
<p>Two things changed in the last six months that turned subgraph migration into a tractable AI-assisted workflow:</p>
<ol>
<li>The <a href="https://docs.envio.dev/docs/HyperIndex/mcp-server" target="_blank" rel="noopener noreferrer">HyperIndex docs MCP server</a> went live, exposing the entire docs site as two tools (<code>docs_search</code> and <code>docs_fetch</code>) over Streamable HTTP at <code>https://docs.envio.dev/mcp</code>. Any IDE or assistant that speaks MCP, including Claude Code, Cursor, Codex, and VS Code, can now ground answers about HyperIndex in the live docs rather than stale training data.</li>
<li>HyperIndex projects ship a <code>.claude/skills/</code> directory that auto-discovers for Cursor, Claude Code, and Codex. The Polymarket reference repo's directory currently ships 14 skills, including a dedicated <code>migrate-from-subgraph</code> skill purpose-built for this workflow, plus <code>indexer-configuration</code>, <code>indexer-schema</code>, <code>indexer-handlers</code>, <code>indexer-factory</code> (dynamic contracts), <code>indexer-external-calls</code> (the Effect API), <code>indexer-multichain</code>, <code>indexer-performance</code>, <code>indexer-testing</code>, <code>indexer-blocks</code>, <code>indexer-filters</code>, <code>indexer-traces</code>, <code>indexer-transactions</code>, and <code>indexer-wildcard</code>. The full list lives at <a href="https://github.com/enviodev/hyperindex/tree/main/packages/cli/templates/static/shared/.claude/skills" target="_blank" rel="noopener noreferrer">the canonical skills directory</a>.</li>
</ol>
<p>Combined, these mean a developer can hand the agent a subgraph repo and a working HyperIndex project shell and ask for a migration. The agent has live docs, a project-resident migration skill, and its own validation tooling.</p>
<p>The <a href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study" target="_blank" rel="noopener noreferrer">Polymarket case study</a> is the production reference for what the end state looks like. The rest of this post walks the AI-assisted version of that same migration on a smaller surface area, anchored to real artifacts in the Polymarket repo.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-four-files-claude-needs-to-see">The Four Files Claude Needs to See<a class="hash-link" aria-label="Direct link to The Four Files Claude Needs to See" title="Direct link to The Four Files Claude Needs to See" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#the-four-files-claude-needs-to-see">​</a></h2>
<p>Every subgraph has the same four primary inputs. Claude reads them in this order.</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">my-subgraph/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  subgraph.yaml          # contracts, networks, event handlers, start blocks</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  schema.graphql         # entity types and relations</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  src/mappings/*.ts      # AssemblyScript handler logic (despite the .ts extension)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  abis/*.json            # contract ABIs the handlers parse logs against</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>subgraph.yaml</code> carries the network, the contract addresses, the start blocks, and the event-to-handler mapping. <code>schema.graphql</code> carries the entity model. The mappings carry the actual logic. The ABIs carry the signatures for the events mappings parse.</p>
<p>HyperIndex needs the same four kinds of input, restructured. The Polymarket reference shows the target shape. From <a href="https://github.com/enviodev/polymarket-indexer/blob/main/config.yaml" target="_blank" rel="noopener noreferrer">the canonical config.yaml</a> (selected events shown for brevity):</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># Source: https://github.com/enviodev/polymarket-indexer/blob/main/config.yaml</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># yaml-language-server: $schema=./node_modules/envio/evm.schema.json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> polymarket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">indexer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Unified Polymarket HyperIndex</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Exchange</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">abi_file_path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ./abis/Exchange.json</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">events</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"OrderFilled(bytes32 indexed orderHash, address indexed maker, address indexed taker, uint256 makerAssetId, uint256 takerAssetId, uint256 makerAmountFilled, uint256 takerAmountFilled, uint256 fee)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"OrdersMatched(...)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"TokenRegistered(...)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ConditionalTokens</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">abi_file_path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ./abis/ConditionalTokens.json</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">events</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"PositionSplit(...)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"PositionsMerge(...)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"PayoutRedemption(...)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">field_selection</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">transaction_fields</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> hash</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> from</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> to</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">chains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">137</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)"># Polygon</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">3764531</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Exchange</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0xC5d563A36AE78145C45a50134d48A1215220f80a"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">33605403</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ConditionalTokens</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">4023686</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Three small differences from subgraph YAML to know up front: HyperIndex uses <code>chains:</code> (not <code>networks:</code>), declares contracts once at the top level with addresses supplied per-chain, and auto-registers handlers from <code>src/handlers/&lt;ContractName&gt;.ts</code> (subgraphs require explicit handler-to-event mapping).</p>
<p>This single file replaces what would otherwise be eight separate <code>subgraph.yaml</code> files. Every shared event (<code>PositionSplit</code>, <code>PositionsMerge</code>, <code>PayoutRedemption</code>) is declared once and routed to a single TypeScript handler that updates every relevant entity in one pass. That architectural detail, "handler merging," is the structural win of the consolidation pattern.</p>
<p><code>schema.graphql</code> carries across with two specific rewrites. Subgraph schemas decorate every type with <code>@entity</code>. HyperIndex schemas have no decorators, per the AGENTS.md: "Unlike TheGraph, schema types have no decorators." Subgraph relations like <code>@derivedFrom</code> are kept; ID conventions stay; the type body is otherwise identical. The built-in <code>indexer-schema</code> skill knows the diffs and applies them.</p>
<p>Handlers are where the migration work happens. The Polymarket reference repo's <a href="https://github.com/enviodev/polymarket-indexer/blob/main/src/handlers/Exchange.ts" target="_blank" rel="noopener noreferrer"><code>Exchange.ts</code></a> shows the canonical TypeScript shape and the conventions the <code>migrate-from-subgraph</code> skill applies (simplified for the post, helper functions inlined):</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// Source: https://github.com/enviodev/polymarket-indexer/blob/main/src/handlers/Exchange.ts</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> Exchange</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">Orderbook</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"generated"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  parseOrderFilled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  updateUserPositionWithBuy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  updateUserPositionWithSell</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"../utils/pnl.js"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">COLLATERAL_SCALE</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"../utils/constants.js"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> scaleBigInt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">ZERO_BD</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"../utils/fpmm.js"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> getMarketMetadata </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"../effects/marketMetadata.js"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">TRADE_TYPE_BUY</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Buy"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">TRADE_TYPE_SELL</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Sell"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Exchange</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">OrderFilled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> side </span><span class="token operator">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">makerAssetId </span><span class="token operator">===</span><span class="token plain"> </span><span class="token number">0n</span><span class="token plain"> </span><span class="token operator">?</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">TRADE_TYPE_BUY</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">TRADE_TYPE_SELL</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> tokenId </span><span class="token operator">=</span><span class="token plain"> side </span><span class="token operator">===</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">TRADE_TYPE_BUY</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">?</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">takerAssetId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">makerAssetId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// 1. Persist the OrderFilled event (chainId in ID prevents cross-chain collisions)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">OrderFilledEvent</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    id</span><span class="token operator">:</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">chainId</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">_</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">block</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation builtin" style="color:rgb(189, 147, 249)">number</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">_</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">logIndex</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    transactionHash</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">transaction</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">hash</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    timestamp</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">BigInt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">timestamp</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    orderHash</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">orderHash</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    maker</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">maker</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    taker</span><span class="token operator">:</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">taker</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// ... rest of the event</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// 2. Read-then-write Orderbook (spread mandatory, returned entities are read-only)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> orderbook </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Orderbook</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">tokenId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">??</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">defaultOrderbook</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">tokenId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Orderbook</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">set</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token operator">...</span><span class="token plain">orderbook</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    tradesQuantity</span><span class="token operator">:</span><span class="token plain"> orderbook</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">tradesQuantity </span><span class="token operator">+</span><span class="token plain"> </span><span class="token number">1n</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    collateralVolume</span><span class="token operator">:</span><span class="token plain"> orderbook</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">collateralVolume </span><span class="token operator">+</span><span class="token plain"> size</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// 3. PnL update. Handler merged with what was previously a separate pnl subgraph</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> order </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">parseOrderFilled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">params</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">order</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">side </span><span class="token operator">===</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"BUY"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">updateUserPositionWithBuy</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> order</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> order</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">positionId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> price</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> order</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">baseAmount</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">updateUserPositionWithSell</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> order</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">account</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> order</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">positionId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> price</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> order</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">baseAmount</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The same handler file also processes <code>OrdersMatched</code> and <code>TokenRegistered</code>. The <code>TokenRegistered</code> handler fetches Polymarket Gamma API metadata via the Effect API:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// Same source file, TokenRegistered handler</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> metadata </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">effect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">getMarketMetadata</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> token0Str</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>createEffect</code> plus <code>context.effect()</code> is the documented pattern for any external call (fetch, RPC, async I/O). From the project's <code>AGENTS.md</code>: "All <code>fetch</code>, RPC, or other async I/O must use <code>createEffect</code> + <code>context.effect()</code>. Never call external services directly in handlers."</p>
<p>The comparable AssemblyScript handler on The Graph would be split across three subgraph repos, each parsing the same OrderFilled log independently, each writing to its own subgraph database, with cross-domain joins happening at query time. Handler merging is the architectural reason the Polymarket reference consolidates 8 subgraphs into 1. It is also the thing that makes AssemblyScript handlers straightforward for an agent to translate: the event parsing is mechanical, the entity writes are explicit, and the conventions are documented in the project-resident skills.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-the-ai-assisted-migration-workflow-runs">How the AI-Assisted Migration Workflow Runs<a class="hash-link" aria-label="Direct link to How the AI-Assisted Migration Workflow Runs" title="Direct link to How the AI-Assisted Migration Workflow Runs" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#how-the-ai-assisted-migration-workflow-runs">​</a></h2>
<p>The flow assumes a developer with Claude Code or Cursor installed, the Envio docs MCP server configured, and the HyperIndex CLI on their machine. From the <a href="https://docs.envio.dev/docs/HyperIndex/quickstart-with-ai" target="_blank" rel="noopener noreferrer">HyperIndex Quickstart with AI</a> the MCP setup is one command for Claude Code:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">claude mcp </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--transport</span><span class="token plain"> http envio-docs https://docs.envio.dev/mcp</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Cursor or VS Code uses the JSON config form on the same page. Once added, every Claude session in that workspace can query the live docs.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-1-scaffold-a-hyperindex-project-from-a-template">Step 1: Scaffold a HyperIndex project from a template<a class="hash-link" aria-label="Direct link to Step 1: Scaffold a HyperIndex project from a template" title="Direct link to Step 1: Scaffold a HyperIndex project from a template" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#step-1-scaffold-a-hyperindex-project-from-a-template">​</a></h3>
<p>Scaffold a fresh HyperIndex project using the template flow. Pass <code>--api-token ""</code> so the init runs non-interactively when an agent is driving:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio@3.0.0-rc.0 init template </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-t</span><span class="token plain"> erc20 </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-l</span><span class="token plain"> typescript </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-d</span><span class="token plain"> ./my-indexer --api-token </span><span class="token string" style="color:rgb(255, 121, 198)">""</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This produces a working HyperIndex project shell with <code>config.yaml</code>, <code>schema.graphql</code>, handler stubs, an <code>AGENTS.md</code>, and the auto-discovered <code>.claude/skills/</code> directory (including the <code>migrate-from-subgraph</code> skill). The current release is tracked at <a href="https://github.com/enviodev/hyperindex/releases" target="_blank" rel="noopener noreferrer">github.com/enviodev/hyperindex/releases</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-2-hand-claude-the-assemblyscript-mappings">Step 2: Hand Claude the AssemblyScript mappings<a class="hash-link" aria-label="Direct link to Step 2: Hand Claude the AssemblyScript mappings" title="Direct link to Step 2: Hand Claude the AssemblyScript mappings" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#step-2-hand-claude-the-assemblyscript-mappings">​</a></h3>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">You: I just initialised a HyperIndex project and the /XYZ folder has my subgraph</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">could you help me migrate that to my HyperIndex project. The generated</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">config.yaml and schema.graphql are in place. The original AssemblyScript</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">mappings are in ../old-subgraph/src/mappings/. Use the migrate-from-subgraph</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">skill to translate them into TypeScript handlers under src/handlers/. Apply the</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">project conventions in AGENTS.md: spread operator for entity updates, Effect</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">API for any external calls, entity_id fields for relationships. Flag anything</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">that uses nested entity loads or AssemblyScript-specific helpers so I can</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">review.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Claude opens the migration skill, walks the mapping files in dependency order, and produces TypeScript handlers under <code>src/handlers/</code>. Every entity load and write is explicit. Every BigInt operation uses native JavaScript <code>BigInt</code> rather than the AssemblyScript <code>BigInt</code> class. Imports come from the auto-generated types, not from <code>@graphprotocol/graph-ts</code>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-3-run-the-indexer-locally-and-compare">Step 3: Run the indexer locally and compare<a class="hash-link" aria-label="Direct link to Step 3: Run the indexer locally and compare" title="Direct link to Step 3: Run the indexer locally and compare" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#step-3-run-the-indexer-locally-and-compare">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> dev</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The indexer comes up against a local Postgres and a Hasura GraphQL endpoint. The deployed subgraph endpoint and the local HyperIndex endpoint can be queried side by side for any entity at any block height. Claude knows how to write the comparison queries because the <code>indexer-testing</code> skill ships in the project.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-4-ship-to-envio-cloud">Step 4: Ship to Envio Cloud<a class="hash-link" aria-label="Direct link to Step 4: Ship to Envio Cloud" title="Direct link to Step 4: Ship to Envio Cloud" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#step-4-ship-to-envio-cloud">​</a></h3>
<p>Envio Cloud uses a GitHub-native deploy model. Push the indexer to a GitHub repo on the <code>envio</code> branch, connect the Envio GitHub App, and register the indexer with <code>envio-cloud indexer add</code>. The full flow from the <a href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex" target="_blank" rel="noopener noreferrer">agentic indexing blog</a>:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">npm</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-g</span><span class="token plain"> envio-cloud</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">envio-cloud login</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># push the migrated indexer to the envio branch</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> checkout </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-b</span><span class="token plain"> envio </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> push </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-u</span><span class="token plain"> origin envio</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># install the Envio GitHub App on the repo</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># https://github.com/apps/envio-deployments/installations/select_target</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># register the indexer</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">envio-cloud indexer </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--name</span><span class="token plain"> my-migrated-indexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--repo</span><span class="token plain"> my-migrated-indexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--description</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Subgraph migrated to HyperIndex"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--branch</span><span class="token plain"> envio </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --skip-repo-check </span><span class="token punctuation" style="color:rgb(248, 248, 242)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--yes</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># track sync state</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">envio-cloud deployment status my-migrated-indexer </span><span class="token operator">&lt;</span><span class="token plain">commit-hash</span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">org</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Every command supports <code>-o json</code> for parseable output. The Polymarket reference indexer is live at <a href="https://envio.dev/app/moose-code/polymarket-indexer/7cad3ad" target="_blank" rel="noopener noreferrer">envio.dev/app/moose-code/polymarket-indexer/7cad3ad</a>. Full CLI reference at <a href="https://docs.envio.dev/docs/HyperIndex/envio-cloud-cli" target="_blank" rel="noopener noreferrer">docs.envio.dev/docs/HyperIndex/envio-cloud-cli</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-the-ai-catches-and-what-it-doesnt">What the AI Catches and What It Doesn't<a class="hash-link" aria-label="Direct link to What the AI Catches and What It Doesn't" title="Direct link to What the AI Catches and What It Doesn't" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#what-the-ai-catches-and-what-it-doesnt">​</a></h2>
<p>After running this workflow on smaller subgraphs internally, here is the honest split.</p>
<p>Claude is reliably good at:</p>
<ul>
<li>Translating event parsing and entity writes (the bulk of any handler)</li>
<li>Replacing AssemblyScript <code>BigInt</code> with native JS <code>BigInt</code></li>
<li>Replacing <code>@graphprotocol/graph-ts</code> imports with the HyperIndex generated types</li>
<li>Stripping the <code>@entity</code> decorator from every schema type (HyperIndex schemas have no decorators per AGENTS.md)</li>
<li>Applying the spread operator pattern on entity updates (mandatory in HyperIndex, returned entities are read-only)</li>
<li>Wrapping any external call from a mapping in <code>createEffect</code> plus <code>context.effect()</code> (the Effect API)</li>
<li>Generating the matching test cases against the Vitest framework HyperIndex ships with</li>
</ul>
<p>Claude needs human review on:</p>
<ul>
<li><strong>Cross-handler shared state.</strong> Subgraphs sometimes encode shared state in entity IDs in ways that look fine until two handlers race at the same block. Handler merging in HyperIndex usually fixes this, but the migration is the moment to redesign it consciously.</li>
</ul>
<p>A migration that runs all four steps with Claude driving and a developer reviewing typically turns a multi-week AssemblyScript rewrite into a one or two day exercise. The Polymarket reference is the upper bound: 8 subgraphs' worth of logic, 50+ entities, four years of handler history. Smaller subgraphs are correspondingly faster.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-migrate-at-all-the-numbers">Why Migrate at All: The Numbers<a class="hash-link" aria-label="Direct link to Why Migrate at All: The Numbers" title="Direct link to Why Migrate at All: The Numbers" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#why-migrate-at-all-the-numbers">​</a></h2>
<p>The reason teams move off The Graph is performance and developer experience. From the public benchmarks:</p>
<table><thead><tr><th>Indexer</th><th>Time (Sentio Uniswap V2 Factory benchmark)</th><th>vs HyperIndex</th></tr></thead><tbody><tr><td>Envio HyperIndex</td><td>8 seconds</td><td>baseline</td></tr><tr><td>Subsquid (SQD)</td><td>2 minutes</td><td>15x slower</td></tr><tr><td>The Graph</td><td>19 minutes</td><td>142x slower</td></tr><tr><td>Ponder</td><td>21 minutes</td><td>157x slower</td></tr></tbody></table>
<p>Full benchmark comparison at <a href="https://docs.envio.dev/docs/HyperIndex/benchmarks" target="_blank" rel="noopener noreferrer">docs.envio.dev/docs/HyperIndex/benchmarks</a>.</p>
<p>Polymarket's full historical sync, 4,000,000,000 events on Polygon, completed in 6 days, and the indexer has since indexed over 6,500,000,000 events in total. The same workload on a single subgraph in the Polymarket setup would have been measured in months and would still leave eight separate APIs to query.</p>
<p>Speed is one half of the story. Developer experience is the other. TypeScript handlers, native npm package use, generated types, real test runners, multichain configuration in a single file, dynamic contract registration without redeployment. Once a team has been on HyperIndex for a sprint, the subgraph workflow stops feeling like a viable alternative.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-long-does-an-ai-assisted-subgraph-migration-to-hyperindex-take">How long does an AI-assisted subgraph migration to HyperIndex take?<a class="hash-link" aria-label="Direct link to How long does an AI-assisted subgraph migration to HyperIndex take?" title="Direct link to How long does an AI-assisted subgraph migration to HyperIndex take?" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#how-long-does-an-ai-assisted-subgraph-migration-to-hyperindex-take">​</a></h3>
<p>For a single-domain subgraph with one or two contracts, the AI-assisted workflow with Claude typically runs in a few hours. For a complex multi-domain setup at the scale of the Polymarket reference (8 subgraphs' worth of logic, 50+ entities, four years of handler history), the migration with Claude assistance runs in days, not weeks. The bulk of the time is human review, not generation.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="does-hyperindex-support-every-subgraph-schema-directive">Does HyperIndex support every subgraph schema directive?<a class="hash-link" aria-label="Direct link to Does HyperIndex support every subgraph schema directive?" title="Direct link to Does HyperIndex support every subgraph schema directive?" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#does-hyperindex-support-every-subgraph-schema-directive">​</a></h3>
<p>Most directives carry across. <code>@derivedFrom</code> and ID-based relations have direct HyperIndex equivalents. The biggest difference is decorators: HyperIndex schemas have no <code>@entity</code> decorator at all. Per the project's <code>AGENTS.md</code>: "Unlike TheGraph, schema types have no decorators." The <code>indexer-schema</code> skill knows the translations and the <code>migrate-from-subgraph</code> skill applies them. Anything without a direct equivalent gets flagged for manual handling.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-if-my-subgraph-uses-dynamic-contracts-factory-pattern">What if my subgraph uses dynamic contracts (factory pattern)?<a class="hash-link" aria-label="Direct link to What if my subgraph uses dynamic contracts (factory pattern)?" title="Direct link to What if my subgraph uses dynamic contracts (factory pattern)?" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#what-if-my-subgraph-uses-dynamic-contracts-factory-pattern">​</a></h3>
<p>HyperIndex supports dynamic contract registration as a first-class feature. Polymarket uses it for FPMM pools created by <code>FPMMFactory</code>. The <code>indexer-factory</code> skill in <code>.claude/skills/</code> handles the translation. See the Polymarket reference handler at <a href="https://github.com/enviodev/polymarket-indexer/blob/main/src/handlers/FPMMFactory.ts" target="_blank" rel="noopener noreferrer">github.com/enviodev/polymarket-indexer/blob/main/src/handlers/FPMMFactory.ts</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-validate-that-the-migrated-indexer-matches-the-original-subgraph">How do I validate that the migrated indexer matches the original subgraph?<a class="hash-link" aria-label="Direct link to How do I validate that the migrated indexer matches the original subgraph?" title="Direct link to How do I validate that the migrated indexer matches the original subgraph?" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#how-do-i-validate-that-the-migrated-indexer-matches-the-original-subgraph">​</a></h3>
<p>Run both endpoints side by side and query the same entity at the same block. The <code>indexer-testing</code> skill in <code>.claude/skills/</code> generates the comparison queries. For production migrations, Envio also provides a CLI validation tool that diffs entity state across both endpoints over a block range. The <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">Polymarket reference repo</a> is the public production example to compare your migrated output against.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="does-the-ai-workflow-work-without-claude">Does the AI workflow work without Claude?<a class="hash-link" aria-label="Direct link to Does the AI workflow work without Claude?" title="Direct link to Does the AI workflow work without Claude?" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#does-the-ai-workflow-work-without-claude">​</a></h3>
<p>Yes. Skills in <code>.claude/skills/</code> auto-discover for Cursor, Claude Code, and Codex per the project's <code>CLAUDE.md</code>. The docs MCP server is MCP-standard so any MCP-capable agent works. The setup commands on the <a href="https://docs.envio.dev/docs/HyperIndex/quickstart-with-ai" target="_blank" rel="noopener noreferrer">Quickstart with AI</a> page cover Claude Code, Cursor, and VS Code explicitly.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-does-hyperindex-do-that-subgraphs-do-not">What does HyperIndex do that subgraphs do not?<a class="hash-link" aria-label="Direct link to What does HyperIndex do that subgraphs do not?" title="Direct link to What does HyperIndex do that subgraphs do not?" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#what-does-hyperindex-do-that-subgraphs-do-not">​</a></h3>
<p>Single multichain config (subgraphs are single-chain). Native TypeScript handlers (subgraphs require AssemblyScript). 142x faster sync on the Sentio Uniswap V2 Factory benchmark. Framework-level reorg handling with no handler logic required. Self-hostable or deployed to Envio Cloud with a GitHub-native flow (<code>envio-cloud indexer add</code> against an <code>envio</code> branch).</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="where-is-the-production-reference-for-a-large-subgraph-migration">Where is the production reference for a large subgraph migration?<a class="hash-link" aria-label="Direct link to Where is the production reference for a large subgraph migration?" title="Direct link to Where is the production reference for a large subgraph migration?" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#where-is-the-production-reference-for-a-large-subgraph-migration">​</a></h3>
<p>The <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">Polymarket HyperIndex reference indexer</a>. 8 subgraphs' worth of logic consolidated into one indexer, with the first 4,000,000,000 events synced in 6 days and over 6,500,000,000 indexed to date. The full repo is public on GitHub and the case study can be found in <a href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study" target="_blank" rel="noopener noreferrer">our blog</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#get-started">​</a></h2>
<p>Migration starts with two things: an existing subgraph (deployed or local) and a Claude Code or Cursor session pointed at a fresh HyperIndex project.</p>
<ul>
<li><a href="https://docs.envio.dev/docs/HyperIndex/quickstart-with-ai" target="_blank" rel="noopener noreferrer">HyperIndex Quickstart with AI</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/mcp-server" target="_blank" rel="noopener noreferrer">HyperIndex docs MCP server</a></li>
<li><a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">Polymarket reference indexer</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/migration-guide" target="_blank" rel="noopener noreferrer">Migration guide (manual reference)</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/envio-cloud-cli" target="_blank" rel="noopener noreferrer">Envio Cloud CLI</a></li>
</ul>
<p>For larger migrations, the Envio team supports the planning and review pass directly. Reach out via Discord or Telegram.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#build-with-envio">​</a></h2>
<p>Envio is the fastest independently benchmarked EVM blockchain indexer for querying real-time and historical data. If you are building onchain and need indexing that keeps up with your chain, check out the <a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">docs</a>, run the benchmarks yourself, and come talk to us about your data needs.</p>
<p>Stay tuned for more updates by subscribing to our newsletter, following us on X, or hopping into our Discord.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a></p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.com/invite/gt7yEUZKeB" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>ai</category>
        </item>
        <item>
            <title><![CDATA[Production Indexer Reliability with HyperIndex]]></title>
            <link>https://docs.envio.dev/blog/production-indexer-reliability-hyperindex</link>
            <guid>https://docs.envio.dev/blog/production-indexer-reliability-hyperindex</guid>
            <pubDate>Thu, 14 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Production indexer reliability with HyperIndex: framework reorg rollback, restart-resistant operation, HyperSync data validation, multi data-source recovery, stable Prometheus metrics.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/production-indexer-reliability-hyperindex.png" alt="Production Indexer Reliability with HyperIndex" width="100%">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>HyperIndex is Envio's multichain blockchain indexing framework for EVM chains. Production reliability lives at the framework level, not bolted on per indexer.</li>
<li>Reorg handling is built in. Entity state history is tracked for every unfinalized block; the framework rolls back automatically when a chain re-orgs. No handler code required.</li>
<li>The indexer is restart-resistant. State (including dynamically registered contracts) is persisted to the database and restored on reboot. If a handler fails, the framework restarts automatically without data loss, the indexer resumes from the last committed block.</li>
<li>HyperSync, Envio's default data engine, ships a robust set of data validation features that RPC does not: block parent hash verification, fork detection, automatic re-sync. The indexer can trust that no events are silently missed, in contrast to raw RPC which only serves whatever the upstream node currently considers canonical.</li>
<li>Multi data-source recovery falls back to a secondary source on primary outage and attempts to recover to the primary 60 seconds later. The indexer stays alive through upstream RPC and HyperSync failures.</li>
<li>Polymarket's HyperIndex reference indexer synced its first 4,000,000,000 events in 6 days on Polygon and has indexed over 6,500,000,000 to date. Public at <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">github.com/enviodev/polymarket-indexer</a>.</li>
</ul></div></div>
<p>A production indexer fails in three ways. The chain reorgs and the indexer either misses the rollback or hand-rolls bespoke logic that breaks at the next edge case. The data source goes down and the indexer either stalls silently or fails over and never comes back to primary. The indexer hits a counter ceiling, a memory leak in a long-running handler, or another silent failure, and the operator finds out from a downstream outage instead of an alert.</p>
<p>HyperIndex is Envio's multichain blockchain indexing framework for EVM chains. Reliability lives at the framework level so that any indexer built on it inherits the behaviour without writing operational code. Four guarantees compound to keep an indexer production-correct: framework-level reorg handling, restart-resistant operation, HyperSync data validation, and multi data-source recovery. Observability through Prometheus layers on top.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-these-four-reliability-pillars-reinforce-each-other">Why These Four Reliability Pillars Reinforce Each Other<a class="hash-link" aria-label="Direct link to Why These Four Reliability Pillars Reinforce Each Other" title="Direct link to Why These Four Reliability Pillars Reinforce Each Other" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#why-these-four-reliability-pillars-reinforce-each-other">​</a></h2>
<p>Reorg handling guarantees your indexer doesn't carry corrupt state forward when a chain rolls back. Restart-resistant operation means a failed indexer process doesn't leak that corruption into a stuck or amnesiac state. HyperSync validation means the data feeding both is the canonical chain, not a stale or partial fork. Multi-source recovery keeps the whole stack live when upstream sources fail. Each pillar protects the rest.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="reorg-handling-at-the-framework-level">Reorg Handling at the Framework Level<a class="hash-link" aria-label="Direct link to Reorg Handling at the Framework Level" title="Direct link to Reorg Handling at the Framework Level" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#reorg-handling-at-the-framework-level">​</a></h2>
<p>The reorg architecture is the deepest piece of work HyperIndex's reliability story rests on. To understand why "framework-level" matters, it helps to be precise about what a reorg actually does to an indexer.</p>
<p>A reorg is a chain rolling back to a previous point in time. A recent block (or several) is no longer canonical, and the new canonical chain has different events at those heights. The implications for an indexer split along a single axis, stateless versus stateful.</p>
<p>Stateless indexers only create entities. On a reorg, the fix is mechanical. Delete the entities written from orphaned blocks, re-ingest from the canonical chain, move on. Stateless indexing parallelises well and is fast.</p>
<p>Stateful indexers also update and delete entities based on previous state. An order book's running volume, an account's balance, a market's open interest, all of these aggregate prior state into current state. On a reorg, you cannot just delete and replay. You have to revert previous operations to the entity state at the pre-reorg point, then replay forward against the canonical chain. Doing that correctly requires tracking the history of every change to every entity for the entire unfinalized window.</p>
<p>HyperIndex's framework keeps that entity history for you.</p>
<blockquote>
<p>"Envio HyperIndex tracks entity state history for all unfinalized blocks. When a reorg is detected, it rolls back entity state to the correct point and reprocesses events from the canonical chain. This happens automatically and does not require any custom rollback logic in your event handlers."</p>
<p>Denham Preen, Envio Co-founder</p>
</blockquote>
<p>Learn more in our <a href="https://docs.envio.dev/blog/indexing-and-reorgs" target="_blank" rel="noopener noreferrer">Indexing and Reorgs</a> blog.</p>
<p>Three architectural details worth knowing about that mechanism:</p>
<ol>
<li>
<p><strong>History is per-entity, not per-block.</strong> The framework persists the prior state of each entity each time a handler writes to it within the unfinalized window. On a reorg, the rollback walks the per-entity history backwards to the pre-reorg state, applies it, and reprocesses forward.</p>
</li>
<li>
<p><strong>History is pruned automatically.</strong> Once a block is finalised, its entries in the entity history are no longer needed. The framework prunes them. The unfinalized window is the only window that ever carries history overhead, which keeps the storage cost bounded regardless of total chain length.</p>
</li>
<li>
<p><strong>Multichain reorg handling is harder than single-chain, and the framework does it.</strong> When a single entity's state is updated by events from multiple chains, a reorg on chain A may force the framework to also reprocess events on chain B that were applied after the reorg point but depended on the rolled-back state. The reorg blog calls this out explicitly. Hand-rolling correct multichain reorg logic is the kind of thing you do not want any application engineer to have to write.</p>
</li>
</ol>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="reorgs-in-the-wild">Reorgs in the Wild<a class="hash-link" aria-label="Direct link to Reorgs in the Wild" title="Direct link to Reorgs in the Wild" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#reorgs-in-the-wild">​</a></h3>
<p>These are not theoretical edge cases. From the same reorg blog:</p>
<ul>
<li><strong>Polygon</strong> has frequent and sometimes deep reorgs. The forum has documented a single <a href="https://forum.polygon.technology/t/157-block-reorg-at-block-height-39599624/11388" target="_blank" rel="noopener noreferrer">157-block reorg at block height 39,599,624</a>. Polymarket runs on Polygon. Polymarket's reference indexer at <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">github.com/enviodev/polymarket-indexer</a> has stayed correct through every Polygon reorg, including the deep ones, because the framework does the work.</li>
<li><strong>Ethereum mainnet</strong> sees roughly 1% of blocks affected by reorgs. Assuming a 50/50 chance of a transaction landing in the orphaned versus canonical fork, that's about 1 in 200 transactions ending up in a reorged block. An indexer that does not roll back state is silently wrong for ~0.5% of the transactions it ingests.</li>
<li><strong>Base and OP-stack chains</strong> are largely reorg-resistant due to single-slot finality, with <a href="https://optimistic.etherscan.io/blocks_forked" target="_blank" rel="noopener noreferrer">documented exceptions</a>.</li>
</ul>
<p>Why this matters operationally:</p>
<ul>
<li><strong>No bespoke per-handler logic.</strong> The most common subgraph reliability bug is a handler that does not handle a reorg correctly because the dev forgot to. With HyperIndex that bug class does not exist.</li>
<li><strong>No "wait for N confirmations" delay.</strong> Some indexers paper over reorgs by lagging behind the chain head by N blocks. HyperIndex stays at chain head and rolls back if needed.</li>
<li><strong>Multichain stays correct.</strong> A multichain indexer with one chain reorging does not corrupt the cross-chain aggregates. The framework rolls back the dependent state on every other chain too.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="multi-data-source-recovery">Multi Data-Source Recovery<a class="hash-link" aria-label="Direct link to Multi Data-Source Recovery" title="Direct link to Multi Data-Source Recovery" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#multi-data-source-recovery">​</a></h2>
<p>HyperIndex's multi data-source recovery is documented in the <a href="https://docs.envio.dev/blog" target="_blank" rel="noopener noreferrer">dev update archive</a> and tracked in the <a href="https://github.com/enviodev/hyperindex/releases" target="_blank" rel="noopener noreferrer">GitHub releases</a>.</p>
<p>The feature has three concrete pieces.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="1-smarter-source-selection">1. Smarter source selection<a class="hash-link" aria-label="Direct link to 1. Smarter source selection" title="Direct link to 1. Smarter source selection" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#1-smarter-source-selection">​</a></h3>
<p>Indexers configured with multiple data sources (a primary plus one or more fallbacks) route requests using selection logic that weights source health. A flapping fallback does not win the rotation purely because it answered fastest.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="2-automatic-failover-within-seconds">2. Automatic failover within seconds<a class="hash-link" aria-label="Direct link to 2. Automatic failover within seconds" title="Direct link to 2. Automatic failover within seconds" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#2-automatic-failover-within-seconds">​</a></h3>
<p>When the primary source goes down, the indexer fails over to a fallback within seconds. When the primary comes back, <a href="https://docs.envio.dev/docs/HyperIndex/whats-new-in-v3#improved-multiple-data-sources-support" target="_blank" rel="noopener noreferrer">HyperIndex attempts to recover to it 60 seconds later</a>. The indexer does not need to be restarted to return to its preferred source.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="3-realtime-mode-enforcement">3. Realtime mode enforcement<a class="hash-link" aria-label="Direct link to 3. Realtime mode enforcement" title="Direct link to 3. Realtime mode enforcement" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#3-realtime-mode-enforcement">​</a></h3>
<p>Realtime mode means the indexer is at chain head and processing new blocks as they arrive. HyperIndex enforces realtime mode strictly: if the indexer's effective progress is stalling on a degraded source, metrics surface it. Operators see the degradation before downstream consumers do.</p>
<p>This pillar is the one operators feel daily. Most indexer outages in 2025 were not chain outages. They were data-source outages that the indexer did not handle gracefully. Multi data-source recovery removes the operator pager from that loop.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resumes-cleanly-across-restarts">Resumes Cleanly Across Restarts<a class="hash-link" aria-label="Direct link to Resumes Cleanly Across Restarts" title="Direct link to Resumes Cleanly Across Restarts" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#resumes-cleanly-across-restarts">​</a></h2>
<p>A production indexer runs for months. The host will restart. Configs will change. The reliability question isn't whether restarts happen, it's what state the indexer is in when they do.</p>
<p>HyperIndex persists indexer state across restarts. On reboot, state is restored from the database, including dynamically registered contracts. The indexer resumes from the last committed block, not from chain head and not from genesis. Application code does not have to track checkpoints or persist offsets, the framework handles it.</p>
<p>Handler-side failures are caught at the framework level too. If a handler throws an unhandled exception, the indexer restarts automatically without data loss. Application code does not have to wrap handlers in try/catch, implement custom retry logic, or rebuild offsets after a crash. The framework does this for you.</p>
<p>The dev environment also preserves data by default. <code>envio dev</code> no longer wipes the database on incompatible config or schema changes; the explicit opt-in is <code>envio dev -r</code>. For some config changes (RPC configuration is the first to land), the indexer can continue indexing through the change without erroring out at all.</p>
<p>This complements the reorg story. Reorg handling protects against chain-side rollbacks; restart persistence protects against indexer-side restarts. Together they cover the failure surface a production indexer actually faces.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="hypersync-data-validation">HyperSync Data Validation<a class="hash-link" aria-label="Direct link to HyperSync Data Validation" title="Direct link to HyperSync Data Validation" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#hypersync-data-validation">​</a></h2>
<p>The data feeding the indexer matters as much as the indexer itself. A reorg-aware framework with restart safety is still only as correct as the events that arrive at the handler.</p>
<p>HyperIndex pulls historical data through HyperSync, Envio's data engine. HyperSync ships a robust set of validation features that raw RPC does not, block parent hash verification, fork detection, automatic re-sync on detected forks. The validation runs at ingestion, not in your handler. The framework's confidence is that no events are silently missed by the data layer.</p>
<p>Raw RPC does not give the same guarantee. A standard RPC endpoint will serve whatever the upstream node currently considers canonical, and a slow rotation between forks (or a single RPC sitting on an orphaned tip) can quietly hand stale events to a downstream indexer. With HyperSync as the data layer, that class of silent corruption is removed before any handler sees it.</p>
<p>For application teams: events that reach your handler are canonical-chain events. For AI agents acting on indexer state: the data they reason over is validated upstream, not a best-effort RPC read.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="why-data-validity-matters-for-ai">Why Data Validity Matters for AI<a class="hash-link" aria-label="Direct link to Why Data Validity Matters for AI" title="Direct link to Why Data Validity Matters for AI" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#why-data-validity-matters-for-ai">​</a></h3>
<p>When an agent acts on indexer data, the agent is only as correct as the data it queries. A missing or stale event in a derivative pricing agent, a position tracker, or a governance bot is not a logging error, it's a financial event. The premise of the AI-onchain stack is that the data layer underneath gives the agent verified, canonical state.</p>
<p>HyperIndex's framework-level guarantees (reorg-aware, restart-persistent, parent-hash-validated upstream) are what let an agent treat indexer output as a stable source of truth rather than a feed to second-guess. The <a href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex" target="_blank" rel="noopener noreferrer">companion blog on agentic blockchain indexing</a> covers the agent-side story end to end.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="observability-through-prometheus">Observability Through Prometheus<a class="hash-link" aria-label="Direct link to Observability Through Prometheus" title="Direct link to Observability Through Prometheus" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#observability-through-prometheus">​</a></h2>
<p>HyperIndex exposes a standard Prometheus <code>/metrics</code> endpoint with three properties operators rely on.</p>
<ul>
<li><strong>Semver-stable contract.</strong> Metric names and labels do not change between minor versions. Grafana dashboards built against this endpoint do not need to be rebuilt every release.</li>
<li><strong>Time units in seconds.</strong> Every duration metric is in seconds, matching Prometheus convention. Histograms use second-based buckets.</li>
<li><strong>Benchmark data points in the standard endpoint.</strong> The data points historically surfaced under a separate benchmark mode are part of the standard <code>/metrics</code> output. Continuous benchmarking against a production deployment does not require a separate run mode.</li>
</ul>
<p>For self-hosted deployments, the endpoint plugs into existing Prometheus infrastructure. For Envio Cloud deployments, alerts are exposed through the standard alert channels (Discord, Slack, Telegram, and Email).</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="reliability-on-envio-cloud">Reliability on Envio Cloud<a class="hash-link" aria-label="Direct link to Reliability on Envio Cloud" title="Direct link to Reliability on Envio Cloud" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#reliability-on-envio-cloud">​</a></h2>
<p>The four pillars above are framework guarantees: they hold whether you self-host or deploy to <a href="https://docs.envio.dev/docs/HyperIndex/hosted-service" target="_blank" rel="noopener noreferrer">Envio Cloud</a>, Envio's fully managed hosting. Envio Cloud adds the operational layer on top.</p>
<ul>
<li><strong>Zero-downtime deployments.</strong> Each indexer gets a static production endpoint. A new version deploys alongside the running one; "promote to production" switches the endpoint instantly, and rolling back to a previous deployment is one click. Consumers see no endpoint change.</li>
<li><strong>Built-in alerts.</strong> Paid plans surface indexer health, performance warnings, and deployment events through Discord, Slack, Telegram, and Email, so the reorg, failover, and restart events the framework handles stay visible without wiring up your own monitoring.</li>
<li><strong>Built-in monitoring.</strong> Logs, per-chain sync status, and deployment health are tracked in real time from the dashboard.</li>
<li><strong>Region choice.</strong> Dedicated plans can pick a primary deployment region (USA or EU) for latency and data-residency needs. Broader cross-region support is in active development.</li>
</ul>
<p>Self-hosting keeps all four framework pillars. Envio Cloud removes the hosting and the on-call wiring on top of them.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-this-looks-like-in-a-real-configuration">What This Looks Like in a Real Configuration<a class="hash-link" aria-label="Direct link to What This Looks Like in a Real Configuration" title="Direct link to What This Looks Like in a Real Configuration" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#what-this-looks-like-in-a-real-configuration">​</a></h2>
<p>The Polymarket reference indexer's <code>config.yaml</code> is the public production example. The structural pieces below are drawn from <a href="https://github.com/enviodev/polymarket-indexer/blob/main/config.yaml" target="_blank" rel="noopener noreferrer">the canonical file</a> (selected events shown for brevity):</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># Source: https://github.com/enviodev/polymarket-indexer/blob/main/config.yaml</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># yaml-language-server: $schema=./node_modules/envio/evm.schema.json</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> polymarket</span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain">indexer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">description</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Unified Polymarket HyperIndex</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># Phase 1A: Fee Module</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> FeeModule</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">abi_file_path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ./abis/FeeModule.json</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">events</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"FeeRefunded(bytes32 indexed orderHash, address indexed to, uint256 id, uint256 refund, uint256 indexed feeCharged)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># Phase 2B: Orderbook</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Exchange</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">abi_file_path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ./abis/Exchange.json</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">events</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"OrderFilled(bytes32 indexed orderHash, address indexed maker, address indexed taker, uint256 makerAssetId, uint256 takerAssetId, uint256 makerAmountFilled, uint256 takerAmountFilled, uint256 fee)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"OrdersMatched(bytes32 indexed takerOrderHash, address indexed takerOrderMaker, uint256 makerAssetId, uint256 takerAssetId, uint256 makerAmountFilled, uint256 takerAmountFilled)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)"># Phase 3: Open Interest + Activity</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ConditionalTokens</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">abi_file_path</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ./abis/ConditionalTokens.json</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">events</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"PositionSplit(address indexed stakeholder, address collateralToken, bytes32 indexed parentCollectionId, bytes32 indexed conditionId, uint256[] partition, uint256 amount)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"PositionsMerge(address indexed stakeholder, address collateralToken, bytes32 indexed parentCollectionId, bytes32 indexed conditionId, uint256[] partition, uint256 amount)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"PayoutRedemption(address indexed redeemer, address indexed collateralToken, bytes32 indexed parentCollectionId, bytes32 conditionId, uint256[] indexSets, uint256 payout)"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">field_selection</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">transaction_fields</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> hash</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> from</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> to</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token key atrule">chains</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">id</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">137</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)"># Polygon</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">3764531</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token key atrule">contracts</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> FeeModule</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0xE3f18aCc55091e2c48d883fc8C8413319d4Ab7b0"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0xB768891e3130F6dF18214Ac804d4DB76c2C37730"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">75253526</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> Exchange</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0xC5d563A36AE78145C45a50134d48A1215220f80a"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">33605403</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">-</span><span class="token plain"> </span><span class="token key atrule">name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> ConditionalTokens</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token key atrule">start_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token number">4023686</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Three details worth pointing at in this config:</p>
<ol>
<li><strong>Two-tier declaration.</strong> The top-level <code>contracts:</code> block declares the contract name, ABI, and event signatures globally. The <code>chains:</code> block (per chain ID) supplies addresses and per-contract <code>start_block</code> overrides. This is how the same contract definition gets reused across multiple deployed addresses (Exchange has two production addresses, FeeModule has two) without duplicating the event signatures.</li>
<li><strong><code>field_selection</code></strong> controls which transaction fields HyperSync ships down to the handler. Polymarket asks for <code>hash</code>, <code>from</code>, and <code>to</code> only. Smaller per-event payload, faster sync, lower memory pressure. Available on every config.</li>
<li><strong>No reorg block.</strong> There is no <code>rollback_on_reorg</code> flag set in the config because rollback is the framework default. The handlers in <code>src/</code> do not contain reorg logic. They write entities, the framework manages history, the database stays consistent.</li>
</ol>
<p>The full file declares 9 V1 contracts (FeeModule, UmaSportsOracle, RelayHub, SafeProxyFactory, USDC, Exchange, ConditionalTokens, NegRiskAdapter, FPMMFactory) plus a dynamic FixedProductMarketMaker registered at runtime, and 5 V2 contracts (CTFExchangeV2, PolyUSD, Rewards, CtfCollateralAdapter, NegRiskCtfCollateralAdapter), all routed through merged handlers in a single multichain-capable config. For a true multichain deployment, the same <code>chains:</code> array gets additional entries (e.g., <code>id: 8453</code> for Base) with their own contracts block.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-reliability-beats-speed-when-you-are-picking-an-indexer">Why Reliability Beats Speed When You Are Picking an Indexer<a class="hash-link" aria-label="Direct link to Why Reliability Beats Speed When You Are Picking an Indexer" title="Direct link to Why Reliability Beats Speed When You Are Picking an Indexer" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#why-reliability-beats-speed-when-you-are-picking-an-indexer">​</a></h2>
<p>Speed is the easier comparison and the one most blog posts lead with. Sentio's independent Uniswap V2 Factory benchmark put HyperIndex at 8 seconds, 142x faster than The Graph and 15x faster than the nearest competitor. Polymarket synced 4 billion events in 6 days. Our <a href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex" target="_blank" rel="noopener noreferrer">agentic indexing blog</a> covers a 400,000-event Monad indexer in roughly 20 seconds.</p>
<p>Reliability is the one that decides whether an indexer stays running for years. The four pillars above (framework reorg handling, restart-resistant operation, HyperSync data validation, and multi data-source recovery) are what separate a production indexer from a benchmark.</p>
<p>Two operational consequences for teams choosing HyperIndex over alternatives:</p>
<ul>
<li><strong>One on-call surface, not three.</strong> The framework handles reorgs, source failover, restart recovery, and observability. The on-call person reads the Prometheus dashboard and the Envio Cloud alerts. They do not also have to maintain custom reorg or checkpoint code.</li>
<li><strong>Source diversity without operator overhead.</strong> Adding a fallback source is a config change. Multi data-source recovery does the runtime work. The operator does not author retry policies.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#get-started">​</a></h2>
<ul>
<li><a href="https://docs.envio.dev/docs/HyperIndex/whats-new-in-v3" target="_blank" rel="noopener noreferrer">What's new in v3</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/getting-started" target="_blank" rel="noopener noreferrer">HyperIndex quickstart</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/quickstart-with-ai" target="_blank" rel="noopener noreferrer">Quickstart with AI</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/benchmarks" target="_blank" rel="noopener noreferrer">Benchmarks</a></li>
<li><a href="https://docs.envio.dev/blog/indexing-and-reorgs" target="_blank" rel="noopener noreferrer">Reorg handling reference</a></li>
<li><a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">Polymarket reference indexer</a></li>
<li><a href="https://docs.envio.dev/docs/HyperIndex/hosted-service" target="_blank" rel="noopener noreferrer">Envio Cloud (alerts, hosted reliability)</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-does-envio-hyperindex-handle-blockchain-reorgs">How does Envio HyperIndex handle blockchain reorgs?<a class="hash-link" aria-label="Direct link to How does Envio HyperIndex handle blockchain reorgs?" title="Direct link to How does Envio HyperIndex handle blockchain reorgs?" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#how-does-envio-hyperindex-handle-blockchain-reorgs">​</a></h3>
<p>HyperIndex tracks entity state history for every unfinalized block at the framework level. When a reorg occurs, the framework walks the per-entity history backwards to the pre-reorg state, applies it, then reprocesses forward against the canonical chain. History is pruned automatically once a block is finalised. No handler code is required.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-does-hypersync-guarantee-canonical-chain-data">How does HyperSync guarantee canonical chain data?<a class="hash-link" aria-label="Direct link to How does HyperSync guarantee canonical chain data?" title="Direct link to How does HyperSync guarantee canonical chain data?" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#how-does-hypersync-guarantee-canonical-chain-data">​</a></h3>
<p>HyperSync ships a robust set of validation features that raw RPC does not, block parent hash verification, fork detection, automatic re-sync on detected forks. The indexer can trust that no events are silently missed by the data layer. The validation runs at ingestion, not in your handler. Raw RPC endpoints serve whatever the upstream node currently considers canonical, which is why a standard RPC-fed indexer can silently ingest stale or orphaned data from a slow-rotating provider.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-often-do-reorgs-actually-happen">How often do reorgs actually happen?<a class="hash-link" aria-label="Direct link to How often do reorgs actually happen?" title="Direct link to How often do reorgs actually happen?" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#how-often-do-reorgs-actually-happen">​</a></h3>
<p>On Ethereum mainnet, roughly 1% of blocks undergo reorgs, meaning approximately 1 in 200 transactions ends up in a reorged block. Polygon experiences deeper reorgs more frequently and has documented a single 157-block reorg at block height 39,599,624. Base and OP-stack chains are largely reorg-resistant due to single-slot finality, with documented exceptions.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-multi-data-source-recovery-in-hyperindex">What is multi data-source recovery in HyperIndex?<a class="hash-link" aria-label="Direct link to What is multi data-source recovery in HyperIndex?" title="Direct link to What is multi data-source recovery in HyperIndex?" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#what-is-multi-data-source-recovery-in-hyperindex">​</a></h3>
<p>Multi data-source recovery automatically routes between configured data sources. On primary outage, the indexer fails over to a fallback within seconds. When the primary returns, the indexer attempts to recover to it 60 seconds later, no restart required. Selection logic weights source health, not just first-response. Realtime mode enforcement surfaces through metrics when forward progress slows on a degraded source.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-happens-to-the-indexer-when-the-process-restarts-or-a-handler-fails">What happens to the indexer when the process restarts or a handler fails?<a class="hash-link" aria-label="Direct link to What happens to the indexer when the process restarts or a handler fails?" title="Direct link to What happens to the indexer when the process restarts or a handler fails?" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#what-happens-to-the-indexer-when-the-process-restarts-or-a-handler-fails">​</a></h3>
<p>HyperIndex is restart-resistant. State persists to the database; on restart, the indexer restores state (including dynamically registered contracts) and resumes from the last committed block. If a handler fails mid-execution, the framework restarts automatically without data loss. Application code does not have to track checkpoints, persist offsets, or wrap handlers in retry logic.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="is-the-hyperindex-prometheus-metrics-endpoint-production-ready">Is the HyperIndex Prometheus metrics endpoint production-ready?<a class="hash-link" aria-label="Direct link to Is the HyperIndex Prometheus metrics endpoint production-ready?" title="Direct link to Is the HyperIndex Prometheus metrics endpoint production-ready?" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#is-the-hyperindex-prometheus-metrics-endpoint-production-ready">​</a></h3>
<p>Yes. The <code>/metrics</code> endpoint follows semver, uses second-based time units, and exposes the benchmark data points historically surfaced under a separate run mode as part of the standard endpoint.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="where-can-i-see-the-production-scale-hyperindex-reference">Where can I see the production-scale HyperIndex reference?<a class="hash-link" aria-label="Direct link to Where can I see the production-scale HyperIndex reference?" title="Direct link to Where can I see the production-scale HyperIndex reference?" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#where-can-i-see-the-production-scale-hyperindex-reference">​</a></h3>
<p>The <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">Polymarket reference indexer</a>. It synced 4,000,000,000 events from block 3,764,531 on Polygon Mainnet in 6 days, replacing 8 separate subgraphs.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-alert-channels-does-envio-cloud-support">What alert channels does Envio Cloud support?<a class="hash-link" aria-label="Direct link to What alert channels does Envio Cloud support?" title="Direct link to What alert channels does Envio Cloud support?" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#what-alert-channels-does-envio-cloud-support">​</a></h3>
<p>Envio Cloud alerts route through the platform's alert channels documented in the <a href="https://docs.envio.dev/docs/HyperIndex/hosted-service" target="_blank" rel="noopener noreferrer">hosted service docs</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="does-hyperindex-stay-at-chain-head-or-lag-for-safety">Does HyperIndex stay at chain head or lag for safety?<a class="hash-link" aria-label="Direct link to Does HyperIndex stay at chain head or lag for safety?" title="Direct link to Does HyperIndex stay at chain head or lag for safety?" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#does-hyperindex-stay-at-chain-head-or-lag-for-safety">​</a></h3>
<p>HyperIndex stays at chain head. Reorgs are handled by rollback, not by lag. There is no "wait N confirmations" mode required for correctness.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#build-with-envio">​</a></h2>
<p>Envio is the fastest independently benchmarked EVM blockchain indexer for querying real-time and historical data. If you are building onchain and need indexing that keeps up with your chain, check out the <a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">docs</a>, run the benchmarks yourself, and come talk to us about your data needs.</p>
<p>Stay tuned for more updates by subscribing to our newsletter, following us on X, or hopping into our Discord.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a></p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.com/invite/gt7yEUZKeB" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Privacy in Public: A Case Study on Privacy Pools]]></title>
            <link>https://docs.envio.dev/blog/privacy-in-public-case-study</link>
            <guid>https://docs.envio.dev/blog/privacy-in-public-case-study</guid>
            <pubDate>Thu, 07 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[What an Envio HyperIndex multichain indexer plus a thin Uniswap V4 price feed reveal about Privacy Pools (21 pools, 4 chains, ~5,200 deposits, $5.78M TVL): a working privacy primitive whose on-chain footprint shows the cryptographic floor holding.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/privacy-pools-case-study.png" alt="Privacy in Public: A Case Study on Privacy Pools" width="100%">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>Privacy Pools is live on <strong>4 chains (Ethereum, Optimism, BSC, Arbitrum) across 21 pools</strong>, with ~$5.78M of TVL, ~5,180 lifetime deposits, ~5,630 withdrawals, and a healthy mainnet ETH pool of <strong>2,320 distinct depositors</strong> behind a strong anonymity set.</li>
<li>The protocol's ZK proof hides which deposit funded which withdrawal cryptographically. Public-data signals an outside observer could attempt to read are heuristic only, and the protocol's design (open ragequit, free decoy construction, relayer flow) makes those heuristics impossible to verify from on-chain data alone.</li>
<li>Indexed end-to-end with one Envio HyperIndex v3 indexer, ClickHouse storage, and a thin Uniswap V4 price feed on BSC. Full multichain sync to head: ~30 seconds.</li>
<li>Full open-source code, queries, and BI report generator at <a href="https://github.com/enviodev/privacy-pools" target="_blank" rel="noopener noreferrer">github.com/enviodev/privacy-pools</a>.</li>
</ul></div></div>
<p><a href="https://privacypools.com/" target="_blank" rel="noopener noreferrer">Privacy Pools</a> is one of the more ambitious privacy primitives shipped on Ethereum and its L2s. The protocol, <a href="https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4563364" target="_blank" rel="noopener noreferrer">co-authored by Vitalik Buterin and others</a>, pairs a zero-knowledge proof of pool membership with an off-chain compliance vetting layer (the <strong>Association Set Provider</strong>, ASP). The result is a privacy mechanism that gives users cryptographic unlinkability between their deposit and their withdrawal, while still letting an off-chain layer say "we don't think this commitment came from a sanctioned address". Both halves matter, and both halves are working.</p>
<p>This post walks through a fully indexed snapshot of every deposit, withdrawal, ragequit, ASP root update, and relayer fee across all 21 live pools on every chain Privacy Pools runs on (14 on Ethereum, 2 on Optimism, 2 on BSC, 3 on Arbitrum). The headline takeaways are positive: the ZK proof is sound, the relayed-withdrawal path that preserves privacy gets used by 91% of withdrawers, and the largest pool has a genuinely diverse depositor base. The smaller, newer pools are doing what newer pools do: building toward those numbers.</p>
<p>The interesting analytical question, then, is what an outside observer with the public on-chain data can or can't say about who linked to whom. The answer is a clean "very little, and never with certainty". This is by design, and the data shows the design holding.</p>
<p>The full stack (indexer, analytics queries, BI report generator) is open-source at <a href="https://github.com/enviodev/privacy-pools" target="_blank" rel="noopener noreferrer">github.com/enviodev/privacy-pools</a> under MIT license.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-privacy-pools">What is Privacy Pools<a class="hash-link" aria-label="Direct link to What is Privacy Pools" title="Direct link to What is Privacy Pools" href="https://docs.envio.dev/blog/privacy-in-public-case-study#what-is-privacy-pools">​</a></h2>
<p>Three on-chain entities matter for indexing:</p>
<ul>
<li><strong>The Entrypoint</strong>: the singleton each pool registers under. Routes deposits and relays withdrawals.</li>
<li><strong>PrivacyPool</strong>: one contract per asset (ETH, USDC, USDT, fxUSD, BOLD, and so on). Emits <code>Deposited</code>, <code>Withdrawn</code>, <code>Ragequit</code>, <code>LeafInserted</code>, <code>PoolDied</code>.</li>
<li><strong>Association Set Provider (ASP)</strong>: off-chain vetting. On-chain footprint is the <code>RootUpdated</code> events from the Entrypoint, each carrying a Merkle root and an IPFS pointer to the approved set.</li>
</ul>
<p>The deposit/withdraw flow produces a commitment in a per-pool Merkle tree on deposit, and on withdrawal proves "I own <em>some</em> commitment in this pool, and that commitment is in the <strong>Association Set</strong> approved by the ASP", without revealing which commitment. <code>Ragequit</code> is the escape hatch: a depositor whose commitment has been excluded from a recent ASP root pulls their position out without the ZK-protected withdrawal flow.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-dataset">The Dataset<a class="hash-link" aria-label="Direct link to The Dataset" title="Direct link to The Dataset" href="https://docs.envio.dev/blog/privacy-in-public-case-study#the-dataset">​</a></h2>
<p>The indexer covers every Entrypoint and every PrivacyPool live across the four supported chains. Headline state at the time of writing (block heights are real-time):</p>
<table><thead><tr><th>chain</th><th>pools</th><th>deposits</th><th>withdrawals</th><th>ragequits</th><th>leaves</th></tr></thead><tbody><tr><td>Ethereum</td><td>14</td><td>4,731</td><td>5,138</td><td>322</td><td>9,883</td></tr><tr><td>Optimism</td><td>2</td><td>124</td><td>128</td><td>37</td><td>254</td></tr><tr><td>BSC</td><td>2</td><td>60</td><td>20</td><td>45</td><td>82</td></tr><tr><td>Arbitrum</td><td>3</td><td>265</td><td>344</td><td>36</td><td>612</td></tr><tr><td><strong>Total</strong></td><td><strong>21</strong></td><td><strong>5,180</strong></td><td><strong>5,630</strong></td><td><strong>440</strong></td><td><strong>10,831</strong></td></tr></tbody></table>
<p>USD TVL across all chains: <strong>~$5.78M</strong>. Largest pools:</p>
<table><thead><tr><th>pool</th><th>TVL (USD)</th></tr></thead><tbody><tr><td>Ethereum USDT</td><td>$2.40M</td></tr><tr><td>Ethereum ETH</td><td>$1.75M</td></tr><tr><td>Ethereum USDC</td><td>$1.46M</td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-mainnet-eth-pool-a-working-anonymity-set">The mainnet ETH pool: a working anonymity set<a class="hash-link" aria-label="Direct link to The mainnet ETH pool: a working anonymity set" title="Direct link to The mainnet ETH pool: a working anonymity set" href="https://docs.envio.dev/blog/privacy-in-public-case-study#the-mainnet-eth-pool-a-working-anonymity-set">​</a></h2>
<p>The Ethereum ETH pool is the protocol's flagship deployment, and its numbers tell a clear story:</p>
<ul>
<li><strong>2,320 distinct depositors</strong> (the next-largest cohort is 253 on Ethereum USDC).</li>
<li><strong>7,889 leaves</strong> in the Merkle tree, more than every other pool combined.</li>
<li><strong>Herfindahl-Hirschman Index of 132</strong> on depositor-value share, far below the 2,500 threshold considered "highly concentrated". The top depositor controls 8.0% of value, the top five 17.4%, the top ten 24.7%. There is no dominant wallet.</li>
</ul>
<p>Together those numbers describe a pool with real anonymity. A withdrawal from this pool has thousands of plausible commitments behind it, and no single dominant depositor for an analyst to single out.</p>
<p>The smaller pools (BNB on BSC, yUSND on Arbitrum, BOLD on Ethereum, and the rest of the long tail) are at much earlier points in the same curve. With anywhere from 1 to ~250 leaves, the long tail is in early-cohort phase. Concentration is high there because the pools are young, not because the protocol is broken.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="anonymity-set-growth">Anonymity-set growth<a class="hash-link" aria-label="Direct link to Anonymity-set growth" title="Direct link to Anonymity-set growth" href="https://docs.envio.dev/blog/privacy-in-public-case-study#anonymity-set-growth">​</a></h2>
<p>Each commitment lives as a leaf in the per-pool Merkle tree. Both deposits and the ZK-replacement leaves emitted on withdrawal contribute, so the leaf count keeps climbing as the pool gets used.</p>
<img src="https://docs.envio.dev/blog-assets/privacy-pools-anonymity-growth.png" alt="Anonymity-set growth (leaves) per pool over time" width="100%">
<p>The Ethereum ETH pool dominates by volume, but every active pool shows steady growth. There is no sign of pool abandonment.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="activity-patterns">Activity patterns<a class="hash-link" aria-label="Direct link to Activity patterns" title="Direct link to Activity patterns" href="https://docs.envio.dev/blog/privacy-in-public-case-study#activity-patterns">​</a></h2>
<p>Aggregating deposits and withdrawals by hour-of-day and day-of-week (UTC) reveals a global usage pattern: activity is roughly continuous, with a mild ramp through European and US business hours and a softer Asia-Pacific tail. Privacy Pools is being used as a steady utility, not as an event-driven product.</p>
<img src="https://docs.envio.dev/blog-assets/privacy-pools-hourly-heatmap.png" alt="Activity heatmap by day-of-week and hour-of-day" width="100%">
<p>The lack of strong timezone clustering is itself a privacy positive: a sharply timezone-skewed user base would be an inadvertent fingerprint. This data shows a globally distributed user set.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="relayed-withdrawal-share">Relayed-withdrawal share<a class="hash-link" aria-label="Direct link to Relayed-withdrawal share" title="Direct link to Relayed-withdrawal share" href="https://docs.envio.dev/blog/privacy-in-public-case-study#relayed-withdrawal-share">​</a></h2>
<p>Withdrawals can be self-submitted (the recipient submits their own proof, paying gas with their own address) or relayed (a relayer submits on the recipient's behalf, taking a fee). Self-submitted withdrawals link the recipient address to the gas-paying address; relayed withdrawals don't.</p>
<p>Across all chains:</p>
<ul>
<li><strong>5,148</strong> withdrawals were relayed.</li>
<li><strong>482</strong> were self-submitted (~8.6%).</li>
</ul>
<p><strong>91.4%</strong> of withdrawals took the privacy-preserving relayed path. That's a strong positive signal: users understand the privacy model and use it.</p>
<p>The relayer market on Ethereum is currently concentrated, with one relayer (<code>0xec15c200…</code>) processing ~77.7% of relayed flow and <code>0x855b4a60…</code> taking 19.9%. The relayer doesn't see the deposit side, so they can't break the ZK link, but the concentration is worth watching as the relayer ecosystem matures. New relayers entering the market would distribute that observability and is a natural maturation step for the protocol.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="linkability-the-public-data-heuristic-and-why-it-can-never-be-proof">Linkability: the public-data heuristic, and why it can never be proof<a class="hash-link" aria-label="Direct link to Linkability: the public-data heuristic, and why it can never be proof" title="Direct link to Linkability: the public-data heuristic, and why it can never be proof" href="https://docs.envio.dev/blog/privacy-in-public-case-study#linkability-the-public-data-heuristic-and-why-it-can-never-be-proof">​</a></h2>
<p>Take every (deposit, withdrawal) pair in the same pool with the same on-chain value, and a time gap of 60 seconds to 2 hours. Treat the withdrawal as <em>possibly linkable</em> to that deposit by an external observer.</p>
<p>This is a heuristic. There is no proof the same actor controls both addresses, only that the visible flow is consistent with that.</p>
<table><thead><tr><th>pool</th><th>candidate pairs</th><th>total withdrawals</th><th>linkable share</th><th>median gap</th></tr></thead><tbody><tr><td>Ethereum USDC</td><td>50</td><td>862</td><td>5.6%</td><td>61 min</td></tr><tr><td>Ethereum USDT</td><td>7</td><td>170</td><td>3.5%</td><td>57 min</td></tr><tr><td>Ethereum ETH</td><td>882</td><td>3,916</td><td>~10.9%</td><td>39 min</td></tr><tr><td>Arbitrum USDC</td><td>26</td><td>150</td><td>16.0%</td><td>57 min</td></tr><tr><td>Arbitrum ETH</td><td>28</td><td>168</td><td>15.5%</td><td>47 min</td></tr><tr><td>Optimism ETH</td><td>13</td><td>60</td><td>15.0%</td><td>61 min</td></tr><tr><td>BSC USDT</td><td>3</td><td>8</td><td>37.5%</td><td>25 min</td></tr><tr><td>Ethereum USDS</td><td>3</td><td>8</td><td>37.5%</td><td>4 min</td></tr></tbody></table>
<p>About one in ten Ethereum ETH withdrawals fits this shape. On the smaller pools, the share is higher because there are fewer deposits to lose oneself in. These are upper bounds on what a naive heuristic can flag, and they are not proofs. The next section shows why.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="decoy-withdrawals-how-the-protocol-absorbs-the-heuristic">Decoy withdrawals: how the protocol absorbs the heuristic<a class="hash-link" aria-label="Direct link to Decoy withdrawals: how the protocol absorbs the heuristic" title="Direct link to Decoy withdrawals: how the protocol absorbs the heuristic" href="https://docs.envio.dev/blog/privacy-in-public-case-study#decoy-withdrawals-how-the-protocol-absorbs-the-heuristic">​</a></h2>
<p>The same-amount heuristic has a known counter, and it is a feature of the privacy model rather than a workaround.</p>
<p>An existing depositor whose funds have been in the pool for weeks or months sees a fresh deposit hit the contract. They withdraw an equivalent amount within the heuristic's time window, to a fresh address that has nothing to do with the new depositor. An outside observer running the same-amount analysis links the new deposit to that withdrawal address.</p>
<p>From outside, the pair looks like "Alice deposited and Alice (the withdrawal recipient) withdrew shortly after". Inside, Alice and the withdrawal recipient have nothing to do with each other. The withdrawer's funds predate Alice entirely.</p>
<p>Querying for deposits followed within 30 minutes by a same-amount withdrawal where the depositor and the withdrawal recipient are different addresses:</p>
<ul>
<li><strong>393</strong> decoy-candidate pairs across the dataset.</li>
<li><strong>163</strong> distinct depositors had a same-amount withdrawal land within 30 minutes from a different address.</li>
<li><strong>160</strong> distinct withdrawal addresses received those decoy-shaped withdrawals.</li>
</ul>
<p>These are candidates, not proven decoys. Every pair could be one of three things, all indistinguishable from public data:</p>
<ol>
<li>The depositor really is the same actor, just routing the receipt through a different address.</li>
<li>Two unrelated parties happen to transact for the same round amount within minutes (more likely on busy pools and round denominations).</li>
<li>An existing depositor deliberately constructs the match to spoof the heuristic.</li>
</ol>
<p>Because option (3) is cheap (one extra withdrawal proof) and option (2) is plausible on common amounts, the linkable-share table above is a <em>plausibility upper bound</em>, not a recall figure. An actor who knows the heuristic exists can deliberately produce false matches, and an actor who is genuinely the same person across both addresses will also show up in the same table. This is the verifiability ceiling that the protocol's design relies on, and it does the load-bearing work of converting the cryptographic guarantee into practical anonymity. Plausible deniability is real precisely because it can never be ruled out from public data.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="ragequit-the-safety-valve-doing-its-job">Ragequit: the safety valve doing its job<a class="hash-link" aria-label="Direct link to Ragequit: the safety valve doing its job" title="Direct link to Ragequit: the safety valve doing its job" href="https://docs.envio.dev/blog/privacy-in-public-case-study#ragequit-the-safety-valve-doing-its-job">​</a></h2>
<p>Ragequit is the escape hatch. When the ASP excludes a commitment from the latest approved root, the depositor still gets their funds back, just through a path that reveals which commitment they originally made.</p>
<p>The mainnet ETH baseline is <strong>6.0% ragequit-by-count, 9.2% by value</strong>. The smaller pools have higher rates:</p>
<img src="https://docs.envio.dev/blog-assets/privacy-pools-ragequit-rate.png" alt="Ragequit rate by pool" width="100%">
<table><thead><tr><th>pool</th><th>ragequit % (count)</th><th>ragequit % (value)</th></tr></thead><tbody><tr><td>BSC BNB</td><td>78.3%</td><td>97.1%</td></tr><tr><td>Arbitrum yUSND</td><td>48.5%</td><td>90.7%</td></tr><tr><td>BSC USDT</td><td>72.9%</td><td>78.6%</td></tr><tr><td>Ethereum USDS</td><td>62.5%</td><td>58.7%</td></tr><tr><td>Ethereum sUSDS</td><td>54.5%</td><td>35.7%</td></tr><tr><td>Ethereum fxUSD</td><td>15.8%</td><td>33.2%</td></tr><tr><td>Ethereum wstETH</td><td>23.5%</td><td>24.0%</td></tr><tr><td>Ethereum ETH</td><td>6.0%</td><td>9.2%</td></tr></tbody></table>
<p>Three pools (BSC BNB, Arbitrum yUSND, BSC USDT) have seen most of their deposit value exit through the ragequit path rather than ordinary withdrawals. Depositors did not lose funds, they got their money back. What was lost on those specific commitments was the cryptographic privacy property, because ragequit reveals which commitment exited.</p>
<p>This is the ASP doing what it is designed to do: rejecting commitments after the fact when the off-chain compliance check changes its mind, and giving users a way out that doesn't trap their funds. The fact that the escape hatch is being exercised on the edges (small, young pools) is the system's compliance layer working as advertised, and it doesn't affect the privacy of any other depositor. For the mainnet ETH pool, where the bulk of activity sits, the ragequit rate is low and stable.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="where-the-public-data-layer-helps">Where the public-data layer helps<a class="hash-link" aria-label="Direct link to Where the public-data layer helps" title="Direct link to Where the public-data layer helps" href="https://docs.envio.dev/blog/privacy-in-public-case-study#where-the-public-data-layer-helps">​</a></h2>
<p>A privacy protocol's job is to provide cryptographic guarantees that an external observer can't link who deposited what to who withdrew. Privacy Pools does that: the ZK proof is sound, the verifiers are deployed, the on-chain mechanism works.</p>
<p>What the on-chain trail also does is record every deposit value, every withdrawal value, every relayer address, every recipient, and every timestamp. From that an indexed dataset gives you:</p>
<ul>
<li>A linkable-share number per pool (5-37% across the indexed pools), constrained by the verifiability ceiling above.</li>
<li>A concentration index per pool that tells you how mature the anonymity set is.</li>
<li>A ragequit-rate signal that confirms the ASP layer is active and that the safety valve is functioning.</li>
<li>A relayed-share number showing 91% of withdrawers using the privacy-preserving path.</li>
<li>A decoy-candidate count that quantifies how much credibility the plausible-deniability layer has on each pool.</li>
</ul>
<p>None of these break the protocol. None of these are verifiable. All of them are useful operational metadata that anyone, including the ASP, the protocol team, and end users, can use to track the protocol's health.</p>
<p>The point of indexing the protocol publicly is precisely that this kind of monitoring should be open. The same dataset that enables the heuristics also exposes the limits of those heuristics, and lets honest actors and the protocol team work on the things that actually matter (anonymity-set growth on the long-tail pools, relayer-market diversification, ASP responsiveness) without anyone needing privileged access.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-this-isnt">What this isn't<a class="hash-link" aria-label="Direct link to What this isn't" title="Direct link to What this isn't" href="https://docs.envio.dev/blog/privacy-in-public-case-study#what-this-isnt">​</a></h2>
<p>A few things this analysis explicitly does <em>not</em> show:</p>
<ul>
<li><strong>It does not break the ZK proof.</strong> Every linkability claim above is heuristic. A withdrawal that matches a deposit by amount and timing is consistent with the same actor controlling both addresses, but it is not proof.</li>
<li><strong>The decoy-candidate count is not a fraud detector.</strong> Many of the 393 decoy-shaped pairs will be coincidence on common round amounts, and some will be the same actor using a fresh address. The count is a ceiling on intentional decoys, not a measurement of them.</li>
<li><strong>High-ragequit pools aren't broken.</strong> Ragequit firing is the system working as designed when the ASP excludes a commitment.</li>
<li><strong>The fee figures are operator drains, not gross protocol revenue.</strong> The Entrypoint emits post-fee deposit values, so we can only observe the cashflow at the <code>FeesWithdrawn</code> step.</li>
</ul>
<p>Any heuristic an analyst can run, a depositor can game. Anyone can construct decoy patterns at low cost. Anyone can split deposits across rounds, jitter timing, and rotate recipient addresses. Public-data heuristics are a probability surface, not a truth function. Privacy Pools is built for exactly that constraint.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-this-was-indexed">How this was indexed<a class="hash-link" aria-label="Direct link to How this was indexed" title="Direct link to How this was indexed" href="https://docs.envio.dev/blog/privacy-in-public-case-study#how-this-was-indexed">​</a></h2>
<p>The full stack is one Envio HyperIndex v3 indexer running locally with dual Postgres + ClickHouse storage:</p>
<ul>
<li><strong>One config</strong>, four chains: Ethereum (1), Optimism (10), BSC (56), Arbitrum (42161). Same <code>Entrypoint</code> and <code>PrivacyPool</code> ABIs reused across all four. The L2s share a deterministic <code>0x44192215…</code> Entrypoint via CreateX, while mainnet has the original <code>0x6818809E…</code>.</li>
<li><strong>One handler set</strong> writes 9 entity types: <code>Pool</code>, <code>Deposit</code>, <code>Withdrawal</code>, <code>Ragequit</code>, <code>MerkleLeaf</code>, <code>AssociationSetRoot</code>, <code>Account</code>, <code>FeeWithdrawal</code>, plus a derived <code>LatestPrice</code>/<code>TokenPrice</code> pair from a thin Uniswap V4 price feed on BSC. All chain-scoped IDs (<code>{chainId}_{address}</code>) so the L2 ETH-pool address collision (<code>0x4626…918ff</code> is the ETH pool on Optimism, BSC, <em>and</em> Arbitrum) doesn't fold rows together.</li>
<li><strong>Multichain sync to head: ~30 seconds.</strong> HyperSync handles 4 chains in parallel; the only non-trivial cost is the V4 price feed, which we keep cheap by starting near BSC's head and filtering Swap events to ~70 hardcoded pricing-pool IDs (see <a href="https://developers.uniswap.org/contracts/v4/deployments" target="_blank" rel="noopener noreferrer">Uniswap V4 deployments</a>). No Initialize handler, no historical V4 backfill, just current prices.</li>
<li><strong>Analytics on ClickHouse.</strong> A Python <code>analytics/</code> package runs the headline queries through <code>clickhouse-connect</code>, charts them with matplotlib, and assembles a markdown BI report that renders to PDF via <code>reportlab</code>. The full report regenerates in a couple of seconds against the live ClickHouse.</li>
</ul>
<p>The schema and the SQL queries are designed for this kind of question. Adding a new heuristic, say "deposits whose precommitment hash has a leading-zero prefix", is an <code>.sql</code> file, not a re-index.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="reproducing-this">Reproducing this<a class="hash-link" aria-label="Direct link to Reproducing this" title="Direct link to Reproducing this" href="https://docs.envio.dev/blog/privacy-in-public-case-study#reproducing-this">​</a></h2>
<p>The full stack lives at <a href="https://github.com/enviodev/privacy-pools" target="_blank" rel="noopener noreferrer"><strong>github.com/enviodev/privacy-pools</strong></a> under MIT license. One HyperIndex v3 indexer plus a Python analytics package that ships the BI report generator and every saved query.</p>
<ul>
<li><code>config.yaml</code>, <code>schema.graphql</code>, <code>src/EventHandlers.ts</code>, <code>src/v4Pricing.ts</code>, <code>src/v4PoolMeta.ts</code>: the indexer.</li>
<li><code>analytics/queries/{health,anonymity,risk,asp,relayers,fees,activity,pricing}/*.sql</code>: every metric in this post.</li>
<li><code>analytics/scripts/generate_bi_report.py</code>: assembles the report markdown plus 6 charts.</li>
<li><code>analytics/scripts/render_pdf.py</code>: markdown to PDF, including image embedding.</li>
</ul>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> clone https://github.com/enviodev/privacy-pools</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> privacy-pools</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">cp</span><span class="token plain"> .env.example .env  </span><span class="token comment" style="color:rgb(98, 114, 164)"># add your free ENVIO_API_TOKEN from envio.dev</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> envio start</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># in another shell</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> analytics</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">cp</span><span class="token plain"> .env.example .env</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">uv </span><span class="token function" style="color:rgb(80, 250, 123)">sync</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">uv run python scripts/generate_bi_report.py</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Multichain sync completes in well under a minute. The BI report regenerates against live ClickHouse in seconds.</p>
<p>If you want to extend the analysis (chain-cross transitive linkability, ASP root vs deposit timing, relayer-collusion graphs, or anything else), every entity carries <code>chainId</code> and <code>blockNumber</code>, and the schema is documented end-to-end in <code>analytics/CLAUDE.md</code>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build with Envio<a class="hash-link" aria-label="Direct link to Build with Envio" title="Direct link to Build with Envio" href="https://docs.envio.dev/blog/privacy-in-public-case-study#build-with-envio">​</a></h2>
<p>Envio HyperIndex is independently benchmarked as the fastest EVM blockchain indexer available. The Privacy Pools indexer is one example of what's possible when multichain coverage and an analytics-grade columnar store are first-class features. If you're building onchain (DeFi, prediction markets, gaming, or something nobody has thought of yet), the <a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">docs</a> are the starting point.</p>
<ul>
<li>Repo: <a href="https://github.com/enviodev/privacy-pools" target="_blank" rel="noopener noreferrer">https://github.com/enviodev/privacy-pools</a></li>
<li>Docs: <a href="https://docs.envio.dev/" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/</a></li>
<li>Discord: <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">https://discord.gg/envio</a></li>
<li>Telegram: <a href="https://t.me/+kAIGElzPjApiMjI0" target="_blank" rel="noopener noreferrer">https://t.me/+kAIGElzPjApiMjI0</a></li>
<li>X: <a href="https://x.com/envio_indexer" target="_blank" rel="noopener noreferrer">https://x.com/envio_indexer</a></li>
</ul>]]></content:encoded>
            <category>case-studies</category>
        </item>
        <item>
            <title><![CDATA[How Revert Finance Fixed 2 Years of Unsynced PancakeSwap V3 Data with Envio]]></title>
            <link>https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex</link>
            <guid>https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex</guid>
            <pubDate>Wed, 06 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Revert Finance's PancakeSwap V3 subgraph on The Graph had been stuck at 70% sync on BNB Smart Chain for over 2 years. Envio HyperIndex synced it to 100% in 10 days, processing 1.7 billion events.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/revert-hyperindex-case-study.png" alt="How Revert Finance Fixed 2 Years of Unsynced PancakeSwap V3 Data with Envio" width="100%">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>Revert Finance's PancakeSwap V3 subgraph on The Graph had been stuck at 70% sync on BNB Smart Chain for over 2 years.</li>
<li>Envio HyperIndex synced 1,711,569,200 events to 100% in 10 days, solving a problem that had gone unresolved for over 2 years.</li>
<li>HyperSync eliminates the RPC bottleneck that causes other indexing frameworks to stall on high-throughput chains, like BNB Smart Chain, while HyperIndex's batch processing and caching ensure the indexer keeps up with the throughput.</li>
</ul></div></div>
<p>Revert Finance builds analytics and management tools for AMM liquidity providers across protocols including PancakeSwap, Uniswap, and others. Accurate, real-time onchain data is the foundation of everything they build.</p>
<p>They run several indexers using Envio, spanning multiple chains and contracts. This case study covers one of them: a PancakeSwap V3 indexer on BNB Smart Chain. Their previous subgraph had been stuck at 70% sync for over 2 years, unable to reach the chain's head.</p>
<img src="https://docs.envio.dev/blog-assets/revert-hyperindex-case-study-1.png" alt="PancakeSwap V3 subgraph on The Graph stuck at 70% sync on BNB Smart Chain" width="100%">
<p>The subgraph instance can be viewed here: <a href="https://thegraph.com/explorer/subgraphs/Hv1GncLY5docZoGtXjo4kwbTvxm3MAhVZqBZE4sUT9eZ?view=Query&amp;chain=bsc" target="_blank" rel="noopener noreferrer">https://thegraph.com/explorer/subgraphs/Hv1GncLY5docZoGtXjo4kwbTvxm3MAhVZqBZE4sUT9eZ?view=Query&amp;chain=bsc</a></p>
<p>Envio built a HyperIndex indexer for PancakeSwap V3 on BNB Smart Chain. It synced 1,711,569,200 events to 100% in 10 days.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-problem-revert-finance-needed-to-solve">The Problem Revert Finance Needed to Solve<a class="hash-link" aria-label="Direct link to The Problem Revert Finance Needed to Solve" title="Direct link to The Problem Revert Finance Needed to Solve" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#the-problem-revert-finance-needed-to-solve">​</a></h2>
<p>Revert Finance requires real-time PancakeSwap V3 position and liquidity data to power its analytics and tooling for liquidity providers. A public subgraph on The Graph's decentralized network had been stuck at 70% sync on BNB Smart Chain for over 2 years, unable to reach chain head.</p>
<p>BNB Smart Chain's high throughput has presented well-documented challenges for RPC-based indexing, with teams reporting sync issues going back to 2021. The volume of events per block outpaces what standard indexing infrastructure can sustain, causing subgraphs to fall progressively further behind until they stall entirely.</p>
<p>A subgraph stuck at 70% sync for over 2 years is effectively unusable.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-solution-envio-hyperindex-on-bnb-smart-chain">The Solution: Envio HyperIndex on BNB Smart Chain<a class="hash-link" aria-label="Direct link to The Solution: Envio HyperIndex on BNB Smart Chain" title="Direct link to The Solution: Envio HyperIndex on BNB Smart Chain" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#the-solution-envio-hyperindex-on-bnb-smart-chain">​</a></h2>
<p>Envio HyperIndex is a real-time multichain blockchain indexing framework for any EVM chain. Developers write event handlers in TypeScript and deploy a single indexer covering multiple contracts and chains simultaneously. It uses <a href="https://docs.envio.dev/docs/HyperSync/overview">HyperSync</a>, Envio's proprietary data engine, which serves filtered event data in bulk directly from a purpose-built data lake, replacing having to poll RPC endpoints block by block. This removes the RPC bottleneck entirely, which is precisely what causes subgraph stalls on BNB Smart Chain.</p>
<p>HyperIndex is independently benchmarked as the fastest blockchain indexer available. In the Uniswap V2 Factory benchmark run by Sentio in May 2025, HyperIndex synced in 8 seconds, 142x faster than The Graph and 15x faster than the nearest competitor. BNB Smart Chain is one of <!-- -->85+<!-- --> EVM chains with native HyperSync coverage.</p>
<p>For a full benchmark breakdown see the <a href="https://docs.envio.dev/docs/HyperIndex/benchmarks" target="_blank" rel="noopener noreferrer">complete blockchain indexer comparison</a>.</p>
<p>Envio built a HyperIndex indexer covering PancakeSwap V3 on BNB Smart Chain, tracking Factory, Pool, and NFPM (Non-Fungible Position Manager) contracts from block 26,956,207.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="contracts-indexed">Contracts Indexed<a class="hash-link" aria-label="Direct link to Contracts Indexed" title="Direct link to Contracts Indexed" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#contracts-indexed">​</a></h3>
<p>The indexer covers the full PancakeSwap V3 contract surface on BNB Smart Chain:</p>
<ul>
<li><strong>Factory</strong> (<code>0x0bfbcf9fa4f9c56b0f40a671ad40e0805a091865</code>): Pool creation and registry</li>
<li><strong>Pool</strong> (dynamic): All Pool events across all dynamically registered pool instances</li>
<li><strong>NFPM</strong> (<code>0x46a15b0b27311cedf172ab29e4f4766fbe7f4364</code>): NFT position management events</li>
</ul>
<p>Dynamic contract registration handles the Pool contracts. As new PancakeSwap V3 pools are created onchain by the Factory, the indexer registers them automatically without requiring a redeployment.</p>
<img src="https://docs.envio.dev/blog-assets/revert-hyperindex-case-study-2.png" alt="Envio Cloud GraphQL playground showing a Position query and JSON response for the revert-indexer-2 deployment" width="100%">
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-results">The Results<a class="hash-link" aria-label="Direct link to The Results" title="Direct link to The Results" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#the-results">​</a></h2>
<table><thead><tr><th>Metric</th><th>Result</th></tr></thead><tbody><tr><td>Chain</td><td>BNB Smart Chain (chain ID 56)</td></tr><tr><td>Events processed</td><td>1,711,569,200</td></tr><tr><td>Historical sync time</td><td>10 days</td></tr><tr><td>Final sync status</td><td>100% at block 88,286,723</td></tr><tr><td>Start block</td><td>26,956,207</td></tr></tbody></table>
<p>Over 1.7 billion events, fully synced, on a chain where the equivalent subgraph had been stuck for over 2 years. The indexer is hosted on Envio Cloud, Envio's managed hosting platform.</p>
<img src="https://docs.envio.dev/blog-assets/revert-hyperindex-case-study-3.png" alt="Revert Finance PancakeSwap V3 indexer synced to 100% on BNB Smart Chain in 10 days" width="100%">
<div style="margin:2rem 0;padding:1.5rem 2rem;border-left:4px solid #f97316;background:rgba(249,115,22,0.06);border-radius:0 8px 8px 0"><p style="font-size:1.1rem;font-style:italic;margin-bottom:0.75rem">"We had a problem with our PancakeSwap V3 data on BNB for over two years. The subgraph just would not catch up, and we'd basically given up on it. Envio synced it in 10 days. Great team, great dev experience!"</p><p style="margin:0;font-weight:600">Mario Romero, Founder at Revert Finance</p></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="envio-vs-the-graph-on-bnb-smart-chain">Envio vs The Graph on BNB Smart Chain<a class="hash-link" aria-label="Direct link to Envio vs The Graph on BNB Smart Chain" title="Direct link to Envio vs The Graph on BNB Smart Chain" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#envio-vs-the-graph-on-bnb-smart-chain">​</a></h2>
<table><thead><tr><th></th><th>The Graph (subgraph)</th><th>Envio HyperIndex</th></tr></thead><tbody><tr><td>BNB Smart Chain sync status</td><td>Stuck, unable to reach chain head for 2+ years</td><td>100% synced in 10 days</td></tr><tr><td>Language</td><td>AssemblyScript</td><td>TypeScript</td></tr><tr><td>Real-time data availability</td><td>No</td><td>Yes</td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-high-throughput-chains-need-hypersync">Why High-Throughput Chains Need HyperSync<a class="hash-link" aria-label="Direct link to Why High-Throughput Chains Need HyperSync" title="Direct link to Why High-Throughput Chains Need HyperSync" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#why-high-throughput-chains-need-hypersync">​</a></h2>
<p>BNB Smart Chain is not an edge case. Any high-throughput EVM chain, whether BNB Smart Chain, Polygon, or a high-activity L2, generates event volumes that stress RPC-based indexing. The pattern is the same: subgraph starts syncing, falls progressively further behind, eventually stalls.</p>
<p>HyperSync eliminates this failure mode by removing RPC polling from the historical sync path entirely. Event data is retrieved in bulk from Envio's data lake, meaning sync speed scales with data volume rather than being bottlenecked by RPC rate limits and polling intervals.</p>
<p>For protocols like Revert Finance that require accurate, real-time onchain data to power liquidity analytics, this is the difference between functional infrastructure and a permanently stale data source.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#get-started">​</a></h2>
<ul>
<li>Quickstart: <a href="https://docs.envio.dev/docs/HyperIndex/contract-import" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperIndex/contract-import</a></li>
<li>Envio docs: <a href="https://docs.envio.dev/" target="_blank" rel="noopener noreferrer">https://docs.envio.dev</a></li>
<li>Discord: <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">https://discord.gg/envio</a></li>
<li>Telegram: <a href="https://t.me/+kAIGElzPjApiMjI0" target="_blank" rel="noopener noreferrer">https://t.me/+kAIGElzPjApiMjI0</a></li>
<li>Follow us on X: <a href="https://x.com/envio_indexer" target="_blank" rel="noopener noreferrer">https://x.com/envio_indexer</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-revert-finance">What is Revert Finance?<a class="hash-link" aria-label="Direct link to What is Revert Finance?" title="Direct link to What is Revert Finance?" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#what-is-revert-finance">​</a></h3>
<p>Revert Finance builds analytics and management tools for liquidity providers in AMM protocols. Its tooling covers position analytics, auto-compounding, and liquidity management across protocols including PancakeSwap, Uniswap, and others.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-pancakeswap-v3">What is PancakeSwap V3?<a class="hash-link" aria-label="Direct link to What is PancakeSwap V3?" title="Direct link to What is PancakeSwap V3?" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#what-is-pancakeswap-v3">​</a></h3>
<p>PancakeSwap V3 is the concentrated liquidity version of PancakeSwap, the largest decentralized exchange on BNB Smart Chain. V3 introduces capital-efficient liquidity positions represented as NFTs, managed via the Non-Fungible Position Manager contract.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="why-was-revert-finances-pancakeswap-v3-subgraph-stuck-for-2-years">Why was Revert Finance's PancakeSwap V3 subgraph stuck for 2 years?<a class="hash-link" aria-label="Direct link to Why was Revert Finance's PancakeSwap V3 subgraph stuck for 2 years?" title="Direct link to Why was Revert Finance's PancakeSwap V3 subgraph stuck for 2 years?" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#why-was-revert-finances-pancakeswap-v3-subgraph-stuck-for-2-years">​</a></h3>
<p>A public PancakeSwap V3 subgraph on The Graph's decentralized network had been stuck at 70% sync on BNB Smart Chain for over 2 years, unable to reach chain head. BNB Smart Chain's high throughput generates more events per block than standard RPC-based indexing can sustain, so subgraphs fall progressively further behind until they stall entirely. Teams have reported similar BNB sync issues going back to 2021.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-does-hypersync-solve-the-bnb-smart-chain-sync-problem">How does HyperSync solve the BNB Smart Chain sync problem?<a class="hash-link" aria-label="Direct link to How does HyperSync solve the BNB Smart Chain sync problem?" title="Direct link to How does HyperSync solve the BNB Smart Chain sync problem?" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#how-does-hypersync-solve-the-bnb-smart-chain-sync-problem">​</a></h3>
<p>HyperSync removes RPC polling from the historical sync path. Instead of fetching block by block through standard RPC, Envio retrieves event data in bulk from a purpose-built data lake, so sync speed scales with data volume rather than being bottlenecked by RPC rate limits and polling intervals. BNB Smart Chain is one of <!-- -->85+<!-- --> EVM chains with native HyperSync coverage.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="which-pancakeswap-v3-contracts-does-the-revert-indexer-cover">Which PancakeSwap V3 contracts does the Revert indexer cover?<a class="hash-link" aria-label="Direct link to Which PancakeSwap V3 contracts does the Revert indexer cover?" title="Direct link to Which PancakeSwap V3 contracts does the Revert indexer cover?" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#which-pancakeswap-v3-contracts-does-the-revert-indexer-cover">​</a></h3>
<p>The indexer covers the full PancakeSwap V3 contract surface on BNB Smart Chain: Factory (<code>0x0bfbcf9fa4f9c56b0f40a671ad40e0805a091865</code>) for Pool creation and registry, Pool contracts (dynamically registered as new pools are created by the Factory), and NFPM (<code>0x46a15b0b27311cedf172ab29e4f4766fbe7f4364</code>) for NFT position management events.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="does-the-revert-indexer-use-dynamic-contract-registration">Does the Revert indexer use dynamic contract registration?<a class="hash-link" aria-label="Direct link to Does the Revert indexer use dynamic contract registration?" title="Direct link to Does the Revert indexer use dynamic contract registration?" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#does-the-revert-indexer-use-dynamic-contract-registration">​</a></h3>
<p>Yes. Dynamic contract registration handles the Pool contracts. As new PancakeSwap V3 pools are created onchain by the Factory, the indexer registers them automatically without requiring a redeployment.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-many-events-did-the-new-hyperindex-indexer-process">How many events did the new HyperIndex indexer process?<a class="hash-link" aria-label="Direct link to How many events did the new HyperIndex indexer process?" title="Direct link to How many events did the new HyperIndex indexer process?" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#how-many-events-did-the-new-hyperindex-indexer-process">​</a></h3>
<p>The HyperIndex indexer for PancakeSwap V3 on BNB Smart Chain processed 1,711,569,200 events to 100% sync in 10 days. It started from block 26,956,207 and reached chain head at block 88,286,723.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="why-did-revert-finance-switch-from-the-graph-to-envio-hyperindex">Why did Revert Finance switch from The Graph to Envio HyperIndex?<a class="hash-link" aria-label="Direct link to Why did Revert Finance switch from The Graph to Envio HyperIndex?" title="Direct link to Why did Revert Finance switch from The Graph to Envio HyperIndex?" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#why-did-revert-finance-switch-from-the-graph-to-envio-hyperindex">​</a></h3>
<p>Revert's PancakeSwap V3 subgraph on The Graph had been stuck at 70% sync for over 2 years on BNB Smart Chain. As founder Mario Romero put it: "We had a problem with our PancakeSwap V3 data on BNB for over two years. The subgraph just would not catch up, and we'd basically given up on it. Envio synced it in 10 days. Great team, great dev experience!" HyperIndex completed the historical sync in 10 days and now serves real-time data.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-envio-cloud">What is Envio Cloud?<a class="hash-link" aria-label="Direct link to What is Envio Cloud?" title="Direct link to What is Envio Cloud?" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#what-is-envio-cloud">​</a></h3>
<p>Envio Cloud is Envio's managed hosting platform for HyperIndex indexers. It handles infrastructure, scaling, and monitoring so teams can run production-ready indexers without managing operational overhead. Revert Finance's PancakeSwap V3 indexer runs on Envio Cloud.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#build-with-envio">​</a></h2>
<p>Envio is independently benchmarked as the fastest EVM blockchain indexer available. If you are building onchain and need indexing that keeps up with your chain, check out the <a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">docs</a>, run the benchmarks yourself, or come talk to us about your data needs.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a></p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://x.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+kAIGElzPjApiMjI0" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>case-studies</category>
        </item>
        <item>
            <title><![CDATA[What is HyperSync?]]></title>
            <link>https://docs.envio.dev/blog/what-is-hypersync</link>
            <guid>https://docs.envio.dev/blog/what-is-hypersync</guid>
            <pubDate>Thu, 30 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[HyperSync is Envio's high-performance blockchain data layer, up to 2000x faster than RPC across dozens of supported chains. Learn what it is, how it works, and how to query it.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="&amp;quot;What is HyperSync? The fastest way to query blockchain data&amp;quot; Envio blog cover" src="https://docs.envio.dev/assets/images/what-is-hypersync-7a7de2b58c25bf12079cf2fc4bd4c175.png" width="1906" height="1115" class="img_ev3q"></p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>HyperSync is Envio's high-performance blockchain data-retrieval layer.</li>
<li>Up to 2000x faster than RPC for getting or fetching the logs, transactions, traces, and blocks across <!-- -->85+<!-- --> chains.</li>
<li>Primary data source for HyperIndex and the data layer behind products like <a href="https://chaindensity.xyz/" target="_blank" rel="noopener noreferrer">ChainDensity.xyz</a>, <a href="https://scope.sh/" target="_blank" rel="noopener noreferrer">Scope.sh</a>, LogTUI, and the Polymarket reference indexer (4 billion events in 6 days).</li>
<li>Client libraries available for TypeScript/Node.js, Python, Rust, and Go.</li>
</ul></div></div>
<p>Reading onchain data is one of the slowest, most expensive parts of building any Web3 product or service. Standard JSON-RPC endpoints work for one-off lookups, but break down the moment you need fast or filtered historical data, multichain coverage, or anything more than a handful of blocks at a time. HyperSync exists to fix that. This post covers what HyperSync is, why Envio built it, how it works, and how to use it in your own application.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-problem-with-rpc">The Problem with RPC<a class="hash-link" aria-label="Direct link to The Problem with RPC" title="Direct link to The Problem with RPC" href="https://docs.envio.dev/blog/what-is-hypersync#the-problem-with-rpc">​</a></h2>
<p>Reading onchain data over JSON-RPC is the default path most teams start with. It also breaks the moment your needs go beyond a single contract on a single chain.</p>
<p>Three things happen as soon as you scale:</p>
<ul>
<li><strong>Speed.</strong> Backfilling a year of events across an L2 takes hours or days because RPC was designed to serve one request at a time, not stream historical data in bulk.</li>
<li><strong>Query Flexibility.</strong> RPC limits you to small block windows, typically 100 to 1000 blocks per request depending on the provider, with strict rate limits and inconsistent behavior across providers. Anything more sophisticated, like fetching every <code>PoolCreated</code> event across an entire chain, still requires hundreds or thousands of separate calls and bespoke retry logic.</li>
<li><strong>Cost.</strong> Data-intensive workloads on premium RPC providers add up fast, and you are still rate-limited at the moment you most need throughput.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-hypersync-is">What HyperSync Is<a class="hash-link" aria-label="Direct link to What HyperSync Is" title="Direct link to What HyperSync Is" href="https://docs.envio.dev/blog/what-is-hypersync#what-hypersync-is">​</a></h2>
<p>HyperSync is a purpose-built data retrieval layer that gives developers direct access to blockchain data at speeds RPC cannot match. It is written in Rust, uses optimised binary encoding and parallel fetching, and exposes a query API that is both fast at serving requested data and flexible about how that data can be filtered and shaped.</p>
<p>Where RPC is a single endpoint serving one block of data at a time, HyperSync is a streaming query engine. You describe what you want once, in a single query object, and it streams back exactly that data across whatever block range you asked for.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="performance-verified">Performance, Verified<a class="hash-link" aria-label="Direct link to Performance, Verified" title="Direct link to Performance, Verified" href="https://docs.envio.dev/blog/what-is-hypersync#performance-verified">​</a></h2>
<p>The numbers below are pulled from the <a href="https://docs.envio.dev/docs/HyperSync/overview" target="_blank" rel="noopener noreferrer">HyperSync overview</a>.</p>
<table><thead><tr><th>Task</th><th>Traditional RPC</th><th>HyperSync</th><th>Improvement</th></tr></thead><tbody><tr><td>Scan Arbitrum for sparse log data</td><td>Hours to days</td><td>2 seconds</td><td>~2000x faster</td></tr><tr><td>Fetch all Uniswap v3 <code>PoolCreated</code> events on Ethereum</td><td>Hours</td><td>Seconds</td><td>~500x faster</td></tr></tbody></table>
<p>HyperSync is also the data layer powering HyperIndex, the fastest blockchain indexer available. Sentio's independent Uniswap V2 Factory benchmark (May 2025) measured HyperIndex completing the test in 8 seconds, 142x faster than The Graph and 15x faster than the nearest competitor (Subsquid).</p>
<p>In production, that translates into projects like the Polymarket reference indexer, which synced 4 billion events in 6 days and replaced 8 separate subgraphs with a single HyperIndex deployment powered by HyperSync.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-hypersync-works">How HyperSync Works<a class="hash-link" aria-label="Direct link to How HyperSync Works" title="Direct link to How HyperSync Works" href="https://docs.envio.dev/blog/what-is-hypersync#how-hypersync-works">​</a></h2>
<p>There are four primitives you need to understand to use HyperSync.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="1-queries">1. Queries<a class="hash-link" aria-label="Direct link to 1. Queries" title="Direct link to 1. Queries" href="https://docs.envio.dev/blog/what-is-hypersync#1-queries">​</a></h3>
<p>A query is a single object that describes the data you want. It includes a block range, a set of filters, and a field selection. You hand it to a HyperSync client and it streams matching results back to you.</p>
<p>Here is a working query in TypeScript that streams every Uniswap v3 event from Ethereum mainnet, starting at genesis. This pattern is taken from the Polymarket trades tutorial and the API Tokens implementation guide.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">Query</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@envio-dev/hypersync-client"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> keccak256</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> toHex </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"viem"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> event_signatures </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"PoolCreated(address,address,uint24,int24,address)"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"Burn(address,int24,int24,uint128,uint256,uint256)"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"Initialize(uint160,int24)"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"Mint(address,address,int24,int24,uint128,uint256,uint256)"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"Swap(address,address,int256,int256,uint160,uint128,int24)"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> topic0_list </span><span class="token operator">=</span><span class="token plain"> event_signatures</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">map</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">keccak256</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">toHex</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">sig</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> client </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  url</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://eth.hypersync.xyz"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  apiToken</span><span class="token operator">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">ENVIO_API_TOKEN</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> query</span><span class="token operator">:</span><span class="token plain"> Query </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  fromBlock</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  logs</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> topics</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">topic0_list</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  fieldSelection</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    log</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"Data"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Address"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic2"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic3"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> stream </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">stream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">while</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> res </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> stream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">recv</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">res </span><span class="token operator">===</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">break</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">data</span><span class="token operator">?.</span><span class="token plain">logs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">Got </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">res</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">data</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">logs</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">length</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)"> logs</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">nextBlock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">fromBlock </span><span class="token operator">=</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">nextBlock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="2-filters">2. Filters<a class="hash-link" aria-label="Direct link to 2. Filters" title="Direct link to 2. Filters" href="https://docs.envio.dev/blog/what-is-hypersync#2-filters">​</a></h3>
<p>You can filter on logs, transactions, traces, and blocks, alone or in combination. Filters narrow down what HyperSync streams back, so you only pay for the data you actually need.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// TypeScript: every USDC Transfer in a given block range</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> logSelection </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  address</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  topics</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Trace filters give you access to execution traces and internal transactions, which is the only way to track native ETH transfers since they do not emit event logs. Traces are accessed via a separate trace-enabled endpoint, for example <code>https://eth-traces.hypersync.xyz</code>. The <a href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync">Native ETH Transfers tutorial</a> walks through that pattern end to end.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="3-field-selection">3. Field Selection<a class="hash-link" aria-label="Direct link to 3. Field Selection" title="Direct link to 3. Field Selection" href="https://docs.envio.dev/blog/what-is-hypersync#3-field-selection">​</a></h3>
<p>HyperSync lets you ask for only the fields you need. Smaller responses, less bandwidth, faster downstream processing.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> fieldSelection </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  block</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"Number"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Timestamp"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  transaction</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"Hash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"From"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"To"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  log</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"Address"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Data"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="4-output-modes">4. Output Modes<a class="hash-link" aria-label="Direct link to 4. Output Modes" title="Direct link to 4. Output Modes" href="https://docs.envio.dev/blog/what-is-hypersync#4-output-modes">​</a></h3>
<p>HyperSync gives you three ways to consume results:</p>
<ul>
<li><code>client.stream(query, config)</code> for direct in-memory processing.</li>
<li><code>client.collect_json(path, query, config)</code> for smaller datasets and debugging.</li>
<li><code>client.collect_parquet(path, query, config)</code> for analytical workloads on large datasets.</li>
</ul>
<p>Streaming is the right default for indexers and real-time applications. Parquet is the right default for ETL pipelines and data science work.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="switching-networks">Switching Networks<a class="hash-link" aria-label="Direct link to Switching Networks" title="Direct link to Switching Networks" href="https://docs.envio.dev/blog/what-is-hypersync#switching-networks">​</a></h2>
<p>Switching chains is a one-line change. The same client works against any of the <!-- -->85+<!-- --> supported networks by changing the URL.</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">// Ethereum</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> client </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  url</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://eth.hypersync.xyz"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  apiToken</span><span class="token operator">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">ENVIO_API_TOKEN</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Arbitrum</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> client </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  url</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://arbitrum.hypersync.xyz"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  apiToken</span><span class="token operator">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">ENVIO_API_TOKEN</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)">// Base</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> client </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  url</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://base.hypersync.xyz"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  apiToken</span><span class="token operator">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">ENVIO_API_TOKEN</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The full list of network URLs is on the <a href="https://docs.envio.dev/docs/HyperSync/hypersync-supported-networks" target="_blank" rel="noopener noreferrer">Supported Networks</a> page.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="try-hypersync-in-30-seconds">Try HyperSync in 30 Seconds<a class="hash-link" aria-label="Direct link to Try HyperSync in 30 Seconds" title="Direct link to Try HyperSync in 30 Seconds" href="https://docs.envio.dev/blog/what-is-hypersync#try-hypersync-in-30-seconds">​</a></h2>
<p>The fastest way to feel HyperSync is to install nothing.</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx logtui aave arbitrum</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>That command launches LogTUI, a terminal-based blockchain event viewer built on HyperSync, and starts streaming Aave events on Arbitrum into your terminal in real time. LogTUI ships with presets for 20+ protocols including Uniswap, Chainlink, Aave, and ENS.</p>
<p>When you are ready for a real client, clone the hypersync-quickstart repo and run one of the included scripts.</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">git</span><span class="token plain"> clone https://github.com/enviodev/hypersync-quickstart.git</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> hypersync-quickstart</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">pnpm</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">node</span><span class="token plain"> run-simple.js</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You will need an API token. Set it as an environment variable.</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token builtin class-name" style="color:rgb(189, 147, 249)">export</span><span class="token plain"> </span><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">ENVIO_API_TOKEN</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">"your-api-token-here"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Generate a token from <a href="https://envio.dev/app/api-tokens" target="_blank" rel="noopener noreferrer">envio.dev/app/api-tokens</a> and read the <a href="https://docs.envio.dev/docs/HyperSync/api-tokens" target="_blank" rel="noopener noreferrer">API Tokens guide</a> for usage and security best practices.</p>
<p>If you are building a full indexer with schema management, event handlers, and a hosted GraphQL API, jump to the <a href="https://docs.envio.dev/docs/HyperIndex/contract-import" target="_blank" rel="noopener noreferrer">HyperIndex Quickstart</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="handling-large-backfills">Handling Large Backfills<a class="hash-link" aria-label="Direct link to Handling Large Backfills" title="Direct link to Handling Large Backfills" href="https://docs.envio.dev/blog/what-is-hypersync#handling-large-backfills">​</a></h2>
<p>A single HyperSync request has a 5-second processing window. For a fresh historical backfill across a high-volume chain, loop through block ranges by feeding the <code>nextBlock</code> from each response back into the next query.</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">current_block </span><span class="token operator">=</span><span class="token plain"> start_block</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">while</span><span class="token plain"> current_block </span><span class="token operator">&lt;</span><span class="token plain"> end_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from_block </span><span class="token operator">=</span><span class="token plain"> current_block</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to_block </span><span class="token operator">=</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">min</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">current_block </span><span class="token operator">+</span><span class="token plain"> </span><span class="token number">1_000_000</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> end_block</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    result </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">collect_parquet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"data"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> config</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    current_block </span><span class="token operator">=</span><span class="token plain"> result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">end_block </span><span class="token operator">+</span><span class="token plain"> </span><span class="token number">1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>For most use cases, the streaming client handles this automatically.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="use-cases">Use Cases<a class="hash-link" aria-label="Direct link to Use Cases" title="Direct link to Use Cases" href="https://docs.envio.dev/blog/what-is-hypersync#use-cases">​</a></h2>
<p>HyperSync makes a class of applications practical that traditional RPC cannot reasonably support.</p>
<ul>
<li><strong><a href="https://docs.envio.dev/blog/what-is-a-blockchain-indexer">Blockchain indexers</a></strong> that build high-performance data pipelines with minimal infrastructure.</li>
<li><strong>Data analytics</strong> that runs complex onchain analysis in seconds instead of days.</li>
<li><strong>Block explorers</strong> that serve responsive UIs with comprehensive historical access.</li>
<li><strong>Monitoring tools</strong> that track blockchain activity with near real-time updates.</li>
<li><strong>Cross-chain applications</strong> that pull unified data across multiple networks from a single query interface.</li>
<li><strong>ETL pipelines</strong> that extract onchain data into data warehouses fast.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-hypersync-powers">What HyperSync Powers<a class="hash-link" aria-label="Direct link to What HyperSync Powers" title="Direct link to What HyperSync Powers" href="https://docs.envio.dev/blog/what-is-hypersync#what-hypersync-powers">​</a></h2>
<p>HyperSync is the data engine underneath a growing set of tools and applications.</p>
<p><strong><a href="https://docs.envio.dev/docs/HyperIndex/overview">HyperIndex</a></strong> is Envio's full indexing framework. It uses HyperSync as its primary data source, then layers on schema management, event handlers, multichain support, automatic reorg handling, and a hosted GraphQL API. HyperIndex is the fastest blockchain indexer available, 142x faster than The Graph and 15x faster than Subsquid on the Sentio Uniswap V2 Factory benchmark (May 2025).</p>
<p><strong><a href="https://chaindensity.xyz/" target="_blank" rel="noopener noreferrer">ChainDensity.xyz</a></strong> uses HyperSync to render transaction and event density across any address on any supported chain. It generates insights in seconds that would take hours over RPC.</p>
<p><strong><a href="https://scope.sh/" target="_blank" rel="noopener noreferrer">Scope.sh</a></strong> is an Account Abstraction-focused block explorer that uses HyperSync for ultra-fast historical data retrieval.</p>
<p><strong>LogTUI</strong> is the zero-install event viewer mentioned above. Try <code>pnpx logtui --help</code> for the full list of presets.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="when-to-use-hypersync-vs-hyperindex">When to Use HyperSync vs HyperIndex<a class="hash-link" aria-label="Direct link to When to Use HyperSync vs HyperIndex" title="Direct link to When to Use HyperSync vs HyperIndex" href="https://docs.envio.dev/blog/what-is-hypersync#when-to-use-hypersync-vs-hyperindex">​</a></h2>
<p>A common question. The short answer.</p>
<p>Use <strong>HyperSync</strong> directly when you want raw blockchain data at maximum speed and you are happy to manage your own pipeline, storage, and downstream API. Good fits include analytics scripts, ETL into a data warehouse, custom alert systems, and anything that needs the absolute thinnest layer between you and the data.</p>
<p>Use <strong>HyperIndex</strong> when you want a complete indexing framework with schema management, event handlers, GraphQL output, multichain support, automatic reorg handling, and managed hosting on Envio Cloud. Good fits include application backends, dashboards, and anything where you would otherwise reach for The Graph or Subsquid. HyperIndex is itself powered by HyperSync.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="common-patterns">Common Patterns<a class="hash-link" aria-label="Direct link to Common Patterns" title="Direct link to Common Patterns" href="https://docs.envio.dev/blog/what-is-hypersync#common-patterns">​</a></h2>
<p>Three patterns we see most often from teams adopting HyperSync.</p>
<p><strong>Pattern 1. Replace a slow RPC backfill.</strong> A team has an existing indexer that takes days to backfill from genesis. Swapping the RPC source for HyperSync brings that down to minutes. The Polymarket case study is the canonical example, with 4 billion events synced in 6 days.</p>
<p><strong>Pattern 2. Query across many chains in one place.</strong> A team builds a multichain dashboard and is tired of stitching together a dozen RPC providers. HyperSync exposes the same query interface for every supported chain, so the only thing that changes between Ethereum, Arbitrum, Base, and Optimism is the URL.</p>
<p><strong>Pattern 3. Build a niche analytics tool fast.</strong> ChainDensity, Scope, and LogTUI are all examples. HyperSync makes it cheap to ship the kind of tool that would otherwise need a dedicated data team.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="pricing-and-access">Pricing and Access<a class="hash-link" aria-label="Direct link to Pricing and Access" title="Direct link to Pricing and Access" href="https://docs.envio.dev/blog/what-is-hypersync#pricing-and-access">​</a></h2>
<p>HyperSync requires an API token. API tokens have been required since 3 November 2025. Generate a token at <a href="https://envio.dev/app/api-tokens" target="_blank" rel="noopener noreferrer">envio.dev/app/api-tokens</a> and read the <a href="https://docs.envio.dev/docs/HyperSync/api-tokens" target="_blank" rel="noopener noreferrer">API Tokens documentation</a> for limits, usage tracking (requests and credits), and security best practices. Indexers deployed to Envio Cloud have special access to HyperSync and do not require a custom API token. For production tier options, see the <a href="https://envio.dev/pricing" target="_blank" rel="noopener noreferrer">Envio pricing page</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/what-is-hypersync#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-fast-is-hypersync-compared-to-rpc">How Fast Is HyperSync Compared to RPC?<a class="hash-link" aria-label="Direct link to How Fast Is HyperSync Compared to RPC?" title="Direct link to How Fast Is HyperSync Compared to RPC?" href="https://docs.envio.dev/blog/what-is-hypersync#how-fast-is-hypersync-compared-to-rpc">​</a></h3>
<p>HyperSync is up to 2000x faster than RPC for sparse log scans. Scanning Arbitrum for sparse log data takes 2 seconds with HyperSync, versus hours or days over RPC. Fetching every Uniswap v3 <code>PoolCreated</code> event on Ethereum is roughly 500x faster.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-chains-does-hypersync-support">What Chains Does HyperSync Support?<a class="hash-link" aria-label="Direct link to What Chains Does HyperSync Support?" title="Direct link to What Chains Does HyperSync Support?" href="https://docs.envio.dev/blog/what-is-hypersync#what-chains-does-hypersync-support">​</a></h3>
<p>HyperSync is natively available on <!-- -->85+<!-- --> chains, including Fuel, with new networks added regularly. The full list is on the <a href="https://docs.envio.dev/docs/HyperSync/hypersync-supported-networks" target="_blank" rel="noopener noreferrer">Supported Networks</a> page.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-client-libraries-are-available">What Client Libraries Are Available?<a class="hash-link" aria-label="Direct link to What Client Libraries Are Available?" title="Direct link to What Client Libraries Are Available?" href="https://docs.envio.dev/blog/what-is-hypersync#what-client-libraries-are-available">​</a></h3>
<p>HyperSync ships official client libraries in Python, Rust, Node.js, and Go. There is also a curl interface for quick testing.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="do-i-need-an-api-token">Do I Need an API Token?<a class="hash-link" aria-label="Direct link to Do I Need an API Token?" title="Direct link to Do I Need an API Token?" href="https://docs.envio.dev/blog/what-is-hypersync#do-i-need-an-api-token">​</a></h3>
<p>Yes. API tokens have been required since 3 November 2025. Generate a token at <a href="https://envio.dev/app/api-tokens" target="_blank" rel="noopener noreferrer">envio.dev/app/api-tokens</a> and pass it as <code>apiToken</code> in TypeScript or <code>bearer_token</code> in Python. Indexers deployed to Envio Cloud have special access and do not need a custom token.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-is-hypersync-different-from-hyperindex">How Is HyperSync Different from HyperIndex?<a class="hash-link" aria-label="Direct link to How Is HyperSync Different from HyperIndex?" title="Direct link to How Is HyperSync Different from HyperIndex?" href="https://docs.envio.dev/blog/what-is-hypersync#how-is-hypersync-different-from-hyperindex">​</a></h3>
<p>HyperSync is the raw data layer. HyperIndex is the full indexing framework built on top of it. Use HyperSync directly when you want maximum speed and full control of your pipeline. Use HyperIndex when you want schema management, event handlers, GraphQL APIs, automatic reorg handling, and managed hosting.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="can-i-use-hypersync-for-real-time-data">Can I Use HyperSync for Real-Time Data?<a class="hash-link" aria-label="Direct link to Can I Use HyperSync for Real-Time Data?" title="Direct link to Can I Use HyperSync for Real-Time Data?" href="https://docs.envio.dev/blog/what-is-hypersync#can-i-use-hypersync-for-real-time-data">​</a></h3>
<p>Yes. HyperSync streams data continuously and you can poll for new blocks at the head of the chain. The <a href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync">Polymarket trades tutorial</a> is a worked example of real-time streaming.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="are-traces-supported-on-every-chain">Are Traces Supported on Every Chain?<a class="hash-link" aria-label="Direct link to Are Traces Supported on Every Chain?" title="Direct link to Are Traces Supported on Every Chain?" href="https://docs.envio.dev/blog/what-is-hypersync#are-traces-supported-on-every-chain">​</a></h3>
<p>No. Trace filters are accessed via separate trace-enabled HyperSync endpoints, for example <code>https://eth-traces.hypersync.xyz</code> for Ethereum mainnet. See the <a href="https://docs.envio.dev/docs/HyperSync/hypersync-supported-networks" target="_blank" rel="noopener noreferrer">Supported Networks</a> page for trace availability.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/what-is-hypersync#build-with-envio">​</a></h2>
<p>Envio HyperIndex is independently benchmarked as the fastest EVM blockchain indexer available (Sentio benchmark, May 2025). If you are building onchain and need indexing that keeps up with your chain, check out the <a href="https://docs.envio.dev/docs/HyperIndex/overview">HyperIndex documentation</a>, run the benchmarks yourself, or come talk to us about your data needs.</p>
<p>Stay tuned for more updates by subscribing to our newsletter, following us on X, or hopping into our Discord.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a></p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.com/invite/gt7yEUZKeB" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Envio Developer Update April 2026]]></title>
            <link>https://docs.envio.dev/blog/envio-developer-update-april-2026</link>
            <guid>https://docs.envio.dev/blog/envio-developer-update-april-2026</guid>
            <pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Envio's April 2026 developer update covering HyperIndex v3 alpha.21 with experimental ClickHouse Sink, the Envio Docs MCP Server, Quickstart with AI guide, Polymarket V2 indexer, Monad traces on HyperSync, Tempo support, and EthCC[9].]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/dev-update-april-2026.png" alt="Cover Image Envio Developer Update April 2026" width="100%">
<p>April was a big step forward for AI-assisted indexing on Envio. We launched the Envio Docs MCP Server and a new Quickstart with AI guide for building or migrating indexers with Claude, Cursor, and other AI coding assistants. HyperIndex v3.0.0 alpha.21 ships with an experimental ClickHouse Sink, improved multiple data-sources support, and an updated testing framework with three ways to feed events. We also released the Polymarket V2 Indexer, which is now powering a new data-driven series breaking down the actual top-PnL traders on Polymarket. HyperSync added Monad trace support with full history from block 0, Envio went live on Tempo, and much more. The team was also at EthCC[9] in Cannes.</p>
<p>Let's dive in.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="hyperindex-v300-alpha-alpha20--alpha21">HyperIndex v3.0.0 Alpha: alpha.20 &amp; alpha.21<a class="hash-link" aria-label="Direct link to HyperIndex v3.0.0 Alpha: alpha.20 &amp; alpha.21" title="Direct link to HyperIndex v3.0.0 Alpha: alpha.20 &amp; alpha.21" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#hyperindex-v300-alpha-alpha20--alpha21">​</a></h2>
<p>Continuing steady progress on V3 across indexing resilience, testing, analytics, and developer experience.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="improved-multiple-data-sources-support">Improved Multiple Data-Sources Support<a class="hash-link" aria-label="Direct link to Improved Multiple Data-Sources Support" title="Direct link to Improved Multiple Data-Sources Support" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#improved-multiple-data-sources-support">​</a></h3>
<p>HyperIndex now handles data source switching more intelligently.</p>
<p>After switching to a fallback source, HyperIndex automatically attempts to recover to the primary source 60 seconds later, rather than staying stuck on the fallback until it goes down or the indexer is restarted. The logic for choosing which source to use next has also been improved, alongside stricter enforcement of source usage configured for live mode.</p>
<p>The result: better indexing resilience, less vendor lock-in, and more predictable failover behaviour in production.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="testing-framework-highlights">Testing Framework Highlights<a class="hash-link" aria-label="Direct link to Testing Framework Highlights" title="Direct link to Testing Framework Highlights" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#testing-framework-highlights">​</a></h3>
<p>Our testing framework has matured with three ways to feed events, making it easier to write tests against the same indexer that runs in production. No database, no Docker, no manual mock wiring.</p>
<ul>
<li>Auto-exit: zero config, processes the first block with matching events</li>
<li>Explicit block range: deterministic CI snapshots</li>
<li>Simulate: typed synthetic events, no network needed</li>
</ul>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> describe</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> it </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"vitest"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> createTestIndexer </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"generated"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">describe</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"ERC20 indexer"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token function" style="color:rgb(80, 250, 123)">it</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"processes the first block with events"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> indexer </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">createTestIndexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> result </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> indexer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> chains</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token number">1</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// Auto-filled by Vitest on first run, just review and commit</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    t</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">expect</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toMatchInlineSnapshot</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">      {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">        "changes": [</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">          {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            "Transfer": {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">              "sets": [</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                  "blockNumber": 10861674,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                  "from": "0x0000000000000000000000000000000000000000",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                  "id": "1-10861674-23",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                  "to": "0x41653c7d61609D856f29355E404F310Ec4142Cfb",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                  "transactionHash": "0x4b37d2f343608457ca...",</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                  "value": 1000000000000000000000000000n,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">                },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">              ],</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            "block": 10861674,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            "chainId": 1,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">            "eventsProcessed": 1,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">          },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">        ],</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">      }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token template-string string" style="color:rgb(255, 121, 198)">    </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="experimental-clickhouse-sink">Experimental ClickHouse Sink<a class="hash-link" aria-label="Direct link to Experimental ClickHouse Sink" title="Direct link to Experimental ClickHouse Sink" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#experimental-clickhouse-sink">​</a></h3>
<img src="https://docs.envio.dev/blog-assets/dev-update-april-2026-1.png" alt="Envio banner titled 'Using ClickHouse Sink' with 'HyperIndex V3' subtitle" width="100%">
<p>HyperIndex V3 Alpha introduces an experimental ClickHouse Sink. Postgres remains the primary database, with your entity data additionally replicated to ClickHouse for analytics workloads.</p>
<p>ClickHouse is a columnar database built for heavy analytical queries on datasets in the 100s of GBs or TBs, a natural fit for onchain data which can easily reach billions of events for a single token. If your indexer is powering a dashboard, leaderboard, historical chart, or any reporting layer on top of a large dataset, ClickHouse is the right tool for that read path.</p>
<p>Enable it on Envio Cloud by setting four environment variables:</p>
<ul>
<li><code>ENVIO_CLICKHOUSE_SINK_HOST</code></li>
<li><code>ENVIO_CLICKHOUSE_SINK_DATABASE</code></li>
<li><code>ENVIO_CLICKHOUSE_SINK_USERNAME</code></li>
<li><code>ENVIO_CLICKHOUSE_SINK_PASSWORD</code></li>
</ul>
<p>Currently supported on the Dedicated Plan only, and you need to bring your own ClickHouse instance. Managed ClickHouse is coming to Envio Cloud, fill out <a href="https://forms.gle/P19S7KXYfdHQM8J69" target="_blank" rel="noopener noreferrer">this form</a> to be one of the first users.</p>
<p>Read the full walkthrough here: <a href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3</a></p>
<p>See the full <a href="https://github.com/enviodev/hyperindex/releases" target="_blank" rel="noopener noreferrer">release notes</a>.
Star us on <a href="https://github.com/enviodev/hyperindex" target="_blank" rel="noopener noreferrer">GitHub</a> ⭐</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-top-hundred-polymarket-traders">The Top Hundred Polymarket Traders<a class="hash-link" aria-label="Direct link to The Top Hundred Polymarket Traders" title="Direct link to The Top Hundred Polymarket Traders" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#the-top-hundred-polymarket-traders">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-april-2026-2.png" alt="Table titled 'Polymarket all-time realized PnL distribution' across 2,684,676 users analyzed, broken down by PnL bucket, users, percent of users, and aggregate PnL" width="100%">
<p>We released the Polymarket V2 Indexer this month, a drop-in reference for teams wanting to collect all v2 market data. It covers the new v2 markets end-to-end, designed to scale alongside Polymarket's growth.</p>
<p>Check it out on GitHub: <a href="https://github.com/enviodev/polymarket-v2-indexer" target="_blank" rel="noopener noreferrer">https://github.com/enviodev/polymarket-v2-indexer</a></p>
<p>Off the back of the release, we kicked off a data-driven series breaking down the actual top-PnL traders on Polymarket. 2.66 million wallets have traded on the platform, and the top 100 captured $853 million in profit between them. None of them are clicking buttons on a phone app between sips of beer.</p>
<p>Day 1 profiles "Bids On Everything", the wallet ranked #24 by realized PnL with roughly $24 million net profit across 2,698,796 fills, 44,954 simultaneous markets, and 289 active days. The strategy in one sentence: post buy orders on every outcome token of every binary market at every price level, then merge YES + NO pairs for one dollar whenever both fill.</p>
<p>It's a strong example of the kind of analysis you can run when you have full historical and real-time access to v2 market data. Stay tuned for more!</p>
<p>Read the full breakdown: <a href="https://x.com/jonjonclark/status/2049067586046816561?s=20" target="_blank" rel="noopener noreferrer">https://x.com/jonjonclark/status/2049067586046816561?s=20</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="envio-docs-mcp-server">Envio Docs MCP Server<a class="hash-link" aria-label="Direct link to Envio Docs MCP Server" title="Direct link to Envio Docs MCP Server" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#envio-docs-mcp-server">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-april-2026-3.png" alt="Envio banner titled 'Introducing Docs MCP Server' with subtitle 'Live docs for your AI assistant' and AI assistant logos linked to a central node" width="100%">
<p>Envio docs now speak AI. Plug your AI coding assistant (Claude Code, Cursor, Copilot, and more) straight into our docs with the new Envio Docs MCP Server.</p>
<ul>
<li>Always up-to-date</li>
<li>Instant accurate context</li>
<li>Easy setup</li>
</ul>
<p>The biggest shift in AI workflows isn't better prompts, it's better context, and that's exactly what the MCP Server solves. Your assistant pulls live documentation on demand instead of relying on stale training data.</p>
<p>Setup guide and more here: <a href="https://docs.envio.dev/blog/envio-docs-mcp-server" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/envio-docs-mcp-server</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="quickstart-with-ai">Quickstart with AI<a class="hash-link" aria-label="Direct link to Quickstart with AI" title="Direct link to Quickstart with AI" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#quickstart-with-ai">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-april-2026-4.png" alt="Quickstart with AI" width="100%">
<p>Build or migrate an indexer end-to-end using Claude, Cursor, or any other AI coding assistant with our new Quickstart with AI guide.</p>
<p>What's included:</p>
<ul>
<li>Live docs via MCP</li>
<li>Non-interactive init</li>
<li>Built-in Claude skills</li>
<li>AI-assisted subgraph migration</li>
<li>Programmatic deploys via the envio-cloud CLI</li>
</ul>
<p>This pulls everything together into a single agentic workflow, from scaffolding to deployment, without touching a config file manually.</p>
<p>Get started here: <a href="https://docs.envio.dev/docs/HyperIndex/quickstart-with-ai" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperIndex/quickstart-with-ai</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="concentrated-liquidity-on-uniswap-v4">Concentrated Liquidity on Uniswap v4<a class="hash-link" aria-label="Direct link to Concentrated Liquidity on Uniswap v4" title="Direct link to Concentrated Liquidity on Uniswap v4" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#concentrated-liquidity-on-uniswap-v4">​</a></h2>
<iframe width="560" height="315" src="https://www.youtube.com/embed/UZGtLVQGliE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"></iframe>
<p>Envio was a Sapphire sponsor of EthCC[9], held at Palais des Festivals in Cannes from March 30 to April 2, 2026.</p>
<p>JonJon took to the Monroe Stage with his talk "From x<em>y=k to Ticks: Seeing Concentrated Liquidity on Uniswap v4 in Real Time", walking through the jump from x</em>y=k to ticks on Uniswap v4, with a real-time visual layer tracking active liquidity and pool behaviour across chains.</p>
<p>Big thanks to the EthCC team, sponsors, organisers, and volunteers for putting on such a great event. Had a great time connecting with some incredible teams and builders across the week, and a special thanks to everyone who swung by our booth.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="monad-traces-live-on-hypersync">Monad Traces Live on HyperSync<a class="hash-link" aria-label="Direct link to Monad Traces Live on HyperSync" title="Direct link to Monad Traces Live on HyperSync" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#monad-traces-live-on-hypersync">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-april-2026-5.png" alt="GitHub repo card for enviodev/export-monad-traces with the Envio logo" width="100%">
<p>Monad traces are live on HyperSync, with full history from block 0.</p>
<p>Stream all Monad trace data in minutes and export it to CSV using our new export tool. Ideal for teams running deep onchain analytics, MEV research, or custom pipelines on top of Monad's execution traces.</p>
<p>Export tool on GitHub: <a href="https://github.com/enviodev/export-monad-traces" target="_blank" rel="noopener noreferrer">https://github.com/enviodev/export-monad-traces</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="envio-is-live-on-tempo">Envio is Live on Tempo<a class="hash-link" aria-label="Direct link to Envio is Live on Tempo" title="Direct link to Envio is Live on Tempo" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#envio-is-live-on-tempo">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-april-2026-6.gif" alt="Envio is Live on Tempo" width="100%">
<p>Envio is live on Tempo, the blockchain built for stablecoin payments at scale.</p>
<p>Index and query real-time payment data, build fully customisable data pipelines, and query millions of events up to 2000x faster than traditional RPC.</p>
<p>Easy, fast, and fully customisable.</p>
<p>Original post on X: <a href="https://x.com/i/status/2042577679380013222" target="_blank" rel="noopener noreferrer">https://x.com/i/status/2042577679380013222</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-to-track-native-eth-transfers-using-hypersync">How to Track Native ETH Transfers Using HyperSync<a class="hash-link" aria-label="Direct link to How to Track Native ETH Transfers Using HyperSync" title="Direct link to How to Track Native ETH Transfers Using HyperSync" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#how-to-track-native-eth-transfers-using-hypersync">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-april-2026-7.png" alt="How to Track Native ETH Transfers Using HyperSync" width="100%">
<p>Tracking native ETH transfers onchain is trickier than ERC-20 transfers. There's no event log to index, so you have to parse traces, which is slow over standard RPC.</p>
<p>Our new tutorial walks through how to use HyperSync's native trace filtering to stream transfers by filtering on <code>call_type=call</code> with a value threshold. It includes a full working example using the Node.js client in a Bun project, streaming results until 10 transfers above 0.005 ETH are collected.</p>
<p>HyperSync trace support is currently available on Ethereum, Base, Arbitrum, Gnosis, and Monad.</p>
<p>Read the full tutorial: <a href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="current--upcoming-events--hackathons">Current &amp; Upcoming Events &amp; Hackathons<a class="hash-link" aria-label="Direct link to Current &amp; Upcoming Events &amp; Hackathons" title="Direct link to Current &amp; Upcoming Events &amp; Hackathons" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#current--upcoming-events--hackathons">​</a></h2>
<ul>
<li><a href="https://ethconf.com/" target="_blank" rel="noopener noreferrer">ETHConf - New York</a>: June 8th -&gt; 10th (sponsoring)</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="featured-developer-claude">Featured Developer: Claude<a class="hash-link" aria-label="Direct link to Featured Developer: Claude" title="Direct link to Featured Developer: Claude" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#featured-developer-claude">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-april-2026-8.png" alt="Featured developer Claude" width="100%">
<p>This month's featured developer is Claude.</p>
<p>A shoutout to Anthropic's Claude, who has become a familiar name in the developer community and a strong collaborator for teams building with AI assistants. With the launch of the Envio Docs MCP Server and Quickstart with AI guide this month, we're excited to see how the community continues to build with AI alongside Envio.</p>
<p>More to come.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="playlist-of-the-month">Playlist of the Month<a class="hash-link" aria-label="Direct link to Playlist of the Month" title="Direct link to Playlist of the Month" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#playlist-of-the-month">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-april-2026-9.png" alt="Spotify public playlist titled 'Apr 26' by Jordy Baby, 21 songs, 1 hr 28 min" width="100%">
<p>▶ <a href="https://open.spotify.com/playlist/240pHTCbwvf6kBMdfWGmw9?si=bb40d616e82a49f3" target="_blank" rel="noopener noreferrer">Open Spotify</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/envio-developer-update-april-2026#build-with-envio">​</a></h2>
<p>Envio is a multichain EVM blockchain indexer for querying real-time and historical data. If you're working on a Web3 project and want a smoother development process, Envio's got your back(end). Check out our docs, join the community, and let's talk about your data needs.</p>
<p>Stay tuned for more monthly updates by subscribing to our newsletter, following us on X, or hopping into our Discord for more up-to-date information.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a> 💌</p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>product-updates</category>
        </item>
        <item>
            <title><![CDATA[Using ClickHouse Storage in HyperIndex V3]]></title>
            <link>https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3</link>
            <guid>https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3</guid>
            <pubDate>Fri, 24 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[HyperIndex V3 Alpha adds experimental ClickHouse Storage. Postgres stays primary, entity data mirrors to ClickHouse for analytics workloads on billions of onchain events.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="Cover image for the ClickHouse Storage blog" src="https://docs.envio.dev/assets/images/clickhouse-storage-d2f888e3165b146a98f61864eb5705a7.png" width="1906" height="1115" class="img_ev3q"></p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>HyperIndex V3 Alpha adds experimental <strong>ClickHouse Storage</strong>, Postgres stays as the primary database, and your entity data is replicated to ClickHouse for analytics workloads.</li>
<li>ClickHouse is a columnar database built for heavy analytical queries on datasets in the 100s of GBs or TBs, a natural fit for onchain data, which can easily reach billions of events for a single token.</li>
<li>You can enable it on Envio Cloud by setting four environment variables: <code>ENVIO_CLICKHOUSE_HOST</code>, <code>ENVIO_CLICKHOUSE_DATABASE</code>, <code>ENVIO_CLICKHOUSE_USERNAME</code>, and <code>ENVIO_CLICKHOUSE_PASSWORD</code>.</li>
<li>Currently supported on the <strong>Dedicated Plan</strong> only, and you need to bring your own ClickHouse instance. Managed ClickHouse is coming to Envio Cloud, <a href="https://forms.gle/P19S7KXYfdHQM8J69" target="_blank" rel="noopener noreferrer"><strong>fill out this form</strong></a> if you want to be one of the first users.</li>
</ul></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-we-built-clickhouse-storage">Why We Built ClickHouse Storage<a class="hash-link" aria-label="Direct link to Why We Built ClickHouse Storage" title="Direct link to Why We Built ClickHouse Storage" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#why-we-built-clickhouse-storage">​</a></h2>
<p>Since day one, HyperIndex has used Postgres as its primary database. Postgres is battle-tested, runs well for small and large indexers alike, and gives you GraphQL out of the box through Hasura. It is a solid default for almost every indexer.</p>
<p>But over the last few months, enough teams have asked the same question that we knew we had to do something about it: <strong>can we replicate the data to ClickHouse?</strong></p>
<p>Most teams asking were building on DEXes, or DeFi protocols where data volumes are large enough that even a well-tuned Postgres query to do analytics starts to slow down. That is exactly the workload ClickHouse is built for. So in HyperIndex V3, we shipped experimental ClickHouse Storage support.</p>
<p>V3 is in alpha at the time of writing, and ClickHouse Storage is flagged as experimental. Both will be marked stable once V3 reaches its stable launch, at which point you can use ClickHouse Storage in production without the experimental label. If you want to try ClickHouse on Envio Cloud today, <a href="https://forms.gle/P19S7KXYfdHQM8J69" target="_blank" rel="noopener noreferrer"><strong>fill out this form</strong></a>, it is currently supported only on the Dedicated Plan.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-clickhouse">What is ClickHouse?<a class="hash-link" aria-label="Direct link to What is ClickHouse?" title="Direct link to What is ClickHouse?" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#what-is-clickhouse">​</a></h2>
<p>ClickHouse is a <strong>columnar database</strong> designed for analytical workloads. Most transactional databases, including Postgres, store data row by row, which is fast when you are reading or writing a single record by its primary key but slow when you are scanning millions of rows to compute an aggregate. A columnar database flips that around, values for each column are stored together on disk, so aggregations across billions of rows finish in seconds instead of minutes.</p>
<p>This matters a lot for blockchain data. For example, just USDC on Ethereum has hundreds of millions of <strong><code>Transfer</code></strong> events. Add in every other chain USDC is deployed on, and you cross into the billions. Now imagine you want to group those transfers by sender, bucket them by hour, and compute the sum per chain. A row store will struggle no matter how many indexes you throw at it. A columnar engine was built for exactly that kind of query.</p>
<p>Onchain data has three properties that make it a near-perfect match for ClickHouse:</p>
<ul>
<li><strong>Append-heavy</strong> - once an event is emitted, it rarely changes.</li>
<li><strong>Highly structured</strong> - every event of the same type has the same shape.</li>
<li><strong>Queried in aggregate</strong> - most analytics questions are counts, sums, averages, or time-bucketed views, not single-row lookups.</li>
</ul>
<p>If your indexer is powering a dashboard, a leaderboard, historical charts, or any kind of reporting layer on top of a large dataset, ClickHouse is the right tool for that read path. Postgres is still great for your day-to-day indexer writes and GraphQL reads, ClickHouse Storage just gives you a second surface that is optimised for the analytical side.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-clickhouse-storage-works-in-hyperindex">How ClickHouse Storage Works in HyperIndex<a class="hash-link" aria-label="Direct link to How ClickHouse Storage Works in HyperIndex" title="Direct link to How ClickHouse Storage Works in HyperIndex" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#how-clickhouse-storage-works-in-hyperindex">​</a></h2>
<p>HyperIndex runs two storage layers in parallel. Postgres remains the primary indexed state that your app queries through GraphQL. ClickHouse is a purpose-built analytics mirror, not a fallback. On every batch, events parsed by your handlers are flushed to both: Postgres gets the current state, ClickHouse gets the history.</p>
<p>ClickHouse Storage writes two things:</p>
<ul>
<li><strong>Entity history tables</strong> - every change to every entity as an <strong><code>INSERT</code></strong>, tagged with a <strong><code>SET</code></strong> or <strong><code>DELETE</code></strong> action and a checkpoint ID linking it to a specific block. ClickHouse never receives an <strong><code>UPDATE</code></strong>, it is optimised for inserts, not mutation.</li>
<li><strong>Checkpoints table</strong> - one row per processed block with block number, block hash, chain ID, and event count.</li>
</ul>
<p>"Current state" is served by <strong>views</strong> that sit on top of the history table and select the latest <strong>SET</strong> row per entity ID. You get a full audit trail for free, and you can query state at any past block just by filtering on checkpoint ID.</p>
<p>Reorgs are handled by a single <strong><code>DELETE</code></strong> per table that removes all rows above the reorg checkpoint, the append only model makes rollbacks trivial, with no partial state to unwind. Schemas are auto-created on startup from your <strong><code>schema.graphql</code></strong>, with type mappings handled for you (<code>BigInt</code> → <code>Decimal</code>, <code>Date</code> → <code>DateTime64</code>, <code>enums</code> → <code>Enum8</code>/<code>Enum16</code>, and so on). No DDL to write.</p>
<p>Both backends are <strong>restart- and reorg-resistant</strong>, the checkpoints table lets the indexer resume cleanly after a crash, and Prometheus metrics carry a <strong><code>storage-name</code></strong> label so you can monitor Postgres and ClickHouse write paths separately.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Note</div><div class="admonitionContent_BuS1"><p>During historical backfill, ClickHouse Storage does not store every intermediate entity change. If an entity is modified multiple times within a single batch, only the final state of that batch is written to ClickHouse. Once the indexer reaches the head and is processing live, every change is captured.</p></div></div>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Warning</div><div class="admonitionContent_BuS1"><p>Do not run multiple indexers writing to the same ClickHouse database at the same time.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-to-enable-clickhouse-on-envio-cloud"><strong>How to Enable ClickHouse on Envio Cloud</strong><a class="hash-link" aria-label="Direct link to how-to-enable-clickhouse-on-envio-cloud" title="Direct link to how-to-enable-clickhouse-on-envio-cloud" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#how-to-enable-clickhouse-on-envio-cloud">​</a></h2>
<p>To scaffold a new V3 alpha indexer, run:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio init</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This will set up a fresh project on the latest alpha release. Enable both storage backends in <code>config.yaml</code>:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token key atrule">storage</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">postgres</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean important">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token key atrule">clickhouse</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token boolean important">true</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>ClickHouse connection is configured via four environment variables, set them in your <code>.env</code> file for local development (<code>envio dev</code> will spin up a ClickHouse Docker container alongside), or from the Envio Cloud dashboard for hosted deployments:</p>
<table><thead><tr><th>Variable</th><th>Description</th></tr></thead><tbody><tr><td><code>ENVIO_CLICKHOUSE_HOST</code></td><td>The host of your ClickHouse instance.</td></tr><tr><td><code>ENVIO_CLICKHOUSE_DATABASE</code></td><td>The ClickHouse database to write into.</td></tr><tr><td><code>ENVIO_CLICKHOUSE_USERNAME</code></td><td>Username for the ClickHouse connection.</td></tr><tr><td><code>ENVIO_CLICKHOUSE_PASSWORD</code></td><td>Password for the ClickHouse connection.</td></tr></tbody></table>
<p>Once those are set, HyperIndex will replicate the same entity data it writes to Postgres into your ClickHouse database. Every entity in your <code>schema.graphql</code> becomes a ClickHouse table with a matching schema, so you can point your analytics queries, BI tools, or dashboards directly at ClickHouse, no extra ETL pipeline needed.</p>
<p>Postgres and GraphQL keep working exactly as they do today. ClickHouse Storage is additive: you get a second read-optimised surface without giving up the one you already have.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="who-can-use-clickhouse-storage">Who Can Use ClickHouse Storage?<a class="hash-link" aria-label="Direct link to Who Can Use ClickHouse Storage?" title="Direct link to Who Can Use ClickHouse Storage?" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#who-can-use-clickhouse-storage">​</a></h2>
<p>Right now, ClickHouse Storage is available on the <strong>Dedicated Plan</strong>, and you need to bring your own ClickHouse instance. If you are already running ClickHouse (or you are comfortable standing one up), you can plug it into your indexer today using the environment variables above.</p>
<p>We are also working on a managed ClickHouse offering on Envio Cloud so teams won't have to run their own instance. If you want to be one of the first users when that rolls out, <a href="https://forms.gle/P19S7KXYfdHQM8J69" target="_blank" rel="noopener noreferrer"><strong>fill out this form</strong></a>. Tell us a bit about your indexer and the kind of analytics you are trying to run and we will get you onboarded.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started"><strong>Get Started</strong><a class="hash-link" aria-label="Direct link to get-started" title="Direct link to get-started" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#get-started">​</a></h2>
<p>ClickHouse Storage is available today on the Dedicated Plan for teams running their own ClickHouse instance. For teams that want managed ClickHouse on Envio Cloud, fill out the waitlist form to be one of the first users when it rolls out.</p>
<ul>
<li>Envio docs: <a href="https://docs.envio.dev/" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/</a></li>
<li>HyperIndex V3 migration guide: <a href="https://docs.envio.dev/docs/HyperIndex/migrate-to-v3" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperIndex/migrate-to-v3</a></li>
<li>Managed ClickHouse waitlist: <a href="https://forms.gle/P19S7KXYfdHQM8J69" target="_blank" rel="noopener noreferrer">https://forms.gle/P19S7KXYfdHQM8J69</a></li>
<li>Discord: <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">https://discord.gg/envio</a></li>
<li>Telegram: <a href="https://t.me/+kAIGElzPjApiMjI0" target="_blank" rel="noopener noreferrer">https://t.me/+kAIGElzPjApiMjI0</a></li>
<li>Follow us on X: <a href="https://x.com/envio_indexer" target="_blank" rel="noopener noreferrer">https://x.com/envio_indexer</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions"><strong>Frequently Asked Questions</strong><a class="hash-link" aria-label="Direct link to frequently-asked-questions" title="Direct link to frequently-asked-questions" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="clickhouse-vs-postgres-when-should-i-use-which">ClickHouse vs Postgres: When Should I Use Which?<a class="hash-link" aria-label="Direct link to ClickHouse vs Postgres: When Should I Use Which?" title="Direct link to ClickHouse vs Postgres: When Should I Use Which?" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#clickhouse-vs-postgres-when-should-i-use-which">​</a></h3>
<p>Use Postgres for transactional reads, your GraphQL API, single-entity lookups, and anything latency-sensitive that your application serves directly to users. Use ClickHouse for analytical queries: large aggregations, time-bucketed views, leaderboards, historical charts, and BI dashboards. The rule of thumb is that if a query scans millions of rows to compute a result, it belongs on ClickHouse. If a query fetches a specific record by ID, it belongs on Postgres.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="can-i-use-bi-tools-like-metabase-superset-or-grafana-with-clickhouse-storage">Can I Use BI Tools Like Metabase, Superset, or Grafana With ClickHouse Storage?<a class="hash-link" aria-label="Direct link to Can I Use BI Tools Like Metabase, Superset, or Grafana With ClickHouse Storage?" title="Direct link to Can I Use BI Tools Like Metabase, Superset, or Grafana With ClickHouse Storage?" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#can-i-use-bi-tools-like-metabase-superset-or-grafana-with-clickhouse-storage">​</a></h3>
<p>Yes. Once ClickHouse Storage is running, your ClickHouse database is a standard ClickHouse instance as far as any external tool is concerned. Any tool with a ClickHouse connector (Metabase, Superset, Grafana, Tableau, Hex, Redash, and most others) can connect directly. Point it at the same host, database, and credentials you configured on Envio Cloud.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="does-clickhouse-storage-slow-down-my-indexer">Does ClickHouse Storage Slow Down My Indexer?<a class="hash-link" aria-label="Direct link to Does ClickHouse Storage Slow Down My Indexer?" title="Direct link to Does ClickHouse Storage Slow Down My Indexer?" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#does-clickhouse-storage-slow-down-my-indexer">​</a></h3>
<p>ClickHouse Storage writes in the same batches HyperIndex uses for Postgres, so there is some additional write work per batch. In practice, ClickHouse inserts are designed to be fast and writes are batched, so the overhead is small for most workloads. If you are seeing lag, the usual culprit is your ClickHouse instance's write capacity or network latency between the indexer and ClickHouse, not HyperIndex itself.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-query-past-state-in-clickhouse">How Do I Query Past State in ClickHouse?<a class="hash-link" aria-label="Direct link to How Do I Query Past State in ClickHouse?" title="Direct link to How Do I Query Past State in ClickHouse?" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#how-do-i-query-past-state-in-clickhouse">​</a></h3>
<p>Because the history tables store every change with a checkpoint ID tied to a specific block, you can reconstruct state at any historical point by filtering on checkpoint ID. This gives you time-travel queries for free, without needing snapshots or a separate archive. The latest-state views handle the "current state" case automatically, so you only reach for checkpoint filtering when you specifically want a past view.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="can-i-add-custom-tables-or-indexes-to-my-clickhouse-database">Can I Add Custom Tables or Indexes to My ClickHouse Database?<a class="hash-link" aria-label="Direct link to Can I Add Custom Tables or Indexes to My ClickHouse Database?" title="Direct link to Can I Add Custom Tables or Indexes to My ClickHouse Database?" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#can-i-add-custom-tables-or-indexes-to-my-clickhouse-database">​</a></h3>
<p>ClickHouse Storage manages its own tables based on your <code>schema.graphql</code> and will create them on startup. You can add your own tables, materialised views, or downstream aggregations in the same database alongside the managed tables, as long as you don't modify or collide with them. A common pattern is to build materialised views on top of the history tables to pre-aggregate heavy queries.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-happens-if-my-clickhouse-instance-goes-down">What Happens If My ClickHouse Instance Goes Down?<a class="hash-link" aria-label="Direct link to What Happens If My ClickHouse Instance Goes Down?" title="Direct link to What Happens If My ClickHouse Instance Goes Down?" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#what-happens-if-my-clickhouse-instance-goes-down">​</a></h3>
<p>Postgres and your GraphQL API keep serving as normal. ClickHouse Storage is additive, so a ClickHouse outage does not stop your indexer from processing events or serving queries from Postgres. Once ClickHouse is back, replication resumes from where it left off using the checkpoints table.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="is-there-a-cost-difference-between-running-with-and-without-clickhouse-storage">Is There a Cost Difference Between Running With and Without ClickHouse Storage?<a class="hash-link" aria-label="Direct link to Is There a Cost Difference Between Running With and Without ClickHouse Storage?" title="Direct link to Is There a Cost Difference Between Running With and Without ClickHouse Storage?" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#is-there-a-cost-difference-between-running-with-and-without-clickhouse-storage">​</a></h3>
<p>On Envio Cloud, ClickHouse Storage itself is available on the Dedicated Plan. The main cost consideration is your ClickHouse instance, you are bringing your own, so storage, compute, and egress costs depend on your provider (ClickHouse Cloud, self-hosted, Altinity, etc.) and the size of your dataset. Entity history tables grow faster than Postgres state tables because every change is stored rather than just the current value.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="why-did-envio-build-this-instead-of-just-recommending-an-etl-pipeline">Why Did Envio Build This Instead of Just Recommending an ETL Pipeline?<a class="hash-link" aria-label="Direct link to Why Did Envio Build This Instead of Just Recommending an ETL Pipeline?" title="Direct link to Why Did Envio Build This Instead of Just Recommending an ETL Pipeline?" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#why-did-envio-build-this-instead-of-just-recommending-an-etl-pipeline">​</a></h3>
<p>Running a separate ETL pipeline (CDC from Postgres to ClickHouse, a Kafka connector, a custom script) adds another system to maintain, another place for data to drift, and another source of lag. Building ClickHouse Storage into HyperIndex means entity data lands in ClickHouse as part of the same batch that writes to Postgres, with reorg handling and schema management already solved. One indexer, two read surfaces, no extra pipeline.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/clickhouse-storage-hyperindex-v3#build-with-envio">​</a></h2>
<p>Envio is the fastest independently benchmarked EVM blockchain indexer for querying real-time and historical data. If you are building onchain and need indexing that keeps up with your chain, plus analytics that keep up with your indexer, check out the <a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">docs</a>, run the benchmarks yourself, and come talk to us about your data needs.</p>
<p>Stay tuned for more updates by subscribing to our newsletter, following us on X, or hopping into our Discord.</p>
<p><a href="https://envio.beehiiv.com/subscribe" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a> 💌</p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.com/invite/gt7yEUZKeB" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a></p>]]></content:encoded>
            <category>tutorials</category>
        </item>
        <item>
            <title><![CDATA[How to Track Native ETH Transfers Using Envio's HyperSync]]></title>
            <link>https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync</link>
            <guid>https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync</guid>
            <pubDate>Fri, 24 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Native ETH transfers don't emit event logs, so tracking them over RPC means slow trace calls. This guide shows how to stream native transfers efficiently using HyperSync's trace filtering with the Node.js client in a Bun project.]]></description>
            <content:encoded><![CDATA[<p><img decoding="async" loading="lazy" alt="Envio blog cover with title &amp;quot;Tracking Native ETH Transfers Using HyperSync&amp;quot; and a network of linked Ethereum nodes" src="https://docs.envio.dev/assets/images/tracking-native-eth-transfers-hypersync-c82b046e0f79cdcb9b7c63a6a5ed7305.png" width="1600" height="936" class="img_ev3q"></p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>Tracking native ETH transfers onchain requires parsing traces rather than event logs, which is slow over standard RPC.</li>
<li>HyperSync exposes trace filtering directly, letting you stream native transfers by filtering on <code>call_type=call</code> with a value threshold.</li>
<li>Full working example uses the Node.js client in a Bun project, streaming results until 10 transfers above 0.005 ETH are collected.</li>
<li>Trace support is available on Ethereum, Base, Arbitrum, Gnosis, and Monad.</li>
</ul></div></div>
<p>Tracking native token transfers onchain is trickier than ERC-20 transfers. There's no event log to index, so you have to dig through traces. With a standard RPC node, that means calling eth_traceBlock and iterating every trace in every block, which is slow.
HyperSync gives you a faster alternative: a data retrieval layer with native trace filtering.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#prerequisites">​</a></h2>
<p>We are going to use <a href="https://bun.com/docs/installation" target="_blank" rel="noopener noreferrer">Bun</a> for this article, so make sure you have it installed. If you want to use another runtime that supports TypeScript, you can do that too.</p>
<p>You will also need an Envio API token to access HyperSync. If you don't have one, go to <a href="https://envio.dev/app/api-tokens" target="_blank" rel="noopener noreferrer">envio.dev/app/api-tokens</a> to create one. Step-by-step instructions are at <a href="https://docs.envio.dev/docs/HyperSync/api-tokens#generating-api-tokens" target="_blank" rel="noopener noreferrer">docs.envio.dev/docs/HyperSync/api-tokens</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="hypersync--queries">HyperSync &amp; Queries<a class="hash-link" aria-label="Direct link to HyperSync &amp; Queries" title="Direct link to HyperSync &amp; Queries" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#hypersync--queries">​</a></h2>
<p>HyperSync is optimized for data retrieval, not consensus, so it's far faster than RPC nodes. To fetch data, you send a query describing what you want and HyperSync returns only that data.</p>
<p>A typical query looks like this:</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"fromBlock"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"transactions"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token property">"from"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"0x5a830d7a5149b2f1a2e72d15cd51b84379ee81e5"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token property">"to"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"0x5a830d7a5149b2f1a2e72d15cd51b84379ee81e5"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"fieldSelection"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"transaction"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"BlockNumber"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Hash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"From"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"To"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Value"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Every query has three main parts: <code>fromBlock</code>, a filter section (one of <code>transactions</code>, <code>blocks</code>, <code>logs</code>, or <code>traces</code>), and <code>fieldSelection</code>. See the <a href="https://docs.envio.dev/docs/HyperSync/hypersync-query#query-structure-reference" target="_blank" rel="noopener noreferrer">full query reference</a> for all available options.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="filtering-for-native-transfers">Filtering for Native Transfers<a class="hash-link" aria-label="Direct link to Filtering for Native Transfers" title="Direct link to Filtering for Native Transfers" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#filtering-for-native-transfers">​</a></h3>
<p>Native ETH transfers occur only in traces where <code>call_type</code> is <code>call</code>, not <code>staticcall</code> or <code>delegatecall</code>. Filtering on <code>callType</code> directly is more efficient than filtering on trace <code>kind</code>, since it lets HyperSync skip irrelevant trace types upfront.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="building-the-fetcher">Building the Fetcher<a class="hash-link" aria-label="Direct link to Building the Fetcher" title="Direct link to Building the Fetcher" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#building-the-fetcher">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="setup">Setup<a class="hash-link" aria-label="Direct link to Setup" title="Direct link to Setup" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#setup">​</a></h3>
<p>Create a new Bun project and install the HyperSync client:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bun init </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-y</span><span class="token plain"> </span><span class="token operator">&amp;&amp;</span><span class="token plain"> bun </span><span class="token function" style="color:rgb(80, 250, 123)">install</span><span class="token plain"> @envio-dev/hypersync-client</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Add your API token to a <code>.env</code> file. If you don't have one, generate it at <a href="https://envio.dev/app/api-tokens" target="_blank" rel="noopener noreferrer">envio.dev/app/api-tokens</a>.</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token assign-left variable" style="color:rgb(189, 147, 249);font-style:italic">ENVIO_API_TOKEN</span><span class="token operator">=</span><span class="token plain">your_token_here</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p><strong>Note:</strong> HyperSync trace support is currently available on Ethereum, Base, Arbitrum, Gnosis, and Monad. <a href="mailto:nikhil@envio.dev" target="_blank" rel="noopener noreferrer">Reach out</a> if you need trace support for other chains.</p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="imports--helpers">Imports &amp; Helpers<a class="hash-link" aria-label="Direct link to Imports &amp; Helpers" title="Direct link to Imports &amp; Helpers" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#imports--helpers">​</a></h3>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">TraceField</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@envio-dev/hypersync-client"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>We'll filter out dust transfers using a minimum threshold and format values as human-readable ETH:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">THRESHOLD_WEI</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">BigInt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"5000000000000000"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// 0.005 ETH</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">WEI_PER_ETH</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">BigInt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"1000000000000000000"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// 1 ETH</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">DECIMALS</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">6</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">weiToEth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">wei</span><span class="token operator">:</span><span class="token plain"> bigint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> whole </span><span class="token operator">=</span><span class="token plain"> wei </span><span class="token operator">/</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">WEI_PER_ETH</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> remainder </span><span class="token operator">=</span><span class="token plain"> wei </span><span class="token operator">%</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">WEI_PER_ETH</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> remainderStr </span><span class="token operator">=</span><span class="token plain"> remainder</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">padStart</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">18</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">slice</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">DECIMALS</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">whole</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">.</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">remainderStr</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="creating-the-client">Creating the Client<a class="hash-link" aria-label="Direct link to Creating the Client" title="Direct link to Creating the Client" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#creating-the-client">​</a></h3>
<p>Use the Ethereum traces endpoint:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> client </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  url</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://eth-traces.hypersync.xyz"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  apiToken</span><span class="token operator">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">ENVIO_API_TOKEN</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="query">Query<a class="hash-link" aria-label="Direct link to Query" title="Direct link to Query" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#query">​</a></h3>
<p>Request only <code>call</code> type traces and select the fields we care about:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> query </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  fromBlock</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">22000000</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  traces</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      callType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"call"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  fieldSelection</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    trace</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"From"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"To"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Value"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"CallType"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"BlockNumber"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> TraceField</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="streaming-results">Streaming Results<a class="hash-link" aria-label="Direct link to Streaming Results" title="Direct link to Streaming Results" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#streaming-results">​</a></h3>
<p>HyperSync offers two fetch modes: <code>get</code> (single response) and <code>stream</code> (continuous). We'll stream and stop once we've collected 10 transfers above the threshold:</p>
<div class="language-ts codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-ts codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Fetching native transfers (call_type=call, value &gt; 0.005 ETH)...\n"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> results</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> from</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> to</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> valueEth</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> stream </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">stream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">outer</span><span class="token operator">:</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">while</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> res </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> stream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">recv</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">res </span><span class="token operator">===</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">break</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// stream exhausted</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">data</span><span class="token operator">?.</span><span class="token plain">traces</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> trace </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">of</span><span class="token plain"> res</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">data</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">traces</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">trace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value </span><span class="token operator">===</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">undefined</span><span class="token plain"> </span><span class="token operator">||</span><span class="token plain"> trace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value </span><span class="token operator">===</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">continue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">trace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value </span><span class="token operator">&lt;=</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">THRESHOLD_WEI</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">continue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      results</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">push</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        from</span><span class="token operator">:</span><span class="token plain"> trace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"unknown"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        to</span><span class="token operator">:</span><span class="token plain"> trace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to </span><span class="token operator">??</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"unknown"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        valueEth</span><span class="token operator">:</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">weiToEth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">trace</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">value</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">results</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">length </span><span class="token operator">&gt;=</span><span class="token plain"> </span><span class="token number">10</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">break</span><span class="token plain"> outer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> stream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">close</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">results</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">length </span><span class="token operator">===</span><span class="token plain"> </span><span class="token number">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"No results found."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">table</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    results</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">map</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      From</span><span class="token operator">:</span><span class="token plain"> r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      To</span><span class="token operator">:</span><span class="token plain"> r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token string-property property">"Value (ETH)"</span><span class="token operator">:</span><span class="token plain"> r</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">valueEth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Run it with:</p>
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">bun run index.ts</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><img decoding="async" loading="lazy" alt="Terminal output from bun run index.ts showing a table of 10 native ETH transfers with From, To, and Value (ETH) columns" src="https://docs.envio.dev/assets/images/native-transfers-cli-output-eeca422b5c46c70a27b11be8f7bf5cef.png" width="880" height="318" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps">Next Steps<a class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#next-steps">​</a></h2>
<p>We only used callType as a filter here. From this starting point you can track a specific wallet by adding from or to address filters to the trace selection, narrow further using other TraceSelection fields like sighash or kind, or switch the endpoint to another HyperSync trace-enabled network to run the same query across chains.</p>
<p>See the HyperSync query reference for the full TraceSelection schema and field list.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-hypersyncs-traces-query">What Is HyperSync's Traces Query?<a class="hash-link" aria-label="Direct link to What Is HyperSync's Traces Query?" title="Direct link to What Is HyperSync's Traces Query?" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#what-is-hypersyncs-traces-query">​</a></h3>
<p><a href="https://docs.envio.dev/docs/HyperSync/overview" target="_blank" rel="noopener noreferrer">HyperSync</a>'s traces query exposes EVM execution traces (<code>call</code>, <code>create</code>, <code>suicide</code>, <code>reward</code>) directly, rather than just contract event logs. This makes it possible to track operations that don't emit events, like native ETH transfers, by filtering on <code>call_type</code> and <code>value</code>. The traces feature is currently available on Ethereum, Base, Arbitrum, Gnosis, and Monad. Other queries (logs, transactions, blocks) work across <!-- -->85+<!-- --> EVM chains with client libraries for Python, Rust, Node.js, and Go.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="why-cant-i-track-native-eth-transfers-using-event-logs">Why Can't I Track Native ETH Transfers Using Event Logs?<a class="hash-link" aria-label="Direct link to Why Can't I Track Native ETH Transfers Using Event Logs?" title="Direct link to Why Can't I Track Native ETH Transfers Using Event Logs?" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#why-cant-i-track-native-eth-transfers-using-event-logs">​</a></h3>
<p>Native ETH transfers don't emit events. The ERC-20 <code>Transfer</code> event is a standard contract event, but native ETH moves at the protocol level and only shows up in transaction traces. To track them, you have to query traces directly.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="whats-the-difference-between-call_type-and-kind-when-filtering-traces">What's the Difference Between <code>call_type</code> and <code>kind</code> When Filtering Traces?<a class="hash-link" aria-label="Direct link to whats-the-difference-between-call_type-and-kind-when-filtering-traces" title="Direct link to whats-the-difference-between-call_type-and-kind-when-filtering-traces" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#whats-the-difference-between-call_type-and-kind-when-filtering-traces">​</a></h3>
<p><code>kind</code> is the trace type (<code>call</code>, <code>create</code>, <code>suicide</code>, <code>reward</code>). <code>call_type</code> is the sub-type of a call trace (<code>call</code>, <code>delegatecall</code>, <code>staticcall</code>). Native ETH transfers only occur when <code>call_type</code> is <code>call</code>, so filtering on <code>call_type</code> directly is more efficient than filtering on <code>kind</code> and then narrowing down.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="which-chains-support-trace-queries-on-hypersync">Which Chains Support Trace Queries on HyperSync?<a class="hash-link" aria-label="Direct link to Which Chains Support Trace Queries on HyperSync?" title="Direct link to Which Chains Support Trace Queries on HyperSync?" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#which-chains-support-trace-queries-on-hypersync">​</a></h3>
<p>Trace support is currently available on Ethereum, Base, Arbitrum, Gnosis, and Monad. If you need trace support on another chain, reach out at <a href="mailto:nikhil@envio.dev" target="_blank" rel="noopener noreferrer">nikhil@envio.dev</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-fast-is-hypersync-compared-to-rpc-for-trace-queries">How Fast Is HyperSync Compared to RPC for Trace Queries?<a class="hash-link" aria-label="Direct link to How Fast Is HyperSync Compared to RPC for Trace Queries?" title="Direct link to How Fast Is HyperSync Compared to RPC for Trace Queries?" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#how-fast-is-hypersync-compared-to-rpc-for-trace-queries">​</a></h3>
<p>HyperSync is up to 2000x faster than standard JSON-RPC for data retrieval workloads. For trace queries specifically, the gap is even wider since RPC trace methods like <code>eth_traceBlock</code> are among the slowest calls on most nodes.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="can-i-use-this-approach-for-erc-20-transfers-too">Can I Use This Approach for ERC-20 Transfers Too?<a class="hash-link" aria-label="Direct link to Can I Use This Approach for ERC-20 Transfers Too?" title="Direct link to Can I Use This Approach for ERC-20 Transfers Too?" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#can-i-use-this-approach-for-erc-20-transfers-too">​</a></h3>
<p>Yes, but for ERC-20 you'd query logs instead of traces since ERC-20 contracts emit a <code>Transfer</code> event. Use the <code>logs</code> filter with the Transfer event signature as <code>topic0</code>. See the <a href="https://docs.envio.dev/docs/HyperSync/hypersync-query" target="_blank" rel="noopener noreferrer">HyperSync query reference</a> for details.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/tracking-native-eth-transfers-hypersync#build-with-envio">​</a></h2>
<p>Envio HyperIndex is independently benchmarked as the fastest EVM blockchain indexer available. If you are building onchain and need indexing that keeps up with your chain, check out the <a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">docs</a>, run the benchmarks yourself, or come talk to us about your data needs.
Stay tuned for more updates by subscribing to our newsletter, following us on X, or hopping into our Discord.
<a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a> 💌</p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.com/invite/gt7yEUZKeB" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>tutorials</category>
        </item>
        <item>
            <title><![CDATA[Introducing the Envio Docs MCP Server]]></title>
            <link>https://docs.envio.dev/blog/envio-docs-mcp-server</link>
            <guid>https://docs.envio.dev/blog/envio-docs-mcp-server</guid>
            <pubDate>Tue, 14 Apr 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Envio's documentation is now available as an MCP server. Connect Claude Code, Cursor, or any MCP-compatible assistant for always up-to-date Envio context.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/envio-docs-mcp-server.png" alt="Introducing the Envio Docs MCP Server" width="100%">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>Envio's documentation is now directly accessible to your AI coding assistant via MCP.</li>
<li>Connect Claude Code, Cursor, Copilot, or any MCP-compatible client in one step.</li>
<li>Your assistant searches and fetches live Envio docs on demand, no copy-pasting required.</li>
<li>Envio Docs MCP quicklink: <a href="https://docs.envio.dev/docs/HyperIndex/mcp-server" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperIndex/mcp-server</a></li>
</ul></div></div>
<p>Envio now has a hosted MCP server for its documentation. Point your AI coding assistant at it and it can search and read Envio docs on demand. No more copy-pasting links into chat and no more watching your model confidently invent a config field that does not exist.</p>
<p>Whether you are building an indexer, querying onchain data with HyperSync, or just exploring what Envio can do, the MCP server gives your agent a direct line to the real documentation while it works.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-an-mcp-server">What is an MCP server?<a class="hash-link" aria-label="Direct link to What is an MCP server?" title="Direct link to What is an MCP server?" href="https://docs.envio.dev/blog/envio-docs-mcp-server#what-is-an-mcp-server">​</a></h2>
<p>Model Context Protocol (MCP) is an open standard for connecting AI assistants to external tools and data sources. An MCP server exposes a set of capabilities, like searching a knowledge base, fetching a document, or calling an API, that any MCP-compatible client can call on demand.</p>
<p>In practice, this means you can give your AI assistant a stable, structured way to reach into a real system, instead of relying on whatever happened to be in its training data or fumbling around the web trying to find something relevant.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-the-envio-docs-mcp-server">What is the Envio Docs MCP Server?<a class="hash-link" aria-label="Direct link to What is the Envio Docs MCP Server?" title="Direct link to What is the Envio Docs MCP Server?" href="https://docs.envio.dev/blog/envio-docs-mcp-server#what-is-the-envio-docs-mcp-server">​</a></h2>
<p>The Envio Docs MCP server is a hosted MCP server that gives AI coding assistants direct access to Envio's documentation. It exposes two tools:</p>
<table><thead><tr><th>Tool</th><th>Description</th></tr></thead><tbody><tr><td><code>docs_search</code></td><td>Full-text search across all Envio documentation. Returns matching pages with titles, URLs, and content snippets.</td></tr><tr><td><code>docs_fetch</code></td><td>Retrieves the full content of a documentation page as markdown.</td></tr></tbody></table>
<p>The server is hosted at:
<a href="https://docs.envio.dev/mcp" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/mcp</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-this-matters-for-envio-users">Why this matters for Envio users<a class="hash-link" aria-label="Direct link to Why this matters for Envio users" title="Direct link to Why this matters for Envio users" href="https://docs.envio.dev/blog/envio-docs-mcp-server#why-this-matters-for-envio-users">​</a></h2>
<p>Without an MCP server, an AI assistant trying to use Envio docs is mostly working blind. It either falls back on whatever it remembers from training, or hops between links and fetches raw HTML pages to parse out the parts it needs. That is slow, noisy, and easy to get wrong: the model ends up sifting through navigation, sidebars, and styling just to find a single config option.</p>
<p>The Envio Docs MCP server replaces that with a structured way for your assistant to ask the docs a question directly. Instead of scraping pages, it can search across all of Envio's documentation and pull back exactly the content it needs.</p>
<p>That means:</p>
<ul>
<li><strong>Always up to date.</strong> The MCP server reads from the same docs site you read. When the docs change, your assistant sees the change immediately.</li>
<li><strong>Grounded in source docs.</strong> Your agent looks up the exact answer in the documentation instead of guessing.</li>
<li><strong>Less copy-paste.</strong> No more shuttling doc snippets back and forth between your browser and your editor.</li>
<li><strong>Useful across the whole stack.</strong> Whether you are building an indexer, pulling onchain data with HyperSync, or exploring Envio Cloud, your assistant has the right context for the job.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-to-connect-it">How to connect it<a class="hash-link" aria-label="Direct link to How to connect it" title="Direct link to How to connect it" href="https://docs.envio.dev/blog/envio-docs-mcp-server#how-to-connect-it">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="claude-code">Claude Code<a class="hash-link" aria-label="Direct link to Claude Code" title="Direct link to Claude Code" href="https://docs.envio.dev/blog/envio-docs-mcp-server#claude-code">​</a></h3>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">claude mcp </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">--transport</span><span class="token plain"> http envio-docs https://docs.envio.dev/mcp</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="cursor--vs-code">Cursor / VS Code<a class="hash-link" aria-label="Direct link to Cursor / VS Code" title="Direct link to Cursor / VS Code" href="https://docs.envio.dev/blog/envio-docs-mcp-server#cursor--vs-code">​</a></h3>
<p>Add the following to your MCP configuration (<code>.cursor/mcp.json</code> or your VS Code MCP settings):</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token property">"mcpServers"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token property">"envio-docs"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token property">"url"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://docs.envio.dev/mcp"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="other-mcp-clients">Other MCP clients<a class="hash-link" aria-label="Direct link to Other MCP clients" title="Direct link to Other MCP clients" href="https://docs.envio.dev/blog/envio-docs-mcp-server#other-mcp-clients">​</a></h3>
<p>Point any MCP-compatible client to <code>https://docs.envio.dev/mcp</code> using the Streamable HTTP transport.</p>
<p>For full, always-current setup instructions, see the Envio Docs MCP Server guide.</p>
<p>Once connected, your assistant can search the docs and pull back full pages whenever it needs context, with no extra prompting from you.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/envio-docs-mcp-server#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-an-mcp-server-1">What Is an MCP Server?<a class="hash-link" aria-label="Direct link to What Is an MCP Server?" title="Direct link to What Is an MCP Server?" href="https://docs.envio.dev/blog/envio-docs-mcp-server#what-is-an-mcp-server-1">​</a></h3>
<p>An MCP server is a server that implements the Model Context Protocol, an open standard for connecting AI assistants to external tools and data sources. It lets AI coding assistants like Claude Code and Cursor access real, structured information on demand rather than relying on training data.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-the-envio-docs-mcp-server-1">What Is the Envio Docs MCP Server?<a class="hash-link" aria-label="Direct link to What Is the Envio Docs MCP Server?" title="Direct link to What Is the Envio Docs MCP Server?" href="https://docs.envio.dev/blog/envio-docs-mcp-server#what-is-the-envio-docs-mcp-server-1">​</a></h3>
<p>The Envio Docs MCP server is a hosted server at <a href="https://docs.envio.dev/mcp" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/mcp</a> that gives AI coding assistants direct access to Envio's documentation. It supports two operations: searching across all docs and fetching the full content of any documentation page.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="which-ai-assistants-does-the-envio-mcp-server-support">Which AI Assistants Does the Envio MCP Server Support?<a class="hash-link" aria-label="Direct link to Which AI Assistants Does the Envio MCP Server Support?" title="Direct link to Which AI Assistants Does the Envio MCP Server Support?" href="https://docs.envio.dev/blog/envio-docs-mcp-server#which-ai-assistants-does-the-envio-mcp-server-support">​</a></h3>
<p>The Envio Docs MCP server works with any MCP-compatible client. Setup instructions are available for Claude Code and Cursor / VS Code. Any other client that supports the Streamable HTTP transport can connect using the endpoint URL directly.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="is-the-envio-mcp-server-always-up-to-date">Is the Envio MCP Server Always Up to Date?<a class="hash-link" aria-label="Direct link to Is the Envio MCP Server Always Up to Date?" title="Direct link to Is the Envio MCP Server Always Up to Date?" href="https://docs.envio.dev/blog/envio-docs-mcp-server#is-the-envio-mcp-server-always-up-to-date">​</a></h3>
<p>Yes. The MCP server reads directly from the live Envio docs site. When documentation is updated, your assistant has access to the latest version immediately.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-get-started-with-envio-hyperindex">How Do I Get Started with Envio HyperIndex?<a class="hash-link" aria-label="Direct link to How Do I Get Started with Envio HyperIndex?" title="Direct link to How Do I Get Started with Envio HyperIndex?" href="https://docs.envio.dev/blog/envio-docs-mcp-server#how-do-i-get-started-with-envio-hyperindex">​</a></h3>
<p>Run <code>pnpx envio init</code> to scaffold your first indexer in minutes. Write event handlers in TypeScript, configure your chains and contracts in <code>config.yaml</code>, and deploy to Envio Cloud for managed hosting. See the <a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">HyperIndex overview</a> and <a href="https://docs.envio.dev/docs/HyperIndex/getting-started" target="_blank" rel="noopener noreferrer">getting started guide</a> for full documentation.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/envio-docs-mcp-server#build-with-envio">​</a></h2>
<p>Envio HyperIndex is independently benchmarked as the fastest EVM blockchain indexer available. If you are building onchain and need indexing that keeps up with your chain, check out the <a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">docs</a>, run the benchmarks yourself, or come talk to us about your data needs.</p>
<p>Stay tuned for more updates by subscribing to our newsletter, following us on X, or hopping into our Discord.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a> 💌</p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>ai</category>
        </item>
        <item>
            <title><![CDATA[How Envio Indexed 4 Billion Polymarket Events]]></title>
            <link>https://docs.envio.dev/blog/polymarket-hyperindex-case-study</link>
            <guid>https://docs.envio.dev/blog/polymarket-hyperindex-case-study</guid>
            <pubDate>Wed, 25 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Envio HyperIndex replaced 8 Polymarket subgraphs with one TypeScript indexer on Polygon, syncing 4 billion events in 6 days. Open source reference included.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/polymarket-hyperindex-case-study.png" alt="Indexing 4 Billion Polymarket Events Using Envio HyperIndex" width="100%">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>Polymarket's 8 independent subgraphs on The Graph were replaced with a single Envio HyperIndex indexer written in TypeScript.</li>
<li>The unified indexer synced over 4,000,000,000 events from block 3,764,531 on Polygon Mainnet in 6 days.</li>
<li>Handler merging processes each shared contract event once, updating all relevant domains simultaneously rather than redundantly across multiple subgraphs.</li>
<li>The full indexer is open source at <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">github.com/enviodev/polymarket-indexer</a>.</li>
</ul></div></div>
<p><a href="https://polymarket.com/" target="_blank" rel="noopener noreferrer">Polymarket</a> is one of the most data-intensive protocols in Web3. Every trade, position, fee, liquidity event, and oracle resolution across its entire prediction market ecosystem lives onchain on Polygon. Querying any of it meaningfully requires a serious blockchain indexer.</p>
<p>For years, Polymarket's data infrastructure relied on 8 independent subgraphs on <a href="https://thegraph.com/" target="_blank" rel="noopener noreferrer">The Graph</a>, each written in AssemblyScript, each tracking a separate domain, all running since 2021. This post documents how all 8 were replaced with a single Envio HyperIndex indexer, syncing over 4,000,000,000 events in 6 days on Polygon Mainnet.</p>
<p>The indexer is fully open source: <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">github.com/enviodev/polymarket-indexer</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="envio-hyperindex-the-fastest-blockchain-indexer-available">Envio HyperIndex: The Fastest Blockchain Indexer Available<a class="hash-link" aria-label="Direct link to Envio HyperIndex: The Fastest Blockchain Indexer Available" title="Direct link to Envio HyperIndex: The Fastest Blockchain Indexer Available" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#envio-hyperindex-the-fastest-blockchain-indexer-available">​</a></h2>
<p>Envio is a real-time multichain blockchain indexing framework for EVM chains. Developers write event handlers in TypeScript and deploy a single indexer that covers multiple contracts, chains, and domains simultaneously.</p>
<p>HyperIndex is independently benchmarked as the fastest blockchain indexer available. In the Uniswap V2 Factory <a href="https://github.com/enviodev/open-indexer-benchmark" target="_blank" rel="noopener noreferrer">benchmark run by Sentio</a> in May 2025, HyperIndex completed in 8 seconds, 142x faster than The Graph and 15x faster than the nearest competitor. In the LBTC benchmark (April 2025), HyperIndex completed in 3 minutes versus 3 hours 9 minutes for The Graph.</p>
<p>This performance comes from <a href="https://docs.envio.dev/docs/HyperSync/overview" target="_blank" rel="noopener noreferrer">HyperSync</a>, Envio's proprietary data engine. Instead of querying RPC endpoints block by block, HyperSync fetches filtered event data in bulk directly from a purpose-built data lake, delivering up to 2,000x faster data access than standard RPC. Polygon is one of <!-- -->85+<!-- --> EVM chains supported with native HyperSync coverage.</p>
<p>See full list of HyperSync supported networks here: <a href="https://docs.envio.dev/docs/HyperSync/hypersync-supported-networks" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperSync/hypersync-supported-networks</a></p>
<table><thead><tr><th>Indexer</th><th>Time (Uniswap V2 Factory benchmark, Sentio May 2025)</th><th>vs HyperIndex</th></tr></thead><tbody><tr><td>Envio HyperIndex</td><td>8 seconds</td><td>baseline</td></tr><tr><td>Subsquid (SQD)</td><td>2 minutes</td><td>15x slower</td></tr><tr><td>The Graph</td><td>19 minutes</td><td>142x slower</td></tr><tr><td>Ponder</td><td>21 minutes</td><td>157x slower</td></tr></tbody></table>
<p>For a full breakdown of how HyperIndex compares across all major blockchain indexers, see the <a href="https://docs.envio.dev/docs/HyperIndex/benchmarks" target="_blank" rel="noopener noreferrer">complete benchmark comparison</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-problem-8-subgraphs-one-protocol-4-years-of-fragmentation">The Problem: 8 Subgraphs, One Protocol, 4 Years of Fragmentation<a class="hash-link" aria-label="Direct link to The Problem: 8 Subgraphs, One Protocol, 4 Years of Fragmentation" title="Direct link to The Problem: 8 Subgraphs, One Protocol, 4 Years of Fragmentation" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#the-problem-8-subgraphs-one-protocol-4-years-of-fragmentation">​</a></h2>
<p>Polymarket's indexing infrastructure grew organically alongside the protocol. By the time the architecture was fully established, 8 independent subgraphs were running in parallel on The Graph:</p>
<table><thead><tr><th>Subgraph</th><th>Domain</th></tr></thead><tbody><tr><td>fee-module</td><td>Fee refunds from FeeModule and NegRiskFeeModule</td></tr><tr><td>sports-oracle</td><td>UMA sports oracle games, markets, and scores</td></tr><tr><td>wallet</td><td>Wallet creation (Gnosis Safe proxies) and USDC balances</td></tr><tr><td>orderbook</td><td>Exchange order fills, matches, per-token and global volume</td></tr><tr><td>open-interest</td><td>Global and per-market open interest via splits, merges, and redemptions</td></tr><tr><td>activity</td><td>Splits, merges, redemptions, and neg-risk conversions</td></tr><tr><td>pnl</td><td>User positions, weighted average cost basis, and realized PnL</td></tr><tr><td>fpmm</td><td>Fixed Product Market Maker analytics: AMM pools, liquidity, and pricing</td></tr></tbody></table>
<p>The core problem with this setup is shared contracts. A single <code>ConditionalTokens</code> event was being listened for and processed independently across 3 or 4 separate subgraphs. Every shared event meant redundant processing, redundant infrastructure, and fragmented data that required joining across multiple APIs at query time. Handlers were written in AssemblyScript, a stricter WebAssembly-compiled subset of TypeScript, adding tooling overhead and limiting what logic could run inside a handler.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-solution-one-hyperindex-indexer-on-polygon">The Solution: One HyperIndex Indexer on Polygon<a class="hash-link" aria-label="Direct link to The Solution: One HyperIndex Indexer on Polygon" title="Direct link to The Solution: One HyperIndex Indexer on Polygon" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#the-solution-one-hyperindex-indexer-on-polygon">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="handler-merging">Handler Merging<a class="hash-link" aria-label="Direct link to Handler Merging" title="Direct link to Handler Merging" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#handler-merging">​</a></h3>
<p>The defining architectural decision in this indexer is handler merging. Rather than running separate listeners per domain for the same contract event, a single handler fires and updates all relevant entities simultaneously.</p>
<p>A <code>ConditionalTokens.PositionSplit</code> event previously triggered separate processing across the open-interest, activity, and pnl subgraphs. In the unified HyperIndex indexer, one handler fires once and simultaneously updates open interest, records the split activity, and adjusts user PnL positions. The event is processed once. That's it.</p>
<p>The full handler structure:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">src/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  handlers/</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">ConditionalTokens.ts       # Open interest + activity + PnL (merged from 4 subgraphs)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Exchange.ts                # Orderbook + PnL</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">NegRiskAdapter.ts          # Open interest + activity + PnL</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">FixedProductMarketMaker.ts # FPMM analytics + PnL + LP tracking</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">FPMMFactory.ts             # Dynamic contract registration</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">FeeModule.ts               # Fee refund tracking</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">UmaSportsOracle.ts         # Sports oracle</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Wallet.ts                  # Wallet creation + USDC balances</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="contracts-indexed">Contracts Indexed<a class="hash-link" aria-label="Direct link to Contracts Indexed" title="Direct link to Contracts Indexed" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#contracts-indexed">​</a></h3>
<p>The indexer covers the full surface area of Polymarket's onchain contracts on Polygon:</p>
<ul>
<li><strong>Exchange + NegRiskExchange</strong>: OrderFilled, OrdersMatched, TokenRegistered</li>
<li><strong>ConditionalTokens</strong>: ConditionPreparation, ConditionResolution, PositionSplit, PositionsMerge, PayoutRedemption</li>
<li><strong>NegRiskAdapter</strong>: MarketPrepared, QuestionPrepared, PositionSplit, PositionsMerge, PayoutRedemption, PositionsConverted</li>
<li><strong>FPMMFactory</strong>: FixedProductMarketMakerCreation, with dynamic contract registration for all FPMM instances</li>
<li><strong>FixedProductMarketMaker (dynamic)</strong>: FPMMBuy, FPMMSell, FPMMFundingAdded, FPMMFundingRemoved, Transfer</li>
<li><strong>FeeModule + NegRiskFeeModule</strong>: FeeRefunded</li>
<li><strong>UmaSportsOracle</strong>: GameCreated, GameSettled, MarketCreated, MarketResolved, and more</li>
<li><strong>USDC / RelayHub / SafeProxyFactory</strong>: Transfer, TransactionRelayed, ProxyCreation</li>
</ul>
<p>Dynamic contract registration is handled through <code>FPMMFactory</code>. As new Fixed Product Market Maker instances are created onchain, the indexer registers them automatically without a redeployment.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="schema-25-entity-types-across-all-domains">Schema: 25+ Entity Types Across All Domains<a class="hash-link" aria-label="Direct link to Schema: 25+ Entity Types Across All Domains" title="Direct link to Schema: 25+ Entity Types Across All Domains" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#schema-25-entity-types-across-all-domains">​</a></h3>
<p>The schema covers every domain previously spread across 8 separate subgraphs, all queryable from a single GraphQL endpoint:</p>
<ul>
<li><strong>Orderbook</strong>: <code>OrderFilledEvent</code>, <code>OrdersMatchedEvent</code>, <code>Orderbook</code>, <code>OrdersMatchedGlobal</code>, <code>MarketData</code></li>
<li><strong>Open Interest</strong>: <code>Condition</code>, <code>MarketOpenInterest</code>, <code>GlobalOpenInterest</code>, <code>NegRiskEvent</code></li>
<li><strong>Activity</strong>: <code>Split</code>, <code>Merge</code>, <code>Redemption</code>, <code>NegRiskConversion</code>, <code>Position</code></li>
<li><strong>PnL</strong>: <code>UserPosition</code>, tracking amount, average price, realized PnL, and total bought per user per token</li>
<li><strong>FPMM</strong>: <code>FixedProductMarketMaker</code>, <code>FpmmTransaction</code>, <code>FpmmFundingAddition</code>, <code>FpmmFundingRemoval</code>, <code>FpmmPoolMembership</code>, <code>Collateral</code></li>
<li><strong>Wallet</strong>: <code>Wallet</code>, <code>GlobalUSDCBalance</code></li>
<li><strong>Fee Module</strong>: <code>FeeRefunded</code></li>
<li><strong>Sports Oracle</strong>: <code>Game</code>, <code>Market</code></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="envio-hyperindex-vs-the-graph-before-and-after">Envio HyperIndex vs The Graph: Before and After<a class="hash-link" aria-label="Direct link to Envio HyperIndex vs The Graph: Before and After" title="Direct link to Envio HyperIndex vs The Graph: Before and After" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#envio-hyperindex-vs-the-graph-before-and-after">​</a></h2>
<table><thead><tr><th></th><th>The Graph (8 subgraphs)</th><th>Envio HyperIndex (1 indexer)</th></tr></thead><tbody><tr><td>Language</td><td>AssemblyScript</td><td>TypeScript</td></tr><tr><td>Subgraphs / indexers</td><td>8</td><td>1</td></tr><tr><td>Event processing</td><td>Redundant across subgraphs</td><td>Once per event, merged handlers</td></tr><tr><td>Cross-domain queries</td><td>Requires joining multiple APIs</td><td>Single GraphQL endpoint</td></tr><tr><td>Deployments to maintain</td><td>8</td><td>1</td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-results">The Results<a class="hash-link" aria-label="Direct link to The Results" title="Direct link to The Results" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#the-results">​</a></h2>
<p>The indexer synced Polymarket's full onchain history on Polygon from block 3,764,531 to 100% sync in 6 days, processing over 4,000,000,000 events. The repo includes 29 tests covering all handler phases, including a HyperSync integration test.</p>
<p>Run it locally with <code>pnpm dev</code> and compare the data with data from Polymarket subgraphs.</p>
<img src="https://docs.envio.dev/blog-assets/polymarket-hyperindex-case-study-1.png" alt="Envio dashboard for the Polymarket indexer showing 4,119,162,600 events processed, 6 days historical sync time, and Polygon Mainnet 100% synced" width="100%">
<p>Live deployment: <a href="https://envio.dev/app/moose-code/polymarket-indexer/7cad3ad" target="_blank" rel="noopener noreferrer">https://envio.dev/app/moose-code/polymarket-indexer/7cad3ad</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-teams-migrate-to-hyperindex-from-the-graph">Why Teams Migrate to HyperIndex from The Graph<a class="hash-link" aria-label="Direct link to Why Teams Migrate to HyperIndex from The Graph" title="Direct link to Why Teams Migrate to HyperIndex from The Graph" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#why-teams-migrate-to-hyperindex-from-the-graph">​</a></h2>
<p>Polymarket's setup before this migration is a pattern that shows up across the ecosystem: multiple subgraphs, shared contracts, AssemblyScript handlers, fragmented data. Here is what changes when teams move to HyperIndex:</p>
<p><strong>Speed.</strong> HyperIndex is 142x faster than The Graph on independent benchmarks. For protocols with years of history like Polymarket, that directly translates to days versus months on historical sync.</p>
<p><strong>TypeScript, not AssemblyScript.</strong> Handlers are standard TypeScript with generated types from both the schema and ABIs. Any npm package works. No WebAssembly compilation. No AssemblyScript-specific constraints.</p>
<p><strong>One codebase.</strong> All domains, all contracts, all chains in a single indexer. One deployment to ship, one codebase to maintain, one endpoint to query.</p>
<p><strong>Single source of truth.</strong> Cross-domain queries happen at the database level, not at the application layer. No joining across APIs at runtime.</p>
<p><strong>Dynamic contract registration.</strong> Factory contracts that create new instances onchain register them automatically, without requiring a redeployment.</p>
<p>Envio offers white-glove migration support for teams moving from The Graph or any other indexer. The Polymarket indexer is an open-source reference for what a large-scale migration looks like end to end.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-polymarket">What is Polymarket?<a class="hash-link" aria-label="Direct link to What is Polymarket?" title="Direct link to What is Polymarket?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#what-is-polymarket">​</a></h3>
<p>Polymarket is the world's largest decentralized prediction market, built on Polygon. Users trade outcome shares on real-world events using USDC. All positions, trades, and settlements are handled entirely onchain via smart contracts with no central custodian.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-many-subgraphs-did-polymarket-use-before-migrating-to-hyperindex">How many subgraphs did Polymarket use before migrating to HyperIndex?<a class="hash-link" aria-label="Direct link to How many subgraphs did Polymarket use before migrating to HyperIndex?" title="Direct link to How many subgraphs did Polymarket use before migrating to HyperIndex?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#how-many-subgraphs-did-polymarket-use-before-migrating-to-hyperindex">​</a></h3>
<p>Polymarket previously ran 8 independent subgraphs on The Graph, each written in AssemblyScript: fee-module, sports-oracle, wallet, orderbook, open-interest, activity, pnl, and fpmm. All 8 were consolidated into a single Envio HyperIndex indexer written in TypeScript.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-did-polymarket-migrate-8-subgraphs-to-hyperindex">How did Polymarket migrate 8 subgraphs to HyperIndex?<a class="hash-link" aria-label="Direct link to How did Polymarket migrate 8 subgraphs to HyperIndex?" title="Direct link to How did Polymarket migrate 8 subgraphs to HyperIndex?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#how-did-polymarket-migrate-8-subgraphs-to-hyperindex">​</a></h3>
<p>The 8 AssemblyScript subgraphs were consolidated into a single TypeScript HyperIndex indexer on Polygon. Because HyperIndex handlers are TypeScript, and AssemblyScript is a subset of TypeScript, most handler logic carried across directly. Envio also provides a <a href="https://docs.envio.dev/docs/HyperIndex/migration-guide" target="_blank" rel="noopener noreferrer">migration guide</a>, a CLI validation tool to compare output between both endpoints, and white-glove migration support.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-handler-merging-in-the-polymarket-indexer">What is handler merging in the Polymarket indexer?<a class="hash-link" aria-label="Direct link to What is handler merging in the Polymarket indexer?" title="Direct link to What is handler merging in the Polymarket indexer?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#what-is-handler-merging-in-the-polymarket-indexer">​</a></h3>
<p>Handler merging lets one handler process a shared contract event once and update all relevant entities simultaneously. A <code>ConditionalTokens.PositionSplit</code> event previously triggered redundant processing across the open-interest, activity, and pnl subgraphs. In the unified HyperIndex indexer, a single handler fires once and updates open interest, records the split activity, and adjusts user PnL positions in one pass.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="which-polymarket-contracts-does-the-open-source-indexer-cover">Which Polymarket contracts does the open-source indexer cover?<a class="hash-link" aria-label="Direct link to Which Polymarket contracts does the open-source indexer cover?" title="Direct link to Which Polymarket contracts does the open-source indexer cover?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#which-polymarket-contracts-does-the-open-source-indexer-cover">​</a></h3>
<p>The indexer covers Exchange and NegRiskExchange, ConditionalTokens, NegRiskAdapter, FPMMFactory, FixedProductMarketMaker (dynamically registered), FeeModule and NegRiskFeeModule, UmaSportsOracle, plus USDC, RelayHub, and SafeProxyFactory. The full handler structure and event list is documented in the post.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="does-hyperindex-support-dynamic-contract-registration">Does HyperIndex support dynamic contract registration?<a class="hash-link" aria-label="Direct link to Does HyperIndex support dynamic contract registration?" title="Direct link to Does HyperIndex support dynamic contract registration?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#does-hyperindex-support-dynamic-contract-registration">​</a></h3>
<p>Yes. The Polymarket indexer uses FPMMFactory to register new Fixed Product Market Maker instances automatically as they are created onchain, without requiring a redeployment.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-long-does-it-take-to-index-polymarkets-full-history-on-polygon">How long does it take to index Polymarket's full history on Polygon?<a class="hash-link" aria-label="Direct link to How long does it take to index Polymarket's full history on Polygon?" title="Direct link to How long does it take to index Polymarket's full history on Polygon?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#how-long-does-it-take-to-index-polymarkets-full-history-on-polygon">​</a></h3>
<p>Using Envio HyperIndex with HyperSync, the full historical sync of Polymarket's onchain data on Polygon, over 4,000,000,000 events from block 3,764,531, completed in 6 days.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="is-the-polymarket-hyperindex-indexer-open-source">Is the Polymarket HyperIndex indexer open source?<a class="hash-link" aria-label="Direct link to Is the Polymarket HyperIndex indexer open source?" title="Direct link to Is the Polymarket HyperIndex indexer open source?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#is-the-polymarket-hyperindex-indexer-open-source">​</a></h3>
<p>Yes. The full indexer is available at <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">github.com/enviodev/polymarket-indexer</a>, with 29 tests covering all handler phases including a HyperSync integration test. Run it locally with <code>pnpm dev</code>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="where-can-i-see-the-live-polymarket-indexer-deployment">Where can I see the live Polymarket indexer deployment?<a class="hash-link" aria-label="Direct link to Where can I see the live Polymarket indexer deployment?" title="Direct link to Where can I see the live Polymarket indexer deployment?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#where-can-i-see-the-live-polymarket-indexer-deployment">​</a></h3>
<p>The live indexer is deployed at <a href="https://envio.dev/app/moose-code/polymarket-indexer/7cad3ad" target="_blank" rel="noopener noreferrer">envio.dev/app/moose-code/polymarket-indexer/7cad3ad</a>. Polygon Mainnet is one of <!-- -->85+<!-- --> EVM chains with native HyperSync coverage.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-index-polymarket-data">How do I index Polymarket data?<a class="hash-link" aria-label="Direct link to How do I index Polymarket data?" title="Direct link to How do I index Polymarket data?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#how-do-i-index-polymarket-data">​</a></h3>
<p>The fastest way to index Polymarket data on Polygon is with Envio HyperIndex and HyperSync. The full open-source reference implementation is available at <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">github.com/enviodev/polymarket-indexer</a>. It covers all 8 domains of Polymarket's onchain activity and syncs the full history in 6 days.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#get-started">​</a></h2>
<p>The Polymarket indexer is fully open source and available as a production reference for anyone building on Polygon or migrating from The Graph. For a hands-on guide to streaming Polymarket trade data in real time, see <a href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync" target="_blank" rel="noopener noreferrer">How to Track Polymarket Trades Using Envio HyperSync</a>.</p>
<ul>
<li>Repo: <a href="https://github.com/enviodev/polymarket-indexer" target="_blank" rel="noopener noreferrer">https://github.com/enviodev/polymarket-indexer</a></li>
<li>Live deployment: <a href="https://envio.dev/app/moose-code/polymarket-indexer/7cad3ad" target="_blank" rel="noopener noreferrer">https://envio.dev/app/moose-code/polymarket-indexer/7cad3ad</a></li>
<li>Envio docs: <a href="https://docs.envio.dev/" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/</a></li>
<li>Discord: <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">https://discord.gg/envio</a></li>
<li>Telegram: <a href="https://t.me/+kAIGElzPjApiMjI0" target="_blank" rel="noopener noreferrer">https://t.me/+kAIGElzPjApiMjI0</a></li>
<li>Follow us on X: <a href="https://x.com/envio_indexer" target="_blank" rel="noopener noreferrer">https://x.com/envio_indexer</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#build-with-envio">​</a></h2>
<p>Envio HyperIndex is independently benchmarked as the fastest EVM blockchain indexer available. The Polymarket indexer is one example of what's possible. If you're building onchain, check out the <a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">docs</a>, run the benchmarks yourself, or talk to us about your data needs.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a> 💌</p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>case-studies</category>
        </item>
        <item>
            <title><![CDATA[How to Track Polymarket Trades Using Envio's HyperSync]]></title>
            <link>https://docs.envio.dev/blog/track-polymarket-trades-hypersync</link>
            <guid>https://docs.envio.dev/blog/track-polymarket-trades-hypersync</guid>
            <pubDate>Tue, 24 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Track Polymarket trades in real time using Envio HyperSync. Stream OrderFilled events on Polygon and decode trade data using TypeScript and Bun.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/polymarket-trades-hypersync.png" alt="Cover Image: Track Polymarket Trades in Real-Time" width="100%">
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>TL;DR</div><div class="admonitionContent_BuS1"><ul>
<li>Build a real-time Polymarket trade tracker using Envio HyperSync and TypeScript with Bun.</li>
<li>Stream block heights from Polygon and query OrderFilled events from the Polymarket Exchange contracts on each new block.</li>
<li>Decode events with Viem, identify buy vs sell trades by checking <code>makerAssetId</code>, and calculate price per share.</li>
<li>Extend with filters for trade amount or specific wallet addresses to track high-conviction traders.</li>
</ul></div></div>
<p>Since the rise of prediction markets like <a href="https://polymarket.com/" target="_blank" rel="noopener noreferrer">Polymarket</a> and <a href="https://kalshi.com/" target="_blank" rel="noopener noreferrer">Kalshi</a>, many people have been tracking activity on them to get a sense of where the money is going. If we try to track every trade on these prediction markets, you will see many people betting like $10 here, $15 there. If you want a stronger signal, then you should track trades with higher amounts, since those traders have more conviction in the outcome they are betting on.</p>
<p>In this article, we are going to build a tool with HyperSync where you can track Polymarket trades above a certain amount. We also have one feature where you can track trades from certain addresses. If you know some addresses from good traders, you can follow them too.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#prerequisites">​</a></h2>
<p>We are going to use Bun for this article, so make sure you have it installed. If not, please check the <a href="https://bun.com/docs/installation" target="_blank" rel="noopener noreferrer">Bun documentation</a> for installation instructions. If you want to use some other runtime that supports TypeScript, you can do that too.</p>
<p>You will also need an Envio API token to access HyperSync. If you don’t have it already, go to <a href="https://envio.dev/app/api-tokens" target="_blank" rel="noopener noreferrer">https://envio.dev/app/api-tokens</a> and you can find your token there.</p>
<p>Here are step-by-step instructions for creating new API tokens: <a href="https://docs.envio.dev/docs/HyperSync/api-tokens#generating-api-tokens" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperSync/api-tokens#generating-api-tokens</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-hypersync">What is HyperSync<a class="hash-link" aria-label="Direct link to What is HyperSync" title="Direct link to What is HyperSync" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#what-is-hypersync">​</a></h2>
<p><a href="https://docs.envio.dev/docs/HyperSync/overview" target="_blank" rel="noopener noreferrer">HyperSync</a> is Envio's high-performance blockchain data retrieval layer, built as an alternative to traditional JSON-RPC endpoints. It gives developers direct access to onchain data up to 2000x faster than standard RPC methods.</p>
<p>For this article, we are using HyperSync to stream real-time block heights and query Polymarket trade events on Polygon as they happen. Client libraries are available for Python, Rust, Node.js, and Go. HyperSync supports <!-- -->85+<!-- --> EVM chains, so the same approach works across any supported network.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="orderfilled-event">OrderFilled Event<a class="hash-link" aria-label="Direct link to OrderFilled Event" title="Direct link to OrderFilled Event" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#orderfilled-event">​</a></h2>
<p>Before we start writing the script, let’s talk about the <code>OrderFilled</code> event. This event is emitted when a trade has been filled, so these are confirmed trades where a user is buying or selling shares. Here is the event:</p>
<div class="language-solidity codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-solidity codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">    event OrderFilled(</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        bytes32 indexed orderHash,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        address indexed maker,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        address indexed taker,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        uint256 makerAssetId,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        uint256 takerAssetId,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        uint256 makerAmountFilled,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        uint256 takerAmountFilled,</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        uint256 fee</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    );</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Most of the fields are self-explanatory, but we still haven’t answered one question: if this event is emitted for all orders, then how do we know which one is buy vs sell? If the value of <code>makerAssetId</code> is <code>0</code>, then that is a buy order where the user is buying shares, and vice versa.</p>
<p>To calculate price per share for a buy trade, we can use <code>makerAmountFilled</code> and <code>takerAmountFilled</code>.</p>
<p>Price per share in a buy trade = <code>makerAmountFilled / takerAmountFilled</code></p>
<p>To calculate per-share price in a sell trade, we just switch those values. Now that we have a basic understanding of what data to fetch and what that data tells us, we can start writing our script with Bun.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="using-hypersync-client">Using HyperSync Client<a class="hash-link" aria-label="Direct link to Using HyperSync Client" title="Direct link to Using HyperSync Client" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#using-hypersync-client">​</a></h2>
<p>To create a Bun project and install the HyperSync client along with Viem for decoding events, you can use the following commands:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">mkdir</span><span class="token plain"> track-trades </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token builtin class-name" style="color:rgb(189, 147, 249)">cd</span><span class="token plain"> track-trades</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bun init </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-y</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">bun </span><span class="token function" style="color:rgb(80, 250, 123)">add</span><span class="token plain"> @envio-dev/hypersync-client viem</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If you’re new to HyperSync clients, please start by going through these examples: <a href="https://docs.envio.dev/docs/HyperSync/hypersync-clients" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/docs/HyperSync/hypersync-clients</a>.</p>
<p>Let’s discuss how we are going to structure our script. Instead of streaming events directly, we are going to stream height. When we get a new height, we query HyperSync to fetch the data we need. Here is a visual representation of that:</p>
<p><img decoding="async" loading="lazy" alt="Sequence diagram showing index.ts streaming new block heights from HyperSync and querying OrderFilled events on each new height" src="https://docs.envio.dev/assets/images/polymarket-data-flow-f286c84bfdd1ad66bc87dda1efd7d90a.png" width="3924" height="2802" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="stream-height">Stream Height<a class="hash-link" aria-label="Direct link to Stream Height" title="Direct link to Stream Height" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#stream-height">​</a></h2>
<p>We already have a height-streaming example in the HyperSync Node client, and we are going to use that here. Open <code>index.ts</code> and paste the following snippet, then we can go over it.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">Query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// for later use</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">type</span><span class="token plain"> </span><span class="token class-name">QueryResponseData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// for later use</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"@envio-dev/hypersync-client"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> decodeEventLog </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"viem"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// for later use</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// Create hypersync client using the mainnet hypersync endpoint</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> client </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    url</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"https://polygon.hypersync.xyz"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    apiToken</span><span class="token operator">:</span><span class="token plain"> process</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">env</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token constant" style="color:rgb(189, 147, 249)">ENVIO_API_TOKEN</span><span class="token operator">!</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// Create a height stream to monitor blockchain height changes</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> heightStream </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">streamHeight</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Height stream created. Listening for height updates..."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// Track the last known height to detect changes</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">while</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token comment" style="color:rgb(98, 114, 164)">// Receive the next event from the height stream</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> event </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> heightStream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">recv</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event </span><span class="token operator">===</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">null</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Height stream ended by server"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">break</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token comment" style="color:rgb(98, 114, 164)">// Handle different types of events</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">switch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">type</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Height"</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">fetchOrderFilledEvents</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">height</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// will be explained later</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">break</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Connected"</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">Connected to height stream</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">break</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">case</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Reconnecting"</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">Reconnecting to height stream in </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">delayMillis</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">ms due to error: </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">event</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">errorMsg</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">break</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">default</span><span class="token operator">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token comment" style="color:rgb(98, 114, 164)">// Tells the typescript compiler that we have covered all possible event types</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> _exhaustiveCheck</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">never</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">Error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Unhandled event type"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Error in height stream:"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">finally</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// Always close the stream to clean up resources</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> heightStream</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">close</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">"Height stream closed"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">main</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">catch</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">error</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The first thing we are doing in <code>main</code> is creating the HyperSync client with <code>url</code> and <code>apiToken</code> (which should be stored in a <code>.env</code> file, so create one and store your Envio API token there).</p>
<p>We have a <code>streamHeight</code> function on the client that emits 3 types of events: <code>Height</code>, <code>Connected</code>, and <code>Reconnecting</code>. When we get a new <code>Height</code> event with the latest block number, we call <code>fetchOrderFilledEvents</code>, where our parsing logic will live.</p>
<p>After creating the stream with <code>streamHeight</code>, we need to listen to those events, so we created a <code>while</code> loop that checks data from <code>.recv()</code> and a <code>switch</code> statement to act on the event type we get. The rest is mostly boilerplate error handling, so we don’t need to go too deep into that.</p>
<p>Now we have our streaming logic, so we can move to <code>fetchOrderFilledEvents</code>, which will handle the event parsing.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="fetchorderfilledevents-function">fetchOrderFilledEvents Function<a class="hash-link" aria-label="Direct link to fetchOrderFilledEvents Function" title="Direct link to fetchOrderFilledEvents Function" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#fetchorderfilledevents-function">​</a></h2>
<p>This function will take the height we got from <code>streamHeight</code> and query blocks to get the events we want. Let’s start with a few basic things we need for fetching and decoding the data:</p>
<ul>
<li>Contract addresses</li>
<li>ABI of the event</li>
<li>Event signature hash (aka <code>Topic0</code>)</li>
</ul>
<p>Here they are, so add them somewhere at the top of the file.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">export</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">EXCHANGE_ADDRESSES</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"0x4bfb41d5b3570defd03c39a9a4d8de6bd8b8982e"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"0xc5d563a36ae78145c45a50134d48a1215220f80a"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">map</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toLowerCase</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">ORDER_FILLED_TOPIC</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token string" style="color:rgb(255, 121, 198)">"0xd0a08e8c493f9c94f29311604c9de1b4e8c8d4c06bd0c789af57f2d65bfec0f6"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toLowerCase</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">ORDER_FILLED_ABI</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  anonymous</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  inputs</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      indexed</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      internalType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"bytes32"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"orderHash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      type</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"bytes32"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      indexed</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      internalType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"address"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"maker"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      type</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"address"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      indexed</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">true</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      internalType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"address"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"taker"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      type</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"address"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      indexed</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      internalType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"uint256"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"makerAssetId"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      type</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"uint256"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      indexed</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      internalType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"uint256"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"takerAssetId"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      type</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"uint256"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      indexed</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      internalType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"uint256"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"makerAmountFilled"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      type</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"uint256"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      indexed</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      internalType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"uint256"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"takerAmountFilled"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      type</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"uint256"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      indexed</span><span class="token operator">:</span><span class="token plain"> </span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      internalType</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"uint256"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"fee"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      type</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"uint256"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  name</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"OrderFilled"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  type</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"event"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">ORDER_FILLED_ABI_ITEMS</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token constant" style="color:rgb(189, 147, 249)">ORDER_FILLED_ABI</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// we can push it to query directly as an array</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Let's define the function signature. We are going to pass the HyperSync client and block height to this function.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">fetchOrderFilledEvents</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">client</span><span class="token operator">:</span><span class="token plain"> HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> height</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">number</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To fetch the data from HyperSync, we need to create a query. If you're not familiar with HyperSync queries, the query builder at <a href="https://builder.hypersync.xyz/" target="_blank" rel="noopener noreferrer">https://builder.hypersync.xyz/</a> is a good starting point. In short, in this query we define which event from which contracts we want to fetch, and what fields we want in the response.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> query</span><span class="token operator">:</span><span class="token plain"> Query </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  fromBlock</span><span class="token operator">:</span><span class="token plain"> height</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  logs</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      address</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">EXCHANGE_ADDRESSES</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      topics</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token constant" style="color:rgb(189, 147, 249)">ORDER_FILLED_TOPIC</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  fieldSelection</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    log</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token string" style="color:rgb(255, 121, 198)">"Data"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token string" style="color:rgb(255, 121, 198)">"Address"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic2"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic3"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token string" style="color:rgb(255, 121, 198)">"TransactionHash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token string" style="color:rgb(255, 121, 198)">"BlockNumber"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Use the <code>get</code> function to fetch the data and store the logs/events in an array that we can loop over.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> res </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> logs </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">data </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> QueryResponseData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">logs </span><span class="token operator">??</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Let’s loop over that array and use <code>decodeEventLog</code> from Viem to decode the data so we can analyze it.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> log </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">of</span><span class="token plain"> logs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> decoded </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">decodeEventLog</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    abi</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">ORDER_FILLED_ABI_ITEMS</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    data</span><span class="token operator">:</span><span class="token plain"> log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">data </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">0x</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation builtin" style="color:rgb(189, 147, 249)">string</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    topics</span><span class="token operator">:</span><span class="token plain"> log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">topics </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">0x</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation builtin" style="color:rgb(189, 147, 249)">string</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token operator">...</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">0x</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation builtin" style="color:rgb(189, 147, 249)">string</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">decoded</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">eventName </span><span class="token operator">!==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"OrderFilled"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">continue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> makerAssetId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> makerAmountFilled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> takerAmountFilled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> maker</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> taker </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    decoded</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">args </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      makerAssetId</span><span class="token operator">:</span><span class="token plain"> bigint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      makerAmountFilled</span><span class="token operator">:</span><span class="token plain"> bigint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      takerAmountFilled</span><span class="token operator">:</span><span class="token plain"> bigint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      maker</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      taker</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// TODO: Check if trade is Buy if yes, then log details along with price per share</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The last part of this script is checking if the trade is a buy trade, which we can confirm when <code>makerAssetId</code> is <code>0</code>. We also need to calculate price per share. We already know the formula: <code>makerAmountFilled / takerAmountFilled</code>. That value should be formatted to 6 decimals, and then we have the price per share.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">formatRatio</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  numerator</span><span class="token operator">:</span><span class="token plain"> bigint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  denominator</span><span class="token operator">:</span><span class="token plain"> bigint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  precision </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">6</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">denominator </span><span class="token operator">===</span><span class="token plain"> </span><span class="token number">0n</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> scale </span><span class="token operator">=</span><span class="token plain"> </span><span class="token number">10n</span><span class="token plain"> </span><span class="token operator">**</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">BigInt</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">precision</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> scaled </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">numerator </span><span class="token operator">*</span><span class="token plain"> scale</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">/</span><span class="token plain"> denominator</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> whole </span><span class="token operator">=</span><span class="token plain"> scaled </span><span class="token operator">/</span><span class="token plain"> scale</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> fraction </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">scaled </span><span class="token operator">%</span><span class="token plain"> scale</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">toString</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">padStart</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">precision</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">whole</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)">.</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">fraction</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><code>fetchOrderFilledEvents</code> should look like this at the end.</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">fetchOrderFilledEvents</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">client</span><span class="token operator">:</span><span class="token plain"> HypersyncClient</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> height</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">number</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// Topic0: 0xd0a08e8c493f9c94f29311604c9de1b4e8c8d4c06bd0c789af57f2d65bfec0f6</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> query</span><span class="token operator">:</span><span class="token plain"> Query </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    fromBlock</span><span class="token operator">:</span><span class="token plain"> height</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    logs</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        address</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">EXCHANGE_ADDRESSES</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        topics</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token constant" style="color:rgb(189, 147, 249)">ORDER_FILLED_TOPIC</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    fieldSelection</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      log</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"Data"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"Address"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic0"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic1"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic2"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"Topic3"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"TransactionHash"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token string" style="color:rgb(255, 121, 198)">"BlockNumber"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> res </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">get</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">query</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> logs </span><span class="token operator">=</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">res</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">data </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> QueryResponseData</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">logs </span><span class="token operator">??</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">for</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> log </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">of</span><span class="token plain"> logs</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> decoded </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">decodeEventLog</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      abi</span><span class="token operator">:</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">ORDER_FILLED_ABI_ITEMS</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      data</span><span class="token operator">:</span><span class="token plain"> log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">data </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">0x</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation builtin" style="color:rgb(189, 147, 249)">string</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      topics</span><span class="token operator">:</span><span class="token plain"> log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">topics </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">0x</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation builtin" style="color:rgb(189, 147, 249)">string</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token operator">...</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">0x</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation builtin" style="color:rgb(189, 147, 249)">string</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">decoded</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">eventName </span><span class="token operator">!==</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"OrderFilled"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">continue</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> makerAssetId</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> makerAmountFilled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> takerAmountFilled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> maker</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> taker </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      decoded</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">args </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">as</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        makerAssetId</span><span class="token operator">:</span><span class="token plain"> bigint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        makerAmountFilled</span><span class="token operator">:</span><span class="token plain"> bigint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        takerAmountFilled</span><span class="token operator">:</span><span class="token plain"> bigint</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        maker</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        taker</span><span class="token operator">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">string</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)">// TODO: Check if trade is Buy if yes, then log details along with price per share</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">makerAssetId </span><span class="token operator">===</span><span class="token plain"> </span><span class="token number">0n</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> pricePerShare </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">formatRatio</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">makerAmountFilled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> takerAmountFilled</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token builtin" style="color:rgb(189, 147, 249)">console</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">log</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token template-string string" style="color:rgb(255, 121, 198)">[BUY] block=</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">log</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">blockNumber</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)"> tx=</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">log</span><span class="token template-string interpolation punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token template-string interpolation">transactionHash</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)"> maker=</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">maker</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)"> taker=</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">taker</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string string" style="color:rgb(255, 121, 198)"> pricePerShare=</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">${</span><span class="token template-string interpolation">pricePerShare</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token template-string template-punctuation string" style="color:rgb(255, 121, 198)">`</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="complete-project">Complete Project<a class="hash-link" aria-label="Direct link to Complete Project" title="Direct link to Complete Project" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#complete-project">​</a></h2>
<p>You can check the project code in this repo: <a href="https://github.com/enviodev/track-poly-trades" target="_blank" rel="noopener noreferrer">https://github.com/enviodev/track-poly-trades</a></p>
<p>For the full production-scale Polymarket indexer covering all 8 subgraph domains and 4 billion events, see the <a href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study" target="_blank" rel="noopener noreferrer">Polymarket HyperIndex Case Study</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="next-steps">Next Steps<a class="hash-link" aria-label="Direct link to Next Steps" title="Direct link to Next Steps" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#next-steps">​</a></h2>
<p>Our aim was to create a tracker that filters trades based on amount and addresses, but we haven’t completed that aim yet. This article gave you the main steps you need to create that tool, so your next step is to add filtering for amount and addresses.</p>
<p>Don’t forget to share it with us on socials or in our Discord. Looking forward to seeing what you build on top of this.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="poly-whales-tui">Poly-Whales TUI<a class="hash-link" aria-label="Direct link to Poly-Whales TUI" title="Direct link to Poly-Whales TUI" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#poly-whales-tui">​</a></h2>
<p>Don’t want to set up the full project but still want to try it out? You can use the Poly-Whales TUI.</p>
<p>Run the following command in your terminal:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx poly-whales</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><img decoding="async" loading="lazy" alt="Terminal UI titled &amp;quot;Polymarket Whale Tracker&amp;quot; with a $500 threshold panel, watch addresses panel, and a live trades list of BUY orders with USD amounts, maker addresses, and timestamps" src="https://docs.envio.dev/assets/images/poly-whales-tui-ab4fc08e86382db675161b5dbeff658b.png" width="1920" height="1080" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="frequently-asked-questions">Frequently Asked Questions<a class="hash-link" aria-label="Direct link to Frequently Asked Questions" title="Direct link to Frequently Asked Questions" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="why-use-hypersync-for-polymarket-trade-tracking-instead-of-rpc">Why use HyperSync for Polymarket trade tracking instead of RPC?<a class="hash-link" aria-label="Direct link to Why use HyperSync for Polymarket trade tracking instead of RPC?" title="Direct link to Why use HyperSync for Polymarket trade tracking instead of RPC?" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#why-use-hypersync-for-polymarket-trade-tracking-instead-of-rpc">​</a></h3>
<p>HyperSync provides up to 2,000x faster data access than standard RPC and exposes a streaming interface tailored to filtered event queries. For Polymarket's high-throughput Exchange contracts on Polygon, this avoids the RPC rate limits and polling overhead that constrain real-time trade trackers built on standard JSON-RPC. Polygon is one of <!-- -->85+<!-- --> EVM chains with native HyperSync coverage, and HyperSync client libraries are available for TypeScript/Node.js, Python, Rust, and Go.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-track-polymarket-trades-in-real-time">How do I track Polymarket trades in real time?<a class="hash-link" aria-label="Direct link to How do I track Polymarket trades in real time?" title="Direct link to How do I track Polymarket trades in real time?" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#how-do-i-track-polymarket-trades-in-real-time">​</a></h3>
<p>Use the Envio HyperSync Node.js client to stream block heights from Polygon, then query the Exchange contract for OrderFilled events on each new block. Decode the event data with Viem to extract maker, taker, asset IDs, and amounts. A <code>makerAssetId</code> of 0 indicates a buy trade.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-identify-buy-vs-sell-trades-on-polymarket">How do I identify buy vs sell trades on Polymarket?<a class="hash-link" aria-label="Direct link to How do I identify buy vs sell trades on Polymarket?" title="Direct link to How do I identify buy vs sell trades on Polymarket?" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#how-do-i-identify-buy-vs-sell-trades-on-polymarket">​</a></h3>
<p>In the OrderFilled event, if <code>makerAssetId</code> is 0, the order is a buy where the maker is spending USDC to purchase shares. If <code>makerAssetId</code> is non-zero, the order is a sell. Price per share for a buy trade is <code>makerAmountFilled / takerAmountFilled</code>, formatted to 6 decimal places.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-are-the-polymarket-exchange-contract-addresses-on-polygon">What are the Polymarket Exchange contract addresses on Polygon?<a class="hash-link" aria-label="Direct link to What are the Polymarket Exchange contract addresses on Polygon?" title="Direct link to What are the Polymarket Exchange contract addresses on Polygon?" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#what-are-the-polymarket-exchange-contract-addresses-on-polygon">​</a></h3>
<p>The Polymarket Exchange contracts on Polygon are <code>0x4bfb41d5b3570defd03c39a9a4d8de6bd8b8982e</code> and <code>0xc5d563a36ae78145c45a50134d48a1215220f80a</code>. The OrderFilled event topic0 is <code>0xd0a08e8c493f9c94f29311604c9de1b4e8c8d4c06bd0c789af57f2d65bfec0f6</code>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="is-there-a-ready-made-polymarket-trade-tracker-i-can-run">Is there a ready-made Polymarket trade tracker I can run?<a class="hash-link" aria-label="Direct link to Is there a ready-made Polymarket trade tracker I can run?" title="Direct link to Is there a ready-made Polymarket trade tracker I can run?" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#is-there-a-ready-made-polymarket-trade-tracker-i-can-run">​</a></h3>
<p>Yes. The full project is available at <a href="https://github.com/enviodev/track-poly-trades" target="_blank" rel="noopener noreferrer">github.com/enviodev/track-poly-trades</a>. For a terminal UI version, run <code>pnpx poly-whales</code> to launch the Poly-Whales TUI, which tracks Polymarket whale activity in real time.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#build-with-envio">​</a></h2>
<p>Envio is the fastest independently benchmarked EVM blockchain indexer for querying real-time and historical data. If you are building onchain and need indexing that keeps up with your chain, check out the <a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">docs</a>, run the benchmarks yourself, and come talk to us about your data needs.</p>
<p>Stay tuned for more updates by subscribing to our newsletter, following us on X, or hopping into our Discord.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a> 💌</p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>tutorials</category>
        </item>
        <item>
            <title><![CDATA[Envio Developer Update March 2026]]></title>
            <link>https://docs.envio.dev/blog/envio-developer-update-march-2026</link>
            <guid>https://docs.envio.dev/blog/envio-developer-update-march-2026</guid>
            <pubDate>Mon, 23 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Envio Developer Update March 2026: HyperIndex alpha.15-19, agentic indexing workflows, subgraph hosting, ecosystem highlights, and upcoming events.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/dev-update-march-2026.png" alt="Cover Image Envio Developer Update March 2026" width="100%">
<p>March saw continued progress across HyperIndex, tooling, and the wider Envio ecosystem. We shipped multiple alpha releases focused on improving scale, flexibility, testing, and observability, alongside new workflows that make it easier to go from idea to production-ready indexers.
This month we also rebranded our Hosted Service to Envio Cloud. Alongside this, we introduced updates across subgraph hosting, agentic indexing workflows, and new ways to explore and interact with prediction market data. Across the ecosystem, we saw strong developer contributions, new projects being built with Envio, and continued momentum leading into upcoming events.</p>
<p>Let's dive in!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="alpha-releases-alpha15---alpha19">Alpha Releases: Alpha.15 -&gt; Alpha.19<a class="hash-link" aria-label="Direct link to Alpha Releases: Alpha.15 -> Alpha.19" title="Direct link to Alpha Releases: Alpha.15 -> Alpha.19" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#alpha-releases-alpha15---alpha19">​</a></h2>
<p>Loads of exciting progress landed across the latest alpha releases this month. This stretch focused on improving scale, flexibility, testing, and the overall developer experience across HyperIndex, with a mix of new features, internal improvements, and important updates to observability.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="alpha15">Alpha.15<a class="hash-link" aria-label="Direct link to Alpha.15" title="Direct link to Alpha.15" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#alpha15">​</a></h3>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="new-getwhere-operators-_gte-_lte-_in">New getWhere operators: <code>_gte</code>, <code>_lte</code>, <code>_in</code><a class="hash-link" aria-label="Direct link to new-getwhere-operators-_gte-_lte-_in" title="Direct link to new-getwhere-operators-_gte-_lte-_in" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#new-getwhere-operators-_gte-_lte-_in">​</a></h4>
<p>Three new filter operators have been added for getWhere queries, following Hasura-style conventions:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Entity</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getWhere</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> amount</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> _gte</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">100n</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Entity</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getWhere</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> amount</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> _lte</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">500n</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">context</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Entity</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">getWhere</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> status</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> _in</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token string" style="color:rgb(255, 121, 198)">"active"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"pending"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="support-double-handler-registration">Support double handler registration<a class="hash-link" aria-label="Direct link to Support double handler registration" title="Direct link to Support double handler registration" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#support-double-handler-registration">​</a></h4>
<p>Allows double handler registration for the same event with similar filters:</p>
<div class="language-typescript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-typescript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token constant" style="color:rgb(189, 147, 249)">ERC20</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"generated"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token constant" style="color:rgb(189, 147, 249)">ERC20</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Transfer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// Your logic here</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token constant" style="color:rgb(189, 147, 249)">ERC20</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Transfer</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token function" style="color:rgb(80, 250, 123)">handler</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> event</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> context </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// And here</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="other-improvements">Other improvements<a class="hash-link" aria-label="Direct link to Other improvements" title="Direct link to Other improvements" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#other-improvements">​</a></h4>
<p>We consistently improve HyperIndex to make it easier to contribute to for both humans and AI. Recent work includes:</p>
<ul>
<li>Restructuring HyperIndex into a pnpm workspace</li>
<li>Moving tests from mocha/chai to vitest</li>
<li>Reworking the CI pipeline to run faster and reuse the production artifact for both testing and publishing</li>
<li>Developing a highly customisable internal testing framework so AI can create reproduction tests for tricky edge cases</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="alpha18">Alpha.18<a class="hash-link" aria-label="Direct link to Alpha.18" title="Direct link to Alpha.18" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#alpha18">​</a></h3>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="support-indexers-with-21b-events-per-chain">Support indexers with 2.1B+ events per chain<a class="hash-link" aria-label="Direct link to Support indexers with 2.1B+ events per chain" title="Direct link to Support indexers with 2.1B+ events per chain" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#support-indexers-with-21b-events-per-chain">​</a></h4>
<p>Scale indexers approaching int32 limits. Now you can build even larger, more performant indexers with HyperIndex.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="breaking-official-metrics-endpoint">Breaking: Official <code>/metrics</code> endpoint<a class="hash-link" aria-label="Direct link to breaking-official-metrics-endpoint" title="Direct link to breaking-official-metrics-endpoint" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#breaking-official-metrics-endpoint">​</a></h4>
<p>Existing Prometheus metrics just got a major upgrade.</p>
<p>We cleaned up metric names and measured data, switched time units to seconds instead of milliseconds, and started following Prometheus naming conventions more closely.</p>
<p>We also added metrics for data points previously covered by the <code>--bench</code> feature.</p>
<p>Starting with v3.0.0, Prometheus metrics are no longer experimental. The <code>/metrics</code> endpoint now follows semver and will be documented.</p>
<p>For more information and to stay up to date with all current and past releases, be sure to check out our release notes below.</p>
<p>See full <a href="https://github.com/enviodev/hyperindex/releases" target="_blank" rel="noopener noreferrer">release notes</a><br>
<!-- -->Star us on <a href="https://github.com/enviodev/hyperindex" target="_blank" rel="noopener noreferrer">GitHub</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="hosted-service-is-now-envio-cloud">Hosted Service is now Envio Cloud<a class="hash-link" aria-label="Direct link to Hosted Service is now Envio Cloud" title="Direct link to Hosted Service is now Envio Cloud" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#hosted-service-is-now-envio-cloud">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/envio-cloud-1.png" alt="Hosted Service renamed to Envio Cloud" width="100%">
<p>We've renamed the Hosted Service to Envio Cloud. Same product, same infrastructure, no changes required on your end.
For those new to it, Envio Cloud is a fully managed hosting solution for your indexers, taking care of all infrastructure, scaling, and monitoring so you can focus on building. Plans range from free dev environments through to enterprise-grade dedicated hosting, with static production endpoints, built-in alerts, and production-ready infrastructure across all tiers.</p>
<p>Learn more in our <a href="https://docs.envio.dev/docs/HyperIndex/hosted-service" target="_blank" rel="noopener noreferrer">docs</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="agentic-blockchain-indexing-with-envio">Agentic blockchain indexing with Envio<a class="hash-link" aria-label="Direct link to Agentic blockchain indexing with Envio" title="Direct link to Agentic blockchain indexing with Envio" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#agentic-blockchain-indexing-with-envio">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-march-2026-1.png" alt="Agentic blockchain indexing with Envio" width="100%">
<p>We explored what it looks like to go from prompt to production-ready indexers using Envio.</p>
<p>This walkthrough shows how to scaffold an indexer for any EVM-compatible chain, push it to GitHub, and deploy it to Envio's Cloud (previously Hosted Service) without manually touching a config file.</p>
<p>As an example, <strong>400,000+ wstETH events were indexed on Monad in ~20 seconds.</strong></p>
<p>Use the following command to scaffold your indexer:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio init template </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-t</span><span class="token plain"> erc20 </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-l</span><span class="token plain"> typescript </span><span class="token parameter variable" style="color:rgb(189, 147, 249);font-style:italic">-d</span><span class="token plain"> ./my-indexer</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Learn more in our blog and test it yourself here: <a href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="host-your-subgraphs-on-envio">Host your subgraphs on Envio<a class="hash-link" aria-label="Direct link to Host your subgraphs on Envio" title="Direct link to Host your subgraphs on Envio" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#host-your-subgraphs-on-envio">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-march-2026-2.png" alt="Envio subgraph hosting page headlined 143x Faster Subgraph Deployments with How it works and What you get checklists" width="100%">
<p>Deploy and host your subgraphs with HyperIndex, with a fully subgraph-compatible GraphQL endpoint and no client changes required.</p>
<p>Migrate your existing subgraphs and keep the same API, with faster sync, quicker backfills, and deployments live in less than a day.</p>
<p>The process is handled end-to-end, converting your subgraph to HyperIndex and getting it up and running without needing to manage infrastructure.</p>
<p>Learn more here: <a href="https://envio.dev/pricing/subgraphs" target="_blank" rel="noopener noreferrer">https://envio.dev/pricing/subgraphs</a><br>
<!-- -->Get started on Discord - open a support ticket: <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">https://discord.gg/envio</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="heatbook-polymarket-orderbooks-as-heatmaps">Heatbook: Polymarket Orderbooks as Heatmaps<a class="hash-link" aria-label="Direct link to Heatbook: Polymarket Orderbooks as Heatmaps" title="Direct link to Heatbook: Polymarket Orderbooks as Heatmaps" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#heatbook-polymarket-orderbooks-as-heatmaps">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-march-2026-3.png" alt="Heatbook orderbook heatmap for the Polymarket market Will Donald Trump win the 2024 US Presidential Election" width="100%">
<p>An interface for visualising Polymarket orderbooks using historical heatmaps. Orderbook heatmaps for prediction markets, with 115M+ fills visualised. View any market and explore activity over time.</p>
<p>Supports <a href="https://polymarket.com/predictions/all" target="_blank" rel="noopener noreferrer">Polymarket</a>, <a href="https://limitless.exchange/markets" target="_blank" rel="noopener noreferrer">Limitless</a>, and more soon.</p>
<p>More here: <a href="https://heatbook.xyz/" target="_blank" rel="noopener noreferrer">https://heatbook.xyz/</a><br>
<!-- -->See original post: <a href="https://x.com/jonjonclark/status/2031016707309949042?s=20" target="_blank" rel="noopener noreferrer">https://x.com/jonjonclark/status/2031016707309949042?s=20</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="ethcc9-sapphire-sponsor">EthCC[9]: Sapphire Sponsor<a class="hash-link" aria-label="Direct link to EthCC[9]: Sapphire Sponsor" title="Direct link to EthCC[9]: Sapphire Sponsor" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#ethcc9-sapphire-sponsor">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-march-2026-4.png" alt="Envio Sapphire Sponsor banner for EthCC[9] at Palais des Festivals Cannes, March 30 to April 2, 2026" width="100%">
<p>Envio is a Sapphire sponsor of <a href="https://ethcc.io/" target="_blank" rel="noopener noreferrer">EthCC[9]</a>, taking place at Palais des Festivals in Cannes from March 30 to April 2, 2026.</p>
<p>EthCC is an annual Ethereum community conference bringing together developers, researchers, and teams from across the ecosystem.</p>
<p>The team will be there across the week. Catch our <a href="https://ethcc.io/speakers/jonjon-clark" target="_blank" rel="noopener noreferrer">talk</a> on the Monroe stage and swing by our booth - let's chat about your data needs.</p>
<p>P.S. be sure to get your hands on one of our snazzy Envio caps and stickers.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="developer-contributions-uniswap-cca-indexer">Developer contributions: Uniswap CCA indexer<a class="hash-link" aria-label="Direct link to Developer contributions: Uniswap CCA indexer" title="Direct link to Developer contributions: Uniswap CCA indexer" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#developer-contributions-uniswap-cca-indexer">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-march-2026-5.png" alt="GitHub repo card for dzmbs/uniswap-cca-indexer, an Envio HyperIndex indexer for Uniswap Continuous Clearing Auction contracts" width="100%">
<p>Check out this Uniswap CCA indexer built with HyperIndex to index continuous clearing auction contracts across Ethereum, Base, Arbitrum, and Unichain. It tracks auctions, bids, ticks, steps, and checkpoints, using HyperSync for logs and selective RPC reads for derived onchain state.</p>
<p>Shoutout to <a href="https://x.com/0xdivergence" target="_blank" rel="noopener noreferrer">@0xdivergence</a> for sharing this and building with Envio.</p>
<p>Check it out on GitHub: <a href="https://github.com/dzmbs/uniswap-cca-indexer" target="_blank" rel="noopener noreferrer">https://github.com/dzmbs/uniswap-cca-indexer</a><br>
<!-- -->Original post on X: <a href="https://x.com/0xdivergence/status/1769735600377133273" target="_blank" rel="noopener noreferrer">https://x.com/0xdivergence/status/1769735600377133273</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="open-indexer-benchmark">Open Indexer Benchmark<a class="hash-link" aria-label="Direct link to Open Indexer Benchmark" title="Direct link to Open Indexer Benchmark" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#open-indexer-benchmark">​</a></h2>
<p>We believe tech should speak for itself.</p>
<p>That's why we started working on and maintaining the Open Indexer Benchmark (originally forked from Sentio).</p>
<p>An honest, objective benchmark for blockchain indexers.</p>
<p>We're reopening it to benchmark new use cases and warmly welcome all contributions:<br>
<a href="https://github.com/enviodev/open-indexer-benchmark" target="_blank" rel="noopener noreferrer">https://github.com/enviodev/open-indexer-benchmark</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="wonderland-ctf">Wonderland CTF<a class="hash-link" aria-label="Direct link to Wonderland CTF" title="Direct link to Wonderland CTF" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#wonderland-ctf">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-march-2026-6.png" alt="Wonderland CTF 2026 sponsor banner listing Grego AI, Envio, runtime verification, and Pashov Audit Group" width="100%">
<p>Envio is a proud sponsor of the Wonderland CTF. The event takes place on April 1, 2026, in person at EthCC[9] in Cannes.</p>
<p>Wonderland CTF is a capture-the-flag event featuring Solidity and Aztec Noir challenges, with tracks ranging from beginner to advanced and teams of 1 to 5 members.</p>
<p>Create your team and learn more here: <a href="https://ctf.wonderland.xyz/" target="_blank" rel="noopener noreferrer">https://ctf.wonderland.xyz</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="polymarket-whale-tracker-tui">Polymarket Whale Tracker TUI<a class="hash-link" aria-label="Direct link to Polymarket Whale Tracker TUI" title="Direct link to Polymarket Whale Tracker TUI" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#polymarket-whale-tracker-tui">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-march-2026-7.png" alt="Polymarket Whale Tracker TUI" width="100%">
<p>We put together a simple whale tracker using HyperSync to track Polymarket whale activity in real time. It follows large traders on Polymarket and surfaces what they're doing as it happens, making it easier to monitor higher-conviction activity without sifting through smaller trades.</p>
<p>Clean, fast, and easy to plug into your workflows.</p>
<p>More here: <a href="https://github.com/enviodev/poly-whale-tracker" target="_blank" rel="noopener noreferrer">https://github.com/enviodev/poly-whale-tracker</a></p>
<p>Run:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">npx poly-whales</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>For a step-by-step guide on how to build your own, see: <a href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/track-polymarket-trades-hypersync</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="best-blockchain-indexers-in-2026">Best blockchain indexers in 2026<a class="hash-link" aria-label="Direct link to Best blockchain indexers in 2026" title="Direct link to Best blockchain indexers in 2026" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#best-blockchain-indexers-in-2026">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-march-2026-8.png" alt="Best blockchain indexers in 2026" width="100%">
<p>We put together a benchmark-driven comparison of blockchain indexers, looking at how different solutions perform in practice. The guide focuses on how indexers handle real workloads, comparing performance, sync speeds, and overall reliability across different approaches.</p>
<p>It's a practical breakdown of the trade-offs between tools and what to consider when choosing an indexer for your use case.</p>
<p>Learn and compare in our latest blog: <a href="https://docs.envio.dev/blog/best-blockchain-indexers-2026" target="_blank" rel="noopener noreferrer">https://docs.envio.dev/blog/best-blockchain-indexers-2026</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="current--upcoming-events--hackathons">Current &amp; Upcoming Events &amp; Hackathons<a class="hash-link" aria-label="Direct link to Current &amp; Upcoming Events &amp; Hackathons" title="Direct link to Current &amp; Upcoming Events &amp; Hackathons" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#current--upcoming-events--hackathons">​</a></h2>
<ul>
<li><a href="https://ethcc.io/" target="_blank" rel="noopener noreferrer">EthCC - Cannes</a>: March 30th -&gt; April 2nd</li>
<li><a href="https://ethconf.com/" target="_blank" rel="noopener noreferrer">EthConf - New York</a>: June 8th -&gt; 10th</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="featured-developer-praveen-matheesha">Featured Developer: Praveen Matheesha<a class="hash-link" aria-label="Direct link to Featured Developer: Praveen Matheesha" title="Direct link to Featured Developer: Praveen Matheesha" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#featured-developer-praveen-matheesha">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-march-2026-9.png" alt="Featured developer Praveen Matheesha" width="100%">
<p>This month's featured developer is Praveen Matheesha, a developer focused on building advanced onchain analytics infrastructure. He is currently working on <a href="https://x.com/paralensdotai" target="_blank" rel="noopener noreferrer">@paralensdotai</a>, a next-generation blockchain analytics engine designed to extract economic behavior and strategy-level insights from raw blockchain transactions. His focus is on turning complex onchain data into meaningful signals for traders, researchers, and analysts, with a particular interest in transaction-level intelligence, MEV analysis, and understanding the economic intent behind smart contract interactions.</p>
<p><strong>What Praveen had to say about Envio:</strong></p>
<blockquote>
<p><em><strong>"Before discovering Envio, I was building my own EVM indexer from scratch in Rust. I implemented support for chain reorg handling, historical backfilling, batched RPC ingestion, and WebSocket streams for real-time updates. While it worked, a significant amount of time went into building and maintaining the infrastructure layer itself. When I discovered Envio and HyperSync, it immediately stood out as a much more efficient approach. It solves many of the challenges around reliable, high-performance blockchain data access that developers often end up rebuilding from scratch. If I had found it earlier, I likely could have saved weeks of work and focused more on the actual analytics and business logic rather than the ingestion pipeline. I also wrote a detailed article about building a production-ready EVM indexer in Rust, where I mentioned Envio as a great option for developers who want to avoid spending weeks building indexing infrastructure themselves. Overall, HyperSync makes it significantly easier to work with large volumes of onchain data and allows developers to focus on building insights and applications instead of reinventing core data infrastructure."</strong></em></p>
</blockquote>
<p>Well done, Praveen. Be sure to follow the team on <a href="https://x.com/hpmszk" target="_blank" rel="noopener noreferrer">X</a> and check out their <a href="https://github.com/matheeshame" target="_blank" rel="noopener noreferrer">GitHub</a> to stay up to date with their latest developments.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="playlist-of-the-month">Playlist of the Month<a class="hash-link" aria-label="Direct link to Playlist of the Month" title="Direct link to Playlist of the Month" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#playlist-of-the-month">​</a></h2>
<img src="https://docs.envio.dev/blog-assets/dev-update-march-2026-10.png" alt="Spotify public playlist Mar 26 by Jordy Baby, 19 songs, 1 hr 14 min" width="100%">
<p>▶ <a href="https://open.spotify.com/playlist/240pHTCbwvf6kBMdfWGmw9?si=bb40d616e82a49f3" target="_blank" rel="noopener noreferrer">Open Spotify</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="build-with-envio">Build With Envio<a class="hash-link" aria-label="Direct link to Build With Envio" title="Direct link to Build With Envio" href="https://docs.envio.dev/blog/envio-developer-update-march-2026#build-with-envio">​</a></h2>
<p>Envio is a multichain EVM blockchain indexer for querying real-time and historical data. If you're working on a Web3 project and want a smoother development process, Envio's got your back(end). Check out our docs, join the community, and let's talk about your data needs.</p>
<p>Stay tuned for more monthly updates by subscribing to our newsletter, following us on X, or hopping into our Discord for more up-to-date information.</p>
<p><a href="https://envio.beehiiv.com/subscribe?utm_source=envio.beehiiv.com&amp;utm_medium=newsletter&amp;utm_campaign=new-post" target="_blank" rel="noopener noreferrer">Subscribe to our newsletter</a> 💌</p>
<p><a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">Website</a> | <a href="https://twitter.com/envio_indexer" target="_blank" rel="noopener noreferrer">X</a> | <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">Discord</a> | <a href="https://t.me/+5mI61oZibEM5OGQ8" target="_blank" rel="noopener noreferrer">Telegram</a> | <a href="https://github.com/enviodev" target="_blank" rel="noopener noreferrer">GitHub</a> | <a href="https://www.youtube.com/channel/UCR7nZ2yzEtc5SZNM0dhrkhA" target="_blank" rel="noopener noreferrer">YouTube</a> | <a href="https://www.reddit.com/user/Envio_indexer" target="_blank" rel="noopener noreferrer">Reddit</a></p>]]></content:encoded>
            <category>product-updates</category>
        </item>
    </channel>
</rss>