<?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>Shutterblock.eth 📸💥 🦇🔊🛸</title>
        <link>https://paragraph.com/@cryptomastery</link>
        <description>aka Shutterblock.eth

BUIDLer | BuidlGuidl 🏰️
Developer Advocate | Scaffold-ETH 🏗️ 
Photographer and Filmmaker | @kevinjonescreates 📸</description>
        <lastBuildDate>Wed, 20 May 2026 20:40:51 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>Shutterblock.eth 📸💥 🦇🔊🛸</title>
            <url>https://storage.googleapis.com/papyrus_images/c040e3a28c12c7f0b6ab21b7f4234b2bbda0d265305e9f851df479e851fae863.jpg</url>
            <link>https://paragraph.com/@cryptomastery</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[🔍 How to Utilize TKN (Token Name Service) Subgraph for Searching 🪙 Token Symbols and Supported Chains ⛓️]]></title>
            <link>https://paragraph.com/@cryptomastery/how-to-utilize-tkn-token-name-service-subgraph-for-searching-token-symbols-and-supported-chains</link>
            <guid>HfmezyqYE32AfslB7o0v</guid>
            <pubDate>Tue, 14 May 2024 15:34:17 GMT</pubDate>
            <description><![CDATA[TKN, short for Token Name Service, is a decentralized protocol designed to manage a registry of token metadata on the Ethereum blockchain. It focuses on decentralization by storing all essential token information, including metadata and logos, directly on-chain, thereby boosting security and ensuring continuous data availability. This functionality is crucial for supporting a variety of decentralized applications (dapps), enabling transparent and verifiable interactions with token data. Furth...]]></description>
            <content:encoded><![CDATA[<p>TKN, short for Token Name Service, is a decentralized protocol designed to manage a registry of token metadata on the Ethereum blockchain. It focuses on decentralization by storing all essential token information, including metadata and logos, directly on-chain, thereby boosting security and ensuring continuous data availability. This functionality is crucial for supporting a variety of decentralized applications (dapps), enabling transparent and verifiable interactions with token data. Furthermore, TKN benefits from a subgraph on The Graph network, facilitating efficient data indexing and querying. This feature helps maintain a reliable and up-to-date dataset, accessible through decentralized methods. You can find the Token Name Service subgraph <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://thegraph.com/explorer/subgraphs/HxdDjjtznb8VFwqxAsHrfKUgjAUdziisERQdC1UcCr5U?v=0&amp;view=Playground&amp;chain=arbitrum-one">here</a>.</p><p>The following example demonstrates how to use the “where” filter to search for specific token symbols. This query provides detailed information about the token, including its name, ID, decimal precision, and a description if available, helping users efficiently access token data on supported chains.</p><pre data-type="codeBlock" text="{
  tokens(where: {symbol: &quot;GRT&quot;}) {
    id
    name
    symbol
    decimals
    tokenAddresses {
      address
      chainID {
        id
      }
    }
    description
  }
}
"><code>{
  <span class="hljs-title function_">tokens</span>(<span class="hljs-params">where: {<span class="hljs-built_in">symbol</span>: <span class="hljs-string">"GRT"</span>}</span>) {
    id
    name
    <span class="hljs-built_in">symbol</span>
    decimals
    tokenAddresses {
      address
      chainID {
        id
      }
    }
    description
  }
}
</code></pre><p>Here is the data response from that query.</p><pre data-type="codeBlock" text="{
  &quot;data&quot;: {
    &quot;tokens&quot;: [
      {
        &quot;decimals&quot;: &quot;18&quot;,
        &quot;description&quot;: &quot;Web3 GraphQL API&quot;,
        &quot;id&quot;: &quot;11&quot;,
        &quot;name&quot;: &quot;The Graph&quot;,
        &quot;symbol&quot;: &quot;GRT&quot;,
        &quot;tokenAddresses&quot;: [
          {
            &quot;address&quot;: &quot;0xc944E90C64B2c07662A292be6244BDf05Cda44a7&quot;,
            &quot;chainID&quot;: {
              &quot;id&quot;: &quot;1&quot;
            }
          },
          {
            &quot;address&quot;: &quot;0x9623063377AD1B27544C965cCd7342f7EA7e88C7&quot;,
            &quot;chainID&quot;: {
              &quot;id&quot;: &quot;42161&quot;
            }
          },
          {
            &quot;address&quot;: &quot;0x5fe2B58c013d7601147DcdD68C143A77499f5531&quot;,
            &quot;chainID&quot;: {
              &quot;id&quot;: &quot;137&quot;
            }
          }
        ]
      }
    ]
  }
}
"><code>{
  "data": {
    "tokens": [
      {
        "decimals": <span class="hljs-string">"18"</span>,
        <span class="hljs-string">"description"</span>: <span class="hljs-string">"Web3 GraphQL API"</span>,
        <span class="hljs-string">"id"</span>: <span class="hljs-string">"11"</span>,
        <span class="hljs-string">"name"</span>: <span class="hljs-string">"The Graph"</span>,
        <span class="hljs-string">"symbol"</span>: <span class="hljs-string">"GRT"</span>,
        <span class="hljs-string">"tokenAddresses"</span>: [
          {
            "<span class="hljs-selector-tag">address</span>": <span class="hljs-string">"0xc944E90C64B2c07662A292be6244BDf05Cda44a7"</span>,
            <span class="hljs-string">"chainID"</span>: {
              "id": <span class="hljs-string">"1"</span>
            }
          },
          {
            "<span class="hljs-selector-tag">address</span>": <span class="hljs-string">"0x9623063377AD1B27544C965cCd7342f7EA7e88C7"</span>,
            <span class="hljs-string">"chainID"</span>: {
              "id": <span class="hljs-string">"42161"</span>
            }
          },
          {
            "<span class="hljs-selector-tag">address</span>": <span class="hljs-string">"0x5fe2B58c013d7601147DcdD68C143A77499f5531"</span>,
            <span class="hljs-string">"chainID"</span>: {
              "id": <span class="hljs-string">"137"</span>
            }
          }
        ]
      }
    ]
  }
}
</code></pre><p>As you can see TKN lists contract addresses for GRT on three different chains.</p><ul><li><p>Address &quot;0xc944E90C64B2c07662A292be6244BDf05Cda44a7&quot; on Chain ID &quot;1&quot; (Ethereum Mainnet).</p></li><li><p>Address &quot;0x9623063377AD1B27544C965cCd7342f7EA7e88C7&quot; on Chain ID &quot;42161&quot; (Arbitrum One).</p></li><li><p>Address &quot;0x5fe2B58c013d7601147DcdD68C143A77499f5531&quot; on Chain ID &quot;137&quot; (Polygon Mainnet).</p></li></ul><p>The combination of Token Name Service and The Graph facilitates a more user-friendly and powerful ecosystem for blockchain applications, making it easier for users to interact with the blockchain and for developers to create powerful, decentralized applications. This integration contributes significantly to the overall usability and accessibility of blockchain technology.</p>]]></content:encoded>
            <author>cryptomastery@newsletter.paragraph.com (Shutterblock.eth 📸💥 🦇🔊🛸)</author>
        </item>
        <item>
            <title><![CDATA[👨‍🚀 Build a dApp quick with The Graph and Scaffold-ETH 2 🏗️]]></title>
            <link>https://paragraph.com/@cryptomastery/build-a-dapp-quick-with-the-graph-and-scaffold-eth-2</link>
            <guid>EqtnvNoTIdn1lEDICBUM</guid>
            <pubDate>Mon, 01 May 2023 05:29:37 GMT</pubDate>
            <description><![CDATA[What is Scaffold-ETH 2?In case you have been living under a rock for the last few years, one of the slickest toolkits for building on Ethereum is Scaffold-ETH. The main advantage to using Scaffold-ETH is that it is open-source, easy to use and comes with everything you will need to build and ship a decentralize application! 🚀 ⚙️ The new and improved version 2 of Scaffold-ETH is built using NextJS, RainbowKit, Hardhat, Wagmi, and Typescript✅ Contract Hot Reload: Your frontend auto-adapts to y...]]></description>
            <content:encoded><![CDATA[<h2 id="h-what-is-scaffold-eth-2" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What is Scaffold-ETH 2?</h2><p>In case you have been living under a rock for the last few years, one of the slickest toolkits for building on Ethereum is Scaffold-ETH. The main advantage to using Scaffold-ETH is that it is open-source, easy to use and comes with everything you will need to build and ship a decentralize application! 🚀</p><p>⚙️ The new and improved version 2 of Scaffold-ETH is built using NextJS, RainbowKit, Hardhat, Wagmi, and Typescript</p><ul><li><p>✅ Contract Hot Reload: Your frontend auto-adapts to your smart contract as you edit it.</p></li><li><p>🔥 Burner Wallet &amp; Local Faucet: Quickly test your application with a burner wallet and local faucet.</p></li><li><p>🔐 Integration with Wallet Providers: Connect to different wallet providers and interact with the Ethereum network.</p></li></ul><p>If you want to learn more about Scaffold-ETH 2, checkout the projects <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/scaffold-eth/scaffold-eth-2">README</a> on Github.</p><h2 id="h-why-should-i-use-the-graph" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why should I use The Graph?</h2><p>If you are building on Ethereum then you know that events are a critical part of your smart contract and are super important to help communicate changes to your front end and at the same time keep historical data about the dapp and its users. However dapps with large amounts of events being rendered in the frontend can exhibit major performance issues. This is where The Graph saves the day.</p><p>The Graph is a decentralized protocol for indexing and querying data from blockchains, starting with Ethereum. It makes it possible to query data that is difficult to query directly.</p><p>Developers who want to take advantage of The Graph protocol create Subgraphs. A subgraph is the secret sauce and tells how and where to extract and organize the blockchain data so that it can be easily queried via GraphQL.</p><p>If you want to learn more about The Graph you can visit their docs <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://thegraph.com/docs/en/about/">here</a>.</p><p>OK, so you want to build a dapp quickly and you want to also dabble with The Graph, where do you start? Well… you are in the right spot. Let’s get into this!</p><h2 id="h-setup-scaffold-eth-2" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Setup Scaffold-ETH 2</h2><p>First, we will start out with a special build of Scaffold-ETH 2 written by Simon from Edge and Node… Thanks Simon! 🫡</p><p>You will need the following installed on your machine before getting started.</p><h5 id="h-prerequisites" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Prerequisites</h5><ul><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://git-scm.com/downloads">Git</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://nodejs.org/en/download/">nodeJS (v18 LTS)</a></p></li><li><p>yarn package manager (<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://classic.yarnpkg.com/en/docs/install/">v1</a> or <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://yarnpkg.com/getting-started/install">v2+</a>)</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.docker.com/get-docker/">Docker Desktop</a></p></li></ul><p>First, we will start out with a special build of Scaffold-ETH 2 written by Simon from Edge and Node… Thanks Simon! 🫡</p><pre data-type="codeBlock" text="git clone -b subgraph-package \
  https://github.com/scaffold-eth/scaffold-eth-2.git \
  scaffold-eth-2-subgraph-package
"><code>git clone <span class="hljs-operator">-</span>b subgraph<span class="hljs-operator">-</span>package \
  https:<span class="hljs-comment">//github.com/scaffold-eth/scaffold-eth-2.git \</span>
  scaffold<span class="hljs-operator">-</span>eth<span class="hljs-number">-2</span><span class="hljs-operator">-</span>subgraph<span class="hljs-operator">-</span>package
</code></pre><p>Once you have this checked out on your machine, navigate into the directory and install all of the dependencies using yarn.</p><pre data-type="codeBlock" text="cd scaffold-eth-2-subgraph-package &amp;&amp; \
  yarn install
"><code>cd scaffold<span class="hljs-operator">-</span>eth<span class="hljs-number">-2</span><span class="hljs-operator">-</span>subgraph<span class="hljs-operator">-</span>package <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> \
  yarn install
</code></pre><p>Next**,** we will want to start up our local blockchain so that we can eventually deploy and test our smart contracts. Scaffold-ETH 2 comes with Hardhat by default. To spin up the chain just type the following yarn command…</p><pre data-type="codeBlock" text="yarn chain
"><code></code></pre><p>You will keep this window up and available so that you can see any output from hardhat console. 🖥️</p><p>Next we are going to spin up our frontend application. Scaffold-ETH 2 comes with NextJS by default and also can be started with a simple yarn command. You will need to open up a new command line and type the following…</p><pre data-type="codeBlock" text="yarn start
"><code>yarn <span class="hljs-keyword">start</span>
</code></pre><p>You will also want to keep this window up at all times so that you can debug any code changes you make to NextJS, debug performance or just check that the server is running properly.</p><p>Next, you will want to open up a third window where you can deploy your smart contract, along with some other useful commands found in Scaffold-ETH. To do a deploy you can simply run the following…</p><pre data-type="codeBlock" text="yarn deploy
"><code></code></pre><p>You should get a tx along with an address and amount of gas spent on the deploy. ⛽</p><p>If you navigate to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://localhost:3000">http://localhost:3000</a> you should see the following NextJS application. Explore the menus and features of Scaffold-ETH 2! Someone call in an emergency, cause hot damn that is fire! 🔥</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ce83ac1e582190f5737d24a1193334647af6ebf26e4ee16735152e95acc69a92.png" alt="Scaffold-ETH 2" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Scaffold-ETH 2</figcaption></figure><p>If you want to test that your dapp is functioning properly, grab some ETH from the faucet (upper right hand corner) and head over to the Example UI tab. Here you can set a new greeting! Just type whatever you like and click “Send” to execute a transaction.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/818466eea33d00e529629b0baf4f351c5efa87ce4ecb3d9b87586bcbd37d77c4.jpg" alt="Set a Greeting... I LOVE THE GRAPH" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Set a Greeting... I LOVE THE GRAPH</figcaption></figure><h2 id="h-setup-the-graph" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Setup The Graph</h2><p>Now that we have spun up our blockchain, started our frontend application and deployed our smart contract, we can start setting up our subgraph and utilize The Graph!</p><p>First, you will want to run the following to clean up any old data.</p><pre data-type="codeBlock" text="yarn clean-node
"><code>yarn clean<span class="hljs-operator">-</span>node
</code></pre><p>We can now spin up a graph node by running the following command… 🧑‍🚀</p><pre data-type="codeBlock" text="yarn run-node
"><code>yarn run-node
</code></pre><p>This will spin up all the containers for The Graph using docker-compose. You will want to keep this window open at all times so that you can see log output from Docker.</p><p><strong><em>Note: If you are running Docker Desktop on Mac you might encounter the following errors… If so please checkout this fix below.</em></strong></p><pre data-type="codeBlock" text="CRIT Database does not use C locale. Please check the graph-node documentation for how to set up the database locale, error: database collation is `en_US.utf8` but must be `C`, pool: main, shard: primary, component: ConnectionPool thread &apos;tokio-runtime-worker&apos; panicked at &apos;Database does not use C locale. Please check the graph-node documentation for how to set up the database locale: database collation is `en_US.utf8` but must be `C`&apos;, store/postgres/src/connection_pool.rs:976:13 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread &apos;main&apos; panicked at &apos;called `Result::unwrap()` on an `Err` value: JoinError::Panic(...)&apos;, /graph-node/store/postgres/src/connection_pool.rs:484:10
"><code>CRIT Database does not <span class="hljs-keyword">use</span> C locale. Please check the graph-node documentation <span class="hljs-keyword">for</span> <span class="hljs-title class_">how</span> to set up the database locale, error: database collation is `en_US.utf8` but must be `C`, pool: main, shard: primary, component: ConnectionPool thread <span class="hljs-symbol">'tokio</span>-runtime-worker' panicked at <span class="hljs-symbol">'Database</span> does not <span class="hljs-keyword">use</span> C locale. Please check the graph-node documentation <span class="hljs-keyword">for</span> <span class="hljs-title class_">how</span> to set up the database locale: database collation is `en_US.utf8` but must be `C`', store/postgres/src/connection_pool.rs:<span class="hljs-number">976</span>:<span class="hljs-number">13</span> note: run with `RUST_BACKTRACE=<span class="hljs-number">1</span>` environment variable to display a backtrace thread <span class="hljs-symbol">'main</span>' panicked at <span class="hljs-symbol">'called</span> `<span class="hljs-type">Result</span>::<span class="hljs-title function_ invoke__">unwrap</span>()` on an `<span class="hljs-literal">Err</span>` value: JoinError::<span class="hljs-title function_ invoke__">Panic</span>(...)', /graph-node/store/postgres/src/connection_pool.rs:<span class="hljs-number">484</span>:<span class="hljs-number">10</span>
</code></pre><p>To fix this, stop the existing node and clean up the data. 🧹</p><pre data-type="codeBlock" text="yarn stop-node &amp;&amp; yarn clean-node 
"><code>yarn stop<span class="hljs-operator">-</span>node <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> yarn clean<span class="hljs-operator">-</span>node 
</code></pre><p>Then add the following to the environment section of your <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/graphprotocol/graph-node/blob/master/docker/docker-compose.yml">docker-compose.yml</a> file.</p><pre data-type="codeBlock" text="      # workaround for https://github.com/docker/for-mac/issues/6270?
      PGDATA: &quot;/var/lib/postgresql/data&quot;
      POSTGRES_INITDB_ARGS: &quot;-E UTF8 --locale=C&quot;
"><code>      <span class="hljs-meta"># workaround for https:<span class="hljs-comment">//github.com/docker/for-mac/issues/6270?</span></span>
      PGDATA: <span class="hljs-string">"/var/lib/postgresql/data"</span>
      POSTGRES_INITDB_ARGS: <span class="hljs-string">"-E UTF8 --locale=C"</span>
</code></pre><p>Then go ahead and start it up again.</p><pre data-type="codeBlock" text="yarn run-node
"><code>yarn run-node
</code></pre><p>As stated before, be sure to keep this window open so that you can see any log output from Docker. 🔎</p><p>Now we can open up a fourth window to finish setting up The Graph. 😅 If you have been following along your windows should look something like this… bonus points if you use <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/tmux/tmux/wiki">tmux</a> like me. ;)</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/bc8310248d3852100e2bff2785d98929353c3a56c4fad200612fd4a5cbfc11ed.jpg" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>In this forth window we will create our local subgraph! You will only need to do this once.</p><pre data-type="codeBlock" text="yarn local-create
"><code>yarn <span class="hljs-keyword">local</span>-<span class="hljs-built_in">create</span>
</code></pre><p>You should see some output stating your Subgraph has been created along with a log output on your graph-node inside docker.</p><p>Next we will ship our subgraph! You will need to give your subgraph a version after executing this command. (e.g. 0.0.1).</p><pre data-type="codeBlock" text="yarn local-ship
"><code>yarn <span class="hljs-keyword">local</span>-ship
</code></pre><p>This command does the following all in one… 🚀🚀🚀</p><ul><li><p>Copies the contracts ABI from the hardhat/deployments folder</p></li><li><p>Generates the networks.json file</p></li><li><p>Generates AssemblyScript types from the subgraph schema and the contract ABIs.</p></li><li><p>Compiles and checks the mapping functions.</p></li><li><p>… and deploy a local subgraph!</p></li></ul><p>You should get a build completed output along with the address of your Subgraph endpoint.</p><pre data-type="codeBlock" text="Build completed: QmYdGWsVSUYTd1dJnqn84kJkDggc2GD9RZWK5xLVEMB9iP

Deployed to http://localhost:8000/subgraphs/name/scaffold-eth/your-contract/graphql

Subgraph endpoints:
Queries (HTTP):     http://localhost:8000/subgraphs/name/scaffold-eth/your-contract
"><code>Build completed: QmYdGWsVSUYTd1dJnqn84kJkDggc2GD9RZWK5xLVEMB9iP

Deployed to http://localhost:8000/subgraphs/name/scaffold-eth/your-contract/graphql

Subgraph endpoints:
Queries (HTTP):     http://localhost:8000/subgraphs/name/scaffold-eth/your-contract
</code></pre><p>Go ahead and head over to your subgraph endpoint and take a look!</p><p>Here is an example query…</p><pre data-type="codeBlock" text="  {
    greetings(first: 25, orderBy: createdAt, orderDirection: desc) {
      id
      greeting
      premium
      value
      createdAt
      sender {
        address
        greetingCount
      }
    }
  }
"><code>  {
    <span class="hljs-selector-tag">greetings</span>(<span class="hljs-attribute">first</span>: <span class="hljs-number">25</span>, <span class="hljs-attribute">orderBy</span>: createdAt, <span class="hljs-attribute">orderDirection</span>: desc) {
      <span class="hljs-selector-tag">id</span>
      <span class="hljs-selector-tag">greeting</span>
      <span class="hljs-selector-tag">premium</span>
      <span class="hljs-selector-tag">value</span>
      <span class="hljs-selector-tag">createdAt</span>
      <span class="hljs-selector-tag">sender</span> {
        <span class="hljs-selector-tag">address</span>
        <span class="hljs-selector-tag">greetingCount</span>
      }
    }
  }
</code></pre><p>If all is well and you’ve sent a transaction to your smart contract then you will see a similar data output!</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/62c084e02ea59299901795538104c7c048c9b1f28a3b0301cb0eb7cb06b4a4a2.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Next up we will dive into a bit more detail on how The Graph works so that as you start adding events to your smart contract you can start indexing and parsing the data you need for your front end application.</p><h2 id="h-adding-additional-events" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Adding Additional Events</h2><p>In my <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mirror.xyz/cryptomastery.eth/8Rt4rbJA_h2tspkVPNauvCwEmvttHB1GaycMjAdvO90">previous post</a>, I outline all of the changes that you need to make in order to add an event to The Graph but I will outline them here in case anyone needs to catch up on how this is done.</p><p>In general to create a subgraph you need to do the following…</p><ol><li><p>Create your entities (located in schema.graphql)</p></li><li><p>Crete mapping functions (mappings.ts)</p></li><li><p>Configure your subgraph data sources (subgraph.yaml)</p></li></ol><p>If you want to read more please checkout <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/scaffold-eth/scaffold-eth-2/tree/subgraph-package/packages/subgraph#:~:text=https%3A//thegraph.com/docs/en/developing/creating%2Da%2Dsubgraph/">these</a> docs. Let’s use the example from my previous post. Here is an example event for sending messages on the Ethereum blockchain.</p><pre data-type="codeBlock" text="event SendMessage(address _from, address _to, string message);

function sendMessage(address _to, string calldata message) external {
    emit SendMessage(msg.sender, _to, message);
}
"><code><span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">SendMessage</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _from, <span class="hljs-keyword">address</span> _to, <span class="hljs-keyword">string</span> message</span>)</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendMessage</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _to, <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> message</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
    <span class="hljs-keyword">emit</span> SendMessage(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, _to, message);
}
</code></pre><p>After you add an event to your smart contract, you will need to first update the GraphQL schema to include the entities you want to store on your Graph node. If you want to catch up on entities <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://thegraph.com/docs/en/developing/creating-a-subgraph/#defining-entities">here</a> is a good link to the docs for that.</p><p>So, using our message example above, if we wanted to create entities for the Message, the Messenger and the Receiver… this is probably a concise example on how we could link that data using our schema.</p><p><em>The schema file is located in packages/subgraph/src/schema.graphql</em></p><pre data-type="codeBlock" text="type Message @entity {
  id: ID!
  _from: Messenger!
  _to: Receiver!
  message: String!
  createdAt: BigInt!
  transactionHash: String!
}

type Messenger @entity {
  id: ID!
  address: Bytes!
  messages: [Message!] @derivedFrom(field: &quot;_from&quot;)
  createdAt: BigInt!
  messageCount: BigInt!
}

type Receiver @entity {
  id: ID!
  address: Bytes!
  createdAt: BigInt!
  messageCount: BigInt!
}
"><code><span class="hljs-keyword">type</span> Message @entity {
  id: ID<span class="hljs-operator">!</span>
  _from: Messenger<span class="hljs-operator">!</span>
  _to: Receiver<span class="hljs-operator">!</span>
  message: String<span class="hljs-operator">!</span>
  createdAt: BigInt<span class="hljs-operator">!</span>
  transactionHash: String<span class="hljs-operator">!</span>
}

<span class="hljs-keyword">type</span> Messenger @entity {
  id: ID<span class="hljs-operator">!</span>
  <span class="hljs-keyword">address</span>: Bytes<span class="hljs-operator">!</span>
  messages: [Message<span class="hljs-operator">!</span>] @derivedFrom(field: <span class="hljs-string">"_from"</span>)
  createdAt: BigInt<span class="hljs-operator">!</span>
  messageCount: BigInt<span class="hljs-operator">!</span>
}

<span class="hljs-keyword">type</span> Receiver @entity {
  id: ID<span class="hljs-operator">!</span>
  <span class="hljs-keyword">address</span>: Bytes<span class="hljs-operator">!</span>
  createdAt: BigInt<span class="hljs-operator">!</span>
  messageCount: BigInt<span class="hljs-operator">!</span>
}
</code></pre><p>You will also need to add these entities to the Subgraph YAML configuration and also add the event handlers as well.</p><p><em>This file is located in packages/subgraph/subgraph.yaml</em></p><pre data-type="codeBlock" text="entities:
        - Greeting
        - Sender
        - Message
        - Messenger
        - Receiver
"><code>entities:
<span class="hljs-bullet">        -</span> Greeting
<span class="hljs-bullet">        -</span> Sender
<span class="hljs-bullet">        -</span> Message
<span class="hljs-bullet">        -</span> Messenger
<span class="hljs-bullet">        -</span> Receiver
</code></pre><pre data-type="codeBlock" text="eventHandlers:
        - event: SendMessage(address,address,string)
          handler: handleMessage
"><code>eventHandlers:
        <span class="hljs-operator">-</span> <span class="hljs-function"><span class="hljs-keyword">event</span>: <span class="hljs-title">SendMessage</span>(<span class="hljs-params"><span class="hljs-keyword">address</span>,<span class="hljs-keyword">address</span>,<span class="hljs-keyword">string</span></span>)
          <span class="hljs-title">handler</span>: <span class="hljs-title">handleMessage</span>
</span></code></pre><p>If you are following along, next you will need to copy over your new abi and regenerate the code.</p><pre data-type="codeBlock" text="yarn abi-copy &amp;&amp; yarn codegen
"><code>yarn <span class="hljs-built_in">abi</span><span class="hljs-operator">-</span>copy <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> yarn codegen
</code></pre><p>Next you will need to update the mappings for the files we have edited above.</p><p><em>The file is located under packages/subgraph/src/mapping.ts</em></p><pre data-type="codeBlock" text="import {
  YourContract,
  GreetingChange,
  SendMessage,
} from &quot;../generated/YourContract/YourContract&quot;;
"><code><span class="hljs-keyword">import</span> {
  <span class="hljs-title class_">YourContract</span>,
  <span class="hljs-title class_">GreetingChange</span>,
  <span class="hljs-title class_">SendMessage</span>,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"../generated/YourContract/YourContract"</span>;
</code></pre><p>As well as the schema file we edited earlier.</p><pre data-type="codeBlock" text="import {
  Greeting,
  Sender,
  Messenger,
  Receiver,
  Message,
} from &quot;../generated/schema&quot;;
"><code><span class="hljs-keyword">import</span> {
  <span class="hljs-title class_">Greeting</span>,
  <span class="hljs-title class_">Sender</span>,
  <span class="hljs-title class_">Messenger</span>,
  <span class="hljs-title class_">Receiver</span>,
  <span class="hljs-title class_">Message</span>,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"../generated/schema"</span>;
</code></pre><p>Lastly, we will need to add the mapping function.</p><pre data-type="codeBlock" text="export function handleMessage(event: SendMessage): void {
  let messengerString = event.params._from.toHexString();
  let receiverString = event.params._to.toHexString();

  let messenger = Messenger.load(messengerString);

  if (messenger === null) {
    messenger = new Messenger(messengerString);
    messenger.address = event.params._from;
    messenger.createdAt = event.block.timestamp;
    messenger.messageCount = BigInt.fromI32(1);
  } else {
    messenger.messageCount = messenger.messageCount.plus(BigInt.fromI32(1));
  }

  let receiver = Receiver.load(receiverString);

  if (receiver === null) {
    receiver = new Receiver(receiverString);
    receiver.address = event.params._from;
    receiver.createdAt = event.block.timestamp;
    receiver.messageCount = BigInt.fromI32(1);
  } else {
    receiver.messageCount = receiver.messageCount.plus(BigInt.fromI32(1));
  }

  let message = new Message(
    event.transaction.hash.toHex() + &quot;-&quot; + event.logIndex.toString()
  );

  message.message = event.params.message;
  message._from = messengerString;
  message._to = receiverString;
  message.createdAt = event.block.timestamp;
  message.transactionHash = event.transaction.hash.toHex();

  receiver.save();
  messenger.save();
  message.save();
}
"><code>export <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleMessage</span>(<span class="hljs-params"><span class="hljs-keyword">event</span>: SendMessage</span>): <span class="hljs-title">void</span> </span>{
  let messengerString <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.params._from.toHexString();
  let receiverString <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.params._to.toHexString();

  let messenger <span class="hljs-operator">=</span> Messenger.load(messengerString);

  <span class="hljs-keyword">if</span> (messenger <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> null) {
    messenger <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Messenger(messengerString);
    messenger.<span class="hljs-built_in">address</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.params._from;
    messenger.createdAt <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.block.timestamp;
    messenger.messageCount <span class="hljs-operator">=</span> BigInt.fromI32(<span class="hljs-number">1</span>);
  } <span class="hljs-keyword">else</span> {
    messenger.messageCount <span class="hljs-operator">=</span> messenger.messageCount.plus(BigInt.fromI32(<span class="hljs-number">1</span>));
  }

  let receiver <span class="hljs-operator">=</span> Receiver.load(receiverString);

  <span class="hljs-keyword">if</span> (receiver <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> null) {
    receiver <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Receiver(receiverString);
    receiver.<span class="hljs-built_in">address</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.params._from;
    receiver.createdAt <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.block.timestamp;
    receiver.messageCount <span class="hljs-operator">=</span> BigInt.fromI32(<span class="hljs-number">1</span>);
  } <span class="hljs-keyword">else</span> {
    receiver.messageCount <span class="hljs-operator">=</span> receiver.messageCount.plus(BigInt.fromI32(<span class="hljs-number">1</span>));
  }

  let message <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Message(
    <span class="hljs-keyword">event</span>.transaction.hash.toHex() <span class="hljs-operator">+</span> <span class="hljs-string">"-"</span> <span class="hljs-operator">+</span> <span class="hljs-keyword">event</span>.logIndex.toString()
  );

  message.message <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.params.message;
  message._from <span class="hljs-operator">=</span> messengerString;
  message._to <span class="hljs-operator">=</span> receiverString;
  message.createdAt <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.block.timestamp;
  message.transactionHash <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.transaction.hash.toHex();

  receiver.save();
  messenger.save();
  message.save();
}
</code></pre><p>After that is done, you are almost done… Simple ship it!</p><pre data-type="codeBlock" text="yarn local-ship
"><code>yarn <span class="hljs-keyword">local</span>-ship
</code></pre><p>If you want to test this out on your own instance of Scaffold-ETH, navigate over to the Debug Contracts tab. Here you can draft up a message and fire it off.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d879154ece18f1b0edae66ddfbd5dfc7fb91a2c61b8335a514291192406a5969.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Next, lets see if our data is in The Graph. Here is an example query that shows us the first message.</p><pre data-type="codeBlock" text="{
    messages(first: 1, orderBy: createdAt, orderDirection: asc) {
      id
      _from {
        messages(first: 1) {
          message
        }
      }
    }
  }
"><code>{
    <span class="hljs-title function_">messages</span>(<span class="hljs-params">first: <span class="hljs-number">1</span>, orderBy: createdAt, orderDirection: asc</span>) {
      id
      _from {
        <span class="hljs-title function_">messages</span>(<span class="hljs-params">first: <span class="hljs-number">1</span></span>) {
          message
        }
      }
    }
  }
</code></pre><p>Drumroll…..</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/09a4831e46e2df5650d7ef14f95c60fee586f1f5498696797b7c43cdb18f699c.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Woohoo! You did it… I guess you are ready for a hackathon eh?</p><h2 id="h-querying-from-an-application" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Querying from an Application</h2><p>Now that you have your subgraph working, the final step in the evolution of your dapp is to query that data from within your application. If you want to dive into the docs, you can read more about this topic <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://thegraph.com/docs/en/querying/querying-from-an-application/">here</a>.</p><p>There are a number of GraphQL Client libraries which allow you to query the subgraph and populate your app with the data indexed by the subgraph.</p><p>One of the more popular clients is <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://thegraph.com/docs/en/querying/querying-from-an-application/#apollo-client">Apollo client</a> and is included with this special build of Scaffold-ETH. I will walk thru the basic configuration here.</p><p>First you will see that ApolloClient is already imported to the root of your application</p><p><em>located in packages/nextjs/pages/_app.tsx</em></p><pre data-type="codeBlock" text="import { ApolloClient, ApolloProvider, InMemoryCache } from &quot;@apollo/client&quot;;
"><code><span class="hljs-keyword">import</span> { <span class="hljs-title class_">ApolloClient</span>, <span class="hljs-title class_">ApolloProvider</span>, <span class="hljs-title class_">InMemoryCache</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"@apollo/client"</span>;
</code></pre><p>The URI for the subgraph and client have already been configured for you as well.</p><pre data-type="codeBlock" text="  const subgraphUri = &quot;http://localhost:8000/subgraphs/name/scaffold-eth/your-contract&quot;;
  const apolloClient = new ApolloClient({
    uri: subgraphUri,
    cache: new InMemoryCache(),
  });
"><code>  const <span class="hljs-attr">subgraphUri</span> = <span class="hljs-string">"http://localhost:8000/subgraphs/name/scaffold-eth/your-contract"</span><span class="hljs-comment">;</span>
  const <span class="hljs-attr">apolloClient</span> = new ApolloClient({
    uri: subgraphUri,
    cache: new InMemoryCache(),
  })<span class="hljs-comment">;</span>
</code></pre><p>The provider is wrapped within the application.</p><pre data-type="codeBlock" text="return(
  &lt;ApolloProvider client={apolloClient}&gt;
  ...
  &lt;/ApolloProvider&gt;
);
"><code><span class="hljs-keyword">return</span>(
  <span class="hljs-operator">&#x3C;</span>ApolloProvider client<span class="hljs-operator">=</span>{apolloClient}<span class="hljs-operator">></span>
  ...
  <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>ApolloProvider<span class="hljs-operator">></span>
);
</code></pre><p>Looking at the ContractData page you will see the hooks have been imported.</p><p><em>This is located in packages/nextjs/components/example-ui/ContractData.tsx</em></p><pre data-type="codeBlock" text="import { gql, useQuery } from &quot;@apollo/client&quot;;
"><code><span class="hljs-keyword">import</span> { gql, useQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">"@apollo/client"</span>;
</code></pre><p>Along with an example graphql query.</p><pre data-type="codeBlock" text="  const GREETINGS_GRAPHQL = `
  {
    greetings(first: 1, orderBy: createdAt, orderDirection: desc) {
      id
      greeting
      premium
      value
      createdAt
      sender {
        address
        greetingCount
      }
    }
  }
  `;

  const GREETINGS_GQL = gql(GREETINGS_GRAPHQL);
  const greetingsData = useQuery(GREETINGS_GQL, { pollInterval: 1000 });
"><code>  const <span class="hljs-attr">GREETINGS_GRAPHQL</span> = `
  {
    greetings(first: 1, orderBy: createdAt, orderDirection: desc) {
      id
      greeting
      premium
      value
      createdAt
      sender {
        address
        greetingCount
      }
    }
  }
  `<span class="hljs-comment">;</span>

  const <span class="hljs-attr">GREETINGS_GQL</span> = gql(GREETINGS_GRAPHQL)<span class="hljs-comment">;</span>
  const <span class="hljs-attr">greetingsData</span> = useQuery(GREETINGS_GQL, { pollInterval: <span class="hljs-number">1000</span> })<span class="hljs-comment">;</span>
</code></pre><p>Now you can build out some ultra fast frontend code for your dapp! 🔥🔥🔥</p><h2 id="h-so-what-next" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">So what next?</h2><p>All the building we’ve done has been locally. At some point you will want to launch your decentralized application to the next level, a public testnet!! Or possibly even YOLO to mainnet. 😂 The world is your oyster.</p><p>In my next blog post, I will cover exactly how to do that using Scaffold-ETH 2, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/graphprotocol/graph-tooling">The Graph CLI</a> and the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://thegraph.com/studio/">Subgraph Studio</a>! Until then… keep BUIDLing my frens.</p>]]></content:encoded>
            <author>cryptomastery@newsletter.paragraph.com (Shutterblock.eth 📸💥 🦇🔊🛸)</author>
        </item>
        <item>
            <title><![CDATA[Scaffold-ETH 🏗️ + The Graph 👨‍🚀🚀= ❤️ - Kevin | Crypto Mastery]]></title>
            <link>https://paragraph.com/@cryptomastery/scaffold-eth-the-graph-kevin-crypto-mastery</link>
            <guid>KWIKyvfAYpghFIQI2zN0</guid>
            <pubDate>Sat, 04 Jun 2022 16:50:56 GMT</pubDate>
            <description><![CDATA[If you are building on Ethereum then you know that events are a critical part of your smart contract and are super important to help communicate changes to your front end and at the same time keep historical data about the dapp and its users. However dapps with large amounts of events being rendered in the frontend can exhibit major performance issues. This is where The Graph saves the day.The Graph The Graph is a decentralized protocol for indexing and querying data from blockchains, startin...]]></description>
            <content:encoded><![CDATA[<p>If you are building on Ethereum then you know that events are a critical part of your smart contract and are super important to help communicate changes to your front end and at the same time keep historical data about the dapp and its users. However dapps with large amounts of events being rendered in the frontend can exhibit major performance issues. This is where The Graph saves the day.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8ade56c532566d9ff12c7baabec893753394781eada222a3bcf35862a2326ebc.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>The Graph</p><p>The Graph is a decentralized protocol for indexing and querying data from blockchains, starting with Ethereum. It makes it possible to query data that is difficult to query directly.</p><p>The Graph learns what and how to index Ethereum data based on subgraph descriptions, known as the subgraph manifest. The subgraph description defines the smart contracts of interest for a subgraph, the events in those contracts to pay attention to, and how to map event data to data that The Graph will store in its database.</p><p>If you want to learn more about The Graph you can visit their docs <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://thegraph.com/docs/en/about/introduction/">here</a>.</p><p>OK, so you want to build a dapp quickly and you want to also dabble with The Graph, where do you start? Setting up a development environment for building on Ethereum can be difficult to do and if you are just starting out in web3 development it can really slow you down. This is where Scaffold-ETH really makes it easy. Scaffold-ETH has everything you need to start building on Ethereum and support for subgraphs out of the box. Scaffold-ETH is Open source and can be found on github.</p><h2 id="h-setup-scaffold-eth" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Setup Scaffold-ETH</h2><p>Lets walkthrough the process of getting setup with Scaffold-ETH and The Graph. Some prerequisites: <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://nodejs.org/en/download/">Node (v16 LTS)</a> plus <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://classic.yarnpkg.com/en/docs/install/">Yarn</a> and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://git-scm.com/downloads">Git</a></p><ol><li><p>Checkout Scaffold-ETH and install requirements</p></li></ol><pre data-type="codeBlock" text="git clone https://github.com/scaffold-eth/scaffold-eth.git scaffold-eth-graph-demo
cd scaffold-eth-graph-demo
yarn install
"><code>git clone https:<span class="hljs-comment">//github.com/scaffold-eth/scaffold-eth.git scaffold-eth-graph-demo</span>
cd scaffold<span class="hljs-operator">-</span>eth<span class="hljs-operator">-</span>graph<span class="hljs-operator">-</span>demo
yarn install
</code></pre><p>2. Start up Hardhat</p><pre data-type="codeBlock" text="yarn chain
"><code></code></pre><p>3. Open a second terminal and start React</p><pre data-type="codeBlock" text="yarn start
"><code>yarn <span class="hljs-keyword">start</span>
</code></pre><p>4. Deploy the default smart contract in a third terminal</p><pre data-type="codeBlock" text="yarn deploy
"><code></code></pre><p>Quickly and easily, you now have your own local Ethereum development environment up and running. If you navigate to <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://localhost:3000/">http://localhost:3000</a> you should see the following React application. Explore the menus and features of Scaffold-ETH.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/9c54a395d7301fbaf730e3fc98e22f47ab3086d47b5e81ec5dcd6f48b28722f9.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h2 id="h-setup-the-graph" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Setup The Graph</h2><p>In this process we will install The Graph locally, deploy a subgraph and test our setup. In order to run The Graph in Scaffold-ETH you will need to have <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.docker.com/products/docker-desktop/">docker</a> installed since the solution uses containers.</p><p>Here is a high level look at how The Graph is deployed in Scaffold-ETH.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/fa99a7f07fb19a50a91044275ea741f0de3ec0581647e3528621d6d49478a217.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><ol><li><p>Clean up any old data</p></li></ol><pre data-type="codeBlock" text="yarn clean-graph-node
"><code>yarn clean<span class="hljs-operator">-</span>graph<span class="hljs-operator">-</span>node
</code></pre><p>2. Spin up The Graph, Postgres and IPFS in Docker</p><pre data-type="codeBlock" text="yarn run-graph-node
"><code>yarn run<span class="hljs-operator">-</span>graph<span class="hljs-operator">-</span>node
</code></pre><p>3. Create the subgraph (Only need to do this step once)</p><pre data-type="codeBlock" text="yarn graph-create-local
"><code>yarn graph-<span class="hljs-built_in">create</span>-<span class="hljs-keyword">local</span>
</code></pre><p>4. Deploy your subgraph (Be sure to enter a version label)</p><pre data-type="codeBlock" text="yarn graph-ship-local
"><code>yarn graph<span class="hljs-operator">-</span>ship<span class="hljs-operator">-</span>local
</code></pre><p>Then anytime you want to update your smart contract and deploy both you can simply run the following command.</p><pre data-type="codeBlock" text="yarn deploy-and-graph
"><code>yarn deploy<span class="hljs-operator">-</span>and<span class="hljs-operator">-</span>graph
</code></pre><p>That is it! You are now up and running with The Graph on top of a local Ethereum development environment packed with features and functionality. Once you start sending some contract interactions with the contract the events will be ingested into The Graph. You navigate to the Subgraph tab in Scaffold-ETH and you should see your events show up using the pre-configured Subgraph along with a GraphiQL explorer. Let’s take a look at a sample query.</p><pre data-type="codeBlock" text="{
    purposes(first: 1, orderBy: createdAt, orderDirection: desc) {
      id
      sender {
        id
      }
    }
  }
"><code>{
    <span class="hljs-selector-tag">purposes</span>(<span class="hljs-attribute">first</span>: <span class="hljs-number">1</span>, <span class="hljs-attribute">orderBy</span>: createdAt, <span class="hljs-attribute">orderDirection</span>: desc) {
      <span class="hljs-selector-tag">id</span>
      <span class="hljs-selector-tag">sender</span> {
        <span class="hljs-selector-tag">id</span>
      }
    }
  }
</code></pre><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/44adeff66e63533d1e426d564f7bc1f6ae984b740920c8fae6fc11ddf1790e35.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>You can see that as the events are emitted they are stored and available for searching within The Graph! Now let’s take this a step further, let’s build out a new function in our smart contract and also build the needed changes to get those into The Graph.</p><h2 id="h-adding-new-events" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Adding New Events</h2><p>First we will update our smart contract located in packages/hardhat/contracts/YourContract.sol to include a simple function that will allow users to send messages between addresses. We will also add the needed event and emit configuration.</p><pre data-type="codeBlock" text="event SendMessage(address _from, address _to, string message);

function sendMessage(address _to, string calldata message) external {
    emit SendMessage(msg.sender, _to, message);
}
"><code><span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">SendMessage</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _from, <span class="hljs-keyword">address</span> _to, <span class="hljs-keyword">string</span> message</span>)</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendMessage</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _to, <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> message</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
    <span class="hljs-keyword">emit</span> SendMessage(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, _to, message);
}
</code></pre><p>Next we will create the needed schema for this event. The schema file is located in packages/subgraph/src/schema.graphql</p><p>In order to get your data indexed into The Graph properly, you need to define the entities. You can read more about entities <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://thegraph.com/docs/en/developer/create-subgraph-hosted/#defining-entities">here</a>.</p><p>We will add the following entities.</p><pre data-type="codeBlock" text="type Message @entity {
  id: ID!
  _from: Messenger!
  _to: Receiver!
  message: String!
  createdAt: BigInt!
  transactionHash: String!
}

type Messenger @entity {
  id: ID!
  address: Bytes!
  messages: [Message!] @derivedFrom(field: &quot;_from&quot;)
  createdAt: BigInt!
  messageCount: BigInt!
}

type Receiver @entity {
  id: ID!
  address: Bytes!
  createdAt: BigInt!
  messageCount: BigInt!
}
"><code><span class="hljs-keyword">type</span> Message @entity {
  id: ID<span class="hljs-operator">!</span>
  _from: Messenger<span class="hljs-operator">!</span>
  _to: Receiver<span class="hljs-operator">!</span>
  message: String<span class="hljs-operator">!</span>
  createdAt: BigInt<span class="hljs-operator">!</span>
  transactionHash: String<span class="hljs-operator">!</span>
}

<span class="hljs-keyword">type</span> Messenger @entity {
  id: ID<span class="hljs-operator">!</span>
  <span class="hljs-keyword">address</span>: Bytes<span class="hljs-operator">!</span>
  messages: [Message<span class="hljs-operator">!</span>] @derivedFrom(field: <span class="hljs-string">"_from"</span>)
  createdAt: BigInt<span class="hljs-operator">!</span>
  messageCount: BigInt<span class="hljs-operator">!</span>
}

<span class="hljs-keyword">type</span> Receiver @entity {
  id: ID<span class="hljs-operator">!</span>
  <span class="hljs-keyword">address</span>: Bytes<span class="hljs-operator">!</span>
  createdAt: BigInt<span class="hljs-operator">!</span>
  messageCount: BigInt<span class="hljs-operator">!</span>
}
</code></pre><p>Next we will update the Subgraph YAML configuration. This file is located in packages/subgraph/subgraph.yaml</p><p>Add the entities we previously configured in the schema here. They should look like this when you are done.</p><pre data-type="codeBlock" text="entities:
        - Purpose
        - Sender
        - Message
        - Messenger
        - Receiver
"><code>entities:
<span class="hljs-bullet">        -</span> Purpose
<span class="hljs-bullet">        -</span> Sender
<span class="hljs-bullet">        -</span> Message
<span class="hljs-bullet">        -</span> Messenger
<span class="hljs-bullet">        -</span> Receiver
</code></pre><p>You will also need to add the additional eventHandler for the SendMessage event that will trigger the handleMessage handler.</p><pre data-type="codeBlock" text="eventHandlers:
        - event: SendMessage(address,address,string)
          handler: handleMessage
"><code>eventHandlers:
        <span class="hljs-operator">-</span> <span class="hljs-function"><span class="hljs-keyword">event</span>: <span class="hljs-title">SendMessage</span>(<span class="hljs-params"><span class="hljs-keyword">address</span>,<span class="hljs-keyword">address</span>,<span class="hljs-keyword">string</span></span>)
          <span class="hljs-title">handler</span>: <span class="hljs-title">handleMessage</span>
</span></code></pre><p>Next we need to update the mapping under packages/subgraph/src/mapping.ts</p><p>We will import the additional event.</p><pre data-type="codeBlock" text="import {
  YourContract,
  SetPurpose,
  SendMessage,
} from &quot;../generated/YourContract/YourContract&quot;;
"><code><span class="hljs-keyword">import</span> {
  <span class="hljs-title class_">YourContract</span>,
  <span class="hljs-title class_">SetPurpose</span>,
  <span class="hljs-title class_">SendMessage</span>,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"../generated/YourContract/YourContract"</span>;
</code></pre><p>As well as the generated schema from our deployment.</p><pre data-type="codeBlock" text="import {
  Purpose,
  Sender,
  Messenger,
  Receiver,
  Message,
} from &quot;../generated/schema&quot;;
"><code><span class="hljs-keyword">import</span> {
  <span class="hljs-title class_">Purpose</span>,
  <span class="hljs-title class_">Sender</span>,
  <span class="hljs-title class_">Messenger</span>,
  <span class="hljs-title class_">Receiver</span>,
  <span class="hljs-title class_">Message</span>,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"../generated/schema"</span>;
</code></pre><p>Lastly we will add the handler function to the mapping.ts file so that we can handle the events.</p><pre data-type="codeBlock" text="export function handleMessage(event: SendMessage): void {
  let messengerString = event.params._from.toHexString();
  let receiverString = event.params._to.toHexString();

  let messenger = Messenger.load(messengerString);

  if (messenger === null) {
    messenger = new Messenger(messengerString);
    messenger.address = event.params._from;
    messenger.createdAt = event.block.timestamp;
    messenger.messageCount = BigInt.fromI32(1);
  } else {
    messenger.messageCount = messenger.messageCount.plus(BigInt.fromI32(1));
  }

  let receiver = Receiver.load(receiverString);

  if (receiver === null) {
    receiver = new Receiver(receiverString);
    receiver.address = event.params._from;
    receiver.createdAt = event.block.timestamp;
    receiver.messageCount = BigInt.fromI32(1);
  } else {
    receiver.messageCount = receiver.messageCount.plus(BigInt.fromI32(1));
  }

  let message = new Message(
    event.transaction.hash.toHex() + &quot;-&quot; + event.logIndex.toString()
  );

  message.message = event.params.message;
  message._from = messengerString;
  message._to = receiverString;
  message.createdAt = event.block.timestamp;
  message.transactionHash = event.transaction.hash.toHex();

  receiver.save();
  messenger.save();
  message.save();
}
"><code>export <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handleMessage</span>(<span class="hljs-params"><span class="hljs-keyword">event</span>: SendMessage</span>): <span class="hljs-title">void</span> </span>{
  let messengerString <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.params._from.toHexString();
  let receiverString <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.params._to.toHexString();

  let messenger <span class="hljs-operator">=</span> Messenger.load(messengerString);

  <span class="hljs-keyword">if</span> (messenger <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> null) {
    messenger <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Messenger(messengerString);
    messenger.<span class="hljs-built_in">address</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.params._from;
    messenger.createdAt <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.block.timestamp;
    messenger.messageCount <span class="hljs-operator">=</span> BigInt.fromI32(<span class="hljs-number">1</span>);
  } <span class="hljs-keyword">else</span> {
    messenger.messageCount <span class="hljs-operator">=</span> messenger.messageCount.plus(BigInt.fromI32(<span class="hljs-number">1</span>));
  }

  let receiver <span class="hljs-operator">=</span> Receiver.load(receiverString);

  <span class="hljs-keyword">if</span> (receiver <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> null) {
    receiver <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Receiver(receiverString);
    receiver.<span class="hljs-built_in">address</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.params._from;
    receiver.createdAt <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.block.timestamp;
    receiver.messageCount <span class="hljs-operator">=</span> BigInt.fromI32(<span class="hljs-number">1</span>);
  } <span class="hljs-keyword">else</span> {
    receiver.messageCount <span class="hljs-operator">=</span> receiver.messageCount.plus(BigInt.fromI32(<span class="hljs-number">1</span>));
  }

  let message <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Message(
    <span class="hljs-keyword">event</span>.transaction.hash.toHex() <span class="hljs-operator">+</span> <span class="hljs-string">"-"</span> <span class="hljs-operator">+</span> <span class="hljs-keyword">event</span>.logIndex.toString()
  );

  message.message <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.params.message;
  message._from <span class="hljs-operator">=</span> messengerString;
  message._to <span class="hljs-operator">=</span> receiverString;
  message.createdAt <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.block.timestamp;
  message.transactionHash <span class="hljs-operator">=</span> <span class="hljs-keyword">event</span>.transaction.hash.toHex();

  receiver.save();
  messenger.save();
  message.save();
}
</code></pre><p>After we have made all the needed changes, let’s do a fresh deploy.</p><pre data-type="codeBlock" text="yarn deploy-and-graph
"><code>yarn deploy<span class="hljs-operator">-</span>and<span class="hljs-operator">-</span>graph
</code></pre><p>After the deployment is finished, navigate over to the Debug Contracts tab and send some messages between your wallet and other addresses using the function we created earlier. This will then trigger events to get pushed into The Graph.</p><p>After you send a few messages, try out a search query.</p><pre data-type="codeBlock" text="{
    messages(first: 1, orderBy: createdAt, orderDirection: asc) {
      id
      _from {
        messages {
          message
        }
      }
    }
  }
"><code>{
    <span class="hljs-selector-tag">messages</span>(<span class="hljs-attribute">first</span>: <span class="hljs-number">1</span>, <span class="hljs-attribute">orderBy</span>: createdAt, <span class="hljs-attribute">orderDirection</span>: asc) {
      <span class="hljs-selector-tag">id</span>
      <span class="hljs-selector-tag">_from</span> {
        <span class="hljs-selector-tag">messages</span> {
          <span class="hljs-selector-tag">message</span>
        }
      }
    }
  }
</code></pre><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ebc8b4c6c55b93975dcb22bce25434edf067927a875f362662ec54f6de802db9.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>Scaffold-ETH GraphiQL Tab</p><p>In this post we walked through how you can easily spin up a local Ethereum development environment with out of the box support for The Graph. We showed how you can create a new event and configure it to be indexed by The Graph!</p><p>Thanks for reading. Please follow me to read more about Ethereum, Scaffold-ETH and other Crypto related topics!</p>]]></content:encoded>
            <author>cryptomastery@newsletter.paragraph.com (Shutterblock.eth 📸💥 🦇🔊🛸)</author>
        </item>
    </channel>
</rss>