<?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>Tue, 02 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[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="How to Index Sei Smart Contract Data in Minutes using 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>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>Add your API token</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="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">pnpx envio init template -t erc20 -d ./sei-indexer</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">cd 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>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-add-your-api-token">Step 2: Add your API token<a class="hash-link" aria-label="Direct link to Step 2: Add your API token" title="Direct link to Step 2: Add your API token" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-2-add-your-api-token">​</a></h2>
<p>The scaffolded <code>.env</code> file ships with three commented lines:</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"># To create or update a token visit https://envio.dev/app/api-tokens</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># Uncomment the line below and set a valid token</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"># ENVIO_API_TOKEN="&lt;YOUR-API-TOKEN&gt;"</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>Uncomment the last line and replace <code>&lt;YOUR-API-TOKEN&gt;</code> with your token so it reads:</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">ENVIO_API_TOKEN="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>
<p>Note: A token is required. Without a valid token, the indexer stops immediately with the error <code>"An API token is required for using HyperSync as a data-source."</code></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-3-configure-the-indexer-for-sei">Step 3: Configure the indexer for Sei<a class="hash-link" aria-label="Direct link to Step 3: Configure the indexer for Sei" title="Direct link to Step 3: Configure the indexer for Sei" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-3-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-4-define-the-data-schema">Step 4: Define the data schema<a class="hash-link" aria-label="Direct link to Step 4: Define the data schema" title="Direct link to Step 4: Define the data schema" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-4-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-5-write-the-event-handler">Step 5: Write the event handler<a class="hash-link" aria-label="Direct link to Step 5: Write the event handler" title="Direct link to Step 5: Write the event handler" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-5-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="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">rm -f 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-6-generate-types">Step 6: Generate types<a class="hash-link" aria-label="Direct link to Step 6: Generate types" title="Direct link to Step 6: Generate types" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-6-generate-types">​</a></h2>
<p>Generate the typed code from your config and schema:</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">pnpm 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-7-run-the-indexer">Step 7: Run the indexer<a class="hash-link" aria-label="Direct link to Step 7: Run the indexer" title="Direct link to Step 7: Run the indexer" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-7-run-the-indexer">​</a></h2>
<p>Start the indexer in development mode:</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">pnpm 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-8-query-your-data">Step 8: Query your data<a class="hash-link" aria-label="Direct link to Step 8: Query your data" title="Direct link to Step 8: Query your data" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-8-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="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">curl -s -X POST http://localhost:8080/v1/graphql \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  -H "Content-Type: application/json" \</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  -d '{"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-9-stop-the-indexer">Step 9: Stop the indexer<a class="hash-link" aria-label="Direct link to Step 9: Stop the indexer" title="Direct link to Step 9: Stop the indexer" href="https://docs.envio.dev/blog/index-sei-smart-contracts-envio#step-9-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="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">pnpm 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> (see Step 2: Add your API token above).</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>]]></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="Polymarket's Top Traders Run on Indexed Data" 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="The 15 minute Bitcoin loop Polymarket trader" 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="The UMA gap Polymarket trader" 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="How Katana Migrated SushiSwap Data from The Graph to 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>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-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/migrate-from-ponder-to-envio#what-is-hypersync">​</a></h3>
<p>HyperSync is Envio's data engine. Instead of pulling historical data through standard RPC, HyperSync fetches filtered event data in bulk from a purpose-built data lake, delivering up to 2,000x faster data access than RPC. 87+ EVM chains have native HyperSync coverage.</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="Why AI Agents Acting Onchain Need an Indexer" 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> <!-- -->86+<!-- --> 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, HyperSync 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="what-skills-ship-with-hyperindex">What skills ship with HyperIndex?<a class="hash-link" aria-label="Direct link to What skills ship with HyperIndex?" title="Direct link to What skills ship with HyperIndex?" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#what-skills-ship-with-hyperindex">​</a></h3>
<p>HyperIndex projects scaffold a <code>.claude/skills/</code> directory that auto-discovers for Cursor, Claude Code, and Codex. The canonical templates ship 14 skill definitions covering <code>indexer-configuration</code>, <code>indexer-schema</code>, <code>indexer-handlers</code>, <code>indexer-factory</code> (dynamic contracts), <code>indexer-external-calls</code> (Effect API), <code>indexer-multichain</code>, <code>indexer-performance</code>, <code>indexer-blocks</code>, <code>indexer-transactions</code>, <code>indexer-traces</code>, <code>indexer-filters</code>, <code>indexer-wildcard</code>, <code>indexer-testing</code>, and <code>migrate-from-subgraph</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>.</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="what-chains-does-hyperindex-support-for-ai-agents">What chains does HyperIndex support for AI agents?<a class="hash-link" aria-label="Direct link to What chains does HyperIndex support for AI agents?" title="Direct link to What chains does HyperIndex support for AI agents?" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#what-chains-does-hyperindex-support-for-ai-agents">​</a></h3>
<p>Any EVM chain. <!-- -->86+<!-- --> have native HyperSync coverage for maximum speed. Any EVM chain without native HyperSync is accessible via standard RPC.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-does-hyperindex-handle-reorgs-for-agents">How does HyperIndex handle reorgs for agents?<a class="hash-link" aria-label="Direct link to How does HyperIndex handle reorgs for agents?" title="Direct link to How does HyperIndex handle reorgs for agents?" href="https://docs.envio.dev/blog/ai-agents-acting-onchain-indexer#how-does-hyperindex-handle-reorgs-for-agents">​</a></h3>
<p>At the framework level. Entity state history is persisted for unfinalized blocks. The framework rolls back automatically on reorg. No handler code is required.</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 HyperSync 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="what-are-the-built-in-hyperindex-skills">What are the built-in HyperIndex skills?<a class="hash-link" aria-label="Direct link to What are the built-in HyperIndex skills?" title="Direct link to What are the built-in HyperIndex skills?" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#what-are-the-built-in-hyperindex-skills">​</a></h3>
<p>HyperIndex projects scaffolded with v3 rc ship a <code>.claude/skills/</code> directory pre-populated with 14 skills covering the core indexing patterns: <code>indexer-configuration</code>, <code>indexer-schema</code>, <code>indexer-handlers</code>, <code>indexer-factory</code>, <code>indexer-multichain</code>, <code>indexer-external-calls</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>, <code>indexer-wildcard</code>, and <code>migrate-from-subgraph</code>. Claude Code auto-discovers them at session start.</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="what-chains-are-supported">What chains are supported?<a class="hash-link" aria-label="Direct link to What chains are supported?" title="Direct link to What chains are supported?" href="https://docs.envio.dev/blog/ai-onchain-app-hyperindex-claude#what-chains-are-supported">​</a></h3>
<p>Any EVM chain. <!-- -->86+<!-- --> have native HyperSync coverage for maximum speed. Any EVM chain without native HyperSync is accessible via standard RPC. The current chain count is published on <a href="https://envio.dev/" target="_blank" rel="noopener noreferrer">envio.dev</a>.</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="can-i-migrate-an-alchemy-subgraph-the-same-way">Can I migrate an Alchemy subgraph the same way?<a class="hash-link" aria-label="Direct link to Can I migrate an Alchemy subgraph the same way?" title="Direct link to Can I migrate an Alchemy subgraph the same way?" href="https://docs.envio.dev/blog/ai-subgraph-migration-hyperindex-claude#can-i-migrate-an-alchemy-subgraph-the-same-way">​</a></h3>
<p>Yes. Alchemy Subgraphs are technically subgraphs, and the same AI-assisted migration flow described in this blog applies, scaffold a HyperIndex project from a template, hand Claude the AssemblyScript mappings, validate locally, and ship.</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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="is-hyperindex-faster-than-the-graph-in-production">Is HyperIndex faster than The Graph in production?<a class="hash-link" aria-label="Direct link to Is HyperIndex faster than The Graph in production?" title="Direct link to Is HyperIndex faster than The Graph in production?" href="https://docs.envio.dev/blog/production-indexer-reliability-hyperindex#is-hyperindex-faster-than-the-graph-in-production">​</a></h3>
<p>Yes. In the Sentio Uniswap V2 Factory benchmark, HyperIndex completed in 8 seconds. The Graph took 19 minutes on the same workload, 142x slower. Subsquid, the nearest competitor, was 15x slower. Full results on the benchmarks page linked in Get Started.</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 HyperSync, 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 1 minute, 143x faster than The Graph and 15x faster than the nearest competitor. BNB Smart Chain is one of <!-- -->86+<!-- --> 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="Revert Finance PancakeSwap V3 indexer running on Envio" 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="what-is-a-blockchain-indexer">What is a blockchain indexer?<a class="hash-link" aria-label="Direct link to What is a blockchain indexer?" title="Direct link to What is a blockchain indexer?" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#what-is-a-blockchain-indexer">​</a></h3>
<p>A blockchain indexer is a system that listens to onchain events and organises them into a structured, queryable database. Developers use blockchain indexers to build fast backends for DeFi protocols, analytics tools, and trading interfaces without querying slow RPC endpoints directly.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-hyperindex">What is HyperIndex?<a class="hash-link" aria-label="Direct link to What is HyperIndex?" title="Direct link to What is HyperIndex?" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#what-is-hyperindex">​</a></h3>
<p>Envio HyperIndex is a real-time multichain blockchain indexing framework for EVM chains. Developers write event handlers in TypeScript and deploy a single indexer covering multiple contracts, chains, and domains. It uses HyperSync, Envio's proprietary data engine, to fetch filtered event data in bulk rather than polling RPC endpoints, enabling historical syncs at speeds not achievable through standard RPC.</p>
<h3 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/revert-finance-pancakeswap-bnb-hyperindex#what-is-hypersync">​</a></h3>
<p>HyperSync is Envio's high-performance data engine. Instead of querying RPC endpoints block by block, HyperSync fetches and serves filtered event data in bulk from a purpose-built data lake, delivering up to 2,000x faster data access than traditional RPC. BNB Smart Chain is one of <!-- -->86+<!-- --> EVM chains with native HyperSync coverage. Any EVM chain can be indexed via standard RPC.</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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-chains-does-envio-support">What chains does Envio support?<a class="hash-link" aria-label="Direct link to What chains does Envio support?" title="Direct link to What chains does Envio support?" href="https://docs.envio.dev/blog/revert-finance-pancakeswap-bnb-hyperindex#what-chains-does-envio-support">​</a></h3>
<p>Envio supports any EVM chain. <!-- -->86+<!-- --> EVM chains have native HyperSync coverage for maximum speed, including BNB Smart Chain, Polygon, Ethereum, Base, Arbitrum, Optimism, and more. Any EVM chain without native HyperSync support can be indexed via standard RPC. See the full list of supported chains at <a href="https://envio.dev/chains" target="_blank" rel="noopener noreferrer">envio.dev/chains</a>.</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/revert-finance-pancakeswap-bnb-hyperindex#how-do-i-migrate-from-the-graph-to-hyperindex">​</a></h3>
<p>Because HyperIndex handlers are written in TypeScript and AssemblyScript is a subset of TypeScript, most handler logic can be carried across directly. Envio provides a full <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 for teams moving from 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/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="Cover image for the What is HyperSync blog" 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 <!-- -->86+<!-- --> 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 <!-- -->86+<!-- --> 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>Blockchain indexers</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>HyperIndex</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 <!-- -->86+<!-- --> 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" 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.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="Experimental ClickHouse Sink" 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="The Top Hundred Polymarket Traders" 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 Docs MCP Server" 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="Monad Traces Live on HyperSync" 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="Playlist of the month" 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="Cover image for the blog with title" 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="Output table showing native transfers" 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-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/tracking-native-eth-transfers-hypersync#what-is-hypersync">​</a></h3>
<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, with client libraries for Python, Rust, Node.js, and Go across <!-- -->86+<!-- --> EVM chains.</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 <!-- -->86+<!-- --> 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="Polymarket indexer sync results" 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="what-is-a-blockchain-indexer">What Is a Blockchain Indexer?<a class="hash-link" aria-label="Direct link to What Is a Blockchain Indexer?" title="Direct link to What Is a Blockchain Indexer?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#what-is-a-blockchain-indexer">​</a></h3>
<p>A blockchain indexer is a system that listens to onchain events and organises them into a structured, queryable database. Developers use blockchain indexers to build fast backends for DeFi protocols, trading interfaces, analytics tools, and onchain AI agents without querying slow RPC endpoints directly.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-the-fastest-blockchain-indexer">What Is the Fastest Blockchain Indexer?<a class="hash-link" aria-label="Direct link to What Is the Fastest Blockchain Indexer?" title="Direct link to What Is the Fastest Blockchain Indexer?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#what-is-the-fastest-blockchain-indexer">​</a></h3>
<p>Envio HyperIndex is independently benchmarked as the fastest blockchain indexer available. In the Uniswap V2 Factory benchmark run by Sentio in May 2025, HyperIndex completed in 8 seconds, 142x faster than The Graph and 15x faster than the nearest competitor (Subsquid).</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-hyperindex">What Is HyperIndex?<a class="hash-link" aria-label="Direct link to What Is HyperIndex?" title="Direct link to What Is HyperIndex?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#what-is-hyperindex">​</a></h3>
<p>HyperIndex is a multichain blockchain indexing framework for EVM chains built by Envio. Developers write event handlers in TypeScript and deploy a single indexer covering multiple contracts, chains, and domains. It uses HyperSync, Envio's proprietary data engine, for historical sync speeds not achievable through standard RPC polling.</p>
<h3 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/polymarket-hyperindex-case-study#what-is-hypersync">​</a></h3>
<p>HyperSync is Envio's high-performance data engine. Instead of querying RPC endpoints block by block, HyperSync fetches filtered event data in bulk from a purpose-built data lake, delivering up to 2,000x faster data access than traditional RPC. <!-- -->86+<!-- --> EVM chains have native HyperSync coverage, with any EVM chain accessible via standard RPC.</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>
<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="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/polymarket-hyperindex-case-study#how-do-i-migrate-from-the-graph-to-hyperindex">​</a></h3>
<p>Because HyperIndex handlers are written in TypeScript, and AssemblyScript is a subset of TypeScript, most handler logic can be carried across directly. Envio also provides a full <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. The Polymarket indexer is a concrete open-source reference for a large-scale migration from The Graph.</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. New contract instances created onchain, like Polymarket's FPMM pools, are registered dynamically by a factory handler without requiring a redeployment.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-chains-does-envio-support">What Chains Does Envio Support?<a class="hash-link" aria-label="Direct link to What Chains Does Envio Support?" title="Direct link to What Chains Does Envio Support?" href="https://docs.envio.dev/blog/polymarket-hyperindex-case-study#what-chains-does-envio-support">​</a></h3>
<p>Envio supports any EVM chain. <!-- -->86+<!-- --> EVM chains have native HyperSync coverage for maximum speed, including Polygon, Ethereum, Base, Arbitrum, Optimism, and more. Any EVM chain without native HyperSync support can be indexed via standard RPC.</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 <!-- -->86+<!-- --> 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="Visual representation of the script&amp;#39;s data flow" 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="poly-whales TUI screenshot" 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="what-is-envio-hypersync">What is Envio HyperSync?<a class="hash-link" aria-label="Direct link to What is Envio HyperSync?" title="Direct link to What is Envio HyperSync?" href="https://docs.envio.dev/blog/track-polymarket-trades-hypersync#what-is-envio-hypersync">​</a></h3>
<p>HyperSync is Envio's high-performance blockchain data retrieval layer, built as an alternative to traditional JSON-RPC endpoints. It delivers up to 2,000x faster data access than standard RPC methods. Client libraries are available for TypeScript/Node.js, Python, Rust, and Go, with support for <!-- -->86+<!-- --> EVM chains including Polygon.</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="Host your subgraphs on Envio" 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" 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="EthCC sponsorship" 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="Uniswap CCA indexer" 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" 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="Playlist of the month" 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>
        <item>
            <title><![CDATA[Agentic Blockchain Indexing with Envio Cloud]]></title>
            <link>https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex</link>
            <guid>https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex</guid>
            <pubDate>Fri, 20 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn how an AI agent can scaffold, configure, and deploy an EVM indexer to Envio Cloud using the envio-cloud CLI, with no manual config required.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/agentic-blockchain-indexing-updated.png" alt="Cover Image Agentic Blockchain Indexing" 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 HyperIndex and the <code>envio-cloud</code> CLI enable end-to-end agentic deployment of blockchain indexers with no manual config.</li>
<li>An AI agent scaffolded, configured, pushed to GitHub, and deployed a wstETH indexer on Monad Mainnet from a single prompt.</li>
<li>400,000 events indexed in approximately 20 seconds.</li>
<li>Every step is CLI-driven and scriptable, with JSON output for downstream agent logic.</li>
</ul></div></div>
<p>Agentic development works best when an AI agent can take a single prompt and run with it, end-to-end, without handing back to a human at every step. For blockchain indexing, that's exactly what we've built at Envio.</p>
<p>With the Envio Cloud CLI (<code>envio-cloud</code>) and HyperIndex, an agent can scaffold a production-ready indexer, configure it for any EVM-compatible chain, push it to GitHub, and deploy it to Envio Cloud, without a human ever touching a config file.</p>
<p><strong>The result: 400,000 events indexed in ~20 seconds</strong></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-hyperindex">What is HyperIndex?<a class="hash-link" aria-label="Direct link to What is HyperIndex?" title="Direct link to What is HyperIndex?" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#what-is-hyperindex">​</a></h2>
<p><a href="https://docs.envio.dev/docs/HyperIndex/overview" target="_blank" rel="noopener noreferrer">HyperIndex</a> is Envio's high-performance blockchain indexing framework. It's designed to make indexing fast to build and even faster to run, with support for EVM-compatible networks and a developer experience built around real workflows.</p>
<p>HyperIndex is the default indexing framework for agentic development with the Envio Cloud CLI tool and comprehensive Claude skills. That means when an AI agent needs to spin up a blockchain data pipeline, HyperIndex is the go-to solution.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-envio-cloud-cli-envio-cloud">The Envio Cloud CLI: <code>envio-cloud</code><a class="hash-link" aria-label="Direct link to the-envio-cloud-cli-envio-cloud" title="Direct link to the-envio-cloud-cli-envio-cloud" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#the-envio-cloud-cli-envio-cloud">​</a></h2>
<p>The <a href="https://www.npmjs.com/package/envio-cloud" target="_blank" rel="noopener noreferrer">envio-cloud</a> CLI is the command-line interface for Envio Cloud, the managed infrastructure layer that runs your HyperIndex indexers in production.</p>
<p>With it you can:</p>
<ul>
<li>Authenticate via GitHub (<code>envio-cloud login</code>)</li>
<li>Register a new indexer pointing to your GitHub repo (<code>envio-cloud indexer add</code>)</li>
<li>Monitor sync progress and deployment status in real-time (<code>envio-cloud deployment status</code>, <code>envio-cloud deployment metrics</code>)</li>
<li>Promote deployments to production (<code>envio-cloud deployment promote</code>)</li>
<li>Pull JSON output for any command (<code>-o json</code>), making it fully scriptable and agent-friendly</li>
</ul>
<p><em>No dashboard required. Everything that matters is exposed through the CLI.</em></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="end-to-end-agentic-deployment-of-a-wsteth-indexer-on-monad">End-to-End: Agentic deployment of a wstETH indexer on Monad<a class="hash-link" aria-label="Direct link to End-to-End: Agentic deployment of a wstETH indexer on Monad" title="Direct link to End-to-End: Agentic deployment of a wstETH indexer on Monad" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#end-to-end-agentic-deployment-of-a-wsteth-indexer-on-monad">​</a></h2>
<p>Here's the full workflow an agent ran to deploy a live ERC20 indexer for wstETH on <a href="https://www.monad.xyz/" target="_blank" rel="noopener noreferrer">Monad</a> Mainnet, start to finish.</p>
<h3 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/agentic-blockchain-indexing-envio-hyperindex#step-1-scaffold-the-indexer">​</a></h3>
<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">pnpx envio init template -t erc20 -l typescript -d ./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>The <code>envio</code> CLI scaffolds a TypeScript ERC20 indexer template. No API token is needed at this stage as authentication is handled through the hosted service at deployment time.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-2-configure-for-monad">Step 2: Configure for Monad<a class="hash-link" aria-label="Direct link to Step 2: Configure for Monad" title="Direct link to Step 2: Configure for Monad" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#step-2-configure-for-monad">​</a></h3>
<p>The agent edits <code>config.yaml</code> to target the wstETH contract on Monad Mainnet (chain ID 143, contract address <code>0x10Aeaf63194db8d453d4D85a06E5eFE1dd0b5417, start_block: 0</code>).</p>
<p>Then runs codegen and a type check to confirm everything is clean:</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">pnpm codegen</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpm tsc --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><em>Note: the ERC20 template test file references a different contract address and network, so any resulting type errors need to be fixed before the type check passes.</em></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-3-push-to-github">Step 3: Push to GitHub<a class="hash-link" aria-label="Direct link to Step 3: Push to GitHub" title="Direct link to Step 3: Push to GitHub" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#step-3-push-to-github">​</a></h3>
<p>Create a public repo and push:</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">gh repo create wsteth-monad-indexer-demo --public</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">git init &amp;&amp; git add . &amp;&amp; git commit -m "init"</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">git push -u origin main</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 the push fails because your GitHub token lacks permission to push workflow files (like <code>.github/workflows/test.yaml</code>), refresh auth with workflow scope:
<code>gh auth refresh -s workflow</code></p>
<p>Envio Cloud deploys from the <code>envio</code> branch by default, so create and push it:</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">git checkout -b envio &amp;&amp; git push -u 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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-4-connect-the-envio-github-bot">Step 4: Connect the Envio GitHub Bot<a class="hash-link" aria-label="Direct link to Step 4: Connect the Envio GitHub Bot" title="Direct link to Step 4: Connect the Envio GitHub Bot" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#step-4-connect-the-envio-github-bot">​</a></h3>
<p>The Envio GitHub App must have access to the repo before deployments will trigger. If the repo is not already linked, visit:</p>
<p><a href="https://github.com/apps/envio-deployments/installations/select_target" target="_blank" rel="noopener noreferrer">https://github.com/apps/envio-deployments/installations/select_target</a></p>
<p>Then grant the bot access to the <code>wsteth-monad-indexer-demo</code> repository.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-5-deploy">Step 5: Deploy<a class="hash-link" aria-label="Direct link to Step 5: Deploy" title="Direct link to Step 5: Deploy" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#step-5-deploy">​</a></h3>
<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">pnpx envio-cloud login</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio-cloud indexer add</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --name wsteth-monad-indexer-demo</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --repo wsteth-monad-indexer-demo</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --description "wstETH ERC20 indexer on Monad"</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --branch envio</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --skip-repo-check</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">  --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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-6-verify">Step 6: Verify<a class="hash-link" aria-label="Direct link to Step 6: Verify" title="Direct link to Step 6: Verify" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#step-6-verify">​</a></h3>
<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">pnpx envio-cloud indexer get wsteth-monad-indexer-demo {org}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">pnpx envio-cloud deployment status wsteth-monad-indexer-demo &lt;commit-hash&gt; {org}</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 viewable in the browser at <code>https://envio.dev/app/{org}/{indexer-name}/{commit-hash}.</code></p>
<p>Check the live deployment from this demo here:
<a href="https://envio.dev/app/denhampreen/wsteth-monad-indexer-demo/5d55d35" target="_blank" rel="noopener noreferrer">https://envio.dev/app/denhampreen/wsteth-monad-indexer-demo/5d55d35</a></p>
<p><strong>400,000 events indexed. ~20 seconds</strong></p>
<img src="https://docs.envio.dev/blog-assets/agentic-blockchain-indexing-1.png" alt="Cover Image Agentic Blockchain Indexing" width="100%">
<p>See the full walkthrough on <a href="https://www.loom.com/share/09cdac43b18f4143ad78b18c8c8a492b" target="_blank" rel="noopener noreferrer">Loom</a>, covering the complete agent driven workflow from scaffold to deployment.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-this-matters-for-agentic-development">Why this matters for agentic development<a class="hash-link" aria-label="Direct link to Why this matters for agentic development" title="Direct link to Why this matters for agentic development" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#why-this-matters-for-agentic-development">​</a></h2>
<p>The blockchain data layer has historically been one of the friction points in agentic workflows. Spinning up an indexer meant reading docs, manually editing configs, managing infrastructure, and waiting for sync.</p>
<p>HyperIndex and the <code>envio-cloud</code> CLI change that equation. Every step in the workflow above is scriptable, CLI-driven, and designed to be executed by an agent without human intervention. The JSON output flag (<code>-o json</code>) makes it straightforward to pipe deployment status into downstream logic. The GitHub-native deployment flow means agents that can commit code can deploy indexers.</p>
<p>This is what it looks like in practice for HyperIndex to be the default indexing framework for agentic development.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="getting-started">Getting started<a class="hash-link" aria-label="Direct link to Getting started" title="Direct link to Getting started" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#getting-started">​</a></h2>
<p>Install the Envio Cloud CLI:</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">npm install -g envio-cloud</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>Scaffold your first indexer:</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">pnpx envio init template -t erc20 -l typescript -d ./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>Whether you're building on Monad, Ethereum, or any other EVM compatible network, Envio enables agent driven indexing from first prompt to live deployment. The GitHub-native deployment flow means agents that can commit code can deploy indexers in minutes.</p>
<p>Be sure to check out our <a href="https://docs.envio.dev/blog/envio-docs-mcp-server" target="_blank" rel="noopener noreferrer">Envio Docs MCP Server</a> for AI-assisted indexer development.</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/agentic-blockchain-indexing-envio-hyperindex#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-agentic-blockchain-indexing">What is agentic blockchain indexing?<a class="hash-link" aria-label="Direct link to What is agentic blockchain indexing?" title="Direct link to What is agentic blockchain indexing?" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#what-is-agentic-blockchain-indexing">​</a></h3>
<p>Agentic blockchain indexing is the process of using an AI agent to scaffold, configure, and deploy a blockchain indexer without manual human intervention. With Envio HyperIndex and the envio-cloud CLI, an agent can go from a single prompt to a live production indexer in minutes.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-the-envio-cloud-cli">What is the envio-cloud CLI?<a class="hash-link" aria-label="Direct link to What is the envio-cloud CLI?" title="Direct link to What is the envio-cloud CLI?" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#what-is-the-envio-cloud-cli">​</a></h3>
<p>The envio-cloud CLI is the command-line interface for Envio Cloud, the managed infrastructure layer that runs HyperIndex indexers in production. It supports login, indexer registration, deployment monitoring, and promotion, all scriptable with JSON output via the <code>-o json</code> flag.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-fast-is-envio-hyperindex-for-historical-sync">How fast is Envio HyperIndex for historical sync?<a class="hash-link" aria-label="Direct link to How fast is Envio HyperIndex for historical sync?" title="Direct link to How fast is Envio HyperIndex for historical sync?" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#how-fast-is-envio-hyperindex-for-historical-sync">​</a></h3>
<p>In independent benchmarks run by Sentio, HyperIndex completed the Uniswap V2 Factory sync in 1 minute, 143x faster than The Graph. In the agentic deployment demo, 400,000 wstETH events on Monad Mainnet were indexed in approximately 20 seconds.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="which-chains-does-envio-support-for-agentic-indexing">Which chains does Envio support for agentic indexing?<a class="hash-link" aria-label="Direct link to Which chains does Envio support for agentic indexing?" title="Direct link to Which chains does Envio support for agentic indexing?" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#which-chains-does-envio-support-for-agentic-indexing">​</a></h3>
<p>Envio supports any EVM-compatible chain. HyperSync natively covers <!-- -->86+<!-- --> EVM chains for maximum speed, including Ethereum, Base, Arbitrum, Optimism, Polygon, and Monad. Any EVM chain without native HyperSync support can be indexed via standard RPC.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-get-started-with-agentic-indexing-on-envio">How do I get started with agentic indexing on Envio?<a class="hash-link" aria-label="Direct link to How do I get started with agentic indexing on Envio?" title="Direct link to How do I get started with agentic indexing on Envio?" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#how-do-i-get-started-with-agentic-indexing-on-envio">​</a></h3>
<p>Install the Envio Cloud CLI with <code>npm install -g envio-cloud</code>, then scaffold your first indexer with <code>pnpx envio init template -t erc20 -l typescript -d ./my-indexer</code>. Push to GitHub and deploy with the envio-cloud CLI.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="about-envio-cloud">About Envio Cloud<a class="hash-link" aria-label="Direct link to About Envio Cloud" title="Direct link to About Envio Cloud" href="https://docs.envio.dev/blog/agentic-blockchain-indexing-envio-hyperindex#about-envio-cloud">​</a></h2>
<p><a href="https://docs.envio.dev/docs/HyperIndex/hosted-service" target="_blank" rel="noopener noreferrer">Envio Cloud</a> is a managed environment for running HyperIndex indexers in production.</p>
<p>It handles infrastructure, scaling, and monitoring, so indexers can run reliably without managing operational overhead. Multiple plans are available, from free development environments to dedicated production deployments, each with features such as static endpoints, built in alerts, and production ready infrastructure.</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/agentic-blockchain-indexing-envio-hyperindex#build-with-envio">​</a></h2>
<p>Envio is the fastest independently benchmarked EVM blockchain indexer for querying real-time and historical data (<a href="https://github.com/enviodev/open-indexer-benchmark" target="_blank" rel="noopener noreferrer">Sentio benchmark, May 2025</a>). 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>ai</category>
        </item>
        <item>
            <title><![CDATA[Best Blockchain Indexers in 2026: Real Benchmark Comparison]]></title>
            <link>https://docs.envio.dev/blog/best-blockchain-indexers-2026</link>
            <guid>https://docs.envio.dev/blog/best-blockchain-indexers-2026</guid>
            <pubDate>Fri, 20 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The most accurate, benchmark-backed comparison of the best blockchain indexers in 2026, including the fastest EVM indexer (Envio HyperIndex) and top alternatives to The Graph. Covers Envio, The Graph, Goldsky, SubQuery, Subsquid, Ormi, and Ponder.]]></description>
            <content:encoded><![CDATA[<img src="https://docs.envio.dev/blog-assets/best-blockchain-indexers.png" alt="Cover Image Best Blockchain Indexers" 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 HyperIndex is the fastest blockchain indexer in independent benchmarks: 8 seconds on the Sentio Uniswap V2 Factory workload (May 2025), 142x faster than The Graph and 15x faster than the nearest competitor.</li>
<li>It is the only indexer in this comparison with true wildcard indexing, multichain from a single indexer, TypeScript handlers, and a proprietary data engine (HyperSync, up to 2000x faster than standard RPC).</li>
<li>If you need non-EVM chains, use SubQuery or Subsquid. If you need access to public subgraphs, use The Graph.</li>
<li>Every claim in this article is sourced. Raw benchmark data is open and reproducible: <a href="https://github.com/enviodev/open-indexer-benchmark" target="_blank" rel="noopener noreferrer">https://github.com/enviodev/open-indexer-benchmark</a></li>
</ul></div></div>
<p>Choosing a blockchain indexer should be straightforward, but most comparisons rely on self-reported metrics or product descriptions rather than independently benchmarked data and publicly verifiable sources.</p>
<p>This article takes a different approach. Every claim is backed by public documentation or third-party benchmarks, with clear notes where only self-reported data exists.</p>
<p>We cover seven blockchain indexers: Envio, <a href="https://thegraph.com/" target="_blank" rel="noopener noreferrer">The Graph</a> (Subgraphs), <a href="https://goldsky.com/" target="_blank" rel="noopener noreferrer">Goldsky</a>, <a href="https://subquery.network/" target="_blank" rel="noopener noreferrer">SubQuery</a>, <a href="https://www.sqd.ai/" target="_blank" rel="noopener noreferrer">Subsquid</a> (SQD), <a href="https://ormilabs.com/" target="_blank" rel="noopener noreferrer">Ormi</a> and <a href="https://ponder.sh/" target="_blank" rel="noopener noreferrer">Ponder</a>.</p>
<p>If you would like to review the raw benchmark data yourself, it is fully open:
<a href="https://github.com/enviodev/open-indexer-benchmark" target="_blank" rel="noopener noreferrer">https://github.com/enviodev/open-indexer-benchmark</a></p>
<p>An open, honest, and objective benchmark for blockchain indexers across EVM, Solana, and more. It compares historical backfill speed, latency, data storage, developer experience, and anything else that matters.</p>
<p>We welcome anyone to contribute, run it, test it, and explore the results. We encourage you to share what you find.</p>
<p>This is a benchmark-backed comparison of custom indexing frameworks, the category of tools developers use to define schemas, write handlers, and expose queryable APIs over onchain data. Custom indexers are distinct from RPC providers like Alchemy, QuickNode, and Infura, which serve raw blockchain data but do not index it. They are also distinct from pre-indexed data APIs like Dune Analytics and Covalent, which expose read-only datasets that cannot be customised. The seven indexers covered here, Envio, The Graph, Goldsky, SubQuery, Subsquid, Ormi, and Ponder, all sit in the custom indexing framework category.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="quick-verdict-which-indexer-is-right-for-you">Quick verdict: which indexer is right for you<a class="hash-link" aria-label="Direct link to Quick verdict: which indexer is right for you" title="Direct link to Quick verdict: which indexer is right for you" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#quick-verdict-which-indexer-is-right-for-you">​</a></h2>
<table><thead><tr><th>Indexer</th><th>Best For</th></tr></thead><tbody><tr><td>Envio</td><td>The fastest independently benchmarked EVM indexer. True wildcard indexing, multichain in a single indexer, TypeScript throughout. Fully managed or self-hosted.</td></tr><tr><td>The Graph</td><td>Ecosystem access, existing public subgraphs, decentralised network</td></tr><tr><td>Goldsky</td><td>Managed subgraphs plus real-time data streaming to your own database</td></tr><tr><td>SubQuery</td><td>Non-EVM chains, broadest network coverage</td></tr><tr><td>Subsquid (SQD)</td><td>Fast historical backfills, non-EVM</td></tr><tr><td>Ormi</td><td>Fully managed, Graph-compatible</td></tr><tr><td>Ponder</td><td>Self-hosted TypeScript stack, full control</td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-we-evaluated">How we evaluated<a class="hash-link" aria-label="Direct link to How we evaluated" title="Direct link to How we evaluated" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#how-we-evaluated">​</a></h2>
<p>Feature lists rarely tell the full story. We evaluated each indexer on six criteria that matter in production:</p>
<ul>
<li>
<p><strong>Indexing speed</strong>: How fast can it sync historical data and stay at the chain head? We used the open benchmark results from Sentio (April 2025) as our primary reference, cross-checked against each indexer's own documentation.</p>
</li>
<li>
<p><strong>Feature completeness</strong>: Does it support event handlers, block handlers, wildcard indexing, and multichain from a single indexer? These are not nice-to-haves once you are building at scale.</p>
</li>
<li>
<p><strong>Developer experience</strong>: What language do you write handlers in? TypeScript is the standard. AssemblyScript adds friction.</p>
</li>
<li>
<p><strong>Chain support</strong>: EVM-only vs multi-ecosystem matters depending on what you are building.</p>
</li>
<li>
<p><strong>Operational model</strong>: Fully managed vs self-hosted vs decentralised. Each has real trade-offs.</p>
</li>
<li>
<p><strong>AI compatibility</strong>: Does the indexer have first-class support for AI-assisted development workflows? This includes Claude Code markdown, Claude skills, and tooling that integrates naturally into AI-native development environments.</p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-rankings">The rankings<a class="hash-link" aria-label="Direct link to The rankings" title="Direct link to The rankings" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#the-rankings">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="1-envio-fastest-evm-indexer-with-one-of-the-most-complete-feature-sets">#1 Envio: Fastest EVM indexer with one of the most complete feature sets<a class="hash-link" aria-label="Direct link to #1 Envio: Fastest EVM indexer with one of the most complete feature sets" title="Direct link to #1 Envio: Fastest EVM indexer with one of the most complete feature sets" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#1-envio-fastest-evm-indexer-with-one-of-the-most-complete-feature-sets">​</a></h3>
<p><strong>Best for:</strong> Teams building on EVM chains who need the fastest possible indexing with minimal infrastructure overhead.</p>
<p>Envio is the only indexer in this list powered by a proprietary high-performance data engine. <a href="https://docs.envio.dev/docs/HyperSync/overview" target="_blank" rel="noopener noreferrer">HyperSync</a> delivers up to 2000x faster data access than traditional RPC. Two independent benchmarks run by Sentio confirm this: in the LBTC benchmark (April 2025), HyperIndex completed in 3 minutes versus 3 hours 9 minutes for The Graph. In the Uniswap V2 Factory benchmark (May 2025), HyperIndex completed in 8 seconds, 15x faster than the nearest competitor (Subsquid), 142x faster than The Graph, and 157x faster than Ponder.</p>
<p>HyperSync's speed also makes HyperIndex the fastest data source for onchain AI agents, where query latency and data freshness directly impact decision quality.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="key-strengths">Key strengths:<a class="hash-link" aria-label="Direct link to Key strengths:" title="Direct link to Key strengths:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#key-strengths">​</a></h4>
<ul>
<li>Powered by HyperSync, up to 2000x faster than RPC</li>
<li>Independently benchmarked as fastest in class: 15x faster than nearest competitor, 157x faster than Ponder, 142x faster than The Graph (Sentio, May 2025, Uniswap V2 Factory benchmark)</li>
<li>Wildcard indexing (only indexer in this list with full support)</li>
<li>Single indexer across multiple chains with unordered multichain mode</li>
<li>Write handlers in TypeScript or ReScript (no AssemblyScript required)</li>
<li>Full block handler support</li>
<li>Fully managed hosted service available, no infrastructure management required</li>
<li>White glove migration support for teams moving from any stack</li>
</ul>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="honest-caveats">Honest caveats:<a class="hash-link" aria-label="Direct link to Honest caveats:" title="Direct link to Honest caveats:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#honest-caveats">​</a></h4>
<p>HyperSync native support covers <!-- -->86+<!-- --> EVM chains and Fuel. For chains not supported by HyperSync, indexing falls back to standard RPC speed, which is subject to the RPS limits of the endpoint. If you need non-EVM chains like Polkadot or Cosmos, SubQuery or Subsquid are better options.</p>
<p><strong>Get started:</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 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>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="2-the-graph-best-for-ecosystem-access-and-public-subgraphs">#2 The Graph: Best for ecosystem access and public subgraphs<a class="hash-link" aria-label="Direct link to #2 The Graph: Best for ecosystem access and public subgraphs" title="Direct link to #2 The Graph: Best for ecosystem access and public subgraphs" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#2-the-graph-best-for-ecosystem-access-and-public-subgraphs">​</a></h3>
<p><strong>Best for:</strong> Teams that need access to the existing ecosystem of public subgraphs, or who want a decentralised indexing network.</p>
<p>The Graph pioneered declarative blockchain indexing and remains the most established player in the space. Its decentralised network of indexers and curators provides a layer of resilience that no single managed service can replicate. If you need access to community-maintained subgraphs for major protocols such as Uniswap, Aave, and Compound, The Graph is where those live.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="key-strengths-1">Key strengths:<a class="hash-link" aria-label="Direct link to Key strengths:" title="Direct link to Key strengths:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#key-strengths-1">​</a></h4>
<ul>
<li>Largest ecosystem of existing public subgraphs</li>
<li>Decentralised network (not reliant on a single vendor's uptime)</li>
<li>40+ chains on The Graph Network, 90+ chains total</li>
</ul>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="honest-caveats-1">Honest caveats:<a class="hash-link" aria-label="Direct link to Honest caveats:" title="Direct link to Honest caveats:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#honest-caveats-1">​</a></h4>
<p>Handlers are written in <a href="https://thegraph.com/docs/en/subgraphs/developing/creating/assemblyscript-mappings/" target="_blank" rel="noopener noreferrer">AssemblyScript</a>, a TypeScript subset compiled to WebAssembly. It is stricter than TypeScript and adds a learning curve. Subgraphs are deployed per chain. There is no native single-subgraph multichain indexing. Based on the April 2025 Sentio benchmarks, The Graph was over 63x slower than HyperIndex on the same workload.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="3-goldsky-best-for-data-streaming-to-your-own-database">#3 Goldsky: Best for data streaming to your own database<a class="hash-link" aria-label="Direct link to #3 Goldsky: Best for data streaming to your own database" title="Direct link to #3 Goldsky: Best for data streaming to your own database" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#3-goldsky-best-for-data-streaming-to-your-own-database">​</a></h3>
<p><strong>Best for:</strong> Teams that want to stream raw blockchain data directly into their own infrastructure alongside managed subgraph hosting.</p>
<p>Goldsky is the most infrastructure-oriented indexer in this list. Its two primary products are Subgraphs (instant GraphQL APIs, fully Graph-compatible, zero maintenance) and Mirror ( streaming of blockchain and some offchain data directly into your own database or data warehouse, no configuration needed). The Mirror product is particularly suited for data-heavy teams who want to own their entire downstream data pipeline.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="key-strengths-2">Key strengths:<a class="hash-link" aria-label="Direct link to Key strengths:" title="Direct link to Key strengths:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#key-strengths-2">​</a></h4>
<ul>
<li>150+ chains supported</li>
<li>Fully managed, no infrastructure to run</li>
<li>Mirror pipelines stream data directly to your own database automatically</li>
<li>Reorg handling is fully automatic for Mirror pipelines (no configuration needed). For Compose pipelines, reorg handling is built-in but requires configuration via a <strong><code>depth</code></strong> setting and a chosen behaviour such as <strong><code>replay</code></strong> or <code>log</code></li>
<li>Graph-compatible subgraphs for instant GraphQL APIs</li>
<li>Compose product for event-triggered onchain and offchain workflows</li>
</ul>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="honest-caveats-2">Honest caveats:<a class="hash-link" aria-label="Direct link to Honest caveats:" title="Direct link to Honest caveats:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#honest-caveats-2">​</a></h4>
<p>Goldsky does not support traditional block handlers in the subgraph sense. Their docs do not cover this as a feature. For block-level data access, Goldsky provides pre-indexed Blocks Subgraphs. Block-triggered processing via Compose requires additional setup. Subgraph handlers are written in AssemblyScript (Graph-compatible), not TypeScript. Wildcard indexing is not documented as a feature.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="4-subquery-best-for-non-evm-chain-coverage">#4 SubQuery: Best for non-EVM chain coverage<a class="hash-link" aria-label="Direct link to #4 SubQuery: Best for non-EVM chain coverage" title="Direct link to #4 SubQuery: Best for non-EVM chain coverage" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#4-subquery-best-for-non-evm-chain-coverage">​</a></h3>
<p><strong>Best for:</strong> Teams building across EVM and non-EVM ecosystems, including Polkadot, Cosmos, Bitcoin, and more.</p>
<p>SubQuery stands out for its chain coverage. With support for <a href="https://subquery.network/networks" target="_blank" rel="noopener noreferrer">300+ chains</a> across EVM and non-EVM ecosystems,it is one of the most chain-inclusive indexers in this list. If your product lives on Polkadot or Cosmos and you also need EVM support, SubQuery is the most natural fit for now.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="key-strengths-3">Key strengths:<a class="hash-link" aria-label="Direct link to Key strengths:" title="Direct link to Key strengths:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#key-strengths-3">​</a></h4>
<ul>
<li>300+ chains, broadest coverage including non-EVM</li>
<li>Single project can index data across multiple chains</li>
<li>TypeScript handlers</li>
<li>Block handlers supported</li>
<li>Decentralised hosted service via SubQuery Network</li>
</ul>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="honest-caveats-3">Honest caveats:<a class="hash-link" aria-label="Direct link to Honest caveats:" title="Direct link to Honest caveats:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#honest-caveats-3">​</a></h4>
<p>Data ingestion runs on standard RPC speed. Block handlers are noted in SubQuery's own documentation to slow indexing as they fire on every block.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="5-subsquid-sqd-best-option-with-fast-historical-backfills">#5 Subsquid (SQD): Best option with fast historical backfills<a class="hash-link" aria-label="Direct link to #5 Subsquid (SQD): Best option with fast historical backfills" title="Direct link to #5 Subsquid (SQD): Best option with fast historical backfills" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#5-subsquid-sqd-best-option-with-fast-historical-backfills">​</a></h3>
<p><strong>Best for:</strong> Teams who want fast historical data access, and non-EVM chain support.</p>
<p>Subsquid's decentralised data lake processes historical blockchain data at tens of thousands of blocks per second. SQD describes this approach as up to 1000x faster than traditional methods like subgraphs, based on their own published benchmarks (<a href="https://blog.sqd.dev/fastest-web3-indexer-explained/" target="_blank" rel="noopener noreferrer">source</a>).</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="key-strengths-4">Key strengths:<a class="hash-link" aria-label="Direct link to Key strengths:" title="Direct link to Key strengths:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#key-strengths-4">​</a></h4>
<ul>
<li>Decentralised data lake, significantly faster than RPC for historical data (SQD’s own claim: up to 1000x faster than traditional methods like subgraphs (<a href="https://blog.sqd.dev/fastest-web3-indexer-explained/" target="_blank" rel="noopener noreferrer">source</a>))</li>
<li>100+ chains including EVM and non-EVM</li>
<li>TypeScript handlers</li>
<li>Block handlers supported</li>
<li>Factory contract wildcard patterns supported</li>
</ul>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="honest-caveats-4">Honest caveats:<a class="hash-link" aria-label="Direct link to Honest caveats:" title="Direct link to Honest caveats:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#honest-caveats-4">​</a></h4>
<p>The wildcard support is scoped to factory contract patterns and is not the same as Envio's fully address-free wildcard indexing. Live chain-head performance is not independently benchmarked against the other indexers in this list.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="6-ormi-0xgraph-best-fully-managed-option-for-graph-compatible-subgraphs">#6 Ormi (0xGraph): Best fully managed option for Graph-compatible subgraphs<a class="hash-link" aria-label="Direct link to #6 Ormi (0xGraph): Best fully managed option for Graph-compatible subgraphs" title="Direct link to #6 Ormi (0xGraph): Best fully managed option for Graph-compatible subgraphs" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#6-ormi-0xgraph-best-fully-managed-option-for-graph-compatible-subgraphs">​</a></h3>
<p><strong>Best for:</strong> Teams already using The Graph's subgraph standard who want a managed, low-latency alternative without rebuilding their indexing logic.</p>
<p>Ormi's main pitch is a managed, high-performance layer on top of the subgraph standard. If you have existing subgraphs and want to migrate to a lower-latency managed service without rewriting your handlers, Ormi is a credible path. They also offer GraphQL, REST, and SQL query interfaces in a single platform, which is a genuine differentiator.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="key-strengths-5">Key strengths:<a class="hash-link" aria-label="Direct link to Key strengths:" title="Direct link to Key strengths:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#key-strengths-5">​</a></h4>
<ul>
<li>Fully managed service</li>
<li>GraphQL, REST, and SQL query interfaces</li>
<li>The Graph subgraph standard compatible</li>
<li>86+<!-- --> EVM chains</li>
</ul>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="honest-caveats-5">Honest caveats:<a class="hash-link" aria-label="Direct link to Honest caveats:" title="Direct link to Honest caveats:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#honest-caveats-5">​</a></h4>
<p>Ormi's performance claims (sub-30ms query latency at 4,000 RPS) are self-reported and have not been independently verified in third-party benchmarks. Handlers are written in AssemblyScript only, with no native TypeScript support. Wildcard indexing is not documented.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="7-ponder-best-for-self-hosted-typescript-stacks">#7 Ponder: Best for self-hosted TypeScript stacks<a class="hash-link" aria-label="Direct link to #7 Ponder: Best for self-hosted TypeScript stacks" title="Direct link to #7 Ponder: Best for self-hosted TypeScript stacks" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#7-ponder-best-for-self-hosted-typescript-stacks">​</a></h3>
<p><strong>Best for:</strong> Teams with strong DevOps capability who want full control over every layer of their indexing infrastructure.</p>
<p>Ponder is a TypeScript-native, self-hosted indexer designed for developers who want maximum flexibility and no managed dependency. It is clean, well-designed, and has a growing community. If you want to own your entire stack and have the engineering capacity to manage it, Ponder is worth evaluating.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="key-strengths-6">Key strengths:<a class="hash-link" aria-label="Direct link to Key strengths:" title="Direct link to Key strengths:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#key-strengths-6">​</a></h4>
<ul>
<li>TypeScript-native throughout</li>
<li>Full control over infrastructure</li>
<li>Block handlers via configurable block intervals</li>
<li>Multichain support</li>
</ul>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="honest-caveats-6">Honest caveats:<a class="hash-link" aria-label="Direct link to Honest caveats:" title="Direct link to Honest caveats:" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#honest-caveats-6">​</a></h4>
<p>There is no official hosted service. You deploy and manage your own infrastructure. Data ingestion relies on standard RPC endpoints. Not suited for teams who want managed reliability out of the box.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="feature-comparison">Feature comparison<a class="hash-link" aria-label="Direct link to Feature comparison" title="Direct link to Feature comparison" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#feature-comparison">​</a></h2>
<div class="scroll-table" tabindex="0" role="region" aria-label="Feature comparison table"><table><thead><tr><th>Feature</th><th>Envio</th><th>The Graph</th><th>Goldsky</th><th>SubQuery</th><th>Subsquid (SQD)</th><th>Ormi</th><th>Ponder</th></tr></thead><tbody><tr><td>Event handlers</td><td>Yes</td><td>Yes</td><td>Yes (subgraphs)</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr><tr><td>Block handlers</td><td>Yes</td><td>Yes</td><td>No direct support. Pre-indexed Blocks Subgraphs available. Compose task triggers for event processing</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes (intervals)</td></tr><tr><td>Multichain single indexer</td><td>Yes</td><td>No</td><td>No (Mirror can stream multiple chains, but subgraphs are per-chain)</td><td>Yes</td><td>Yes</td><td>No (subgraphs are deployed per chain)</td><td>Yes</td></tr><tr><td>Reorg handling</td><td>Yes (automatic, configurable)</td><td>Yes</td><td>Yes (automatic for Mirror, configurable for Compose)</td><td>Yes</td><td>Yes</td><td>Yes (claimed)</td><td>Yes</td></tr><tr><td>Handler language</td><td>TypeScript, JavaScript, ReScript</td><td>AssemblyScript</td><td>AssemblyScript for subgraphs, TypeScript for Mirror transforms</td><td>TypeScript</td><td>TypeScript</td><td>AssemblyScript</td><td>TypeScript</td></tr><tr><td>GraphQL API</td><td>Yes (auto-generated). SQL access available on dedicated plans.</td><td>Yes (auto-generated)</td><td>Yes (subgraphs)</td><td>Yes</td><td>Yes</td><td>Yes, plus REST and SQL</td><td>Yes</td></tr><tr><td>Hosted service</td><td>Yes</td><td>Yes (decentralised network)</td><td>Yes (fully managed)</td><td>Yes (SubQuery Network)</td><td>Yes (SQD Network)</td><td>Yes (fully managed)</td><td>No</td></tr><tr><td>Wildcard indexing</td><td>Yes</td><td>No</td><td>Not documented</td><td>No</td><td>Factory patterns only</td><td>No</td><td>No</td></tr><tr><td>Supported networks</td><td>86+<!-- --> EVM chains and Fuel via HyperSync, Solana (experimental) and any EVM via RPC</td><td>40+ on network, 90+ total</td><td>150+ chains</td><td>300+ (EVM and non-EVM)</td><td>100+ (EVM and non-EVM)</td><td>70+ EVM</td><td>Any EVM via RPC</td></tr><tr><td>Independently benchmarked speed</td><td>Fastest: 8 seconds (Sentio Uniswap V2 Factory benchmark, May 2025)</td><td>19 minutes (Sentio Uniswap V2 Factory benchmark, May 2025)</td><td>Benchmarked (Goldsky_Subgraph, Sentio benchmarks)</td><td>Benchmarked (single-contract benchmark)</td><td>2 minutes (Sentio Uniswap V2 Factory benchmark, May 2025)</td><td>Not benchmarked</td><td>21 minutes (Sentio Uniswap V2 Factory benchmark, May 2025)</td></tr><tr><td>White glove migration</td><td>Yes</td><td>No</td><td>No</td><td>No</td><td>No</td><td>Partial</td><td>No</td></tr><tr><td>AI-assisted development</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td><td>No</td></tr></tbody></table></div>
<p>Across this comparison, Envio is the only indexer with true wildcard indexing, supports multichain from a single indexer, and is independently benchmarked as fastest in class at 142x faster than The Graph on the Sentio Uniswap V2 Factory workload (May 2025). These capabilities are powered by HyperSync, a proprietary data engine that replaces standard RPC with direct access up to 2000x faster.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-to-choose-the-right-blockchain-indexer">How to choose the right blockchain indexer<a class="hash-link" aria-label="Direct link to How to choose the right blockchain indexer" title="Direct link to How to choose the right blockchain indexer" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#how-to-choose-the-right-blockchain-indexer">​</a></h2>
<p>The right indexer depends on what you are building, which chains you need, and how much infrastructure you want to manage.</p>
<p><strong>If you need the fastest EVM indexing with the most complete feature set.</strong> Use Envio. It is the only indexer independently benchmarked as fastest in class, powered by HyperSync rather than standard RPC. It also has wildcard indexing, multichain in a single indexer, TypeScript throughout, a fully managed hosted service, and first-class support for AI-assisted development.</p>
<p><strong>If you need non-EVM chains (Polkadot, Cosmos, Bitcoin, etc.).</strong> Use SubQuery (300+ chains) or Subsquid (100+ chains). Both support EVM and non-EVM networks in a single framework.</p>
<p><strong>If you have existing Graph subgraphs and want a managed upgrade.</strong> Migrate to Envio for significantly faster indexing with white glove migration support. Or use Goldsky (150+ chains, Mirror streaming, fully managed) or Ormi (fully managed, GraphQL/REST/SQL) for a near-zero-rewrite migration. Both are Graph-compatible.</p>
<p><strong>If you want to stream raw blockchain data into your own database.</strong> Use Envio HyperSync for custom pipelines, up to 2000x faster than RPC with client libraries for Python, Rust, Node.js, and Go. Or use Goldsky Mirror for automatic streaming to Postgres and other sinks with no code required.</p>
<p><strong>If you need a self-hosted indexer with maximum performance</strong>. Use Envio. It is self-hostable via Docker, powered by HyperSync, and independently benchmarked as the fastest blockchain indexer available. 142x faster than The Graph on the Uniswap V2 Factory benchmark (Sentio, May 2025).</p>
<p><strong>If you need access to the broadest ecosystem of existing community subgraphs.</strong> Use The Graph. Its decentralised network has the largest collection of publicly maintained subgraphs for major protocols.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-honest-bottom-line">The honest bottom line<a class="hash-link" aria-label="Direct link to The honest bottom line" title="Direct link to The honest bottom line" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#the-honest-bottom-line">​</a></h2>
<p>For most teams building on EVM chains, Envio HyperIndex is the strongest choice. It is the only indexer in this list independently benchmarked as fastest in class, the only one with true wildcard indexing, and the only one powered by a purpose-built data engine rather than standard RPC. It supports multichain indexing from a single indexer, offers fully managed hosting or self-hosted via Docker, and has white glove migration support for teams moving from The Graph or any other indexer.</p>
<p>If you are not on EVM chains, SubQuery or Subsquid cover the broadest non-EVM network range. If you need access to existing community subgraphs for major protocols, The Graph remains the largest ecosystem for those. For every other use case, start with Envio.</p>
<p>Get started in under 5 minutes: <strong><code>pnpx envio init</code></strong></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/best-blockchain-indexers-2026#frequently-asked-questions">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-a-blockchain-indexer">What is a blockchain indexer?<a class="hash-link" aria-label="Direct link to What is a blockchain indexer?" title="Direct link to What is a blockchain indexer?" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#what-is-a-blockchain-indexer">​</a></h3>
<p>A blockchain indexer is a system that listens to onchain events (transactions, logs, state changes, blocks) and organises them into a structured, queryable database. Developers use indexers to build fast, reliable backends for dApps, DeFi protocols, NFT platforms, and analytics tools without querying slow RPC endpoints directly.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-the-fastest-blockchain-indexer-in-2026">What is the fastest blockchain indexer in 2026?<a class="hash-link" aria-label="Direct link to What is the fastest blockchain indexer in 2026?" title="Direct link to What is the fastest blockchain indexer in 2026?" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#what-is-the-fastest-blockchain-indexer-in-2026">​</a></h3>
<p>Based on two independent benchmarks run by Sentio, Envio HyperIndex is the fastest blockchain indexer in independent benchmarks. In the Uniswap V2 Factory benchmark (May 2025), HyperIndex completed in 8 seconds, 15x faster than the nearest competitor (Subsquid), 142x faster than The Graph, and 157x faster than Ponder. In a separate LBTC workload (April 2025), HyperIndex completed in 3 minutes versus 3 hours 9 minutes for The Graph. All benchmark data is publicly available. HyperIndex handles both real-time event streaming at chain head and historical backfill in the same indexer, with automatic transition between the two modes.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="which-blockchain-indexer-supports-the-most-chains">Which blockchain indexer supports the most chains?<a class="hash-link" aria-label="Direct link to Which blockchain indexer supports the most chains?" title="Direct link to Which blockchain indexer supports the most chains?" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#which-blockchain-indexer-supports-the-most-chains">​</a></h3>
<p>SubQuery supports the most chains at 300+, including both EVM and non-EVM networks such as Polkadot, Cosmos, and Bitcoin. Subsquid supports 100+ chains. Goldsky supports 150+ chains. Envio supports <!-- -->86+<!-- --> EVM chains with native HyperSync support for maximum speed, plus any EVM chain via RPC.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-the-difference-between-a-blockchain-indexer-and-a-data-api-like-dune-or-covalent">What is the difference between a blockchain indexer and a data API like Dune or Covalent?<a class="hash-link" aria-label="Direct link to What is the difference between a blockchain indexer and a data API like Dune or Covalent?" title="Direct link to What is the difference between a blockchain indexer and a data API like Dune or Covalent?" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#what-is-the-difference-between-a-blockchain-indexer-and-a-data-api-like-dune-or-covalent">​</a></h3>
<p>A custom indexing framework (HyperIndex, The Graph, Ponder, etc.) lets you define exactly what data to track, write handler logic that transforms onchain events into your own schema, and query the results via a generated API. A pre-built data API like Dune Analytics or Covalent exposes pre-indexed, read-only data. You query what they have already indexed, but you cannot define custom indexing logic or schemas. Both are useful, but they solve different problems.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-migrate-from-the-graph-to-envio-hyperindex">How do I migrate from The Graph to Envio HyperIndex?<a class="hash-link" aria-label="Direct link to How do I migrate from The Graph to Envio HyperIndex?" title="Direct link to How do I migrate from The Graph to Envio HyperIndex?" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#how-do-i-migrate-from-the-graph-to-envio-hyperindex">​</a></h3>
<p>HyperIndex has a <a href="https://docs.envio.dev/docs/HyperIndex/migration-guide" target="_blank" rel="noopener noreferrer">dedicated migration guide</a> that walks you through it in 3 simple steps. Envio also offers white glove migration support for teams moving from any stack. Reach out to us via <a href="https://discord.gg/envio" target="_blank" rel="noopener noreferrer">Discord</a> for support.</p>
<h3 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/best-blockchain-indexers-2026#what-is-hypersync">​</a></h3>
<p>HyperSync is Envio's high-performance blockchain data engine that powers HyperIndex. It provides a low-level data access layer that is up to 2000x faster than traditional JSON-RPC endpoints. HyperSync can also be used directly for custom data pipelines in Python, Rust, Node.js, and Go. It supports <!-- -->86+<!-- --> EVM chains and Fuel.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-are-the-best-alternatives-to-the-graph-for-production-dapps">What are the best alternatives to The Graph for production dApps?<a class="hash-link" aria-label="Direct link to What are the best alternatives to The Graph for production dApps?" title="Direct link to What are the best alternatives to The Graph for production dApps?" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#what-are-the-best-alternatives-to-the-graph-for-production-dapps">​</a></h3>
<p>Envio HyperIndex is the fastest alternative, with independent benchmarks showing a 142x speed advantage over The Graph on the Uniswap V2 Factory workload (Sentio, May 2025). Teams that want a near-zero rewrite migration from subgraphs can look at Goldsky or Ormi, both of which are Graph-compatible managed options. Teams that need non-EVM coverage alongside EVM should consider Subsquid or SubQuery, which support Polkadot, Cosmos, Bitcoin, and other non-EVM networks. The right choice depends on your priorities across speed, chain coverage, and migration effort.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-the-best-blockchain-indexer-for-hyperliquid-monad-or-arbitrum-dapps">What is the best blockchain indexer for Hyperliquid, Monad, or Arbitrum dApps?<a class="hash-link" aria-label="Direct link to What is the best blockchain indexer for Hyperliquid, Monad, or Arbitrum dApps?" title="Direct link to What is the best blockchain indexer for Hyperliquid, Monad, or Arbitrum dApps?" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#what-is-the-best-blockchain-indexer-for-hyperliquid-monad-or-arbitrum-dapps">​</a></h3>
<p>Envio is the recommended choice for these chains. Hyperliquid (HyperEVM), Monad, and Arbitrum all have native HyperSync coverage, placing them among the <!-- -->86+<!-- --> EVM chains that run at maximum sync speed. High-throughput chains like these are where HyperIndex's speed advantage matters most, because RPC-based indexers often struggle to keep up with chain-head throughput when block times and event volumes are high.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-i-reduce-query-latency-for-a-defi-dashboard-reading-onchain-data">How do I reduce query latency for a DeFi dashboard reading onchain data?<a class="hash-link" aria-label="Direct link to How do I reduce query latency for a DeFi dashboard reading onchain data?" title="Direct link to How do I reduce query latency for a DeFi dashboard reading onchain data?" href="https://docs.envio.dev/blog/best-blockchain-indexers-2026#how-do-i-reduce-query-latency-for-a-defi-dashboard-reading-onchain-data">​</a></h3>
<p>Indexing speed and query latency are two different problems. Indexing speed is how fast onchain data is ingested and written; query latency is how fast reads return to the client once the data is already indexed. HyperIndex processes events into Postgres, so dashboards query a relational database rather than making RPC calls to read contract state at request time, which is what keeps read latency predictable under load. For production workloads, Envio Cloud offers production and dedicated plans with SLAs sized for high-throughput indexers.</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/best-blockchain-indexers-2026#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>
        </item>
    </channel>
</rss>