<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[berachain-devs - Medium]]></title>
        <description><![CDATA[Bevelopers of Berachain — building the next Layer1 EVM Proof-of-Liquidity Chain - Medium]]></description>
        <link>https://medium.com/berachain-devs?source=rss----b629d42886be---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>berachain-devs - Medium</title>
            <link>https://medium.com/berachain-devs?source=rss----b629d42886be---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 02:00:58 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/berachain-devs" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[How To Setup Rainbowkit On Berachain Using Vite]]></title>
            <link>https://medium.com/berachain-devs/how-to-setup-rainbowkit-on-berachain-using-vite-66eaefa5fa2d?source=rss----b629d42886be---4</link>
            <guid isPermaLink="false">https://medium.com/p/66eaefa5fa2d</guid>
            <category><![CDATA[web3]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[how-to]]></category>
            <dc:creator><![CDATA[De]]></dc:creator>
            <pubDate>Wed, 29 May 2024 22:10:08 GMT</pubDate>
            <atom:updated>2024-05-29T21:55:59.492Z</atom:updated>
            <content:encoded><![CDATA[<h4>Step-by-step guide to setting up Rainbowkit on Berachain via Vite</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4jJlNySx4VCdWFLtJ_pBMg.png" /></figure><p>Bm bm! 🐻</p><p>We’re back with another guide to help dApps use existing SDK’s out there and help connect their dApps to Berachain’s Artio Testnet.</p><h3>🛠️ What are we building ?</h3><p>In this guide we will be setting up the Rainbowkit’s <a href="https://www.rainbowkit.com/docs/connect-button">Connect Wallet button</a> on Berachain Artio using Vite (React + Typescript).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*tVfZgZRKZGHhyKMe.gif" /><figcaption>Metamask Connection</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-RGI61sXguP6DrXY.gif" /><figcaption>Checking Wallet Balance</figcaption></figure><h3>🏃 ViteJS</h3><p>Vite is a great way to create single page applications and is another alternative to server-side rendering applications like NextJS.</p><h3>🌈 RainbowKit Advantages</h3><p>When building Web3 dApps, it’s crucial to balance usability and flexibility. RainbowKit is a great tool for this, making it easier to design a dApp wallet that looks good and is user-friendly.</p><p>In the past, adding wallets to dApps was a rigid process. Developers had to tailor the dApp to a specific wallet, like Metamask, which limited users to that wallet only.</p><p><a href="https://www.rainbowkit.com/">RainbowKit</a> changes the game by providing a toolkit that lets developers customize the entire wallet connection process. You can choose different themes to match your dApp’s look and offer a range of supported wallets, allowing users to pick their favorite, whether it’s <a href="https://metamask.io/">Metamask</a>, Trust <a href="https://trustwallet.com/">Wallet</a>, or others, for a smooth experience.</p><p>Additionally, developers can create custom ‘connect’ buttons that blend seamlessly with their dApp’s design, making the user interface more familiar and fluid.</p><h3>⚠️ Prerequisites</h3><ul><li>Knowledge of React.</li><li>Development environment: VSCode or Atom.</li><li>Node version &gt;v18.16.0.</li></ul><h3>✅ Step-by-Step Guide Implementing RainbowKit In Your dApp</h3><h3>Step 1: Creating a React Project</h3><p>Create a new React-typescript application using Vite.</p><pre>npm create vite@latest berachain-rainbowkit -- --react-ts; <br># Need to install the following packages:<br># create-vite@5.2.3<br># Ok to proceed? (y) y<br># ✔ Select a framework: › React<br># ✔ Select a variant: › TypeScript<br><br># Scaffolding project in /Users/dethebera/BeraWork/berarainbowkit/berachain-rainbowkit...<br># Done. Now run:<br>#   cd berachain-rainbowkit<br>#   npm install<br>#   npm run dev<br># npm notice <br># npm notice New minor version of npm available! 10.2.4 -&gt; 10.5.2<br># npm notice Changelog: https://github.com/npm/cli/releases/tag/v10.5.2<br># npm notice Run npm install -g npm@10.5.2 to update!<br># npm notice</pre><p><strong>OR</strong></p><p>You can also install Vite using the command below and you’ll be prompted to enter a project name; input your desired name.</p><pre>npm create vite@latest</pre><ul><li>Afterward, choose the <strong>React</strong> framework when prompted to select a framework.</li><li>Following that, opt for the <strong>Typescript</strong> variant when asked for the variant.</li></ul><p>Go to your new project directory, install dependencies, and run the app</p><pre>cd berachain-rainbowkit<br>npm install<br>npm run dev</pre><p>Navigate to your local server at <a href="http://localhost:5173/">http://localhost:5173/</a> and you should see an interface displayed as follows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HoQQvLenb3qm-mZa.png" /><figcaption>Initial Vite Template</figcaption></figure><p>Once we’ve set up our React project, we can move forward to install RainbowKit along with other necessary dependencies.</p><h3>Step 2 — Install RainbowKit and Additional Dependencies:</h3><p>RainbowKit depends on wagmi and other libraries. You can install these by running:</p><pre>npm install @rainbow-me/rainbowkit wagmi<br># added 33 packages, removed 82 packages, changed 60 packages, and audited 1193 packages in 1m<br># 137 packages are looking for funding<br>#   run `npm fund` for details<br># found 0 vulnerabilities</pre><p>Now that we know how RainbowKit allows developers to customize their wallet connection experiences let’s put it into action with a practical guide.</p><p>We will be going through a step-by-step process, starting from scratch, to seamlessly integrate a RainbowKit button across various chains.</p><p>By now, you’re all set to make use of the RainbowKit package in your project.</p><h3>Step 3: Configuring RainbowKit and Wagmi</h3><p>Let’s import the packages into our project. We’ll add these imports at the top of the main.tsx file:</p><p><strong>File:</strong>./src/main.tsx</p><pre>import &quot;./polyfills&quot;;<br>import &quot;./global.css&quot;;<br>import &quot;@rainbow-me/rainbowkit/styles.css&quot;;<br>import React from &quot;react&quot;;<br>import ReactDOM from &quot;react-dom/client&quot;;<br>import App from &quot;./App&quot;;<br>import { getDefaultConfig, RainbowKitProvider } from &quot;@rainbow-me/rainbowkit&quot;;<br>import { WagmiProvider } from &quot;wagmi&quot;;<br>import { berachainTestnet } from &quot;wagmi/chains&quot;;<br>import { QueryClient, QueryClientProvider } from &quot;@tanstack/react-query&quot;;<br>const config = getDefaultConfig({<br>  appName: &quot;RainbowKit demo&quot;,<br>  projectId: &quot;YOUR_PROJECT_ID&quot;,<br>  chains: [berachainTestnet],<br>});<br>const queryClient = new QueryClient();<br>ReactDOM.createRoot(document.getElementById(&quot;root&quot;)!).render(<br>  &lt;React.StrictMode&gt;<br>    &lt;WagmiProvider config={config}&gt;<br>      &lt;QueryClientProvider client={queryClient}&gt;<br>        &lt;RainbowKitProvider&gt;<br>          &lt;App /&gt;<br>        &lt;/RainbowKitProvider&gt;<br>      &lt;/QueryClientProvider&gt;<br>    &lt;/WagmiProvider&gt;<br>  &lt;/React.StrictMode&gt;<br>);</pre><p>For this guide, we’ll set up the supported chains for our project and use “<strong><em>berachainTestnet”</em></strong> , keeping it unchanged, along with the provider required by Wagmi to interact with the blockchain.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fgohZphiXStu6y9G.png" /><figcaption>berachainTesnet Config</figcaption></figure><p>For a comprehensive overview of various ways to configure your connection modal, you can refer to <a href="https://www.rainbowkit.com/">RainbowKit’s documentation</a>.</p><p>We’ll also need a <strong>Project ID</strong>.</p><p>You can get one from <a href="https://walletconnect.com/">WalletConnect Cloud</a> and it will look something like this: 4322794c0c46b……..ca48ba15fc3. This unique identifier is integral to your project’s interaction with WalletConnect Cloud, enabling seamless connections with various wallets.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GjwMbFl5_36EQTlz.png" /><figcaption>WalletConnect Cloud Dashboard</figcaption></figure><h3>Step 4: Getting a RainbowKit Project ID</h3><p>To generate a Project ID, access <a href="http://walletconnect/">WalletConnect Cloud</a> by signing in and selecting the <strong><em>Create</em></strong> option, as illustrated below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*pemENgnKMCf_WLrK.png" /><figcaption>WalletConnect — Project’s Dashboard</figcaption></figure><p>Provide a name for the project and then click on the <strong><em>Create</em></strong> button to proceed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*kUdDP3h3GYIQ1sjG.png" /><figcaption>Creating A New Project</figcaption></figure><p>Following these steps, you should obtain a <strong>Project ID</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-n35SIh-ynWlIOTy.png" /><figcaption>Project’s Details</figcaption></figure><h3>Step 5: Polyfills Fix</h3><p>The <a href="https://vitejs.dev/">Vite</a> bundler doesn’t provide Node polyfills, so you’ll need to include polyfills for global, Buffer and process.env.</p><p>Create a new file named Polyfills.ts and add the following code to it.</p><p><strong>File:</strong>./src/Polyfills.ts</p><pre>import { Buffer } from &quot;buffer&quot;;<br>window.global = window.global ?? window;<br>window.Buffer = window.Buffer ?? Buffer;<br>window.process = window.process ?? { env: {} }; // Minimal process polyfill<br>export {};</pre><h3>Step 6: Optional — Adding Global.css</h3><p>In certain instances you might notice the Global.css file might be missing.</p><p>Head over to src folder and create a new file name Global.css and add the following code in it.</p><p><strong>File:</strong>./src/Global.css</p><pre>body {<br>    margin: 0;<br>    font-family: -apple-system, BlinkMacSystemFont, &#39;Segoe UI&#39;, &#39;Roboto&#39;, &#39;Oxygen&#39;,<br>        &#39;Ubuntu&#39;, &#39;Cantarell&#39;, &#39;Fira Sans&#39;, &#39;Droid Sans&#39;, &#39;Helvetica Neue&#39;,<br>        sans-serif;<br>    -webkit-font-smoothing: antialiased;<br>    -moz-osx-font-smoothing: grayscale;<br>}</pre><h3>Step 7: Adding the Connect Button</h3><p>To include the connect button, import it from RainbowKit at the top of your <strong>App.tsx</strong> file.</p><p>Your entire App.tsx looks something similar to what we have below. Essentially, this file controls how your app looks and works. It includes different parts of your app and adds the RainbowKit connect button to make it easy for users to connect their wallets.</p><p><strong>File:</strong>./src/App.tsx</p><pre>import { ConnectButton } from &quot;@rainbow-me/rainbowkit&quot;;<br>function App() {<br>  return (<br>    &lt;div<br>      style={{<br>        display: &quot;flex&quot;,<br>        justifyContent: &quot;flex-end&quot;,<br>        padding: 12,<br>      }}<br>    &gt;<br>      &lt;ConnectButton /&gt;<br>    &lt;/div&gt;<br>  );<br>}<br>export default App;</pre><p>Once everything is up and running on your local system, you should have something similar to this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*u6YuVEyHbr_7-0Is.png" /></figure><p>When you click <strong>Connect Wallet</strong>, a pop-up window, similar to the image below, will appear:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*PBfVoB5vnFHQqGYs.png" /></figure><p>If you click on any of the wallets (i.e. metamask), you should be able to connect your wallet and the chain of your choice.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jbuF-n67QswxSEP1.png" /></figure><p>Congratulations for making it to the end of the tutorial and successfully integrating RainbowKit!</p><h3>Complete Code</h3><p><strong>File:</strong>./src/main.tsx</p><pre>import &quot;./polyfills&quot;;<br>import &quot;./global.css&quot;;<br>import &quot;@rainbow-me/rainbowkit/styles.css&quot;;<br>import React from &quot;react&quot;;<br>import ReactDOM from &quot;react-dom/client&quot;;<br>import App from &quot;./App&quot;;<br>import { getDefaultConfig, RainbowKitProvider } from &quot;@rainbow-me/rainbowkit&quot;;<br>import { WagmiProvider } from &quot;wagmi&quot;;<br>import { berachainTestnet } from &quot;wagmi/chains&quot;;<br>import { QueryClient, QueryClientProvider } from &quot;@tanstack/react-query&quot;;<br>const config = getDefaultConfig({<br>  appName: &quot;RainbowKit demo&quot;,<br>  projectId: &quot;YOUR_PROJECT_ID&quot;,<br>  chains: [berachainTestnet],<br>});<br>const queryClient = new QueryClient();<br>ReactDOM.createRoot(document.getElementById(&quot;root&quot;)!).render(<br>  &lt;React.StrictMode&gt;<br>    &lt;WagmiProvider config={config}&gt;<br>      &lt;QueryClientProvider client={queryClient}&gt;<br>        &lt;RainbowKitProvider&gt;<br>          &lt;App /&gt;<br>        &lt;/RainbowKitProvider&gt;<br>      &lt;/QueryClientProvider&gt;<br>    &lt;/WagmiProvider&gt;<br>  &lt;/React.StrictMode&gt;<br>);</pre><p><strong>File:</strong>./src/App.tsx</p><pre>import { ConnectButton } from &quot;@rainbow-me/rainbowkit&quot;;<br>function App() {<br>  return (<br>    &lt;div<br>      style={{<br>        display: &quot;flex&quot;,<br>        justifyContent: &quot;flex-end&quot;,<br>        padding: 12,<br>      }}<br>    &gt;<br>      &lt;ConnectButton /&gt;<br>    &lt;/div&gt;<br>  );<br>}<br>export default App;</pre><p><strong>File:</strong>./src/Polyfills.ts</p><pre>import { Buffer } from &quot;buffer&quot;;<br>window.global = window.global ?? window;<br>window.Buffer = window.Buffer ?? Buffer;<br>window.process = window.process ?? { env: {} }; // Minimal process polyfill<br>export {};</pre><p><strong>File:</strong>./src/Global.css</p><pre>body {<br>    margin: 0;<br>    font-family: -apple-system, BlinkMacSystemFont, &#39;Segoe UI&#39;, &#39;Roboto&#39;, &#39;Oxygen&#39;,<br>        &#39;Ubuntu&#39;, &#39;Cantarell&#39;, &#39;Fira Sans&#39;, &#39;Droid Sans&#39;, &#39;Helvetica Neue&#39;,<br>        sans-serif;<br>    -webkit-font-smoothing: antialiased;<br>    -moz-osx-font-smoothing: grayscale;<br>}</pre><p>Head over to Berachain guides repo using the link below and find the template for the above guide to directly test the dApp out!</p><p><a href="https://github.com/berachain/guides/tree/main/apps/rainbowkit-vite">guides/apps/rainbowkit-vite at main · berachain/guides</a></p><h3>Recap</h3><p>RainbowKit offers a range of useful tools without requiring much effort from developers. It integrates seamlessly with the Wagmi library, enabling easy utilization of Wagmi’s features such as message signing and transactions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Own-xjfszcLiRXzl.png" /><figcaption>WalletConnect Button</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*iVAXVQtrMYVlt3jS.png" /></figure><blockquote><strong><em>Note:</em></strong><em> The alignment of the Connect Wallet button might seem different from the SDK initially — that is because of slight change in css that we made.</em></blockquote><p>This guide demonstrates setting up a Vite project with RainbowKit to function with Berachain’s Artio testnet, simplifying wallet connections and enabling developers to setup their dApp’s user onboarding.</p><h3>🛠️ Want To Build and How To Get Support ?</h3><p>If you’re interested in understanding and developing more on Berachain, try various example repos provided in the official guides repo.</p><p><a href="https://github.com/berachain/guides/">GitHub - berachain/guides: A demonstration of different contracts, languages, and libraries that work with Berachain EVM.</a></p><p>Berachain’s developer documentation also has multiple starter guides with goto tools such as Hardhat, Foundry and more! Head over to developer section on the docs using the link below.</p><p><a href="https://docs.berachain.com/developers/">Connecting to Berachain</a></p><h4>How to get Developer Support ?</h4><p>⚠️ Still facing issues or have doubts?</p><p>Head over to <a href="https://discord.com/invite/berachain"><strong><em>Official Berachain Discord</em></strong></a> and raise a ticket as shown in the gif below!</p><p>Our DevRel team will be happy to assist! 🤝</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*qrzimlKxegU_EJeN.gif" /></figure><p>Byyeeee bears! 🐻</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=66eaefa5fa2d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/berachain-devs/how-to-setup-rainbowkit-on-berachain-using-vite-66eaefa5fa2d">How To Setup Rainbowkit On Berachain Using Vite</a> was originally published in <a href="https://medium.com/berachain-devs">berachain-devs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Indexing on Berachain Atio Testnet with Envio SDK]]></title>
            <link>https://medium.com/berachain-devs/indexing-on-berachain-atio-testnet-with-envio-sdk-14766aa70e7c?source=rss----b629d42886be---4</link>
            <guid isPermaLink="false">https://medium.com/p/14766aa70e7c</guid>
            <category><![CDATA[web3]]></category>
            <category><![CDATA[guides-and-tutorials]]></category>
            <category><![CDATA[indexing]]></category>
            <category><![CDATA[contracts]]></category>
            <dc:creator><![CDATA[De]]></dc:creator>
            <pubDate>Tue, 23 Apr 2024 14:16:06 GMT</pubDate>
            <atom:updated>2024-04-29T12:24:59.864Z</atom:updated>
            <content:encoded><![CDATA[<h3>Indexing on Berachain Artio Testnet with Envio SDK</h3><h4>How to deploy a local Indexer on Berachain Artio ?</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dpezntklf9L9k3afjSmJ0A.png" /></figure><p>Bm dev bears! 🐻</p><p>In this short walkthrough we will be learning to deploy a Indexer that supports Berachain Artio!</p><p>Special mention to <a href="https://twitter.com/denhampreen"><strong><em>Denham</em></strong></a> and <a href="https://twitter.com/svenmuller95"><strong><em>Sven</em></strong></a> from Evio for preparing the initial resource on Github!</p><h3><strong>Why are Indexers Needed?</strong></h3><p>Indexers are critical components in blockchain ecosystems, serving several pivotal roles:</p><ol><li><strong>Query Optimization</strong>: They restructure blockchain data into query-friendly formats, significantly enhancing query performance beyond the blockchain’s inherent sequential data storage.</li><li><strong>Data Structuring</strong>: Indexers transform raw blockchain data into a more digestible and interpretable format, facilitating easier access and analysis.</li><li><strong>Scalability Solutions</strong>: By offloading data queries from the main blockchain infrastructure, indexers mitigate scalability constraints, handling large data volumes efficiently.</li><li><strong>Load Alleviation</strong>: They reduce direct blockchain query loads, preserving network performance and responsiveness.</li><li><strong>Advanced Query Support</strong>: Indexers enable complex data queries, accommodating sophisticated operational demands beyond simple blockchain transactions.</li><li><strong>Real-time Data Provision</strong>: They support applications requiring immediate data feeds, ensuring timely data delivery without burdening the primary blockchain network.</li><li><strong>Historical Data Analysis</strong>: Indexers organize and maintain accessible historical records, simplifying retrospective data examinations.</li></ol><p>In essence, indexers are indispensable for maintaining operational efficiency, facilitating complex data interactions, and enhancing the overall utility of blockchain platforms in sophisticated development environments.</p><h3><strong>🛠️ What are we building?</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lPqlRivOq2dCYC8NKtSnRQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QPxfLutTfs_ktHs1UFTCdA.png" /></figure><p>This developer guide will walk you through setting up an indexer, to query any ERC20 contract on the Berachain network using a GraphQL API, all with <a href="https://envio.dev/"><strong><em>Envio</em></strong></a>.</p><p>This guide analyzes all WETH token “approval” and “transfer” event logs emitted by the WETH contract to gain real-time insights into metrics such as token holders, balances, and transfers of the WETH token.</p><p>For this specific guide, let’s analyze the top ten accounts with the largest WETH holdings, by querying the balance of token holders.</p><p>The full github code repository can be found in the<strong><em> </em></strong><a href="https://github.com/berachain/guides/"><strong><em>guides section</em></strong></a><strong><em> </em></strong>of this repository under <a href="https://github.com/berachain/guides/tree/main/apps/envio-indexing-erc20"><strong><em>Index ERC20 Contract Using Envio</em></strong></a>.</p><p><a href="https://github.com/berachain/guides/tree/main/apps/envio-indexer-erc20">guides/apps/envio-indexer-erc20 at main · berachain/guides</a></p><h3>Pre-requisites</h3><p>Before beginning, make sure you have the following installed or setup on your computer before hand.<a href="https://docs.envio.dev/docs/getting-started#prerequisites">​</a></p><p>The following are the prerequisite packages required for Envio:</p><ol><li><a href="https://nodejs.org/en/download/current"><strong><em>Node.js</em></strong></a> (use <a href="https://nodejs.org/download/release/v18.18.0/">v18</a> or newer)</li><li><a href="https://pnpm.io/installation"><strong><em>pnpm</em></strong></a> (use v8 or newer)</li><li><a href="https://www.docker.com/products/docker-desktop/"><strong><em>Docker Desktop</em></strong></a><strong><em> (</em></strong>Docker is required specifically for running the Envio indexer locally).</li></ol><h3>Berachain-Envio Setup</h3><h4>Install And Setup Envio<a href="https://docs.envio.dev/docs/getting-started#install-envio">​</a></h4><p>You can install Envio by running the command below:</p><pre>sudo npm i -g envio<br># Password:<br><br># added 2 packages in 3sLet’s start by initializing the indexer and generating a boilerplate to index all events emitted by the WETH ERC20 token contract on Berachain.</pre><p>This is the WETH contract address: <a href="https://artio.beratrail.io/token/0x8239FBb3e3D0C2cDFd7888D8aF7701240Ac4DcA4"><strong><em>0x8239FBb3e3D0C2cDFd7888D8aF7701240Ac4DcA4</em></strong></a>.</p><ol><li>Open your terminal in a preferred directory and run the command envio init.</li><li>Name your indexer anything you’d like (e.g. weth-berachain-indexer), and specify a folder name (e.g.weth-berachain-indexer.)</li><li>3. Choose a preferred language, select Template, and then select Erc20.</li></ol><pre>envio init<br># &gt; Name your indexer: weth-berachain-envio-test<br># &gt; Specify a folder name (ENTER to skip):  weth-berachain-envio-test<br># &gt; Which language would you like to use? Typescript<br># &gt; Choose an initialization option Template<br># &gt; Which template would you like to use? Erc20<br># Project template ready<br># Running codegen<br># installing packages...<br># Checking for pnpm package...<br># 8.14.1<br># Package pnpm is already installed. Continuing...<br># Scope: all 2 workspace projects</pre><blockquote><em>Note: Indexers on Envio can be written in JavaScript, TypeScript, or ReScript. For this demonstration, we’ve chosen to use TypeScript as the preferred language.</em></blockquote><p>A project template is generated with all the required files to run your indexer.</p><h4>Changes to Generated Code</h4><p>Open the existing code via IDE of yout choice, we’re using <a href="https://code.visualstudio.com/">VS Code</a> (Visual Code Studio).</p><ol><li><strong>File:</strong> <strong>./config.yaml</strong></li></ol><p>This file defines the network, start block, contract address, and events we want to index on Berachain.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*k6qKvrGBgNEMxSWKKqAw0Q.png" /></figure><p>Replace the placeholder values for network, start block and contract address with the correct values, i.e.</p><ul><li>Network Id = 80085</li><li>Start Block = 0</li><li>Contract Address = 0x8239FBb3e3D0C2cDFd7888D8aF7701240Ac4DcA4</li></ul><p>Post changes the file should look exactly like below —</p><p><strong>File:</strong> <strong>./config.yaml</strong></p><pre>name: weth-berachain-indexer<br>description: ERC-20 indexer<br>networks:<br>  - id: 80085 # Berachain Artio Testnet<br>    start_block: 0<br>    contracts:<br>      - name: ERC20<br>        address: &quot;0x8239FBb3e3D0C2cDFd7888D8aF7701240Ac4DcA4&quot; #WETH<br>        handler: src/EventHandlers.ts<br>        events:<br>          - event: &quot;Approval(address indexed owner, address indexed spender, uint256 value)&quot;<br>            requiredEntities:<br>              - name: &quot;Account&quot;<br>              - name: &quot;Approval&quot;<br>          - event: &quot;Transfer(address indexed from, address indexed to, uint256 value)&quot;<br>            requiredEntities:<br>              - name: &quot;Account&quot;<br>              - name: &quot;Approval&quot;</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*c9kz6uzJwpu8BWbBFfcDyw.png" /></figure><p>The contract addresse used above is the contract address for WETH on Berachain Artio Testnet. Feel free to check it out on Berachain Explorer <a href="https://artio.beratrail.io/token/0x8239FBb3e3D0C2cDFd7888D8aF7701240Ac4DcA4">https://artio.beratrail.io/token/0x8239FBb3e3D0C2cDFd7888D8aF7701240Ac4DcA4</a>.</p><p><strong>2. File:</strong> <strong>./Schema.graphql</strong></p><p>This file saves and defines the data structures for selected events, such as the Approval event.</p><pre>## Pls note - there are no changes required below for this guide, but obv changes can be made based on requirements<br><br>type Account {<br>  # id is the address of the account<br>  id: ID!<br>  # approvals are a list of approvals that this account has given<br>  approvals: [Approval!]! @derivedFrom(field: &quot;owner&quot;)<br>  # account balance of tokens<br>  balance: BigInt!<br>}<br><br>type Approval {<br>  # id is the owner address and spender address [owner-spender]<br>  id: ID!<br>  # amount is the amount of tokens approved<br>  amount: BigInt!<br>  # owner is the account that approved the tokens<br>  owner: Account!<br>  # spender is the account that is approved to spend the tokens<br>  spender: Account!<br>}</pre><p><strong>3. File:</strong> <strong>./src/EventHandlers.ts</strong></p><p>This file defines what happens when an event is emitted and saves what code is going to run, allowing customization in data handling.</p><pre>import {<br>  ERC20Contract_Approval_loader,<br>  ERC20Contract_Approval_handler,<br>  ERC20Contract_Transfer_loader,<br>  ERC20Contract_Transfer_handler,<br>} from &quot;../generated/src/Handlers.gen&quot;;<br><br>import { AccountEntity, ApprovalEntity } from &quot;../generated/src/Types.gen&quot;;<br><br>ERC20Contract_Approval_loader(({ event, context }) =&gt; {<br>  // loading the required Account entity<br>  context.Account.load(event.params.owner.toString());<br>});<br><br>ERC20Contract_Approval_handler(({ event, context }) =&gt; {<br>  //  getting the owner Account entity<br>  let ownerAccount = context.Account.get(event.params.owner.toString());<br><br>  if (ownerAccount === undefined) {<br>    // Usually an accoun that is being approved alreay has/has had a balance, but it is possible they havent.<br><br>    // create the account<br>    let accountObject: AccountEntity = {<br>      id: event.params.owner.toString(),<br>      balance: 0n,<br>    };<br>    context.Account.set(accountObject);<br>  }<br><br>  let approvalId =<br>    event.params.owner.toString() + &quot;-&quot; + event.params.spender.toString();<br><br>  let approvalObject: ApprovalEntity = {<br>    id: approvalId,<br>    amount: event.params.value,<br>    owner_id: event.params.owner.toString(),<br>    spender_id: event.params.spender.toString(),<br>  };<br><br>  // this is the same for create or update as the amount is overwritten<br>  context.Approval.set(approvalObject);<br>});<br><br>ERC20Contract_Transfer_loader(({ event, context }) =&gt; {<br>  context.Account.load(event.params.from.toString());<br>  context.Account.load(event.params.to.toString());<br>});<br><br>ERC20Contract_Transfer_handler(({ event, context }) =&gt; {<br>  let senderAccount = context.Account.get(event.params.from.toString());<br><br>  if (senderAccount === undefined || senderAccount === null) {<br>    // create the account<br>    // This is likely only ever going to be the zero address in the case of the first mint<br>    let accountObject: AccountEntity = {<br>      id: event.params.from.toString(),<br>      balance: 0n - event.params.value,<br>    };<br><br>    context.Account.set(accountObject);<br>  } else {<br>    // subtract the balance from the existing users balance<br>    let accountObject: AccountEntity = {<br>      id: senderAccount.id,<br>      balance: senderAccount.balance - event.params.value,<br>    };<br>    context.Account.set(accountObject);<br>  }<br><br>  let receiverAccount = context.Account.get(event.params.to.toString());<br><br>  if (receiverAccount === undefined || receiverAccount === null) {<br>    // create new account<br>    let accountObject: AccountEntity = {<br>      id: event.params.to.toString(),<br>      balance: event.params.value,<br>    };<br>    context.Account.set(accountObject);<br>  } else {<br>    // update existing account<br>    let accountObject: AccountEntity = {<br>      id: receiverAccount.id,<br>      balance: receiverAccount.balance + event.params.value,<br>    };<br><br>    context.Account.set(accountObject);<br>  }<br>});</pre><h4>Deploying Local Indexer</h4><p>Starting the Indexer &amp; Exploring Indexed Data.</p><p>Now, let’s run our indexer locally by running envio dev command.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Vvl5423CzRXopIQ4Zv5JsQ.png" /><figcaption>Localhost Login Screen</figcaption></figure><p>Your browser would have opened a local Hasura console at <a href="http://localhost:8080/console">http://localhost:8080/console</a>.</p><p>Head over to the Hasura console, type in the admin-secret password = <strong><em>testing </em></strong>.</p><p>Your localhost should look something like below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_SjCZF1d0rI0nlum9UzYBA.png" /><figcaption>Localhost Homepage: Hasura</figcaption></figure><h4>Exploring Indexed Data</h4><ol><li>Head over to the Hasura console, type in the admin-secret password testing, and navigate to “Data” in the above column to explore the data. For example, you can:</li></ol><ul><li>View “events_sync_state” table to see which block number you are on to monitor the indexing progress.</li><li>View the “chain_metadata” table to see the block height of the chain.</li><li>View the “raw_events” table to see all events being indexed.</li></ul><p>If you view the “Account” table, you will see a column called “balance”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hX3Sxsd7eqdYIZkWY8aX6w.png" /></figure><p>2. Let’s analyze our data, by clicking “API” in the above column to access the GraphQL endpoint to query real-time data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*aPLpgX4OB3N4XqBw8W66Tg.png" /></figure><p>3. From there you can run a query to explore details such as holders and their respective balances of the WETH ERC-20 token.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7D8v2spPjncRHaeDcsqgyg.png" /></figure><p>That’s it! We’ve indexed the required data from existing WETH contract. By now you would have learned to deploy a local indexer on Berachain and then query the data from desired contracts on Berachain Artio!</p><h3>Full Code and Repository</h3><p><strong>File:</strong> <strong>./config.yaml</strong></p><pre>name: weth-berachain-indexer<br>description: ERC-20 indexer<br>networks:<br>  - id: 80085 # Berachain Artio Testnet<br>    start_block: 0<br>    contracts:<br>      - name: ERC20<br>        address: &quot;0x8239FBb3e3D0C2cDFd7888D8aF7701240Ac4DcA4&quot; #WETH<br>        handler: src/EventHandlers.ts<br>        events:<br>          - event: &quot;Approval(address indexed owner, address indexed spender, uint256 value)&quot;<br>            requiredEntities:<br>              - name: &quot;Account&quot;<br>              - name: &quot;Approval&quot;<br>          - event: &quot;Transfer(address indexed from, address indexed to, uint256 value)&quot;<br>            requiredEntities:<br>              - name: &quot;Account&quot;<br>              - name: &quot;Approval&quot;</pre><p><strong>2. File:</strong> <strong>./Schema.graphql</strong></p><pre>## Pls note - there are no changes required below for this guide, but obv changes can be made based on requirements<br><br>type Account {<br>  # id is the address of the account<br>  id: ID!<br>  # approvals are a list of approvals that this account has given<br>  approvals: [Approval!]! @derivedFrom(field: &quot;owner&quot;)<br>  # account balance of tokens<br>  balance: BigInt!<br>}<br>type Approval {<br>  # id is the owner address and spender address [owner-spender]<br>  id: ID!<br>  # amount is the amount of tokens approved<br>  amount: BigInt!<br>  # owner is the account that approved the tokens<br>  owner: Account!<br>  # spender is the account that is approved to spend the tokens<br>  spender: Account!<br>}</pre><p><strong>3. File:</strong> <strong>./src/EventHandlers.ts</strong></p><pre>import {<br>  ERC20Contract_Approval_loader,<br>  ERC20Contract_Approval_handler,<br>  ERC20Contract_Transfer_loader,<br>  ERC20Contract_Transfer_handler,<br>} from &quot;../generated/src/Handlers.gen&quot;;<br><br>import { AccountEntity, ApprovalEntity } from &quot;../generated/src/Types.gen&quot;;<br>ERC20Contract_Approval_loader(({ event, context }) =&gt; {<br>  // loading the required Account entity<br>  context.Account.load(event.params.owner.toString());<br>});<br>ERC20Contract_Approval_handler(({ event, context }) =&gt; {<br>  //  getting the owner Account entity<br>  let ownerAccount = context.Account.get(event.params.owner.toString());<br>  if (ownerAccount === undefined) {<br>    // Usually an accoun that is being approved alreay has/has had a balance, but it is possible they havent.<br>    // create the account<br>    let accountObject: AccountEntity = {<br>      id: event.params.owner.toString(),<br>      balance: 0n,<br>    };<br>    context.Account.set(accountObject);<br>  }<br>  let approvalId =<br>    event.params.owner.toString() + &quot;-&quot; + event.params.spender.toString();<br>  let approvalObject: ApprovalEntity = {<br>    id: approvalId,<br>    amount: event.params.value,<br>    owner_id: event.params.owner.toString(),<br>    spender_id: event.params.spender.toString(),<br>  };<br>  // this is the same for create or update as the amount is overwritten<br>  context.Approval.set(approvalObject);<br>});<br>ERC20Contract_Transfer_loader(({ event, context }) =&gt; {<br>  context.Account.load(event.params.from.toString());<br>  context.Account.load(event.params.to.toString());<br>});<br>ERC20Contract_Transfer_handler(({ event, context }) =&gt; {<br>  let senderAccount = context.Account.get(event.params.from.toString());<br>  if (senderAccount === undefined || senderAccount === null) {<br>    // create the account<br>    // This is likely only ever going to be the zero address in the case of the first mint<br>    let accountObject: AccountEntity = {<br>      id: event.params.from.toString(),<br>      balance: 0n - event.params.value,<br>    };<br>    context.Account.set(accountObject);<br>  } else {<br>    // subtract the balance from the existing users balance<br>    let accountObject: AccountEntity = {<br>      id: senderAccount.id,<br>      balance: senderAccount.balance - event.params.value,<br>    };<br>    context.Account.set(accountObject);<br>  }<br>  let receiverAccount = context.Account.get(event.params.to.toString());<br>  if (receiverAccount === undefined || receiverAccount === null) {<br>    // create new account<br>    let accountObject: AccountEntity = {<br>      id: event.params.to.toString(),<br>      balance: event.params.value,<br>    };<br>    context.Account.set(accountObject);<br>  } else {<br>    // update existing account<br>    let accountObject: AccountEntity = {<br>      id: receiverAccount.id,<br>      balance: receiverAccount.balance + event.params.value,<br>    };<br>    context.Account.set(accountObject);<br>  }<br>});</pre><h4>Github Repository</h4><p>The complete template of the above guide is available at <a href="https://github.com/berachain/guides/tree/main/apps/envio-indexer-erc20"><strong><em>https://github.com/berachain/guides/tree/main/apps/envio-indexer-erc20</em></strong></a><strong><em> .</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JP64Pqv4J96x7dXFfnozIw.png" /><figcaption>Envio Template on Berachain Repo</figcaption></figure><h3>More dApps and How To Get Support ?</h3><p>If you’re interested in understanding and developing more on Berachain, try various example repos provided in the official guides repo —</p><p><a href="https://github.com/berachain/guides/tree/main/apps">guides/apps at main · berachain/guides</a></p><p>Berachain’s developer documentation also has multiple starter guides with goto tools such as Hardhat, Foundry and more! Head over to developer section on the docs using the link below.</p><p><a href="https://docs.berachain.com/developers/">Connecting to Berachain</a></p><h4>How to get Developer Support?</h4><p>⚠️ Still facing issues or have doubts? Head over to <a href="https://discord.gg/berachain"><strong><em>Official Berachain Discord</em></strong></a> and raise a ticket as shown in the gif below!</p><p>Our DevRel team will be happy to assist! 🤝</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/0*068RyUlhuE7gf2pQ.gif" /></figure><p>Adiós dev bears! Catch ya in then next one! 💪🏼 🐻</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=14766aa70e7c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/berachain-devs/indexing-on-berachain-atio-testnet-with-envio-sdk-14766aa70e7c">Indexing on Berachain Atio Testnet with Envio SDK</a> was originally published in <a href="https://medium.com/berachain-devs">berachain-devs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Berachain Wallet Connect with Thirdweb SDK]]></title>
            <link>https://medium.com/berachain-devs/berachain-wallet-connect-with-thirdweb-sdk-a7775d72811d?source=rss----b629d42886be---4</link>
            <guid isPermaLink="false">https://medium.com/p/a7775d72811d</guid>
            <category><![CDATA[typescript]]></category>
            <category><![CDATA[web3]]></category>
            <category><![CDATA[sdk]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[guides-and-tutorials]]></category>
            <dc:creator><![CDATA[De]]></dc:creator>
            <pubDate>Tue, 23 Apr 2024 13:59:26 GMT</pubDate>
            <atom:updated>2024-04-23T13:59:26.451Z</atom:updated>
            <content:encoded><![CDATA[<h4>Learn how to build a wallet dApp on Berachain using the Thirdweb SDK</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*clx8HKpe--haxOgkVjebiw.png" /></figure><p>Bm bm! 🐻</p><p>In the evolving landscape of Web3 applications, the integration of user wallets is not just a feature but a fundamental necessity. This detailed guide focuses on learning to build a wallet dApp on Berachain using the Thirdweb SDK button in your Web3 app using <a href="https://thirdweb.com/"><strong><em>Thirdweb SDK</em></strong></a>, a full stack web3 development platform and a powerful tool for building blockchain applications.</p><p>We will explore every step of this integration, understanding its significance, ensuring that even new developer beras 🐻 will be equipped to get their dApps setup to connect with Berachain Artio!</p><p>As a bonus for the ones who read through the tutorial entirely — we’ve also added additional steps to show to capture wallet addresses of users trying to interact with your dApp. 🤓</p><h4>🤔 Why Connect Wallet Button?</h4><p>In Web3 applications, user interaction is heavily reliant on blockchain transactions, which necessitates a secure and efficient way to connect user wallets to the application. This connection enables a seamless interaction with smart contracts, allowing for a range of functionalities from executing transactions to querying blockchain data.</p><p>A <strong><em>Connect Wallet</em></strong> button is more than just a user interface element; it’s the bridge that links the decentralized world of blockchain with the user-centric interface of your application. It ensures that users can securely interact with your application while maintaining control over their digital assets and identity.</p><h4>🛠️ What are we building?</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jDPcIF1184XUPYrLU0zm8Q.png" /><figcaption>Berachain Thirdweb Connect Button Landing Page</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QEUrmGCYXHD8eA-2UPMTbg.png" /><figcaption>Berachain Thirdweb Connect Button (After connecting Metamask)</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oiEjgmgUgt2CcF2SIuj2yQ.png" /><figcaption>Expanded Menu — Connect Wallet Button</figcaption></figure><p>In this comprehensive guide, we’re building a dApp on Berachain that would serve as a one-stop template for devs trying to onboard developers onto their dApps via <strong>connect wallet</strong> button.</p><p>This feature is not merely a technical requirement but a gateway to the Berachain ecosystem, providing users with the ability to securely interact with your application. Remember, the ‘Connect Wallet’ button is more than a utility; it’s the first step in the user’s journey within your application.</p><p>The existing template is available on official Berachain repo-</p><p><a href="https://github.com/berachain/guides/tree/main/apps/thirdweb-connectwallet-nextjs">guides/apps/thirdweb-connectwallet-nextjs at main · berachain/guides</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*n2KcwQogCicUsNr0DHVO_g.png" /><figcaption>Berachain Guide Repo — Thirdweb dApp Template</figcaption></figure><h3>Pre-requisites</h3><ol><li>Node js &gt; 20 and latest npm. Please follow this guide if needed: <a href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm"><em>https://docs.npmjs.com/downloading-and-installing-node-js-and-npm</em></a>.</li><li>IDEs like VScode, Replit etc.</li></ol><h3>Setting Up Your Project</h3><p>Creating a robust foundation is crucial for the development of any application. Let’s start by setting up our project environment using Thirdweb.</p><h4>Step 1: Creating a New App with Thirdweb</h4><p>Creating your app with Third Web is the first step towards building your Web3 application. Here’s how to do it:</p><ol><li><strong>Launch Your Terminal</strong>: Start by opening your terminal. This is where you’ll enter the commands to create your project.</li><li><strong>Run the Creation Command</strong>: Type npx thirdweb@latest create app in your terminal. This command fetches the latest version of Thirdweb and initiates the creation of your Web3 application.</li></ol><pre>npx thirdweb@latest create app<br># Need to install the following packages:<br># thirdweb@0.13.43<br># Ok to proceed? (y) y<br># npm WARN deprecated @safe-global/safe-ethers-lib@1.9.4: WARNING: This package is now bundled in @safe-global/protocol-kit. Please, follow the migration guide https://docs.safe.global/safe-core-aa-sdk/protocol-kit/reference/v1<br><br>#     $$\     $$\       $$\                 $$\                         $$\       <br>#     $$ |    $$ |      \__|                $$ |                        $$ |      <br>#   $$$$$$\   $$$$$$$\  $$\  $$$$$$\   $$$$$$$ |$$\  $$\  $$\  $$$$$$\  $$$$$$$\  <br>#   \_$$  _|  $$  __$$\ $$ |$$  __$$\ $$  __$$ |$$ | $$ | $$ |$$  __$$\ $$  __$$\ <br>#     $$ |    $$ |  $$ |$$ |$$ |  \__|$$ /  $$ |$$ | $$ | $$ |$$$$$$$$ |$$ |  $$ |<br>#     $$ |$$\ $$ |  $$ |$$ |$$ |      $$ |  $$ |$$ | $$ | $$ |$$   ____|$$ |  $$ |<br>#     \$$$$  |$$ |  $$ |$$ |$$ |      \$$$$$$$ |\$$$$$\$$$$  |\$$$$$$$\ $$$$$$$  |<br>#      \____/ \__|  \__|\__|\__|       \_______| \_____\____/  \_______|\_______/ <br><br>#  💎 thirdweb v0.13.43 💎</pre><p>Type “y” and press enter to proceed. Once the installation is done you will be given multiple other options starting with “? What is your project named?”. Follow the steps mentioned in “Project Configuration” below.</p><p><strong>3. Project Configuration</strong>:</p><ul><li><strong>Naming Your Project</strong>: Assign a name to your project, such as “Connect”. This helps in identifying your project within your workspace.</li><li><strong>Note:</strong> We often get support questions regarding “Not being able to select customised name”, make sure to click on “Tab” button on your keyboard and it will highlight the “thirdwe-app” — then you should be able to make the changes.</li><li><strong>Framework and Language Selection</strong>: Choose a framework that suits your development style (e.g., Next.js) and select a programming language (e.g., TypeScript) based on your proficiency and project requirements. But for this tutorial we will be going ahead with Next.js as the framework and TypeScript language.</li><li>Selecting the path to the new project getting created — Choose the path where your project will be saved.</li></ul><p>Your overall output in terminal should look similar to -</p><pre># 💎 thirdweb v0.13.43 💎<br><br># ✔ What is your project named? … berathirdwebWallet<br># ✔ What framework do you want to use? › Next.js<br># ✔ What language do you want to use? › TypeScript<br># Creating a new thirdweb app in /Users/dethebera/BeraWork/berachain-thridweb/berachainThirdweb/berathirdwebwallet.<br><br># Downloading files with framework next. This might take a moment.<br># Installing packages. This might take a couple of minutes.<br><br># yarn install v1.22.21<br># info No lockfile found.<br># [1/4] 🔍  Resolving packages...<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @magic-ext/connect@6.7.2: Connect extension has been merged to magic-sdk, please download the latest magic-sdk to unlock more features<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @safe-global/safe-core-sdk@3.3.5: WARNING: This project has been renamed to @safe-global/protocol-kit. Please, follow the migration guide https://docs.safe.global/safe-core-aa-sdk/protocol-kit/reference/v1<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @safe-global/safe-ethers-adapters &gt; @safe-global/safe-core-sdk@3.3.5: WARNING: This project has been renamed to @safe-global/protocol-kit. Please, follow the migration guide https://docs.safe.global/safe-core-aa-sdk/protocol-kit/reference/v1<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @safe-global/safe-ethers-lib@1.9.4: WARNING: This package is now bundled in @safe-global/protocol-kit. Please, follow the migration guide https://docs.safe.global/safe-core-aa-sdk/protocol-kit/reference/v1<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @blocto/sdk &gt; eip1193-provider@1.0.1: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @safe-global/safe-core-sdk &gt; zksync-web3@0.14.4: This package has been deprecated in favor of zksync-ethers@5.0.0<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @blocto/sdk &gt; eip1193-provider &gt; @json-rpc-tools/provider@1.7.6: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/sdk &gt; @thirdweb-dev/storage &gt; cid-tool &gt; cids@1.1.9: This module has been superseded by the multiformats module<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/sdk &gt; @thirdweb-dev/storage &gt; cid-tool &gt; multibase@4.0.6: This module has been superseded by the multiformats module<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/sdk &gt; @thirdweb-dev/storage &gt; cid-tool &gt; cids &gt; multibase@4.0.6: This module has been superseded by the multiformats module<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/sdk &gt; @thirdweb-dev/storage &gt; cid-tool &gt; multihashes &gt; multibase@4.0.6: This module has been superseded by the multiformats module<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @blocto/sdk &gt; eip1193-provider &gt; @json-rpc-tools/provider &gt; @json-rpc-tools/utils@1.7.6: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/sdk &gt; @thirdweb-dev/storage &gt; cid-tool &gt; cids &gt; multicodec@3.2.1: This module has been superseded by the multiformats module<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @walletconnect/modal &gt; @walletconnect/modal-ui &gt; motion &gt; @motionone/vue@10.16.4: Motion One for Vue is deprecated. Use Oku Motion instead https://oku-ui.com/motion<br># warning @thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @blocto/sdk &gt; eip1193-provider &gt; @json-rpc-tools/provider &gt; @json-rpc-tools/utils &gt; @json-rpc-tools/types@1.7.6: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.<br># [2/4] 🚚  Fetching packages...<br># warning abitype@0.2.5: The engine &quot;pnpm&quot; appears to be invalid.<br># [3/4] 🔗  Linking dependencies...<br># warning &quot;@thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @magic-sdk/provider@13.6.2&quot; has unmet peer dependency &quot;localforage@^1.7.4&quot;.<br># warning &quot;@thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @safe-global/safe-ethers-adapters@0.1.0-alpha.17&quot; has unmet peer dependency &quot;@ethersproject/abstract-provider@^5.7.0&quot;.<br># warning &quot;@thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @safe-global/safe-ethers-adapters@0.1.0-alpha.17&quot; has unmet peer dependency &quot;@ethersproject/abstract-signer@^5.7.0&quot;.<br># warning &quot;@thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @safe-global/safe-ethers-adapters@0.1.0-alpha.17&quot; has unmet peer dependency &quot;@ethersproject/bignumber@^5.7.0&quot;.<br># warning &quot;@thirdweb-dev/react &gt; @thirdweb-dev/wallets &gt; @safe-global/safe-ethers-adapters@0.1.0-alpha.17&quot; has unmet peer dependency &quot;@ethersproject/properties@^5.7.0&quot;.<br># warning &quot;@thirdweb-dev/react &gt; @thirdweb-dev/react-core &gt; @thirdweb-dev/auth &gt; fastify-type-provider-zod@1.1.9&quot; has unmet peer dependency &quot;fastify@^4.0.0&quot;.<br># [4/4] 🔨  Building fresh packages...<br># success Saved lockfile.<br># ✨  Done in 44.53s.<br><br># Initialized a git repository.<br><br># Success! Created berathirdwebwallet at /Users/dethebera/BeraWork/berachain-thridweb/berachainThirdweb/berathirdwebwallet<br># Inside that directory, you can run several commands:<br><br>#   yarn dev<br>#     Starts the development server.<br><br>#   yarn build<br>#     Builds the app for production.<br><br># We suggest that you begin by typing:<br><br>#   cd berathirdwebwallet<br>#   yarn dev</pre><p>Once you’ve mastered the art of understanding and have become and “OG Dev Bera” you will feel more confident in setting the stage and the tone for your development process. Choosing the right framework and language is essential as it affects the ease of development and the scalability of your application.</p><p><em>💡 </em><strong><em>Fun Fact:</em></strong><em> Thirdweb sdk supports multiple frameworks. More below.</em></p><h3>Testing the Existing Template</h3><p>Now that everything is installed. It’s time to test the template and see what it offers in-house and we will plan the customization needed for Berachain Artio support accordingly!</p><p>Run the following in the same terminal:</p><pre>cd berathirdwebWallet <br>yarn dev</pre><p>then in your browser search for <a href="http://localhost:3000/">http://localhost:3000</a>. You should be able to see output similar to below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7kH34e4a2vR5RG9KEkQP6w.png" /><figcaption>Thirdweb dApp on localhost</figcaption></figure><p>Lets connect our Berachain Wallet to this existing dApp and see what’up. Click on the the “Connect Wallet” button and select “Metamask”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2BTpKOWE5UH_GwHHsVAHRw.png" /><figcaption>Select Wallet Screen</figcaption></figure><p>It’s interesting to see that the template itself is almost functional and it does read the amount of $BERA in wallet correctly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DwGr6V_kXG13ImgvT58SZw.png" /></figure><p>But, given thirdweb’s existing template uses “Ethereum” as their standard for templates and examples. The exiting dApp dosent know which chain exactly would Berachain be and what is the symbol of it’s token/ $BERA.</p><p>Let’s fix that in the upcoming section.</p><h3>Step 2: Implementing the Connect Wallet Button</h3><p>The ‘Connect Wallet’ button is central to the user experience in your Web3 application. Let’s integrate it.</p><ol><li><strong>Prepare the Workspace</strong>: Clean your <strong>index.tsx</strong> file by removing any pre-existing template code. This file will be the canvas for our &#39;Connect Wallet&#39; button.</li></ol><p>Sharing an example below on how the inital<strong>index.tsx</strong>file after the cleanup would look like.</p><p><strong>Filename: </strong><strong>./pages/index.tsx</strong></p><pre>import { ConnectWallet } from &quot;@thirdweb-dev/react&quot;;<br>import styles from &quot;../styles/Home.module.css&quot;;<br>import Image from &quot;next/image&quot;;<br>import { NextPage } from &quot;next&quot;;<br><br>const Home: NextPage = () =&gt; {<br>  return (<br>    &lt;main className={styles.main}&gt;<br>      &lt;div className={styles.container}&gt;<br>        &lt;div className={styles.header}&gt;<br><br>// ........<br>// deleted portion <br>// ........<br><br>        &lt;/div&gt;<br>      &lt;/div&gt;<br>    &lt;/main&gt;<br>  );<br>};<br><br>export default Home;</pre><p>2. <strong>Incorporate the Connect Wallet component</strong> into this file by adding “&lt;ConnectWallet /&gt;” in the “deleted” section above. Note, we’ve also made changes to the structure with main inside div.</p><p><strong>Filename: </strong><strong>./pages/index.tsx</strong></p><pre>import { ConnectWallet } from &quot;@thirdweb-dev/react&quot;;<br>import styles from &quot;../styles/Home.module.css&quot;;<br>import Image from &quot;next/image&quot;;<br>import { NextPage } from &quot;next&quot;;<br><br>const Home: NextPage = () =&gt; {<br>  return (<br><br>// Changes performed below  <br>    &lt;div className={styles.container}&gt;<br>      &lt;main className={styles.main}&gt; <br>        &lt;ConnectWallet /&gt;  // Connect wallet button<br>      &lt;/main&gt;<br>    &lt;/div&gt;<br>  );  <br>};<br><br>export default Home;</pre><p>Let’s check our dApp again, you would notice that the button appears in the top-left corner of the screen- rather than the middle.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RvkMjvmCgQDcQEsfAFzU3w.png" /></figure><p>That looks weird, gead over to File: <em>Home.module.css</em> — or just search for “.container” in the search bar in code. Replace the existing code in their with the following.</p><p><strong>Filename: </strong><strong>./styles/Home.module.css</strong></p><pre>/* Changes performed below ----------------------*/<br><br>.container {<br>  position: absolute;<br>    top: 50%;<br>    left: 50%;<br>    transform: translate(-50%, -50%);<br>}<br><br>/* -----------------------------------------*/ <br><br>.gradientText0 {<br>  background: -webkit-linear-gradient(#bfa3da, #84309c, #c735b0);<br>  -webkit-background-clip: text;<br>  background-clip: text;<br>  -webkit-text-fill-color: transparent;<br>}<br><br>.gradientText1 {<br>  background: -webkit-linear-gradient(#a79af9, #7aa8d2);<br>  -webkit-background-clip: text;<br>  background-clip: text;<br>  -webkit-text-fill-color: transparent;<br>}<br><br>.gradientText2 {<br>  background: -webkit-linear-gradient(#bfa3da, #743f93);<br>  -webkit-background-clip: text;<br>  background-clip: text;<br>  -webkit-text-fill-color: transparent;<br>}<br><br>.gradientText3 {<br>  background: -webkit-linear-gradient(#c35ab1, #e9a8d9);<br>  -webkit-background-clip: text;<br>  background-clip: text;<br>  -webkit-text-fill-color: transparent;<br>}<br><br>.title a:hover,<br>.title a:focus,<br>.title a:active {<br>  text-decoration: underline;<br>  text-decoration-color: #84309c;<br>}<br><br>.title {<br>  line-height: 1.15;<br>  font-size: 4rem;<br>}<br><br>.title,<br>.description {<br>  text-align: left;<br>}<br><br>.connect {<br>  margin-bottom: 2rem;<br>}<br><br>.description {<br>  margin-top: 2rem;<br>  margin-bottom: 2rem;<br>  line-height: 1.5;<br>  font-size: 1.5rem;<br>}<br><br>.code {<br>  background: #555;<br>  border-radius: 5px;<br>  padding: 0.5em;<br>  font-size: 1.1rem;<br>}<br><br>.grid {<br>  display: flex;<br>  justify-content: left;<br>  flex-wrap: wrap;<br>  gap: 20px;<br>}<br><br>.card {<br>  background-color: #131313;<br>  text-align: left;<br>  color: inherit;<br>  text-decoration: none;<br>  border-radius: 10px;<br>  transition: color 0.15s ease, border-color 0.15s ease;<br>  max-width: 440px;<br>  overflow: none;<br>  border: none;<br>}<br><br>.cardText {<br>  padding: 1rem;<br>}<br><br>.card img {<br>  display: block;<br>  width: 100%;<br>  height: auto;<br>  border-radius: 4px 4px 0 0;<br>  margin-bottom: 12px;<br>  border: none;<br>}<br><br>.card:hover,<br>.card:focus,<br>.card:active {<br>  background-color: #272c34;<br>  opacity: 80%;<br>}<br><br>.card h2 {<br>  margin: 0 0 0.75rem 0;<br>}<br><br>.card p {<br>  margin: 0;<br>  font-size: 1rem;<br>  line-height: 1.75;<br>}<br><br>.logo {<br>  height: 1em;<br>  margin-left: 0.5rem;<br>}<br><br>@media (max-width: 768px) {<br>  .header {<br>    margin-left: 0;<br>  }<br>  .grid {<br>    width: 100%;<br>    flex-direction: column;<br>  }<br>  .title {<br>    font-size: 3rem;<br>    line-height: 1.15;<br>  }<br>}<br><br>.card,<br>.footer {<br>  border-color: #222;<br>}<br>.logo img {<br>  filter: invert(1);<br>}<br></pre><p>Nice. Now the button looks aligned.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KMcYj41IHAzUS1whwa7vbg.png" /><figcaption>Button Centre Aligned After CSS Change</figcaption></figure><h3>Step 3: Customizing the Button to Berachain Artio</h3><p>Customization plays a key role in aligning the button with the look and feel of your application and the specific needs of our Bera-users.</p><ol><li><strong>Blockchain Selection</strong>: In the <strong>app.tsx</strong> file, we need to specify Berachain Artio that your application will primarily interact with.</li></ol><p>Given Artio is still very new, we don’t expect all the amazing devtools to support it right of the bad like ethereum which is used in most templates. But we will be there for sure :) soon.</p><p>For now let’s try and see what happens if we directly input “BerachainArtio” as an activechain.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*k8NtohO_W9bboJ7rXiqzZA.png" /></figure><p>You will notice it says it is a supported chain. Well that isn’t true as thirdweb sdk sources it’s chain from chainlist where Artio support has already been added. Let’s fix this.</p><p><strong>2. Importing Berachain Artio:</strong></p><p>I will be showing you an amazing and an easy way to get the customization done for Berachain Artio.</p><p>Head over to <a href="https://thirdweb.com/chainlist"><strong><em>https://thirdweb.com/chainlist</em></strong></a> and search for Berachain Artio.</p><p>Click on Berachain Artio and scroll down to the “Getting Started with Berachain Artio” Section.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kfoAO5OMQ3cKyTdWunclnw.png" /></figure><p>Copy “import { BerachainArtio } from “@thirdweb-dev/chains”; “ and add it to the _app.tsx file.</p><p>Additionally the “ {activechain} “ in function MyApp needs to be updates as well. Replace it with “ {BerachainArtio} “.</p><p>The final _app.tsx should look like the code below…</p><p><strong>Filename: </strong><strong>/pages/_app.tsx</strong></p><pre>import type { AppProps } from &quot;next/app&quot;;<br>import { ThirdwebProvider } from &quot;@thirdweb-dev/react&quot;;<br>import &quot;../styles/globals.css&quot;;<br><br>// Added import here <br>import { BerachainArtio } from &quot;@thirdweb-dev/chains&quot;;<br><br><br>// This is the chain your dApp will work on.<br>// Change this to the chain your app is built for.<br>// You can also import additional chains from `@thirdweb-dev/chains` and pass them directly.<br><br>// Active Chain Replaced with Berachain Artio<br>const activeChain = &quot;BerachainArtio&quot;;<br><br>function MyApp({ Component, pageProps }: AppProps) {<br>  return (<br>    &lt;ThirdwebProvider<br>      clientId={process.env.NEXT_PUBLIC_TEMPLATE_CLIENT_ID}<br>      activeChain={BerachainArtio}  <br>    &gt;<br>      &lt;Component {...pageProps} /&gt;<br>    &lt;/ThirdwebProvider&gt;<br>  );<br>}<br><br>export default MyApp;</pre><p>Now hit save and let’s check the our connect wallet button. Disconnect the existing wallet and refresh the page.</p><p>Click on “Connect Wallet” button and login via Metamask.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*32tI-TWaZdqnaRxbQfPxpA.png" /></figure><p>Any visible changes? …… 🤔 Looking closely you would see that instead of “<em>ETH</em>” now the wallet read “<em>BERA</em>”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9c9VGvqfPtRwcekeIRrWig.png" /></figure><p>Expanding the wallet further we can see it even recognized Berachain Artio along with it’s official Logo.</p><h3>Step 5: Configuring Supported Wallets</h3><p>Now if you’re looking to support other wallets — Thirdweb now supports most popular wallets out there right via the existing template. Let’s look at quick steps to configure any wallet.</p><ol><li><strong>Defining Supported Chains and Wallets</strong>: Clearly list the chains and wallets your application will support in an array format. This clarity is essential for users to understand the capabilities and limitations of your app.</li><li><strong>Inclusion of Diverse Wallet Options</strong>: Add more wallet options, such as Smart Wallet or Email Wallet, to increase accessibility and user choice.</li><li><strong>Including only Metamask?</strong>: Let’s say you wanna build a dApp with only 1 wallet — example Metamask to show up on the screen and none of the other wallets? How would you do it?</li></ol><p>Let’s take a look at our existing _app.tsx. And add a “supportedWallets” property right after “activeChain”.</p><p><strong>Filename: </strong><strong>./pages/_app.tsx</strong></p><pre>import type { AppProps } from &quot;next/app&quot;;<br>import { ThirdwebProvider } from &quot;@thirdweb-dev/react&quot;;<br>import &quot;../styles/globals.css&quot;;<br><br>// Added import here <br>import { BerachainArtio } from &quot;@thirdweb-dev/chains&quot;;<br><br>// This is the chain your dApp will work on.<br>// Change this to the chain your app is built for.<br>// You can also import additional chains from `@thirdweb-dev/chains` and pass them directly.<br><br>// Active Chain Replaced with Berachain Artio<br>const activeChain = &quot;BerachainArtio&quot;;<br>function MyApp({ Component, pageProps }: AppProps) {<br>  <br>// supportedWallets <br>return (<br>    &lt;ThirdwebProvider<br>      clientId={process.env.NEXT_PUBLIC_TEMPLATE_CLIENT_ID}<br>      activeChain={BerachainArtio}<br>      supportedWallets={[<br>        metamaskWallet()<br>      ]}<br>    &gt;<br>      &lt;Component {...pageProps} /&gt;<br>    &lt;/ThirdwebProvider&gt;<br>  );<br>}<br><br>export default MyApp;</pre><p>This should now give only Metamask as the default wallet option and clicking the “Connect Wallet” button should automatically trigger Metamask without the user choosing which wallet.</p><p>This is a good option for saving a few steps and ensuring a master onboarding takes place.</p><h3>Step 6: Styling the Button</h3><p><strong>1.Theme Customization</strong>: Choose between dark and light themes to match the aesthetic of your app. Property: <em>theme</em></p><p>Thirdweb currently supports Dark and light theme. For this guide let’s select light.</p><p>In <strong>index.tsx</strong>, under &lt;ConnectWallet /&gt; add the <strong>theme=&quot;light”.</strong></p><p><strong>Filename: </strong><strong>./pages/index.tsx</strong></p><pre>import { ConnectWallet, useAddress } from &quot;@thirdweb-dev/react&quot;;<br>import styles from &quot;../styles/Home.module.css&quot;;<br>import Image from &quot;next/image&quot;;<br>import { NextPage } from &quot;next&quot;;<br><br>const Home: NextPage = () =&gt; {<br>  const address = useAddress();<br>  console.log(address);<br><br>  return (<br>    &lt;div className={styles.container}&gt;<br>      &lt;main className={styles.main}&gt;<br>        &lt;ConnectWallet<br>          theme=&quot;light&quot;<br>          btnTitle=&quot;Bera Connect&quot;<br>          className={styles.beraWallet}<br>        /&gt;<br>      &lt;/main&gt;<br>    &lt;/div&gt;<br>  );<br>};<br><br>export default Home;</pre><p><strong>2. Button Text and CSS Styling</strong>: Change the button text for better integration into your app’s user flow. Apply custom CSS styles to make the button a seamless part of your application’s design language.</p><p>Property :btnTitle, className</p><p>Here, we would be changing the “Connect Wallet” to “Bera Connect” and additionally via className — changing the colour of the button to make it more suited to Berachain’s branding.</p><p>Add the following code right below theme.</p><p><strong>Filename: </strong><strong>./pages/_app.tsx</strong></p><pre>import type { AppProps } from &quot;next/app&quot;;<br>import { ThirdwebProvider, metamaskWallet } from &quot;@thirdweb-dev/react&quot;;<br>import &quot;../styles/globals.css&quot;;<br>import { BerachainArtio } from &quot;@thirdweb-dev/chains&quot;;<br><br>// This is the chain your dApp will work on.<br>// Change this to the chain your app is built for.<br>// You can also import additional chains from `@thirdweb-dev/chains` and pass them directly.<br>const activeChain = &quot;BerachainArtio&quot;;<br><br>function MyApp({ Component, pageProps }: AppProps) {<br>  return (<br>    &lt;ThirdwebProvider<br>      clientId={process.env.NEXT_PUBLIC_TEMPLATE_CLIENT_ID}<br>      activeChain={BerachainArtio}<br>      supportedWallets={[<br>        metamaskWallet()<br>      ]}<br>    &gt;<br>      &lt;Component {...pageProps} /&gt;<br>    &lt;/ThirdwebProvider&gt;<br>  );<br>}<br><br>export default MyApp;</pre><p>Now head over to <strong>Home.module.css</strong><em> </em>file and add the following code at the end of the file.</p><p><strong>Filename: </strong><strong>./styles/Home.module.css</strong></p><pre>/* add the following to the end of the css file*/<br><br>.beraWallet {<br> background-color: ##2C1A16 !important;<br>}</pre><h3>Complete Code Used in Tutorial</h3><p><strong>Filename: </strong><strong>./pages/_app.tsx</strong></p><pre>import type { AppProps } from &quot;next/app&quot;;<br>import { ThirdwebProvider, metamaskWallet } from &quot;@thirdweb-dev/react&quot;;<br>import &quot;../styles/globals.css&quot;;<br>import { BerachainArtio } from &quot;@thirdweb-dev/chains&quot;;<br><br><br>// This is the chain your dApp will work on.<br>// Change this to the chain your app is built for.<br>// You can also import additional chains from `@thirdweb-dev/chains` and pass them directly.<br>const activeChain = &quot;BerachainArtio&quot;;<br><br>function MyApp({ Component, pageProps }: AppProps) {<br>  return (<br>    &lt;ThirdwebProvider<br>      clientId={process.env.NEXT_PUBLIC_TEMPLATE_CLIENT_ID}<br>      activeChain={BerachainArtio}<br>      supportedWallets={[<br>        metamaskWallet()<br>      ]}<br>    &gt;<br>      &lt;Component {...pageProps} /&gt;<br>    &lt;/ThirdwebProvider&gt;<br>  );<br>}<br><br>export default MyApp;</pre><p><strong>Filename: </strong><strong>./pages/_app.tsx</strong></p><pre>import { ConnectWallet, useAddress } from &quot;@thirdweb-dev/react&quot;;<br>import styles from &quot;../styles/Home.module.css&quot;;<br>import Image from &quot;next/image&quot;;<br>import { NextPage } from &quot;next&quot;;<br><br>const Home: NextPage = () =&gt; {<br>  const address = useAddress();<br>  console.log(address);<br><br>  return (<br>    &lt;div className={styles.container}&gt;<br>      &lt;main className={styles.main}&gt;<br>        &lt;ConnectWallet<br>          theme=&quot;light&quot;<br>          btnTitle=&quot;Bera Connect&quot;<br>          className={styles.beraWallet}<br>        /&gt;<br>      &lt;/main&gt;<br>    &lt;/div&gt;<br>  );<br>};<br><br>export default Home;</pre><p><strong>Filename: </strong><strong>./styles/globals.css</strong></p><pre>@import url(https://medium.com/&quot;https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&amp;display=swap&quot;);<br>html,<br>body {<br>  padding: 0;<br>  margin: 0;<br>  font-family: &quot;Inter&quot;, sans-serif;<br>}<br>a {<br>  color: #84309c;<br>  text-decoration: none;<br>}<br>* {<br>  box-sizing: border-box;<br>}<br>body {<br>  color: #e7e8e8;<br>  background: #F47226;<br>}</pre><p><strong>Filename: </strong><strong>./styles/Home.module.css</strong></p><pre>.container {<br>  position: absolute;<br>    top: 50%;<br>    left: 50%;<br>    transform: translate(-50%, -50%);<br>}<br><br>.gradientText0 {<br>  background: -webkit-linear-gradient(#bfa3da, #84309c, #c735b0);<br>  -webkit-background-clip: text;<br>  background-clip: text;<br>  -webkit-text-fill-color: transparent;<br>}<br><br>.gradientText1 {<br>  background: -webkit-linear-gradient(#a79af9, #7aa8d2);<br>  -webkit-background-clip: text;<br>  background-clip: text;<br>  -webkit-text-fill-color: transparent;<br>}<br><br>.gradientText2 {<br>  background: -webkit-linear-gradient(#bfa3da, #743f93);<br>  -webkit-background-clip: text;<br>  background-clip: text;<br>  -webkit-text-fill-color: transparent;<br>}<br><br>.gradientText3 {<br>  background: -webkit-linear-gradient(#c35ab1, #e9a8d9);<br>  -webkit-background-clip: text;<br>  background-clip: text;<br>  -webkit-text-fill-color: transparent;<br>}<br><br>.title a:hover,<br>.title a:focus,<br>.title a:active {<br>  text-decoration: underline;<br>  text-decoration-color: #84309c;<br>}<br><br>.title {<br>  line-height: 1.15;<br>  font-size: 4rem;<br>}<br><br>.title,<br>.description {<br>  text-align: left;<br>}<br><br>.connect {<br>  margin-bottom: 2rem;<br>}<br><br>.description {<br>  margin-top: 2rem;<br>  margin-bottom: 2rem;<br>  line-height: 1.5;<br>  font-size: 1.5rem;<br>}<br><br>.code {<br>  background: #555;<br>  border-radius: 5px;<br>  padding: 0.5em;<br>  font-size: 1.1rem;<br>}<br><br>.grid {<br>  display: flex;<br>  justify-content: left;<br>  flex-wrap: wrap;<br>  gap: 20px;<br>}<br><br>.card {<br>  background-color: #131313;<br>  text-align: left;<br>  color: inherit;<br>  text-decoration: none;<br>  border-radius: 10px;<br>  transition: color 0.15s ease, border-color 0.15s ease;<br>  max-width: 440px;<br>  overflow: none;<br>  border: none;<br>}<br><br>.cardText {<br>  padding: 1rem;<br>}<br><br>.card img {<br>  display: block;<br>  width: 100%;<br>  height: auto;<br>  border-radius: 4px 4px 0 0;<br>  margin-bottom: 12px;<br>  border: none;<br>}<br><br>.card:hover,<br>.card:focus,<br>.card:active {<br>  background-color: #272c34;<br>  opacity: 80%;<br>}<br><br>.card h2 {<br>  margin: 0 0 0.75rem 0;<br>}<br><br>.card p {<br>  margin: 0;<br>  font-size: 1rem;<br>  line-height: 1.75;<br>}<br><br>.logo {<br>  height: 1em;<br>  margin-left: 0.5rem;<br>}<br><br>@media (max-width: 768px) {<br>  .header {<br>    margin-left: 0;<br>  }<br>  .grid {<br>    width: 100%;<br>    flex-direction: column;<br>  }<br>  .title {<br>    font-size: 3rem;<br>    line-height: 1.15;<br>  }<br>}<br><br>.card,<br>.footer {<br>  border-color: #222;<br>}<br>.logo img {<br>  filter: invert(1);<br>}<br><br>.beraWallet {<br> background-color: #2C1A16 !important;<br>}Additional: Accessing Wallet Address</pre><h3>Additional: Accessing Wallet Address</h3><h4><strong>How to get users wallet addresses?</strong></h4><p>The ability to access and use the wallet address is fundamental for any Web3 application. The use-cases are vast. Let’s show you a simple way of capturing the wallet addresses of the users connecting their wallets to your dApp.</p><p>The ability to access and use the wallet address is fundamental for any Web3 application. The use-cases are vast. Let’s show you a simple way of capturing the wallet addresses of the users connecting their wallets to your dApp.</p><h3>Step 7: Using the Use Address Hook</h3><ol><li><strong>Implementing the Hook</strong>: Utilize the useAddress hook in <strong>index.tsx </strong>to capture the address of the connected wallet. This is crucial for transactions and smart contract interactions.</li></ol><pre>const Home: NextPage = () =&gt; {<br>  const address = useAddress();</pre><p><strong>2. Verification</strong>: Display the retrieved address in the console to verify successful integration and functionality.</p><pre>console.log(address);</pre><p>Now after connecting the wallet and opening the console in your browser. You would be able to see the wallet addresses available.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*k_ueI-BJV4AUTgbJnFZLUw.png" /></figure><p>Overall the final <strong>index.tsx</strong> file will look like below.</p><p><strong>Filename: </strong><strong>./pages/index.tsx</strong></p><pre>import { ConnectWallet, useAddress } from &quot;@thirdweb-dev/react&quot;;<br>import styles from &quot;../styles/Home.module.css&quot;;<br>import Image from &quot;next/image&quot;;<br>import { NextPage } from &quot;next&quot;;<br><br>const Home: NextPage = () =&gt; {<br>  const address = useAddress();<br>  console.log(address);<br><br>  return (<br>    &lt;div className={styles.container}&gt;<br>      &lt;main className={styles.main}&gt;<br>        &lt;ConnectWallet<br>          theme=&quot;light&quot;<br>          btnTitle=&quot;Bera Connect&quot;<br>          className={styles.beraWallet}<br>        /&gt;<br>      &lt;/main&gt;<br>    &lt;/div&gt;<br>  );<br>};<br><br>export default Home;</pre><p>And that’s all! With this additional step you’ve not only created a dApp that can now let users connect their wallets but you are also able to see user’s wallet addresses.</p><h3>More dApps and How To Get Support ?</h3><p><strong>Learning Resources</strong>: Explore additional guides currently available via our docs at <a href="https://docs.berachain.com/developers">https://docs.berachain.com/developers</a>.</p><p><a href="https://docs.berachain.com/developers">Connecting to Berachain</a></p><h4>How To Get Support ?</h4><p><strong>Discord Community</strong>: Join the Third Web Discord community for further assistance, discussions, and to stay updated with the latest developments in Web3.</p><p>⚠️ Still facing issues or have doubts? Head over to discord and raise a ticket as shown in the gif below!</p><p>Our DevRel team will be happy to assist! 🤝</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*QmeL3wtqcBhiHbnieK6LaQ.gif" /></figure><p>Byyeeee dev bears! 🐻</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a7775d72811d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/berachain-devs/berachain-wallet-connect-with-thirdweb-sdk-a7775d72811d">Berachain Wallet Connect with Thirdweb SDK</a> was originally published in <a href="https://medium.com/berachain-devs">berachain-devs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How To Deploy And Verify Contracts On Berachain]]></title>
            <link>https://medium.com/berachain-devs/how-to-deploy-and-verify-contracts-on-berachain-cd6642029641?source=rss----b629d42886be---4</link>
            <guid isPermaLink="false">https://medium.com/p/cd6642029641</guid>
            <category><![CDATA[deployment]]></category>
            <category><![CDATA[solidity]]></category>
            <category><![CDATA[web3]]></category>
            <category><![CDATA[contracts]]></category>
            <category><![CDATA[guides-and-tutorials]]></category>
            <dc:creator><![CDATA[De]]></dc:creator>
            <pubDate>Tue, 23 Apr 2024 13:35:40 GMT</pubDate>
            <atom:updated>2024-04-23T13:35:40.513Z</atom:updated>
            <content:encoded><![CDATA[<h4>Ultimate Guide to Deploying an ERC-721 NFT and Verifying Contracts on Berachain Artio</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*n6YaCSsTyW9PaPbpxySlPA.png" /><figcaption>Main Banner</figcaption></figure><h3>Introduction to Berachain Artio Testnet</h3><p>In the burgeoning world of 100+ blockchain technology, Berachain emerges as a goto cosmos based evm compatible chain for developers to build on. Known for its POL design, robust scalability, and enhanced security, Berachain stands out as a haven for developers as its lucrative for users to interact with the chain. Its early adoption of wide array of decentralized applications (dApps) and evm compatibility makes it an ideal choice for developers to build and test their products on.</p><p>Like any other blockchains Artio testnet is a key component for upcoming Berachain Mainnet, providing a testing ground for developers to prepare, test their tools well in advance. It’s here that bear magic of smart contracts, especially the ERC-721 standard for Non-Fungible Tokens (NFTs), comes to life. 🐻 ❤️</p><h3>🤔 Why Hardhat?</h3><p>Hardhat is a pivotal tool in Ethereum development. It streamlines various processes such as compiling, deploying, testing, and debugging smart contracts. Think of it as your personal blockchain workshop, equipped with all the tools you need for dApp development.</p><h3>🛠️ What are we Building?</h3><p>In this tutorial, we will guide you through creating and deploying an ERC-721 smart contract on the Berachain Testnet (Artio) using hardhat-ethers. This tutorial focuses on writing, deploying and also verifying the non-fungible (ERC-721) token smart contract using Hardhat, ethers.js onto Berachain Testnet!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/967/1*SxY61Hr1_g5KCzRvXwG7WQ.png" /><figcaption>Snippet of Successful Contract Deployment Using Hardhat</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2zFFRHhpEBEsUdREO5yvJA.png" /><figcaption>Snippet of Successful Verification of Deployed Contract Using Hardhat</figcaption></figure><p>We will majorly be covering the initial setup, creation, and deployment of the contract!</p><h3>⚠️ Prerequisites</h3><p>Before embarking on this technical tutorial about, it’s imperative to equip yourself with the following:</p><ul><li>A solid understanding of blockchain fundamentals and smart contract principles.</li><li>Proficiency in Solidity, the primary language for Ethereum-based contract development.</li><li>The latest versions of Node.js and npm installed on your machine, verifiable through the command line with node -v.</li></ul><h3>Step 1: Initiating a Node.js Project</h3><p>Begin by creating a new Node.js project. This foundational step involves setting up a dedicated project directory and initializing it with Node’s package management tools.</p><pre>mkdir bera-hardhatTest &amp;&amp; cd bera-hardhatTest</pre><pre>npm init -y<br># Wrote to /Users/dethebera/BeraWork/hardhat-verification-bera/package.json:<br><br># {<br>#  &quot;name&quot;: &quot;hardhat-verification-bera&quot;,<br>#   &quot;version&quot;: &quot;1.0.0&quot;,<br>#  &quot;description&quot;: &quot;&quot;,<br>#   &quot;main&quot;: &quot;index.js&quot;,<br>#   &quot;scripts&quot;: {<br>#     &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;<br>#   },<br>#   &quot;keywords&quot;: [],<br>#   &quot;author&quot;: &quot;&quot;,<br>#   &quot;license&quot;: &quot;ISC&quot;<br># }</pre><p>This command sequence crafts a new directory and then triggers the Node.js project initialization with default parameters.</p><h3>Step 2: Setting Up Hardhat</h3><p>Install Hardhat in your project directory and initiate a new project environment:</p><pre>npm install --save-dev hardhat<br><br># added 263 packages, and audited 264 packages in 31s<br><br># 52 packages are looking for funding<br>#  run `npm fund` for details<br><br># found 0 vulnerabilities</pre><p>Select TypeScript as your project language and follow through the setup prompts, ensuring the inclusion of a .gitignore file and necessary dependencies.</p><p>Note: DEPRECATION WARNING</p><p>Initializing a project with npx hardhat is deprecated and will be removed in the future. Please use <em>npx hardhat init</em> instead.</p><pre>npx hardhat init<br># 888    888                      888 888               888<br># 888    888                      888 888               888<br># 888    888                      888 888               888<br># 8888888888  8888b.  888d888 .d88888 88888b.   8888b.  888888<br># 888    888     &quot;88b 888P&quot;  d88&quot; 888 888 &quot;88b     &quot;88b 888<br># 888    888 .d888888 888    888  888 888  888 .d888888 888<br># 888    888 888  888 888    Y88b 888 888  888 888  888 Y88b.<br># 888    888 &quot;Y888888 888     &quot;Y88888 888  888 &quot;Y888888  &quot;Y888<br><br># 👷 Welcome to Hardhat v2.21.0 👷‍<br><br># ✔ What do you want to do? · Create a TypeScript project<br># ✔ Hardhat project root: · /Users/dethebera/BeraWork/hardhat-verification-bera<br># ✔ Do you want to add a .gitignore? (Y/n) · y<br># ✔ Do you want to install this sample project&#39;s dependencies with npm (@nomicfoundation/hardhat-toolbox)? (Y/n) · y<br><br># npm install --save-dev &quot;@nomicfoundation/hardhat-toolbox@^4.0.0&quot;<br><br># added 273 packages, and audited 537 packages in 40s<br><br># 90 packages are looking for funding<br>#   run `npm fund` for details<br><br># found 0 vulnerabilities<br><br># ✨ Project created ✨<br><br># See the README.md file for some example tasks you can run<br><br># Give Hardhat a star on Github if you&#39;re enjoying it! ⭐️✨<br><br>#      https://github.com/NomicFoundation/hardhat</pre><p>After setting up Hardhat, verify its proper functioning with:</p><pre>npx hardhat test<br><br>#Downloading compiler 0.8.24<br># Compiled 1 Solidity file successfully (evm target: paris).<br><br><br>#   Lock<br>#     Deployment<br>#       ✔ Should set the right unlockTime (691ms)<br>#       ✔ Should set the right owner<br>#       ✔ Should receive and store the funds to lock<br>#       ✔ Should fail if the unlockTime is not in the future<br>#     Withdrawals<br>#       Validations<br>#         ✔ Should revert with the right error if called too soon<br>#         ✔ Should revert with the right error if called from another account<br>#         ✔ Shouldn&#39;t fail if the unlockTime has arrived and the owner calls it<br>#       Events<br>#         ✔ Should emit an event on withdrawals<br>#       Transfers<br>#         ✔ Should transfer the funds to the owner<br><br><br>#   9 passing (717ms)</pre><h3>Step 3: Diving into NFT Smart Contract Development</h3><p>Now, delve into the heart of your project — the NFT smart contract. Navigate to the contracts folder and begin scripting your ERC-721 contract. This phase is crucial as it involves the actual code that defines your NFT&#39;s characteristics and behavior.</p><p>Head over to contracts folder and create a new file <strong>NFT.sol</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WnzJ54tVAJM5L8zeHqOPDw.png" /></figure><p>Here’s a basic template using OpenZeppelin’s secure and reputable libraries:</p><p><strong>File:</strong> <strong>./contracts/NFT.sol</strong></p><pre>// SPDX-License-Identifier: MIT<br>pragma solidity ^0.8.23;<br><br>import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;<br><br>contract NFT is ERC721 {<br>    uint256 public currentTokenId;<br><br>    constructor() ERC721(&quot;NFT Name&quot;, &quot;NFT&quot;) {}<br><br>    function mint(address recipient) public payable returns (uint256) {<br>        uint256 newItemId = ++currentTokenId;<br>        _safeMint(recipient, newItemId);<br>        return newItemId;<br>    }<br>}<br></pre><p>OpenZeppelin’s contracts are a treasure trove of pre-written, secure code snippets. They significantly reduce the development time and enhance the security of your smart contracts.</p><pre>npm install @openzeppelin/contracts<br><br># added 1 package, and audited 539 packages in 2s<br><br># 91 packages are looking for funding<br>#   run `npm fund` for details<br><br># found 0 vulnerabilities</pre><p>In your <strong>NFT.sol</strong> file, ensure that the Solidity version is in sync with the one specified in <strong>hardhat.config.ts</strong>. Explain the purpose of each component, highlighting the role of OpenZeppelin&#39;s contracts in your NFT&#39;s architecture.</p><h3>Step 5: Integrating MetaMask &amp; Berachain Artio with Hardhat</h3><p>This step involves linking your MetaMask wallet and the Berachain Testnet to the Hardhat environment. This connection is pivotal for deploying your smart contract on the Berachain Artio.</p><ol><li><strong>Installing dotenv</strong>: A tool for managing environment variables.</li></ol><pre>npm install dotenv --save<br><br># added 1 package, and audited 538 packages in 612ms<br><br># 91 packages are looking for funding<br>#   run `npm fund` for details<br><br># found 0 vulnerabilities</pre><p><strong>2. Configuring the .env File</strong>: Safely store your MetaMask private key in a newly created .env file in your project&#39;s root directory.</p><p>Create a .env file in your project root directory and add your MetaMask private key. For help exporting your key from MetaMask, see <a href="https://metamask.zendesk.com/hc/en-us/articles/360015289632">this guide</a>.</p><p>Your .env file should look like this:</p><pre>PRIV_KEY = 0x&quot;your exported private key&quot;</pre><h3>Step 6: Configuring hardhat.config.js</h3><p>This step is about fine-tuning your Hardhat setup to align with Berachain’s specifications. Update your hardhat.config.ts file with necessary dependencies and network configurations, paying special attention to the custom chains settings for Berachain Artio.</p><p><strong>File:</strong> <strong>./hardhat.config.ts</strong></p><pre>import { HardhatUserConfig } from &quot;hardhat/config&quot;;<br>import &quot;@nomicfoundation/hardhat-toolbox&quot;;<br>import &quot;@nomicfoundation/hardhat-verify&quot;;<br><br>require(&quot;dotenv&quot;).config();<br><br>const config: HardhatUserConfig = {<br>  solidity: {<br>    version: &quot;0.8.23&quot;,<br>  },<br>  networks: {<br>    // for testnet<br>    &quot;berachain-artio&quot;: {<br>      url: &quot;https://rpc.ankr.com/berachain_testnet&quot;,<br>      accounts: [process.env.WALLET_KEY as string],<br>      chainId: 80085,<br>      // gas: &quot;auto&quot;,<br>      gasPrice: 10000000000,<br>    },<br>    // for local dev environment<br>    &quot;berachain-local&quot;: {<br>      url: &quot;http://localhost:8545&quot;,<br>      gasPrice: 1000000000,<br>    },<br>  },<br>  defaultNetwork: &quot;hardhat&quot;,<br>  etherscan: {<br>    apiKey: {<br>      berachainArtio: &quot;berachainArtio&quot;, // apiKey is not required, just set a placeholder<br>    },<br>    customChains: [<br>      {<br>        network: &quot;berachainArtio&quot;,<br>        chainId: 80085,<br>        urls: {<br>          apiURL:<br>            &quot;https://api.routescan.io/v2/network/testnet/evm/80085/etherscan&quot;,<br>          browserURL: &quot;https://artio.beratrail.io&quot;,<br>        },<br>      },<br>    ],<br>  },<br>};<br><br>export default config;</pre><h3>Step 7: Creating the Deployment Script</h3><p>In your scripts/ directory, draft the deployment script (update deploy.ts). This script is the blueprint for deploying your smart contract on the blockchain. Explain each line of code and its role in leveraging Hardhat&#39;s deployment features.</p><p><strong>File:</strong> <strong>./scripts/deploy.ts</strong></p><pre>import { setBlockGasLimit } from &#39;@nomicfoundation/hardhat-toolbox/network-helpers&#39;;<br>import { ethers } from &#39;hardhat&#39;;<br><br>async function main() {<br>  const nft = await ethers.deployContract(&#39;NFT&#39;);<br><br>  await nft.waitForDeployment();<br><br>  console.log(&#39;NFT Contract Deployed at &#39; + nft.target);<br>}<br><br>// We recommend this pattern to be able to use async/await everywhere<br>// and properly handle errors.<br>main().catch((error) =&gt; {<br>  console.error(error);<br>  process.exitCode = 1;<br>});</pre><h3>Step 8: Actual Deployment</h3><p>Execute the deployment of your contract to the Berachain Artio:</p><pre>npx hardhat run scripts/deploy.ts --network berachain-artio<br># NFT Contract Deployed at 0xBC862C68CE9EE3aFa762DbF7A51712E3c6E79215</pre><p>Guide the reader through interpreting the deployment output and confirm the successful launch of the contract.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/967/1*SxY61Hr1_g5KCzRvXwG7WQ.png" /></figure><h3>Understanding the overall changes performed to Hardhat</h3><p>This section can be skipped if you already understood the changes made to the above deployment script and the hardhat configuration to work with Berachain Artio.</p><ol><li>The default Hardhat deployContract does have some issues. But crafting the deploy transaction manually with gasLimit and gasPrice specified works with Artio.</li><li>Removing the gas: “auto” setting in hardhat config file is must. Having it set to Auto increases the time to deploy and causes delay for the transaction to get submitted.</li><li>Building the transaction manually and setting a forced gas limit override (this may be more expensive gas-wise, but not significantly).</li></ol><h3>Verifying Contracts on Berachain</h3><p>Verification is a crucial post-deployment step. It involves publicly associating the deployed bytecode with its corresponding source code. This process enhances transparency and trust in the blockchain community.</p><p>Install the @nomicfoundation/hardhat-verify plugin and guide the users through the verification process, emphasizing the criticality of using the correct contract address.</p><h4>Installation</h4><p>Install hardhat-verify plugin that will help verify contracts directly via hardhat.</p><pre>npm install --save-dev @nomicfoundation/hardhat-verify<br><br># up to date, audited 539 packages in 3s<br><br># 91 packages are looking for funding<br>#   run `npm fund` for details<br><br># found 0 vulnerabilities</pre><p>We’ve already included the following code for Routescan api which helps in verifying contracts.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4af2Q7hHyy9msVnuAvcEUA.png" /></figure><p>For more info head over to <a href="https://artio.beratrail.io/documentation/recipes/hardhat-verification">https://artio.beratrail.io/documentation/recipes/hardhat-verification</a>.</p><h3>Verify</h3><p>Now to verify the contract all you need is the contract address of the contract deployed.</p><pre>npx hardhat verify --network berachain-artio &lt;0x...&gt;</pre><p>Make sure to relace the whole “&lt;0xaddress&gt; “. Correct example would be :-</p><p>✅ npx hardhat verify — network berachain-artio 0x3229075dd6F75bD879F7af07d384A0856c30a806</p><p>❌ npx hardhat verify — network berachain-artio &lt;0x3229075dd6F75bD879F7af07d384A0856c30a806&gt; <strong>(This is incorrect)</strong></p><p>Once done should give you an output similar to below.</p><pre><br># [INFO] Sourcify Verification Skipped: Sourcify verification is currently disabled. To enable it, add the following entry to your Hardhat configuration:<br><br># sourcify: {<br>#   enabled: true<br># }<br><br># Or set &#39;enabled&#39; to false to hide this message.<br><br># For more information, visit https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-verify#verifying-on-sourcify<br># The contract 0xBC862C68CE9EE3aFa762DbF7A51712E3c6E79215 has already been verified on Etherscan.<br># https://artio.beratrail.io/address/0xBC862C68CE9EE3aFa762DbF7A51712E3c6E79215#code</pre><p>If we head over to Berachain Explorer(Beratrail) using the link provided in terminal- we will be able to see the contract’s source code has been verified successfully.!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UclOk5ZjgfAnEwA5ZP_IBQ.png" /></figure><h3>Complete Code</h3><p><strong>File:</strong> <strong>./contracts/NFT.sol</strong></p><pre>// SPDX-License-Identifier: MIT<br>pragma solidity ^0.8.23;<br><br>import &quot;@openzeppelin/contracts/token/ERC721/ERC721.sol&quot;;<br>contract NFT is ERC721 {<br>    uint256 public currentTokenId;<br>    constructor() ERC721(&quot;NFT Name&quot;, &quot;NFT&quot;) {}<br>    function mint(address recipient) public payable returns (uint256) {<br>        uint256 newItemId = ++currentTokenId;<br>        _safeMint(recipient, newItemId);<br>        return newItemId;<br>    }<br>}</pre><p><strong>File:</strong> <strong>./scripts/deploy.ts</strong></p><pre>import { setBlockGasLimit } from &#39;@nomicfoundation/hardhat-toolbox/network-helpers&#39;;<br>import { ethers } from &#39;hardhat&#39;;<br>async function main() {<br>  const nft = await ethers.deployContract(&#39;NFT&#39;);<br>  await nft.waitForDeployment();<br>  console.log(&#39;NFT Contract Deployed at &#39; + nft.target);<br>}<br>// We recommend this pattern to be able to use async/await everywhere<br>// and properly handle errors.<br>main().catch((error) =&gt; {<br>  console.error(error);<br>  process.exitCode = 1;<br>});</pre><p><strong>File:</strong> <strong>./hardhat.config.ts</strong></p><pre>import { HardhatUserConfig } from &quot;hardhat/config&quot;;<br>import &quot;@nomicfoundation/hardhat-toolbox&quot;;<br>import &quot;@nomicfoundation/hardhat-verify&quot;;<br>require(&quot;dotenv&quot;).config();<br>const config: HardhatUserConfig = {<br>  solidity: {<br>    version: &quot;0.8.23&quot;,<br>  },<br>  networks: {<br>    // for testnet<br>    &quot;berachain-artio&quot;: {<br>      url: &quot;https://rpc.ankr.com/berachain_testnet&quot;,<br>      accounts: [process.env.WALLET_KEY as string],<br>      chainId: 80085,<br>      // gas: &quot;auto&quot;,<br>      gasPrice: 10000000000,<br>    },<br>    // for local dev environment<br>    &quot;berachain-local&quot;: {<br>      url: &quot;http://localhost:8545&quot;,<br>      gasPrice: 1000000000,<br>    },<br>  },<br>  defaultNetwork: &quot;hardhat&quot;,<br>  etherscan: {<br>    apiKey: {<br>      berachainArtio: &quot;berachainArtio&quot;, // apiKey is not required, just set a placeholder<br>    },<br>    customChains: [<br>      {<br>        network: &quot;berachainArtio&quot;,<br>        chainId: 80085,<br>        urls: {<br>          apiURL:<br>            &quot;https://api.routescan.io/v2/network/testnet/evm/80085/etherscan&quot;,<br>          browserURL: &quot;https://artio.beratrail.io&quot;,<br>        },<br>      },<br>    ],<br>  },<br>};<br>export default config;</pre><p>You should also be able to get the complete code on our Official Github repository using the link below.</p><p><a href="https://github.com/berachain/guides/tree/main/apps/hardhat-contract-verification">guides/apps/hardhat-contract-verification at main · berachain/guides</a></p><h3>Recap</h3><p>This guide aims to be a comprehensive resource, guiding readers through every step of deploying an ERC-721 NFT and mainly, <strong>verifying contracts on Berachain Artio. </strong>We’ve covered<strong> </strong>the basics of deploying using Hardhat to the a few intricacies and customization needed for smart contract development and verification.</p><h3>Want To Build and How To Get Support ?</h3><p><strong>Learning Resources</strong>: Explore additional guides currently available via our docs at <a href="https://docs.berachain.com/developers">https://docs.berachain.com/developers</a>.</p><p><a href="https://docs.berachain.com/developers">Connecting to Berachain</a></p><h4>How To Get Support ?</h4><p><strong>Discord Community</strong>: Join the Third Web Discord community for further assistance, discussions, and to stay updated with the latest developments in Web3.</p><p>⚠️ Still facing issues or have doubts? Head over to discord and raise a ticket as shown in the gif below!</p><p>Our DevRel team will be happy to assist! 🤝</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*QmeL3wtqcBhiHbnieK6LaQ.gif" /></figure><p>Byyeeee bears! 🐻</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cd6642029641" width="1" height="1" alt=""><hr><p><a href="https://medium.com/berachain-devs/how-to-deploy-and-verify-contracts-on-berachain-cd6642029641">How To Deploy And Verify Contracts On Berachain</a> was originally published in <a href="https://medium.com/berachain-devs">berachain-devs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Bridge any Token to Berachain with LayerZero V2]]></title>
            <link>https://medium.com/berachain-devs/bridge-any-token-to-berachain-with-layerzero-v2-0c5705ef2fe1?source=rss----b629d42886be---4</link>
            <guid isPermaLink="false">https://medium.com/p/0c5705ef2fe1</guid>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[erc20]]></category>
            <category><![CDATA[interoperability]]></category>
            <category><![CDATA[blockchain]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <dc:creator><![CDATA[Beary the Cucumber]]></dc:creator>
            <pubDate>Mon, 22 Apr 2024 22:28:44 GMT</pubDate>
            <atom:updated>2024-04-23T21:41:34.477Z</atom:updated>
            <content:encoded><![CDATA[<h4>LayerZero’s OFTs Expand Existing Tokens to Berachain</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J6Ikto4PPJzfNTinVxgElg.png" /></figure><h3>Deploying Omnichain Tokens Using LayerZero V2</h3><h4>Introduction to OFTs</h4><p><strong><em>Omnichain Fungible Tokens</em> </strong>(OFTs) are a new token standard pioneered by <a href="https://layerzero.network/"><strong>LayerZero</strong></a> for cross-chain assets. OFTs allow fungible tokens to be transferred across different blockchains without the need for asset wrapping or liquidity pools, all whilst maintaining a unified supply.</p><p>LayerZero is a general-purpose cross-chain messaging protocol, but in this article, we will focus on its bridging applications, specifically OFTs.</p><h4>LayerZero V2</h4><p>Launched in January 2024, LayerZero V2 brings significant upgrades by separating message verification from execution (these were bundled together in LayerZero V1 using <a href="https://layerzero.gitbook.io/docs/ecosystem/relayer/layerzero-relayer">Relayers</a>):</p><ul><li>Application owners can choose a set of <a href="https://docs.layerzero.network/v2/home/modular-security/security-stack-dvns">Decentralized Verifier Networks</a> (DVNs) to verify message payloads; and</li><li>Execution of messages on destination chains is handled by <a href="https://docs.layerzero.network/explore/executors">Executors</a></li></ul><p>Among other improvements, these changes enhance the scalability and customization available to omnichain app developers. See this <a href="https://medium.com/layerzero-official/layerzero-v2-deep-dive-869f93e09850"><strong><em>article</em></strong></a> for a deeper dive.</p><p><strong><em>In this article, we show you how to leverage LayerZero OFTs to bridge </em></strong><strong><em>$UNI tokens from Sepolia Testnet to the Berachain Testnet.</em></strong></p><h3>📋 Requirements</h3><p>Before we move on, make sure you have the following installed and set up on your computer.</p><ul><li>Node v20.11.0 or greater</li><li><a href="https://pnpm.io/installation">pnpm</a></li><li>A wallet configured with <a href="https://docs.berachain.com/developers/"><strong>Berachain Artio Network</strong></a><strong> </strong>and<strong> </strong><a href="https://moralis.io/how-to-add-the-sepolia-network-to-metamask-full-guide/#:~:text=Sepolia%20test-,network,-New%20RPC%20URL"><strong>Sepolia Testnet</strong></a></li><li>$BERA or Berachain Testnet Tokens in that wallet — see <a href="http://artio.faucet.berachain.com/"><strong><em>Berachain Faucet</em></strong></a></li><li>$ETH on Sepolia Testnet in that wallet — see <a href="https://faucet.quicknode.com/ethereum/sepolia"><strong><em>Sepolia Faucet</em></strong></a></li><li>Obtain Sepolia $UNI — see <a href="https://app.uniswap.org/swap?outputCurrency=0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984&amp;inputCurrency=ETH"><strong><em>Uniswap</em></strong></a><strong><em> </em></strong>(0.0001 is used in this guide)</li></ul><h4>Foundry</h4><p>This guide requires Foundry to be installed. In a terminal window, run:</p><pre>curl -L https://foundry.paradigm.xyz | bash;<br><br>foundryup; <br># foundryup installs the &#39;forge&#39; and &#39;cast&#39; binaries, used later</pre><p>For more installation instructions, see Foundry’s <a href="https://book.getfoundry.sh/getting-started/installation">installation guide</a>. For more details using Foundry on Berachain, see this <a href="https://docs.berachain.com/developers/guides/create-erc20-contract-using-foundry">guide</a>.</p><h3>Creating Our LayerZero Project</h3><p>First, we’re going to set up your development environment using Foundry.</p><p>Start by creating a new project folder and initializing Foundry:</p><pre>forge init layerzero-oft --no-git --no-commit;<br><br>cd layerzero-oft;<br># We observe the following basic layout<br># .<br># ├── foundry.toml<br># ├── script<br># │   └── Counter.s.sol<br># ├── src<br># │   └── Counter.sol<br># └── test<br>#     └── Counter.t.sol</pre><h4>Installing Dependencies</h4><p>We will be leveraging a number of dependencies related to <a href="https://docs.layerzero.network/contracts/overview">LayerZero</a> and <a href="https://docs.openzeppelin.com/contracts/5.x/">OpenZeppelin</a> tooling, so install them below:</p><pre># FROM: ./layerzero-oft<br><br>pnpm init;<br>pnpm add -D @layerzerolabs/lz-evm-oapp-v2 @layerzerolabs/toolbox-foundry @layerzerolabs/lz-evm-protocol-v2 @layerzerolabs/lz-evm-messagelib-v2 @layerzerolabs/lz-definitions @openzeppelin/contracts --ignore-workspace;</pre><p>Replace the contents of foundry.toml with the following to remap our dependencies:</p><pre>[profile.default]<br>src = &quot;src&quot;<br>out = &quot;out&quot;<br>libs = [<br>    &#39;node_modules/@layerzerolabs/toolbox-foundry/lib&#39;,<br>    &#39;node_modules&#39;,<br>]<br>remappings = [<br>    &#39;forge-std/=node_modules/@layerzerolabs/toolbox-foundry/lib/forge-std&#39;,<br>    &#39;@layerzerolabs/=node_modules/@layerzerolabs/&#39;,<br>    &#39;@openzeppelin/=node_modules/@openzeppelin/&#39;,<br>]</pre><h3>Overview of Interactions</h3><p>Before we write the contracts, let’s briefly go over the interactions involved in the process of bridging the $UNI token from Sepolia to Berachain:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lLVhrwVtNmSw36WCTZLekA.png" /><figcaption>Overview of Interactions</figcaption></figure><ol><li>On the Source Chain, the User executes a bridging tx on the OFT Adapter contract (created by us)</li><li>$UNI is locked in the OFT Adapter</li><li>The LayerZero Endpoint contract sends a message containing instructions to mint $UNI tokens on the Destination Chain</li><li>The message is verified by a DVN</li><li>An Executor calls lzReceive() on the Endpoint contract at the Destination Chain, receiving the message</li><li>$lzUNI (an OFT created by us) is minted and sent to the User</li></ol><h3>Writing the Smart Contracts</h3><p>We’re going to need a number of smart contract deployments to facilitate the process above, on both the Source and Destination Chains.</p><p>Create a new file ./src/MyAdapter.sol and paste in the following:</p><pre>// SPDX-License-Identifier: MIT<br>pragma solidity ^0.8.22;<br><br>import {OFTAdapter} from &quot;@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFTAdapter.sol&quot;;<br>import {Ownable} from &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;<br><br>contract MyAdapter is OFTAdapter {<br>    constructor(<br>        address _token, // a deployed, already existing ERC20 token address<br>        address _layerZeroEndpoint, // local endpoint address<br>        address _delegate // token owner used as a delegate in LayerZero Endpoint<br>    ) OFTAdapter(_token, _layerZeroEndpoint, _delegate) Ownable(_delegate) {}<br>}</pre><p>This contract simply implements the OFTAdapter contract, which we recall is the contract on the <strong>Source Chain </strong>responsible for locking tokens and extending cross-chain functionality to existing tokens. Learn more about OFT Adapters <a href="https://docs.layerzero.network/contracts/oft-adapter"><strong><em>here</em></strong></a>.</p><p>Additionally, a contract delegate is set, granting this address the ability to <a href="https://docs.layerzero.network/contracts/oft#setting-delegates">handle critical tasks</a> such as setting configurations.</p><p>Next, create a file ./src/MyOFT.sol and paste in the following:</p><pre>// SPDX-License-Identifier: UNLICENSED<br>pragma solidity ^0.8.22;<br><br>import {Ownable} from &quot;@openzeppelin/contracts/access/Ownable.sol&quot;;<br>import {OFT} from &quot;@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFT.sol&quot;;<br><br>contract MyOFT is OFT {<br>    constructor(<br>        string memory _name,<br>        string memory _symbol,<br>        address _lzEndpoint,<br>        address _delegate<br>    ) OFT(_name, _symbol, _lzEndpoint, _delegate) Ownable(_delegate) {}<br>}</pre><p>This contract implements the OFT contract, and is where we define the token details on the <strong>Destination Chain </strong>(e.g. name, symbol). Again, a delegate is defined.</p><p>(You may delete src/Counter.sol , test/Counter.t.sol and script/Counter.s.sol which were generated with the project).</p><h3>Deployment and Execution</h3><h4><strong>Step 1: Deploy OFT Adapter to Sepolia</strong></h4><p>Create a /.env file at the project root with the following and populate your PRIVATE_KEY to start:</p><pre>PRIVATE_KEY=<br>SEPOLIA_ADAPTER_ADDRESS=<br>BERACHAIN_OFT_ADDRESS=</pre><p>We’re going to create a couple of Foundry scripts to help with deployment. Start by creating ./script/MyAdapter.s.sol and populate it with the following:</p><pre>// SPDX-License-Identifier: UNLICENSED<br>pragma solidity ^0.8.22;<br><br>import {Script} from &quot;forge-std/Script.sol&quot;;<br>import &quot;../src/MyAdapter.sol&quot;;<br><br>contract MyAdapterScript is Script {<br>    address constant UNI_TOKEN = 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984;<br>    address constant LAYERZERO_ENDPOINT =<br>        0x6EDCE65403992e310A62460808c4b910D972f10f;<br><br>    function run() public {<br>        // Setup<br>        uint256 privateKey = vm.envUint(&quot;PRIVATE_KEY&quot;);<br>        vm.startBroadcast(privateKey);<br><br>        // Deploy<br>        MyAdapter myAdapter = new MyAdapter(<br>            UNI_TOKEN,<br>            LAYERZERO_ENDPOINT,<br>            vm.addr(privateKey) // Address of private key<br>        );<br><br>        vm.stopBroadcast();<br>    }<br>}</pre><p>Running the following command will deploy the MyAdapter contract on Sepolia Testnet.</p><p>(optionally add flags — etherscan-api-key YOUR_ETHERSCAN_API_KEY — verify to verify the contract):</p><pre># FROM: ./layerzero-oft<br><br>forge script script/MyAdapter.s.sol --rpc-url https://rpc.sepolia.org/ --broadcast <br><br># [Example Output]:<br># ##### sepolia<br># ✅  [Success]Hash: 0x16702f69752f1f7243793202435da6bd54d2ebec89294728c2bf0d55584ed732<br># Contract Address: 0xB66e0518570eA48286983322fc8F85301f955406<br># Block: 5525968<br># Paid: 0.007448778064556076 ETH (2482926 gas * 3.000000026 gwei)</pre><p><strong>Update </strong><strong>SEPOLIA_ADAPTER_ADDRESS in your </strong><strong>.env file with the address of your </strong><strong>MyAdapter deployment.</strong></p><h4>Step 2: Deploy OFT to Berachain</h4><p>Next, create ./script/MyOFT.s.sol and populate it with the following:</p><pre>// SPDX-License-Identifier: UNLICENSED<br>pragma solidity ^0.8.22;<br><br>import {Script} from &quot;forge-std/Script.sol&quot;;<br>import &quot;../src/MyOFT.sol&quot;;<br><br>contract MyOFTScript is Script {<br>    address constant LAYERZERO_ENDPOINT =<br>        0x6EDCE65403992e310A62460808c4b910D972f10f;<br><br>    uint32 constant SEPOLIA_ENDPOINT_ID = 40161;<br><br>    function run() public {<br>        // Setup<br>        address SEPOLIA_ADAPTER_ADDRESS = vm.envAddress(<br>            &quot;SEPOLIA_ADAPTER_ADDRESS&quot;<br>        );<br>        uint256 privateKey = vm.envUint(&quot;PRIVATE_KEY&quot;);<br>        vm.startBroadcast(privateKey);<br><br>        // Deploy<br>        MyOFT myOFT = new MyOFT(<br>            &quot;Layer Zero UNI&quot;,<br>            &quot;lzUNI&quot;,<br>            LAYERZERO_ENDPOINT,<br>            vm.addr(privateKey) // Wallet address of signer<br>        );<br><br>        // Hook up Berachain OFT to Sepolia&#39;s adapter<br>        myOFT.setPeer(<br>            SEPOLIA_ENDPOINT_ID,<br>            bytes32(uint256(uint160(SEPOLIA_ADAPTER_ADDRESS)))<br>        );<br>        vm.stopBroadcast();<br>    }<br>}</pre><p>Next, execute your script to 1) deploy your OFT contract to Berachain, and 2) make it aware of its Sepolia peer contract:</p><pre># FROM: ./layerzero-oft<br><br>forge script script/MyOFT.s.sol --rpc-url https://artio.rpc.berachain.com/ --broadcast<br><br># [Example Output]<br># ##### 80085<br># ✅  [Success]Hash: 0x16cf8daa6f335fb65dedee8e722c01adb45b87aeccad0d6dc751d6c04c466a5f<br># Contract Address: 0x42993d9A691636cbb23C201729b36B5C6e750733<br># Block: 1147280<br># Paid: 0.040444634965884468 ETH (2842719 gas * 14.227447372 gwei)<br># <br># ##### 80085<br># ✅  [Success]Hash: 0xd670e01e028fe50d9e8c323007a777590d202fada28d80d6a9f9973abcb8b607<br># Block: 1147281<br># Paid: 0.000682799744815656 ETH (47666 gas * 14.324670516 gwei)</pre><p><strong>Update </strong><strong>BERACHAIN_OFT_ADDRESS in your </strong><strong>.env file with the address of your </strong><strong>MyOFT deployment.</strong></p><h4>Step 3: Bridge Tokens from Sepolia to Berachain</h4><p>Now, we’re going to tie all of the components together and bridge $UNI from Sepolia to Berachain.</p><p>Create ./script/Bridge.s.sol and populate it with the following:</p><pre>pragma solidity ^0.8.22;<br><br>import &quot;forge-std/Script.sol&quot;;<br>import {IOFT, SendParam} from &quot;@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol&quot;;<br>import {IOAppCore} from &quot;@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/interfaces/IOAppCore.sol&quot;;<br>import {MessagingFee} from &quot;@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFTCore.sol&quot;;<br>import {OptionsBuilder} from &quot;@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/libs/OptionsBuilder.sol&quot;;<br>import &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;<br><br>interface IAdapter is IOAppCore, IOFT {}<br><br>contract SendOFTScript is Script {<br>    using OptionsBuilder for bytes;<br><br>    uint32 constant BERACHAIN_ENPOINT_ID = 40256;<br>    address constant SEPOLIA_UNI_ADDRESS =<br>        0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984;<br><br>    function run() external {<br>        address SEPOLIA_ADAPTER_ADDRESS = vm.envAddress(<br>            &quot;SEPOLIA_ADAPTER_ADDRESS&quot;<br>        );<br>        address BERACHAIN_OFT_ADDRESS = vm.envAddress(&quot;BERACHAIN_OFT_ADDRESS&quot;);<br><br>        uint256 privateKey = vm.envUint(&quot;PRIVATE_KEY&quot;);<br>        vm.startBroadcast(privateKey);<br>        address signer = vm.addr(privateKey);<br><br>        // Get the Adapter contract instance<br>        IAdapter sepoliaAdapter = IAdapter(SEPOLIA_ADAPTER_ADDRESS);<br><br>        // Hook up Sepolia Adapter to Berachain&#39;s OFT<br>        sepoliaAdapter.setPeer(<br>            BERACHAIN_ENPOINT_ID,<br>            bytes32(uint256(uint160(BERACHAIN_OFT_ADDRESS)))<br>        );<br><br>        // Define the send parameters<br>        uint256 tokensToSend = 0.0001 ether; // 0.0001 $UNI tokens<br><br>        bytes memory options = OptionsBuilder<br>            .newOptions()<br>            .addExecutorLzReceiveOption(200000, 0);<br><br>        SendParam memory sendParam = SendParam(<br>            BERACHAIN_ENPOINT_ID,<br>            bytes32(uint256(uint160(signer))),<br>            tokensToSend,<br>            tokensToSend,<br>            options,<br>            &quot;&quot;,<br>            &quot;&quot;<br>        );<br><br>        // Quote the send fee<br>        MessagingFee memory fee = sepoliaAdapter.quoteSend(sendParam, false);<br>        console.log(&quot;Native fee: %d&quot;, fee.nativeFee);<br><br>        // Approve the OFT contract to spend UNI tokens<br>        IERC20(SEPOLIA_UNI_ADDRESS).approve(<br>            SEPOLIA_ADAPTER_ADDRESS,<br>            tokensToSend<br>        );<br><br>        // Send the tokens<br>        sepoliaAdapter.send{value: fee.nativeFee}(sendParam, fee, signer);<br><br>        console.log(&quot;Tokens bridged successfully!&quot;);<br>    }<br>}</pre><p>Let’s break down what this script does:</p><ul><li>We first attach to an instance of the deployed Sepolia Adapter</li><li>We then call setPeer to inform the Adapter of the OFT contract on Berachain</li><li>Options are defined to define the gas amounts the Executor pays for message delivery (read more <a href="https://docs.layerzero.network/contracts/options"><strong><em>here</em></strong></a>), prepare a message payload, and request a fee quote for this transaction</li><li>We approve the Adapter contract to spend our $UNI tokens</li><li>Finally, the Adapter’s send method is invoked with the message payload and fee</li></ul><p>Run the script with the following:</p><pre># FROM: ./layerzero-oft<br><br>forge script script/Bridge.s.sol --rpc-url https://rpc.sepolia.org/ --broadcast</pre><p>After a few moments to wait for the a LayerZero Executor to pick up the request, we will see the bridged $lzUNI tokens show up in our Berachain wallet!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xsFOgKhzJSevuY0UH4QCYw.png" /></figure><h3>Recap</h3><p>Congratulations, you’ve successfully bridged an existing token to Berachain using LayerZero OFTs 🎉</p><p>To learn more about OFTs and all that cross-chain messaging enables, we invite you to check out the <a href="https://docs.layerzero.network/contracts/overview"><strong><em>LayerZero docs</em></strong></a>.</p><p><strong><em>Disclaimer: </em>The OFT and OFT Adapter are solutions for protocol developers to bring their protocol’s token to new chains. Unsanctioned OFT deployments of existing tokens are unlikely to gain support.</strong></p><h3>🐻 Full Code Repository</h3><p>If you want to see the final code and see other guides, check out<strong><em> </em></strong><a href="https://github.com/berachain/guides/tree/main/apps/layerzero-oft"><strong><em>Berachain LayerZero Guide Code</em></strong></a>.</p><p><a href="https://github.com/berachain/guides/tree/main/apps/layerzero-oft">guides/apps/layerzero-oft at main · berachain/guides</a></p><h3>🛠️ Want To Build More?</h3><p>Want to build more on Berachain and see more examples. Take a look at our <a href="https://github.com/berachain/guides"><strong><em>Berachain GitHub Guides Repo</em></strong></a> for a wide variety of implementations that include NextJS, Hardhat, Viem, Foundry, and more.</p><p><a href="https://github.com/berachain/guides/tree/main">GitHub - berachain/guides: A demonstration of different contracts, languages, and libraries that work with Berachain EVM.</a></p><p>If you’re looking to dive deeper into the details, take a look at our <a href="https://docs.berachain.com/"><strong><em>Berachain Docs</em></strong></a>.</p><p><a href="https://docs.berachain.com/">Berachain Docs</a></p><h3>Looking For Dev Support?</h3><p>Make sure to join our <a href="https://discord.com/invite/berachain"><strong><em>Berachain Discord</em></strong></a> server and check out our developer channels to ask questions.</p><p>❤️ Don’t forget to show some love for this article 👏🏼</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=0c5705ef2fe1" width="1" height="1" alt=""><hr><p><a href="https://medium.com/berachain-devs/bridge-any-token-to-berachain-with-layerzero-v2-0c5705ef2fe1">Bridge any Token to Berachain with LayerZero V2</a> was originally published in <a href="https://medium.com/berachain-devs">berachain-devs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Index & Query Berachain Data with Goldsky ]]></title>
            <link>https://medium.com/berachain-devs/index-query-berachain-data-with-goldsky-4eb7b98ec4fe?source=rss----b629d42886be---4</link>
            <guid isPermaLink="false">https://medium.com/p/4eb7b98ec4fe</guid>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <category><![CDATA[defi]]></category>
            <dc:creator><![CDATA[Beary the Cucumber]]></dc:creator>
            <pubDate>Mon, 08 Apr 2024 15:30:13 GMT</pubDate>
            <atom:updated>2024-04-08T15:30:12.970Z</atom:updated>
            <content:encoded><![CDATA[<h4>How to Index ERC20 tokens on Berachain with Goldsky Subgraphs</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZQZzMqsfh_JhLfulfBo_uA.png" /></figure><h3>What is Goldsky and Why Should I Care about Indexing?</h3><p><a href="https://goldsky.com/">Goldsky</a> lets developers build <a href="https://graphql.org/">GraphQL</a> APIs that store and query data from the blockchain. This data is highly customizable and can be used to uncover trends such as token supply growth over time, or instantaneous data such as user token balances.</p><p>A subgraph contains logic for indexing data from a blockchain, transforming raw data and storing it in a form that can be easily queried.</p><p>In this tutorial, we teach you to develop a subgraph which queries users’ ERC20 balances on the <a href="https://www.berachain.com/"><strong>Berachain</strong></a> network.</p><h3>Pre-requisites 📋</h3><ul><li>Nodejs v20.11.0 or greater</li><li>pnpm</li><li>An IDE e.g. VSCode, Replit, etc.</li></ul><p>For those with existing subgraphs deployed on <a href="https://thegraph.com/">The Graph</a> who want to deploy to Berchain/Goldsky, skip to the section <strong>Getting Set up on Goldsky</strong>. Goldsky and The Graph subgraphs are fully compatible with one another!</p><h3>Building your Subgraph 🛠️</h3><p>To begin, enter in your terminal:</p><pre>mkdir goldsky-subgraph;<br>cd goldsky-subgraph;<br><br>pnpm init; <br><br>pnpm install @graphprotocol/graph-cli @graphprotocol/graph-ts;<br><br># Accept all of the defaults, hitting enter when prompted<br><br># name: (project-name) project-name<br># version: (0.0.0) 0.0.1<br># description: The Project Description<br># entry point: //leave empty<br># test command: //leave empty<br># git repository: //the repositories url<br># keywords: //leave empty<br># author: // your name<br># license: N/A<br><br># @graphprotocol dependencies provide subgraph development tooling</pre><p>In the root of your project, create the following project structure (empty files are fine for now):</p><pre># FROM: ./goldsky-subgraph;<br><br>.<br>├── abis<br>│   └── Erc20.json<br>├── package.json<br>├── schema.graphql<br>├── src<br>│   ├── mapping.ts<br>│   ├── utils.ts<br>└── subgraph.yaml</pre><p>In ./abis/Erc20.json paste in the contents below, which define the ERC20 contract interface:</p><pre>[<br>  {<br>    &quot;constant&quot;: true,<br>    &quot;inputs&quot;: [],<br>    &quot;name&quot;: &quot;name&quot;,<br>    &quot;outputs&quot;: [{ &quot;name&quot;: &quot;&quot;, &quot;type&quot;: &quot;string&quot; }],<br>    &quot;payable&quot;: false,<br>    &quot;stateMutability&quot;: &quot;view&quot;,<br>    &quot;type&quot;: &quot;function&quot;<br>  },<br>  {<br>    &quot;constant&quot;: false,<br>    &quot;inputs&quot;: [<br>      { &quot;name&quot;: &quot;_spender&quot;, &quot;type&quot;: &quot;address&quot; },<br>      { &quot;name&quot;: &quot;_value&quot;, &quot;type&quot;: &quot;uint256&quot; }<br>    ],<br>    &quot;name&quot;: &quot;approve&quot;,<br>    &quot;outputs&quot;: [{ &quot;name&quot;: &quot;&quot;, &quot;type&quot;: &quot;bool&quot; }],<br>    &quot;payable&quot;: false,<br>    &quot;stateMutability&quot;: &quot;nonpayable&quot;,<br>    &quot;type&quot;: &quot;function&quot;<br>  },<br>  {<br>    &quot;constant&quot;: true,<br>    &quot;inputs&quot;: [],<br>    &quot;name&quot;: &quot;totalSupply&quot;,<br>    &quot;outputs&quot;: [{ &quot;name&quot;: &quot;&quot;, &quot;type&quot;: &quot;uint256&quot; }],<br>    &quot;payable&quot;: false,<br>    &quot;stateMutability&quot;: &quot;view&quot;,<br>    &quot;type&quot;: &quot;function&quot;<br>  },<br>  {<br>    &quot;constant&quot;: false,<br>    &quot;inputs&quot;: [<br>      { &quot;name&quot;: &quot;_from&quot;, &quot;type&quot;: &quot;address&quot; },<br>      { &quot;name&quot;: &quot;_to&quot;, &quot;type&quot;: &quot;address&quot; },<br>      { &quot;name&quot;: &quot;_value&quot;, &quot;type&quot;: &quot;uint256&quot; }<br>    ],<br>    &quot;name&quot;: &quot;transferFrom&quot;,<br>    &quot;outputs&quot;: [{ &quot;name&quot;: &quot;&quot;, &quot;type&quot;: &quot;bool&quot; }],<br>    &quot;payable&quot;: false,<br>    &quot;stateMutability&quot;: &quot;nonpayable&quot;,<br>    &quot;type&quot;: &quot;function&quot;<br>  },<br>  {<br>    &quot;constant&quot;: true,<br>    &quot;inputs&quot;: [],<br>    &quot;name&quot;: &quot;decimals&quot;,<br>    &quot;outputs&quot;: [{ &quot;name&quot;: &quot;&quot;, &quot;type&quot;: &quot;uint8&quot; }],<br>    &quot;payable&quot;: false,<br>    &quot;stateMutability&quot;: &quot;view&quot;,<br>    &quot;type&quot;: &quot;function&quot;<br>  },<br>  {<br>    &quot;constant&quot;: true,<br>    &quot;inputs&quot;: [{ &quot;name&quot;: &quot;_owner&quot;, &quot;type&quot;: &quot;address&quot; }],<br>    &quot;name&quot;: &quot;balanceOf&quot;,<br>    &quot;outputs&quot;: [{ &quot;name&quot;: &quot;balance&quot;, &quot;type&quot;: &quot;uint256&quot; }],<br>    &quot;payable&quot;: false,<br>    &quot;stateMutability&quot;: &quot;view&quot;,<br>    &quot;type&quot;: &quot;function&quot;<br>  },<br>  {<br>    &quot;constant&quot;: true,<br>    &quot;inputs&quot;: [],<br>    &quot;name&quot;: &quot;symbol&quot;,<br>    &quot;outputs&quot;: [{ &quot;name&quot;: &quot;&quot;, &quot;type&quot;: &quot;string&quot; }],<br>    &quot;payable&quot;: false,<br>    &quot;stateMutability&quot;: &quot;view&quot;,<br>    &quot;type&quot;: &quot;function&quot;<br>  },<br>  {<br>    &quot;constant&quot;: false,<br>    &quot;inputs&quot;: [<br>      { &quot;name&quot;: &quot;_to&quot;, &quot;type&quot;: &quot;address&quot; },<br>      { &quot;name&quot;: &quot;_value&quot;, &quot;type&quot;: &quot;uint256&quot; }<br>    ],<br>    &quot;name&quot;: &quot;transfer&quot;,<br>    &quot;outputs&quot;: [{ &quot;name&quot;: &quot;&quot;, &quot;type&quot;: &quot;bool&quot; }],<br>    &quot;payable&quot;: false,<br>    &quot;stateMutability&quot;: &quot;nonpayable&quot;,<br>    &quot;type&quot;: &quot;function&quot;<br>  },<br>  {<br>    &quot;constant&quot;: true,<br>    &quot;inputs&quot;: [<br>      { &quot;name&quot;: &quot;_owner&quot;, &quot;type&quot;: &quot;address&quot; },<br>      { &quot;name&quot;: &quot;_spender&quot;, &quot;type&quot;: &quot;address&quot; }<br>    ],<br>    &quot;name&quot;: &quot;allowance&quot;,<br>    &quot;outputs&quot;: [{ &quot;name&quot;: &quot;&quot;, &quot;type&quot;: &quot;uint256&quot; }],<br>    &quot;payable&quot;: false,<br>    &quot;stateMutability&quot;: &quot;view&quot;,<br>    &quot;type&quot;: &quot;function&quot;<br>  },<br>  { &quot;payable&quot;: true, &quot;stateMutability&quot;: &quot;payable&quot;, &quot;type&quot;: &quot;fallback&quot; },<br>  {<br>    &quot;anonymous&quot;: false,<br>    &quot;inputs&quot;: [<br>      { &quot;indexed&quot;: true, &quot;name&quot;: &quot;owner&quot;, &quot;type&quot;: &quot;address&quot; },<br>      { &quot;indexed&quot;: true, &quot;name&quot;: &quot;spender&quot;, &quot;type&quot;: &quot;address&quot; },<br>      { &quot;indexed&quot;: false, &quot;name&quot;: &quot;value&quot;, &quot;type&quot;: &quot;uint256&quot; }<br>    ],<br>    &quot;name&quot;: &quot;Approval&quot;,<br>    &quot;type&quot;: &quot;event&quot;<br>  },<br>  {<br>    &quot;anonymous&quot;: false,<br>    &quot;inputs&quot;: [<br>      { &quot;indexed&quot;: true, &quot;name&quot;: &quot;from&quot;, &quot;type&quot;: &quot;address&quot; },<br>      { &quot;indexed&quot;: true, &quot;name&quot;: &quot;to&quot;, &quot;type&quot;: &quot;address&quot; },<br>      { &quot;indexed&quot;: false, &quot;name&quot;: &quot;value&quot;, &quot;type&quot;: &quot;uint256&quot; }<br>    ],<br>    &quot;name&quot;: &quot;Transfer&quot;,<br>    &quot;type&quot;: &quot;event&quot;<br>  }<br>]</pre><h4>Configuring the Subgraph</h4><p>The primary step in creating a subgraph is to define the data sources we read from, and the data structures (entities) we index this data into. This is accomplished in the subgraph.yaml, or the subgraph manifest.</p><p>In ./subgraph.yaml paste the following:</p><pre>specVersion: 0.0.4<br>description: ERC-20 subgraph with event handlers &amp; entities<br>schema:<br>  file: ./schema.graphql<br>dataSources:<br>  - kind: ethereum/contract<br>    name: Erc20<br>    network: berachain-public-testnet<br>    source:<br>      address: &quot;0xB734c264F83E39Ef6EC200F99550779998cC812d&quot;<br>      abi: Erc20<br>      startBlock: 54354<br>    mapping:<br>      kind: ethereum/events<br>      apiVersion: 0.0.7<br>      language: wasm/assemblyscript<br>      entities:<br>        - Token<br>        - Account<br>        - TokenBalance<br>      abis:<br>        - name: Erc20<br>          file: ./abis/Erc20.json<br>      eventHandlers:<br>        - event: Transfer(indexed address,indexed address,uint256)<br>          handler: handleTransfer<br>      file: ./src/mapping.ts</pre><p>In this manifest, a few things are worth pointing out:</p><ol><li>source: The address is the <a href="https://artio.beratrail.io/token/0xB734c264F83E39Ef6EC200F99550779998cC812d">MIM token</a>, which employs the Erc20 interface, to be indexed from the startBlock it was deployed</li><li>entities can be thought of as JavaScript objects which can be queried. Entities can have relational mappings between one another and are defined in a GraphQL schema (below)</li><li>eventHandlers: Every time a tokenTransfer event is emitted, the handleTransfer method in ./src/mapping.ts is called to perform indexing logic</li></ol><h4>Writing the Schema</h4><p>In ./schema.graphql we define our schema, containing properties and relationships of the different entities existing within our subgraph:</p><pre># Token details<br>type Token @entity {<br>  id: ID!<br>  #token name<br>  name: String!<br>  #token symbol<br>  symbol: String!<br>  #decimals used<br>  decimals: BigDecimal!<br>}<br><br># account details<br>type Account @entity {<br>  #account address<br>  id: ID!<br>  #balances<br>  balances: [TokenBalance!]! @derivedFrom(field: &quot;account&quot;)<br>}<br><br># token balance details<br>type TokenBalance @entity {<br>  id: ID!<br>  #token<br>  token: Token!<br>  #account<br>  account: Account!<br>  #amount<br>  amount: BigDecimal!<br>}</pre><p>The Token entity is straightforward, containing well-known properties of ERC20 tokens.</p><p>The Account entity contains an id of the wallet address and more interestingly, a list of balances of the type TokenBalance. The @derivedFrom directive means that an Account’s balances property is defined by reverse lookup, based on the account property in TokenBalance entities.</p><p>TokenBalance leverages both Account and Token entities, to define the token balance of each particular user.</p><p>For this tutorial, it’s wasn’t absolutely necessary to have both Token and TokenBalance entities. Users’ MIM balances could conceivably have been captured in just the Account entity. However, this design makes it possible to extend the subgraph to capture multiple token balances.</p><h4>Creating Mappings</h4><p>The mapping file is where everything comes together ✨ Blockchain data is associated with the entities we have defined in our schema. Below, we define the interations that happen when the handleTransfer event handler is invoked.</p><p>In ./src/mapping.ts add the following code:</p><pre>//import event class from generated files<br>import { Transfer } from &quot;../generated/Erc20/Erc20&quot;;<br>//import the functions defined in utils.ts<br>import { fetchTokenDetails, fetchAccount, updateTokenBalance } from &quot;./utils&quot;;<br>//import datatype<br>import { BigInt } from &quot;@graphprotocol/graph-ts&quot;;<br><br>export function handleTransfer(event: Transfer): void {<br>  // 1. Get token details<br>  let token = fetchTokenDetails(event);<br>  if (!token) {<br>    return;<br>  }<br><br>  // 2. Get account details<br>  let fromAddress = event.params.from.toHex();<br>  let toAddress = event.params.to.toHex();<br><br>  let fromAccount = fetchAccount(fromAddress);<br>  let toAccount = fetchAccount(toAddress);<br><br>  if (!fromAccount || !toAccount) {<br>    return;<br>  }<br><br>  // 3. Update the token balances<br>  // Setting the token balance of the &#39;from&#39; account<br>  updateTokenBalance(<br>    token,<br>    fromAccount,<br>    BigInt.fromI32(0).minus(event.params.value)<br>  );<br><br>  // Setting the token balance of the &#39;to&#39; account<br>  updateTokenBalance(token, toAccount, event.params.value);<br>}</pre><p>The handleTransfer takes the Transfer event as a parameter, containing the information (fromAddress, toAddress, transferAmount). With this info, the handler is empowered to perform the following functions:</p><ol><li>Fetch token details</li><li>Fetch account details</li><li>Update account balances</li></ol><p>At a high level, this handler code will dutifuly update ERC20 account balances every time a Transfer event is emitted.</p><h4><strong>Working With Entities</strong></h4><p>You may have noticed that the code in mapping.ts is rather simple — that’s because the heavy lifting of interacting with entities has been abstracted into a utility file. Let’s go over the nuts and bolts of working with subgraph entities now.</p><p>In ./src/utils.ts add the following code:</p><pre>//import smart contract class from generated files<br>import { Erc20 } from &quot;../generated/Erc20/Erc20&quot;;<br>//import entities<br>import { Account, Token, TokenBalance } from &quot;../generated/schema&quot;;<br>//import datatypes<br>import { BigDecimal, ethereum, BigInt } from &quot;@graphprotocol/graph-ts&quot;;<br><br>const ZERO_ADDRESS = &quot;0x0000000000000000000000000000000000000000&quot;;<br><br>// Fetch token details<br>export function fetchTokenDetails(event: ethereum.Event): Token | null {<br>  //check if token details are already saved<br>  let token = Token.load(event.address.toHex());<br>  if (!token) {<br>    //if token details are not available<br>    //create a new token<br>    token = new Token(event.address.toHex());<br><br>    //set some default values<br>    token.name = &quot;N/A&quot;;<br>    token.symbol = &quot;N/A&quot;;<br>    token.decimals = BigDecimal.fromString(&quot;0&quot;);<br><br>    //bind the contract<br>    let erc20 = Erc20.bind(event.address);<br><br>    //fetch name<br>    let tokenName = erc20.try_name();<br>    if (!tokenName.reverted) {<br>      token.name = tokenName.value;<br>    }<br><br>    //fetch symbol<br>    let tokenSymbol = erc20.try_symbol();<br>    if (!tokenSymbol.reverted) {<br>      token.symbol = tokenSymbol.value;<br>    }<br><br>    //fetch decimals<br>    let tokenDecimal = erc20.try_decimals();<br>    if (!tokenDecimal.reverted) {<br>      token.decimals = BigDecimal.fromString(tokenDecimal.value.toString());<br>    }<br><br>    //save the details<br>    token.save();<br>  }<br>  return token;<br>}<br><br>// Fetch account details<br>export function fetchAccount(address: string): Account | null {<br>  //check if account details are already saved<br>  let account = Account.load(address);<br>  if (!account) {<br>    //if account details are not available<br>    //create new account<br>    account = new Account(address);<br>    account.save();<br>  }<br>  return account;<br>}<br><br>export function updateTokenBalance(<br>  token: Token,<br>  account: Account,<br>  amount: BigInt<br>): void {<br>  // Don&#39;t update zero address<br>  if (ZERO_ADDRESS == account.id) return;<br><br>  // Get existing account balance or create a new one<br>  let accountBalance = getOrCreateAccountBalance(account, token);<br>  let balance = accountBalance.amount.plus(bigIntToBigDecimal(amount));<br><br>  // Update the account balance<br>  accountBalance.amount = balance;<br>  accountBalance.save();<br>}<br><br>function getOrCreateAccountBalance(<br>  account: Account,<br>  token: Token<br>): TokenBalance {<br>  let id = token.id + &quot;-&quot; + account.id;<br>  let tokenBalance = TokenBalance.load(id);<br><br>  // If balance is not already saved<br>  // create a new TokenBalance instance<br>  if (!tokenBalance) {<br>    tokenBalance = new TokenBalance(id);<br>    tokenBalance.account = account.id;<br>    tokenBalance.token = token.id;<br>    tokenBalance.amount = BigDecimal.fromString(&quot;0&quot;);<br><br>    tokenBalance.save();<br>  }<br><br>  return tokenBalance;<br>}<br><br>function bigIntToBigDecimal(quantity: BigInt, decimals: i32 = 18): BigDecimal {<br>  return quantity.divDecimal(<br>    BigInt.fromI32(10)<br>      .pow(decimals as u8)<br>      .toBigDecimal()<br>  );<br>}</pre><ul><li>fetchAccount() returns an Account entity. We first see whether an Account entity with the passed in address exists. If it doesn’t, we create a new one</li><li>fetchTokenDetails() returns a Token entity. If no Tokenexists, we instantiate a new one by binding the token address with the ERC20 interface, letting us access the public read functions from the token contract. This allows us to retrieve and set token properties such as name, symbol and decimals</li><li>updateTokenBalance() is perhaps the most important, as it updates users’ TokenBalance entities with each transfer. Referring back to the mapping.ts file, this function is invoked twice with each Transfer event — a negative amount is passed in for the transferer, denoting a loss of token balance, and conversely, a positive amount for the recipient. This way, an accurate accounting of token balances is maintained</li></ul><h4>Building the Subgraph</h4><p>In the root of your project directory, run the following in your terminal:</p><pre># FROM: ./goldsky-subgraph;<br><br>pnpm codegen;<br>pnpm build;</pre><p>These commands generate TypeScript class files from your contract ABIs, compiles your code, and creates build outputs in the /build directory.</p><p>Before we deploy, we have to get you set up on Goldsky.</p><h3>Getting Set up on Goldsky</h3><p>Goldsky will host your subgraph and do all the necessary indexing. Follow the instructions below to get your account set up:</p><ol><li>Create an account at <a href="https://app.goldsky.com/">app.goldsky.com</a></li><li>Create an API key on the <a href="https://app.goldsky.com/dashboard/settings">Settings page</a></li><li>Install the Goldsky CLI:</li></ol><pre>curl https://goldsky.com | sh</pre><p>4. Log in with the API key created earlier:</p><pre>goldsky login</pre><h4>Deploy your Subgraph 🚀</h4><p>In the root of your project, run the following:</p><pre># FROM: ./goldsky-subgraph;<br><br>goldsky subgraph deploy erc20-subgraph/1.0.0 --path .</pre><p>Once successfully deployed, <a href="https://app.goldsky.com/dashboard/subgraphs">view your deployed subgraph</a>. It won’t be usable right away, because the indexing process requires going over every block to update token balances.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YVrvOZaUxZ1V7brOCHYcZw.png" /><figcaption>Goldsky Subgraph Dashboard</figcaption></figure><h4>Querying your Data</h4><p>In your dashboard, you will see a “Public GraphQL link” which provides a nice interface for you to write queries. Now let’s give our new subgraph a spin with this query:</p><pre>{  <br>  accounts {  <br>    id  <br>    balances {  <br>      id  <br>      token {  <br>        id  <br>        name  <br>        symbol  <br>        decimals  <br>      }  <br>      amount  <br>    }  <br>  }  <br>}</pre><p>If you want an example to play along with, use this <a href="https://api.goldsky.com/api/public/project_clteviu2hajla01r51uil7cp5/subgraphs/erc20-subgraph/1.0.0/gn">live subgraph</a>.</p><p>Cross checking users’s MIM balances against Berachain’s <a href="https://artio.beratrail.io/address/0x000000000746a93872fecf15c2f22b998131df94">block explorer</a>, we see that our subgraph has accurately indexed users’ token balances ✅</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*O1abUoHQkFva2zLalpFZiQ.png" /><figcaption>Comparison of Subgraph and Block Explorer Token Balances</figcaption></figure><h4>Recap</h4><p>And that, frens, is how you use Goldsky subgraphs to index token balances of Berachain wallets. Goldsky is a data-availability platform, providing a way for developers to easily store and query customized blockchain data.</p><h4>🐻 Full Code Repository</h4><p>If you want to see the final code and see other guides, check out <a href="https://github.com/berachain/guides/tree/main/apps/goldsky-subgraph"><strong><em>Berachain Goldsky Guide Code</em></strong></a>.</p><p><a href="https://github.com/berachain/guides/tree/feat/goldsky-subgraph/apps/goldsky-subgraph">guides/apps/goldsky-subgraph at feat/goldsky-subgraph · berachain/guides</a></p><h4>🛠️ Want To Build More?</h4><p>Want to build more on Berachain and see more examples. Take a look at our <a href="https://github.com/berachain/guides"><strong><em>Berachain GitHub Guides Repo</em></strong></a> for a wide variety of implementations that include NextJS, Hardhat, Viem, Foundry, and more.</p><p><a href="https://github.com/berachain/guides">GitHub - berachain/guides: A demonstration of different contracts, languages, and libraries that work with Berachain EVM.</a></p><p>If you’re looking to dive deeper into the details, take a look at our <a href="https://docs.berachain.com/"><strong><em>Berachain Docs</em></strong></a>.</p><p><a href="https://docs.berachain.com/">Berachain Docs</a></p><h4>Looking For Dev Support?</h4><p>Make sure to join our <a href="https://discord.com/invite/berachain"><strong><em>Berachain Discord</em></strong></a> server and check out our developer channels to ask questions.</p><p>❤️ Don’t forget to show some love for this article 👏🏼</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4eb7b98ec4fe" width="1" height="1" alt=""><hr><p><a href="https://medium.com/berachain-devs/index-query-berachain-data-with-goldsky-4eb7b98ec4fe">Index &amp; Query Berachain Data with Goldsky 🧮</a> was originally published in <a href="https://medium.com/berachain-devs">berachain-devs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Social Login dApp with Particle Network on Berachain Testnet]]></title>
            <link>https://medium.com/berachain-devs/social-login-dapp-with-particle-network-on-berachain-testnet-daee55b6242b?source=rss----b629d42886be---4</link>
            <guid isPermaLink="false">https://medium.com/p/daee55b6242b</guid>
            <category><![CDATA[development]]></category>
            <category><![CDATA[account-abstraction]]></category>
            <category><![CDATA[web3]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[tutorial]]></category>
            <dc:creator><![CDATA[De]]></dc:creator>
            <pubDate>Fri, 01 Mar 2024 09:24:04 GMT</pubDate>
            <atom:updated>2024-04-05T13:52:08.794Z</atom:updated>
            <content:encoded><![CDATA[<h4>How to Create Account Abstraction based Social Login dApp on Berachain Artio ?</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qkWQNyx1zDxKv_r00IsM3A.png" /></figure><p>Bm dev bears! 🐻</p><p>The launch of Berachain’s Artio Testnet has made waves within the community. Artio’s hype among users remains unmatched and it being built on a strong implementing of Proof-of-Liquidity consensus mechanism, just adds to the excitement developers and teams have to start getting deployed on the testnet!</p><p>Shortly after the launch of Berachain’s Artio Testnet, Particle Network launched <a href="https://developers.particle.network/reference/introduction-to-particle-wallet"><strong><em>Smart Wallet-as-a-Service</em></strong></a> support which allows developers building on Berachain to immediately begin prototyping applications that natively leverage social logins for the creation and management of both EOAs and associated smart accounts (currently <a href="https://github.com/berachain/guides/tree/main/apps/particle-auth-core-vite"><strong><em>SimpleAccount implementations</em></strong></a>) on Berachain.</p><p><strong>This article is a joint effort with </strong><a href="https://twitter.com/TABASCOweb3"><strong><em>Tabasco</em></strong></a><strong> from Particle Network’s DevRel team, all the help during the time of formulating the dApp template from scratch is widely appreciated! 🤝 🐻</strong></p><h4><strong>Pre-requisites</strong></h4><ol><li>Node js &gt; 20 and latest npm. Please follow this guide if needed: <a href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm"><em>https://docs.npmjs.com/downloading-and-installing-node-js-and-npm</em></a>.</li><li>IDEs like VScode, Replit etc.</li><li>$BERA: Berachain’s native gas token, which will be required by newly created wallet which will be used in the demo. <em>(</em><a href="https://artio.faucet.berachain.com/"><em>https://artio.faucet.berachain.com</em></a><em>)</em></li><li>$HONEY: Berachain’s native stablecoin, obtained via the official Berachain Dex/ Bex. <em>(</em><a href="https://artio.bex.berachain.com/"><em>https://artio.bex.berachain.com</em></a><em>)</em></li><li>Access to the Particle Network developer dashboard. <em>(</em><a href="https://dashboard.particle.network/"><em>https://dashboard.particle.network/</em></a><em>)</em></li></ol><h3>Social Logins with Particle Auth Core</h3><h4><strong>🤔 Why Social Logins?</strong></h4><p>Social based logins have proven to be a step-closer towards the narrative of “easier web3 onboarding”, especially for users that have experienced majorly web2 apps.</p><p>By leveraging Social Login, your users can easily authenticate themselves using their preferred social media accounts, simplifying the onboarding process. As we know to interact with Web3 dApps we require having a wallet. This is where Particle Networks bridges the gap by enables a user to obtain a web3 wallet address associated with the user’s account once they have been successfully been authenticated.</p><h4>🛠️ What are we building?</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UYEArnJL1WR1G0JElOp73Q.gif" /></figure><p>This tutorial would be focusing on building a smart WaaS-enabled application on Berachain Artio Testnet through Particle Auth Core and Particle&#39;s AA SDK. This application will replicate the functionality found within the embedded dApp shown above.</p><p>We won’t be focusing on frontend in this guide but the guide does share frontend code. In-all we would be:</p><ul><li>Initiating a social login (in this example, through Google or X, alongside a general authentication modal).</li><li>Assigning a SimpleAccount to the resulting EOA (generated via a social login).</li><li>Executing a gasless burn transaction (of 0.001 $BERA)</li><li>Executing a burn of 1 $HONEY, Berachain’s native stablecoin.</li></ul><p>By the end of this, you’ll ideally have a good idea of how to implement Particle Auth Core within your project on Berachain or simply get a social login template on Berachain Testnet, leveraging the structure and utilization flow showcased here.</p><h4>Building Base for Your Application</h4><ol><li><strong>Initialize your project:</strong> Create a new React-typescript application using Vite.</li></ol><pre>npm create vite@latest berachain-particleTest -- --react-ts; <br><br># Expected Output<br># Need to install the following packages:<br># create-vite@5.2.1<br># Ok to proceed? (y) y<br># ✔ Package name: … berachain-particletest<br># ✔ Select a framework: › React<br># ✔ Select a variant: › TypeScript<br><br># Scaffolding project in /Users/dethebera/BeraWork/berachain-particle-testterminal/berachain-particleTest...<br><br># Done. Now run:<br><br>#   cd berachain-particleTest<br>#   npm install<br>#   npm run dev</pre><pre>cd berachain-particleTest;<br>npm intall;<br><br><br># Expected Output<br># added 219 packages, and audited 220 packages in 8s<br><br># 41 packages are looking for funding<br>#   run `npm fund` for details<br><br># found 0 vulnerabilities</pre><p>2. <strong>Install dependencies for this project</strong></p><pre>npm install @types/events antd buffer react-dom<br><br># Expected Output<br># added 71 packages, and audited 291 packages in 5s<br><br># 45 packages are looking for funding<br>#   run `npm fund` for details<br><br># found 0 vulnerabilities<br><br><br></pre><pre>npm i ethers@5.7.2<br><br># Expected Output<br># added 44 packages, and audited 335 packages in 4s<br><br># 76 packages are looking for funding<br>#   run `npm fund` for details<br><br># found 0 vulnerabilities</pre><p>3. <strong>Install Particle Libraries</strong>: To begin building this demo and explore the process of implementing Particle Auth Core, you’ll need to install a few key libraries that we’ll be using for configuration. Specifically, you’ll need to install:</p><ol><li>@particle-network/auth-core-modal, the central SDK for implementing Particle Auth Core, formerly @particle-network/auth.</li><li>@particle-network/aa, to assign a SimpleAccount and generate a custom AA-enabled EIP-1193 provider object to control the smart account with Ethers.</li><li>@particle-network/chains, for configuring Particle Auth Core with an object containing Berachain-specific information, (BerachainArtio).</li></ol><p>Then, copy one of the two following commands and execute it at the root of your project to install both SDKs through either Yarn or npm (alternative package managers such as pnpm will follow a similar syntax):</p><pre>yarn add @particle-network/auth-core-modal @particle-network/chains @particle-network/aa;<br><br># OR (Remember to use either and not both) <br><br>npm install @particle-network/auth-core-modal @particle-network/chains @particle-network/aa;<br><br><br># Expected Output<br># added 368 packages, and audited 703 packages in 41s<br><br># 109 packages are looking for funding<br>#   run `npm fund` for details<br><br># 8 moderate severity vulnerabilities<br><br># To address issues that do not require attention, run:<br>#   npm audit fix<br><br># Some issues need review, and may require choosing<br># a different dependency.<br><br># Run `npm audit` for details.</pre><h4><strong>Getting Keys from Particle Dashboard</strong></h4><p>Before constructing AuthCoreContextProvider, you&#39;ll need three values to initialize Particle Auth Core. When configuring any SDK from Particle Network, whether it&#39;s <a href="https://developers.particle.network/reference/auth-web"><strong><em>Particle Auth Core</em></strong></a><strong><em>, </em></strong><a href="https://developers.particle.network/reference/connect-web"><strong><em>Particle Connect</em></strong></a><strong><em>, or </em></strong><a href="https://developers.particle.network/reference/aa-web"><strong><em>Particle&#39;s AA SDK</em></strong></a>, you&#39;ll need to retrieve a project ID, client key, and app ID from the Particle dashboard.</p><p>These values link your application with your project on the Particle dashboard, therefore authenticating API requests, tracking users, allowing for no-code modal customization, etc.</p><ol><li>Head over to <a href="http://particlenetwork.com/"><em>particlenetwork</em>.com</a> and then click on “<em>Dashboard</em>” on the top right corner.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_Ddz7tK6qlj1e0ePD4Ba1A.png" /><figcaption>Particle Network’s Homepage</figcaption></figure><p>2. Click on “Add New Project” with the Project Name of your choice and click on “Save”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*14i80KNEwmULnTgWfjl1wA.png" /><figcaption>Dashboard Homepage</figcaption></figure><p>3. You will now have access to “Project ID” and “Client Key”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ids-bEzxWjlHAkBWF4e8lQ.png" /><figcaption>Application Screen</figcaption></figure><p>4. For obtaining “App ID” click on “Web” under “Your Apps” tab. And click on “Ok”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_tLnF1eOTgGDEVojO9QUAw.png" /><figcaption>Web App section highlighted in Application</figcaption></figure><p>5. Write the name of your choice in your “App Name”. For Domain either you can give “goggle.com” or you can give a domain of your choice where you app is hosted (if hosted already).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*28l6h-8rnvwMRvfBLTpzNg.png" /><figcaption>Fetching App ID</figcaption></figure><p>6 . “App ID” should now be visible under “Your Apps” section.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gciyn2xUJzQPc_J1PVTbJw.png" /><figcaption>App ID under Your Apps</figcaption></figure><p>Once these libraries are installed, you’re ready to go through the process of configuration.</p><h4>Implementing Social Logins through Particle Auth Core:</h4><p>Particle Auth Core manages configuration through AuthCoreContextProvider (imported from @particle-network/auth-core-modal), an object used within your index file to wrap your primary App component (or its equivalent). This contains key values authenticating your instance of Particle Auth and enabling core customization of the social login or embedded wallet modals.</p><p>With a project and application set up through the <a href="https://dashboard.particle.network/">Particle dashboard</a>, you’re ready to configure AuthCoreContextProvider.</p><p><strong>File:</strong> <strong>./src/index.tsx</strong></p><pre>// Imports<br>// ========================================================<br>import React from &quot;react&quot;;<br>import ReactDOM from &quot;react-dom/client&quot;;<br>import { BerachainArtio } from &quot;@particle-network/chains&quot;;<br>import { AuthCoreContextProvider } from &quot;@particle-network/auth-core-modal&quot;;<br>import App from &quot;./App&quot;;<br><br>import(&quot;buffer&quot;).then(({ Buffer }) =&gt; {<br>  window.Buffer = Buffer;<br>});<br><br>ReactDOM.createRoot(document.getElementById(&quot;root&quot;) as HTMLElement).render(<br>  &lt;React.StrictMode&gt;<br>    &lt;AuthCoreContextProvider<br>      options={{<br>        projectId:  process.env.REACT_APP_PROJECT_ID, // Replace YOUR_PROJECT_ID_HERE with the actual project ID<br>        clientKey: process.env.REACT_APP_CLIENT_KEY, // Replace YOUR_CLIENT_KEY_HERE with the actual client key<br>        appId:  process.env.REACT_APP_CLIENT_KEY, // Replace YOUR_APP_ID_HERE with the actual app ID<br>        erc4337: {<br>          name: &quot;SIMPLE&quot;,                  //name of the smart account you&#39;d like to be displayed on the modal <br>          version: &quot;1.0.0&quot;,<br>        },<br>        wallet: {<br>          visible: true,                   //boolean dictating whether or not the Particle Wallet modal is shown after login<br>          customStyle: {<br>            supportChains: [BerachainArtio], //an array of chains for the Particle Wallet modal (if visible is true) will be locked to.<br>          },<br>        },<br>      }}<br>    &gt;<br>      &lt;App /&gt;<br>    &lt;/AuthCoreContextProvider&gt;<br>  &lt;/React.StrictMode&gt;<br>);‎</pre><blockquote><strong>Note: Due to specific env constraints we’re passing our keys directly as a string and not via the .env file.</strong></blockquote><h4>Configuring Smart Account</h4><p>Now that AuthCoreContextProvider has been configured and Particle Auth Core is initialized, you&#39;re ready to move onto the implementation of your primary application component (in the example above, this was App).</p><p>Before you can begin executing transactions, you&#39;ll need to first configure your smart account.</p><p>In this setup, Particle Auth Core is used to initiate a social login and generate an EOA. Past that point, Particle&#39;s AA SDK (@particle-network/aa) is responsible for assigning and facilitating interaction with a smart account.</p><p>An example of the process covered above can be found below.</p><p><strong>File:</strong> <strong>./src/App.tsx</strong></p><pre>// Imports<br>// ========================================================<br>import { BerachainArtio } from &quot;@particle-network/chains&quot;;<br>import {<br>  AAWrapProvider,<br>  SendTransactionMode,<br>  SmartAccount,<br>} from &quot;@particle-network/aa&quot;;<br>import {<br>  useEthereum<br>} from &quot;@particle-network/auth-core-modal&quot;;<br><br><br> // Import App<br>// ========================================================<br>import &quot;./App.css&quot;;<br><br><br><br>const App = () =&gt; {<br>  const { provider } = useEthereum();<br>  const { connect, disconnect } = useConnect();<br>  const { userInfo } = useAuthCore();<br><br>  const [balance, setBalance] = useState(null);<br><br>// Smart Account Config <br>// ========================================================<br>  const smartAccount = new SmartAccount(provider, {<br>    projectId: &quot;YOUR_PROJECT_ID_HERE&quot;, // Replace YOUR_PROJECT_ID_HERE with the actual project ID<br>        clientKey: &quot;YOUR_CLIENT_KEY_HERE&quot;, // Replace YOUR_CLIENT_KEY_HERE with the actual client key<br>        appId: &quot;YOUR_APP_ID_HERE&quot;, // Replace YOUR_APP_ID_HERE with the actual app ID<br>    aaOptions: {<br>      accountContracts: {<br>        SIMPLE: [{ chainIds: [BerachainArtio.id], version: &#39;1.0.0&#39; }],<br>      }<br>    }<br>  });</pre><h4>Setting-up Ethers</h4><p>This instance of SmartAccount in the example above can then be used directly within AAWrapProvider to construct an AA-enabled provider object to use within a new instance of ethers.providers.Web3Provider (or if you&#39;re using v6, ethers.BrowserProvider). This same structure can be applied to Web3.js or viem.</p><p>We&#39;ll use SendTransactionMode.Gasless within AAWrapProvider, ensuring that transactions sent through this provider object will be subject to sponsorship if they pass the conditions we set within the Paymaster (although in this example there are none, so transactions will be sponsored indiscriminately).</p><p>Your custom Ethers provider should look like the following:</p><p><strong>File:</strong> <strong>./src/App.tsx</strong></p><pre>// Imports<br>// ========================================================<br>import { BerachainArtio } from &quot;@particle-network/chains&quot;;<br>import {<br>  AAWrapProvider,<br>  SendTransactionMode,<br>  SmartAccount,<br>} from &quot;@particle-network/aa&quot;;<br>import {<br>  useEthereum<br>} from &quot;@particle-network/auth-core-modal&quot;;<br><br><br> // Import App<br>// ========================================================<br>import &quot;./App.css&quot;;<br><br>const App = () =&gt; {<br>  const { provider } = useEthereum();<br>  const { connect, disconnect } = useConnect();<br>  const { userInfo } = useAuthCore();<br><br>  const [balance, setBalance] = useState(null);<br><br>// Smart Account Config <br>// ========================================================<br>  const smartAccount = new SmartAccount(provider, {<br>    projectId: &quot;YOUR_PROJECT_ID_HERE&quot;, // Replace YOUR_PROJECT_ID_HERE with the actual project ID<br>        clientKey: &quot;YOUR_CLIENT_KEY_HERE&quot;, // Replace YOUR_CLIENT_KEY_HERE with the actual client key<br>        appId: &quot;YOUR_APP_ID_HERE&quot;, // Replace YOUR_APP_ID_HERE with the actual app ID<br>    aaOptions: {<br>      accountContracts: {<br>        SIMPLE: [{ chainIds: [BerachainArtio.id], version: &#39;1.0.0&#39; }],<br>      }<br>    }<br>  });<br><br><br>// Ethers Provider Setup<br>const customProvider = new ethers.providers.Web3Provider(new AAWrapProvider(smartAccount, SendTransactionMode.Gasless), &quot;any&quot;);</pre><p>With this object initialized (customProvider in this case), you&#39;ll be able to facilitate transactions, retrieve balances, message signatures, etc. through Particle. However, before being able to facilitate any of these, you’ll first need to facilitate social login — that is what we will be covering next.</p><h4>Setting-up Social Login</h4><p>Social login with Particle Auth Core is simple, directed by two functions derived from the useConnect hook, connect and disconnect. Upon calling connect, social login will immediately be initiated and the user will undergo the login process for the specified social login mechanism. Similarly for disconnect, a user will be removed from their account upon calling.</p><p>Also, we need to import the specific type SocialAuthType imported from @particle-network/auth-core. (This would in imports).</p><p><strong>File:</strong> <strong>./src/App.tsx</strong></p><pre>// Imports<br>// ========================================================<br>import { BerachainArtio } from &quot;@particle-network/chains&quot;;<br>import {<br>  AAWrapProvider,<br>  SendTransactionMode,<br>  SmartAccount,<br>} from &quot;@particle-network/aa&quot;;<br>import {<br>  useEthereum<br>} from &quot;@particle-network/auth-core-modal&quot;;<br><br><br>// New addition of Imports- SocialAuthType<br>// ========================================================<br>import { SocialAuthType } from &quot;@particle-network/auth-core&quot;;<br><br><br> // Import App<br>// ========================================================<br>import &quot;./App.css&quot;;<br><br>const App = () =&gt; {<br>  const { provider } = useEthereum();<br>  const { connect, disconnect } = useConnect();<br>  const { userInfo } = useAuthCore();<br><br>  const [balance, setBalance] = useState(null);<br><br>// Smart Account Config <br>// ========================================================<br>  const smartAccount = new SmartAccount(provider, {<br>    projectId: &quot;YOUR_PROJECT_ID_HERE&quot;, // Replace YOUR_PROJECT_ID_HERE with the actual project ID<br>        clientKey: &quot;YOUR_CLIENT_KEY_HERE&quot;, // Replace YOUR_CLIENT_KEY_HERE with the actual client key<br>        appId: &quot;YOUR_APP_ID_HERE&quot;, // Replace YOUR_APP_ID_HERE with the actual app ID<br>    aaOptions: {<br>      accountContracts: {<br>        SIMPLE: [{ chainIds: [BerachainArtio.id], version: &#39;1.0.0&#39; }],<br>      }<br>    }<br>  });<br><br>// Ethers Provider Setup<br>const customProvider = new ethers.providers.Web3Provider(new AAWrapProvider(smartAccount, SendTransactionMode.Gasless), &quot;any&quot;);<br><br>// Login Setup<br>// ========================================================<br>const handleLogin = async (authType: SocialAuthType) =&gt; {  //can be mapped to &quot;Sign in with Google,&quot; &quot;Sign in with X,&quot; and a miscellaneous button on the frontend by purely changing the string passed into socialType on connect<br>    if (!userInfo) {<br>      await connect({<br>        socialType: authType,           //a string dictating the specific authentication type to be used (such as &#39;google&#39;, &#39;twitter&#39;, etc.)<br>        chain: BerachainArtio,         //the specific chain you&#39;d like to connect to. This should be BerachainArtio<br>      });<br>    }<br>  };‎</pre><p>With a custom Ethers object constructed and the user logged in (through connect), transaction requests can be made directly to Particle through its embedded wallet. As mentioned, this will be done directly through methods on the aforementioned Ethers object (customProvider here), which need no special configuration to work with Particle.</p><h4>Setting up Burn Transaction for BERA</h4><p>We will be facilitating two transaction for this demo and another transaction for burning 1 $HONEY.</p><p>For the first transaction, we’ll be executing a gasless burn of 0.001 $BERA, which essentially involves sending $BERA to a dead address, often 0x000000000000000000000000000000000000dEaD .</p><p>This transaction will be quite programmatically simple, following a structure similar to the following:</p><p><strong>File:</strong> <strong>./src/App.tsx</strong></p><pre>// Imports<br>// ========================================================<br>import { BerachainArtio } from &quot;@particle-network/chains&quot;;<br>import {<br>  AAWrapProvider,<br>  SendTransactionMode,<br>  SmartAccount,<br>} from &quot;@particle-network/aa&quot;;<br>import {<br>  useEthereum<br>} from &quot;@particle-network/auth-core-modal&quot;;<br><br>// New addition of Imports- SocialAuthType<br>// ========================================================<br>import { SocialAuthType } from &quot;@particle-network/auth-core&quot;;<br><br> // Import App<br>// ========================================================<br>import &quot;./App.css&quot;;<br><br>const App = () =&gt; {<br>  const { provider } = useEthereum();<br>  const { connect, disconnect } = useConnect();<br>  const { userInfo } = useAuthCore();<br><br>  const [balance, setBalance] = useState(null);<br><br>// Smart Account Config <br>// ========================================================<br>  const smartAccount = new SmartAccount(provider, {<br>    projectId: &quot;YOUR_PROJECT_ID_HERE&quot;, // Replace YOUR_PROJECT_ID_HERE with the actual project ID<br>        clientKey: &quot;YOUR_CLIENT_KEY_HERE&quot;, // Replace YOUR_CLIENT_KEY_HERE with the actual client key<br>        appId: &quot;YOUR_APP_ID_HERE&quot;, // Replace YOUR_APP_ID_HERE with the actual app ID<br>    aaOptions: {<br>      accountContracts: {<br>        SIMPLE: [{ chainIds: [BerachainArtio.id], version: &#39;1.0.0&#39; }],<br>      }<br>    }<br>  });<br><br>// Ethers Provider Setup<br>const customProvider = new ethers.providers.Web3Provider(new AAWrapProvider(smartAccount, SendTransactionMode.Gasless), &quot;any&quot;);<br><br>// Login Setup<br>// ========================================================<br>const handleLogin = async (authType: SocialAuthType) =&gt; {  //can be mapped to &quot;Sign in with Google,&quot; &quot;Sign in with X,&quot; and a miscellaneous button on the frontend by purely changing the string passed into socialType on connect<br>    if (!userInfo) {<br>      await connect({<br>        socialType: authType,           //a string dictating the specific authentication type to be used (such as &#39;google&#39;, &#39;twitter&#39;, etc.)<br>        chain: BerachainArtio,         //the specific chain you&#39;d like to connect to. This should be BerachainArtio<br>      });<br>    }<br>  };‎<br><br>// Burn 0.001 $BERA<br>// ========================================================<br>const executeUserOp = async () =&gt; {<br>    const signer = customProvider.getSigner();<br><br>    const tx = {<br>      to: &quot;0x000000000000000000000000000000000000dEaD&quot;,<br>      value: ethers.utils.parseEther(&quot;0.001&quot;),              //value of the $BERA that will be coverted to which needs to be converted to wei through<br>    };<br><br>    const txResponse = await signer.sendTransaction(tx);  //sendTransaction method<br>    const txReceipt = await txResponse.wait();<br><br>    notification.success({<br>      message: &quot;Transaction Successful&quot;,<br>      description: (<br>        &lt;div&gt;<br>          Transaction Hash:{&quot; &quot;}<br>          &lt;a<br>            href={`https://artio.beratrail.io/tx/${txReceipt.transactionHash}`}<br>            target=&quot;_blank&quot;<br>            rel=&quot;noopener noreferrer&quot;<br>          &gt;<br>            {txReceipt.transactionHash}<br>          &lt;/a&gt;<br>        &lt;/div&gt;<br>      ),<br>    });<br>  };</pre><h4>Setting up Burn Transaction for $HONEY</h4><blockquote><strong>Note: </strong>If you don’t have $HONEY, but would like some to test this function, Berachain has a <a href="https://artio.bex.berachain.com/">native DEX</a> that supports swapping $BERA for $HONEY.</blockquote><p>As for the second transaction, the burn of 1 $HONEY, Berachain’s native stablecoin, we can take a similar approach, although instead of calling a method on signer directly, we&#39;ll have to create a contract object for $HONEY, on which we can call the transfer method.</p><p>This can be done by simply initiating ethers.Contract, passing in 0x7EeCA4205fF31f947EdBd49195a7A88E6A91161B (the $HONEY contract address on Berachain Artio), alongside the ABI. <em>(</em><a href="https://artio.beratrail.io/token/0x7EeCA4205fF31f947EdBd49195a7A88E6A91161B"><em>https://artio.beratrail.io/token/0x7EeCA4205fF31f947EdBd49195a7A88E6A91161B</em></a><em>)</em></p><p><strong>File:</strong> <strong>./src/App.tsx</strong></p><pre><br>// Imports<br>// ========================================================<br>import { BerachainArtio } from &quot;@particle-network/chains&quot;;<br>import {<br>  AAWrapProvider,<br>  SendTransactionMode,<br>  SmartAccount,<br>} from &quot;@particle-network/aa&quot;;<br>import {<br>  useEthereum<br>} from &quot;@particle-network/auth-core-modal&quot;;<br><br>// New addition of Imports- SocialAuthType<br>// ========================================================<br>import { SocialAuthType } from &quot;@particle-network/auth-core&quot;;<br><br> // Import App<br>// ========================================================<br>import &quot;./App.css&quot;;<br><br>const App = () =&gt; {<br>  const { provider } = useEthereum();<br>  const { connect, disconnect } = useConnect();<br>  const { userInfo } = useAuthCore();<br><br>  const [balance, setBalance] = useState(null);<br><br>// Smart Account Config <br>// ========================================================<br>  const smartAccount = new SmartAccount(provider, {<br>    projectId: &quot;YOUR_PROJECT_ID_HERE&quot;, // Replace YOUR_PROJECT_ID_HERE with the actual project ID<br>        clientKey: &quot;YOUR_CLIENT_KEY_HERE&quot;, // Replace YOUR_CLIENT_KEY_HERE with the actual client key<br>        appId: &quot;YOUR_APP_ID_HERE&quot;, // Replace YOUR_APP_ID_HERE with the actual app ID<br>    aaOptions: {<br>      accountContracts: {<br>        SIMPLE: [{ chainIds: [BerachainArtio.id], version: &#39;1.0.0&#39; }],<br>      }<br>    }<br>  });<br><br>// Ethers Provider Setup<br>const customProvider = new ethers.providers.Web3Provider(new AAWrapProvider(smartAccount, SendTransactionMode.Gasless), &quot;any&quot;);<br><br>// Login Setup<br>// ========================================================<br>const handleLogin = async (authType: SocialAuthType) =&gt; {  //can be mapped to &quot;Sign in with Google,&quot; &quot;Sign in with X,&quot; and a miscellaneous button on the frontend by purely changing the string passed into socialType on connect<br>    if (!userInfo) {<br>      await connect({<br>        socialType: authType,           //a string dictating the specific authentication type to be used (such as &#39;google&#39;, &#39;twitter&#39;, etc.)<br>        chain: BerachainArtio,         //the specific chain you&#39;d like to connect to. This should be BerachainArtio<br>      });<br>    }<br>  };‎<br><br>// Burn 0.001 $BERA<br>// ========================================================<br>const executeUserOp = async () =&gt; {<br>    const signer = customProvider.getSigner();<br><br>    const tx = {<br>      to: &quot;0x000000000000000000000000000000000000dEaD&quot;,<br>      value: ethers.utils.parseEther(&quot;0.001&quot;),              //value of the $BERA that will be coverted to which needs to be converted to wei through<br>    };<br><br>    const txResponse = await signer.sendTransaction(tx);  //sendTransaction method<br>    const txReceipt = await txResponse.wait();<br><br>    notification.success({<br>      message: &quot;Transaction Successful&quot;,<br>      description: (<br>        &lt;div&gt;<br>          Transaction Hash:{&quot; &quot;}<br>          &lt;a<br>            href={`https://artio.beratrail.io/tx/${txReceipt.transactionHash}`}<br>            target=&quot;_blank&quot;<br>            rel=&quot;noopener noreferrer&quot;<br>          &gt;<br>            {txReceipt.transactionHash}<br>          &lt;/a&gt;<br>        &lt;/div&gt;<br>      ),<br>    });<br>  };<br><br><br>// Burn 1 $HONEY<br>// ========================================================<br>const executeUserOpHONEY = async () =&gt; {<br>    const signer = customProvider.getSigner();<br><br>    const tokenContract = new ethers.Contract(<br>      &quot;0x7EeCA4205fF31f947EdBd49195a7A88E6A91161B&quot;,                      //official  $HONEY contract address<br>      [&quot;function transfer(address to, uint256 amount)&quot;],                 <br>      signer                                                             //retrieved through {your ethers object}.getSigner      <br>    );<br><br>    const txResponse = await tokenContract.transfer(<br>      &quot;0x000000000000000000000000000000000000dEaD&quot;,<br>      ethers.utils.parseEther(&quot;1&quot;)                                      // value of the $HONEY <br>    );<br>    const txReceipt = await txResponse.wait();<br><br>    notification.success({<br>      message: &quot;Transaction Successful&quot;,<br>      description: (<br>        &lt;div&gt;<br>          Transaction Hash:{&quot; &quot;}<br>          &lt;a<br>            href={`https://artio.beratrail.io/tx/${txReceipt.transactionHash}`}<br>            target=&quot;_blank&quot;<br>            rel=&quot;noopener noreferrer&quot;<br>          &gt;<br>            {txReceipt.transactionHash}<br>          &lt;/a&gt;<br>        &lt;/div&gt;<br>      ),<br>    });<br>  };</pre><p>If you’re leveraging the built-in Particle Wallet interface (shown by setting visible to true within AuthCoreContextProvider), many ERC-20 and ERC-721 tokens won’t be automatically picked up (including $HONEY). If these aren’t automatically reflected within the modal, you’ll need to manually add the token through the plus icon near the list of balances.‎</p><p>For the complete <strong>App.tsx </strong>code, please refer the “<em>Complete Code</em>” section right below “<em>Recap</em>”.</p><p><strong>dApp CSS</strong></p><p>As mentioned before, we would be focusing mostly on backend and getting the dApp running. Follow the link below and add the css code to your existing <strong>../src/App.css.</strong></p><p><strong>../src/App.css<br></strong>Head over to <a href="https://github.com/berachain/guides/tree/main/apps/particle-auth-core-vite"><em>https://github.com/berachain/guides/tree/main/apps/particle-auth-core-vite</em></a> and use the existing code from the template!</p><p>✅ Deploying the dApp</p><pre> npm run dev;<br><br>#Expected Output:<br>&gt; vite-project@0.0.0 dev<br>&gt; vite<br><br><br>  VITE v5.1.3  ready in 117 ms<br><br>  ➜  Local:   http://localhost:5173/<br>  ➜  Network: use --host to expose<br>  ➜  press h + enter to show help</pre><p>dApp should be successfully deployed on <a href="http://localhost:5173/"><em>http://localhost:5173/</em></a><em>.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J7lCqtoX8v1DXkQ8j80Izg.png" /><figcaption>Localhost :— After Deployment</figcaption></figure><h3>Recap</h3><p>Here’s a quick break-down of the steps that were performed in this guide!</p><ol><li>Setting up your dev environment and install the required libraries.</li><li>Getting keys from particle dashboard</li><li>Configuring Smart Account</li><li>Setting-up Ethers</li><li>Setting-up Social Login</li><li>Setting up Burn Transaction for $BERA and $HONEY</li><li>Deploying and Testing the dApp!</li></ol><p>This guide serves as a one-stop solution for new dApps looking to integrate a wallet that facilitates social-based login along with added AA support! structure and flow similar to the above can be applied directly to both existing and new applications.</p><h3>Complete Code</h3><p><strong>../src/index.tsx</strong></p><pre>import React from &quot;react&quot;;<br>import ReactDOM from &quot;react-dom/client&quot;;<br>import { BerachainArtio } from &quot;@particle-network/chains&quot;;<br>import { AuthCoreContextProvider } from &quot;@particle-network/auth-core-modal&quot;;<br>import App from &quot;./App&quot;;<br><br>import(&quot;buffer&quot;).then(({ Buffer }) =&gt; {<br>  window.Buffer = Buffer;<br>});<br><br>ReactDOM.createRoot(document.getElementById(&quot;root&quot;) as HTMLElement).render(<br>  &lt;React.StrictMode&gt;<br>    &lt;AuthCoreContextProvider<br>      options={{<br>        projectId: &quot;YOUR_PROJECT_ID_HERE&quot;, // Replace YOUR_PROJECT_ID_HERE with the actual project ID<br>        clientKey: &quot;YOUR_CLIENT_KEY_HERE&quot;, // Replace YOUR_CLIENT_KEY_HERE with the actual client key<br>        appId: &quot;YOUR_APP_ID_HERE&quot;, // Replace YOUR_APP_ID_HERE with the actual app ID<br>        erc4337: {<br>          name: &quot;SIMPLE&quot;,<br>          version: &quot;1.0.0&quot;,<br>        },<br>        wallet: {<br>          visible: true,<br>          customStyle: {<br>            supportChains: [BerachainArtio],<br>          },<br>        },<br>      }}<br>    &gt;<br>      &lt;App /&gt;<br>    &lt;/AuthCoreContextProvider&gt;<br>  &lt;/React.StrictMode&gt;<br>);</pre><p><strong>../src/App.tsx</strong></p><pre>import React, { useState, useEffect } from &quot;react&quot;;<br>import { BerachainArtio } from &quot;@particle-network/chains&quot;;<br>import {<br>  AAWrapProvider,<br>  SendTransactionMode,<br>  SmartAccount,<br>} from &quot;@particle-network/aa&quot;;<br>import {<br>  useEthereum,<br>  useConnect,<br>  useAuthCore,<br>} from &quot;@particle-network/auth-core-modal&quot;;<br>import { ethers } from &quot;ethers&quot;;<br>import { Modal, notification } from &quot;antd&quot;;<br><br>import &quot;./App.css&quot;;<br><br>import { SocialAuthType } from &quot;@particle-network/auth-core&quot;;<br><br>const App = () =&gt; {<br>  const { provider } = useEthereum();<br>  const { connect, disconnect } = useConnect();<br>  const { userInfo } = useAuthCore();<br><br>   const smartAccount = new SmartAccount(provider, {<br>    projectId: &quot;YOUR_PROJECT_ID_HERE&quot;, // Replace YOUR_PROJECT_ID_HERE with the actual project ID<br>        clientKey: &quot;YOUR_CLIENT_KEY_HERE&quot;, // Replace YOUR_CLIENT_KEY_HERE with the actual client key<br>        appId: &quot;YOUR_APP_ID_HERE&quot;, // Replace YOUR_APP_ID_HERE with the actual app ID<br>    aaOptions: {<br>      accountContracts: {<br>        SIMPLE: [{ chainIds: [BerachainArtio.id], version: &#39;1.0.0&#39; }],<br>      }<br>    }<br>  });<br><br>  const customProvider = new ethers.providers.Web3Provider(<br>    new AAWrapProvider(smartAccount, SendTransactionMode.Gasless),<br>    &quot;any&quot;<br>  );<br><br>  useEffect(() =&gt; {<br>    if (userInfo) {<br>      fetchBalance();<br>    }<br>  }, [userInfo]);<br><br>  const [balance, setBalance] = useState&lt;string | null&gt;(null);<br><br>  const fetchBalance = async () =&gt; {<br>    const address = await smartAccount.getAddress();<br>    const balanceResponse = await customProvider.getBalance(address);<br>    setBalance(ethers.utils.formatEther(balanceResponse));<br>  };<br><br>  const handleLogin = async (authType: SocialAuthType) =&gt; {<br>    if (!userInfo) {<br>      await connect({<br>        socialType: authType,<br>        chain: BerachainArtio,<br>      });<br>    }<br>  };<br><br>  const executeUserOp = async () =&gt; {<br>    const signer = customProvider.getSigner();<br><br>    const tx = {<br>      to: &quot;0x000000000000000000000000000000000000dEaD&quot;,<br>      value: ethers.utils.parseEther(&quot;0.001&quot;),<br>    };<br><br>    const txResponse = await signer.sendTransaction(tx);<br>    const txReceipt = await txResponse.wait();<br><br>    notification.success({<br>      message: &quot;Transaction Successful&quot;,<br>      description: (<br>        &lt;div&gt;<br>          Transaction Hash:{&quot; &quot;}<br>          &lt;a<br>            href={`https://artio.beratrail.io/tx/${txReceipt.transactionHash}`}<br>            target=&quot;_blank&quot;<br>            rel=&quot;noopener noreferrer&quot;<br>          &gt;<br>            {txReceipt.transactionHash}<br>          &lt;/a&gt;<br>        &lt;/div&gt;<br>      ),<br>    });<br>  };<br><br>  const executeUserOpHONEY = async () =&gt; {<br>    const signer = customProvider.getSigner();<br><br>    const tokenContract = new ethers.Contract(<br>      &quot;0x7EeCA4205fF31f947EdBd49195a7A88E6A91161B&quot;,<br>      [&quot;function transfer(address to, uint256 amount)&quot;],<br>      signer<br>    );<br><br>    const txResponse = await tokenContract.transfer(<br>      &quot;0x000000000000000000000000000000000000dEaD&quot;,<br>      ethers.utils.parseEther(&quot;1&quot;)<br>    );<br>    const txReceipt = await txResponse.wait();<br><br>    notification.success({<br>      message: &quot;Transaction Successful&quot;,<br>      description: (<br>        &lt;div&gt;<br>          Transaction Hash:{&quot; &quot;}<br>          &lt;a<br>            href={`https://artio.beratrail.io/tx/${txReceipt.transactionHash}`}<br>            target=&quot;_blank&quot;<br>            rel=&quot;noopener noreferrer&quot;<br>          &gt;<br>            {txReceipt.transactionHash}<br>          &lt;/a&gt;<br>        &lt;/div&gt;<br>      ),<br>    });<br>  };<br><br>  return (<br>    &lt;div className=&quot;App&quot;&gt;<br>      &lt;div className=&quot;logo-section&quot;&gt;<br>        &lt;img<br>          src=&quot;https://i.imgur.com/EerK7MS.png&quot;<br>          alt=&quot;Logo 1&quot;<br>          className=&quot;logo logo-big&quot;<br>        /&gt;<br>        &lt;img<br>          src=&quot;https://i.imgur.com/OdR3YLW.png&quot;<br>          alt=&quot;Logo 2&quot;<br>          className=&quot;logo&quot;<br>        /&gt;<br>      &lt;/div&gt;<br>      {!userInfo ? (<br>        &lt;div className=&quot;login-section&quot;&gt;<br>          &lt;button<br>            className=&quot;sign-button google-button&quot;<br>            onClick={() =&gt; handleLogin(&quot;google&quot;)}<br>          &gt;<br>            &lt;img<br>              src=&quot;https://i.imgur.com/nIN9P4A.png&quot;<br>              alt=&quot;Google&quot;<br>              className=&quot;icon&quot;<br>            /&gt;<br>            Sign in with Google<br>          &lt;/button&gt;<br>          &lt;button<br>            className=&quot;sign-button twitter-button&quot;<br>            onClick={() =&gt; handleLogin(&quot;twitter&quot;)}<br>          &gt;<br>            &lt;img<br>              src=&quot;https://i.imgur.com/afIaQJC.png&quot;<br>              alt=&quot;Twitter&quot;<br>              className=&quot;icon&quot;<br>            /&gt;<br>            Sign in with X<br>          &lt;/button&gt;<br>        &lt;/div&gt;<br>      ) : (<br>        &lt;div className=&quot;profile-card&quot;&gt;<br>          &lt;h2&gt;{userInfo.name}&lt;/h2&gt;<br>          &lt;div className=&quot;balance-section&quot;&gt;<br>            &lt;small&gt;{balance} BERA&lt;/small&gt;<br>            &lt;button className=&quot;sign-message-button&quot; onClick={executeUserOp}&gt;<br>              Burn 0.001 $BERA<br>            &lt;/button&gt;<br>            &lt;button<br>              className=&quot;sign-message-button honey&quot;<br>              onClick={executeUserOpHONEY}<br>            &gt;<br>              Burn 1 $HONEY<br>            &lt;/button&gt;<br>            &lt;button className=&quot;disconnect-button&quot; onClick={() =&gt; disconnect()}&gt;<br>              Logout<br>            &lt;/button&gt;<br>          &lt;/div&gt;<br>        &lt;/div&gt;<br>      )}<br>    &lt;/div&gt;<br>  );<br>};<br><br>export default App;</pre><p><strong>../src/App.css<br></strong>Head over to <a href="https://github.com/berachain/guides/tree/main/apps/particle-auth-core-vite"><em>https://github.com/berachain/guides/tree/main/apps/particle-auth-core-vite</em></a> and use the existing code from the template!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KctLtBW0df9d3pQK4dqGTw.png" /></figure><h3><strong>More dApps and How To Get Support ?</strong></h3><p>If you’re interested in understanding and developing more on Berachain, try various example repos provided in the official guides repo —</p><p><a href="https://github.com/berachain/guides/tree/main/apps/particle-auth-core-vite">guides/apps/particle-auth-core-vite at main · berachain/guides</a></p><p>Berachain’s developer documentation also has multiple starter guides with goto tools such as Hardhat, Foundry and more! Head over to developer section on the docs using the link below.</p><p><a href="https://docs.berachain.com/developers/">Connecting to Berachain</a></p><h4><strong>How to get Developer Support?</strong></h4><p>⚠️ Still facing issues or have doubts? Head over to <a href="https://discord.gg/berachain"><strong><em>Official Berachain Discord</em></strong></a> and raise a ticket as shown in the gif below!</p><p>Our DevRel team will be happy to assist! 🤝</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*QmeL3wtqcBhiHbnieK6LaQ.gif" /></figure><p>Byyeeee dev bears! 🐻</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=daee55b6242b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/berachain-devs/social-login-dapp-with-particle-network-on-berachain-testnet-daee55b6242b">Social Login dApp with Particle Network on Berachain Testnet</a> was originally published in <a href="https://medium.com/berachain-devs">berachain-devs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build A Berachain Mobile dApp With WalletConnect & Expo]]></title>
            <link>https://medium.com/berachain-devs/build-a-berachain-mobile-dapp-with-walletconnect-expo-c5cde75dbac2?source=rss----b629d42886be---4</link>
            <guid isPermaLink="false">https://medium.com/p/c5cde75dbac2</guid>
            <category><![CDATA[expo]]></category>
            <category><![CDATA[web3]]></category>
            <category><![CDATA[walletconnect]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[berachain]]></category>
            <dc:creator><![CDATA[Manny]]></dc:creator>
            <pubDate>Thu, 29 Feb 2024 21:16:39 GMT</pubDate>
            <atom:updated>2024-05-21T17:06:17.598Z</atom:updated>
            <content:encoded><![CDATA[<h4>How To Build A Mobile Web3 dApp With WalletConnect &amp; React Native Using Expo</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*w2YU-AfXyLKmRK_MIoVa5A.png" /><figcaption>Learn To Build A Berachain Mobile DApp</figcaption></figure><h3>🛠️ Let’s Build A Mobile dApp On Berachain</h3><p>Most web3 dApps are typically built for web and don’t have much love for mobile. In this tutorial we’re going to change that by building an iOS app with <a href="https://expo.dev/"><strong><em>Expo</em></strong></a> that works with <a href="https://www.berachain.com/"><strong><em>Berachain</em></strong></a>.</p><p>Our mobile dApp will be able to connect our MetaMask mobile wallet, sign a message, and deploy the bytecode for a <a href="https://github.com/berachain/guides/blob/main/apps/hardhat-viem-helloworld/contracts/HelloWorld.sol"><strong><em>HelloWorld contract</em></strong></a><strong><em> </em></strong>to Berachain Artio (Berachain Testnet).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J6sztHxqq-rGBsv77qWvRA.png" /><figcaption>Berachain Mobile dApp With WalletConnect Web3Modal &amp; Expo</figcaption></figure><h4>Why Expo?</h4><p>Expo has been gaining popularity in the React Native space for mobile development and three main reasons why developers are choosing Expo over Native development or just React Native are:</p><ol><li>Support for multiple platforms — iOS and Android</li><li>Prebuilt components and functionality</li><li>Expo EAS (Expo Application Service) which allows for immediate updates versus going through AppStore approvals for each update</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IpttAhdyojpj674uE_Odcw.png" /><figcaption><a href="https://expo.dev/">https://expo.dev/</a></figcaption></figure><h4>WalletConnect &amp; Mobile</h4><p>WalletConnect has been a staple for most web3 dApps and making sure projects are setup to support has many wallets, while giving easy tooling for developers to get out-of-the-box wallet connection integration with their SDKs.</p><p>WalletConnect also has a mobile specific SDK that allows for wallet connections and interactions to happen directly on your mobile device. This is the SDK that we’ll be using for this tutorial.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6U1OxVR1Yotz9WTqmhjEgg.png" /><figcaption><a href="https://docs.walletconnect.com/web3modal/react-native/about"><em>WalletConnect Web3Modal For React Native</em></a></figcaption></figure><h3>📋 Requirements</h3><p>Make sure to have the following installed or setup prior to continuing.</p><blockquote><strong>NOTE:</strong> For the purposes of this tutorial we’ll be focusing on iOS</blockquote><ul><li>NVM or Node v20.11.0</li><li><a href="https://expo.dev/expo-go"><strong><em>Expo Go</em></strong></a></li><li>Xcode with iOS Simulator</li><li><a href="https://metamask.io/download/"><strong><em>iOS MetaMask Mobile Wallet</em></strong></a></li><li>Berachain $BERA tokens — (Need <a href="https://artio.faucet.berachain.com/"><strong><em>Berachain faucet tokens</em></strong></a>?)</li></ul><h3>💻 Pre-Step iOS Simulator On Sonoma</h3><p>With the latest Mac OS Sonoma and Xcode, Apple has decided to create an extra step that would require developers to download a specific runtime simulator that may not be pre-installed.</p><p>To start, run <strong><em>Xcode</em></strong>, and go to <strong><em>Window</em></strong> &gt; <strong><em>Devices &amp; Simulators</em></strong>. This will open up a new window. Select <strong><em>Simulators</em></strong> in the top left, and from the dropdown for <strong><em>Device Type</em></strong> select <strong><em>iPhone 15 Pro Max</em></strong> and for <strong><em>OS Version</em></strong> choose <strong><em>Download more simulator runtimes….</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*58v6k2Gn4flBW_pKPLeKAg.png" /><figcaption>Xcode Simulator Runtimes</figcaption></figure><p>This will open another window to then download <strong>iOS 17.2</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iGU3xySMqLmLc7hjU2RhDQ.png" /><figcaption>Xcode Simulator Runtimes Download Platforms</figcaption></figure><p>Wait until this download completes and double check that your Simulator.app has successfully downloaded by running:</p><pre>open /Applications/Xcode.app/Contents/Developer/Applications/Simulator.app;</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GL8vh94rTaP6AcIfuHuUrw.png" /><figcaption>iOS Simulator Successfully Running</figcaption></figure><h3>📱Building A Berachain Mobile dApp</h3><p>Now that we our iOS Simulator setup, we should be good to build out our entire mobile application.</p><h4>WalletConnect Project ID</h4><p>Before we start coding, we’ll need to make sure that we setup a WalletConnect Project ID at <a href="https://cloud.walletconnect.com/app"><em>https://cloud.walletconnect.com/app</em></a>.</p><p>If you already have a project id, you can skip this step.</p><p>Go the <a href="https://cloud.walletconnect.com/app"><strong><em>WalletConnect Cloud Sign-In</em></strong></a><strong> </strong>to create a new account.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*f914LLFN7JB_j2gdyzV6Gw.png" /><figcaption><a href="https://cloud.walletconnect.com/sign-in">https://cloud.walletconnect.com/sign-in</a></figcaption></figure><p>When in the dashboard, create a new project.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vg99c-yEmLYI1Gj8IfHveg.png" /><figcaption>WalletConnect — Create Project</figcaption></figure><p>Enter the details of your project.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7m8_w14M7m9bZpddWn1cNw.png" /><figcaption>WalletConnect — Project Details</figcaption></figure><p>Get your project id, we’ll need this for later.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qHpE9WMTTSv8M1H9x-TU_w.png" /><figcaption>WalletConnect Project ID</figcaption></figure><h4>Project Setup</h4><p>Now that we have our WalletConnect project id, let’s create a base expo project and add our needed dependencies.</p><pre> npx create-expo-app berachain-walletconnect-expo -t;<br><br># [Expected Prompt &amp; Output]:<br># ? Choose a template: › - Use arrow-keys. Return to submit.<br>#     Blank<br># ❯   Blank (TypeScript) - blank app with TypeScript enabled<br>#     Navigation (TypeScript)<br>#     Blank (Bare)<br># ...<br># ✅ Your project is ready!<br>#<br># To run your project, navigate to the directory and run one of the following npm commands.<br>#<br># - cd berachain-walletconnect-expo<br># - npm run android<br># - npm run ios<br># - npm run web</pre><p>Install our needed dependencies.</p><blockquote><strong>NOTE:</strong> We’ll be using pnpm which has been known to have some issues with expo. We also recommend using yarn with expo whenever possible.</blockquote><pre>cd berachain-walletconnect-expo;<br><br>pnpm add @web3modal/wagmi-react-native wagmi@1.4.13 viem@1.21.4 @react-native-async-storage/async-storage react-native-get-random-values react-native-svg react-native-modal @react-native-community/netinfo @walletconnect/react-native-compat expo-application expo-linking;<br># If in a monorepo / turbo repo, run the following right after in the dir<br># pnpm install --ignore-workspace;<br><br># @web3modal/wagmi-react-native - walletconnect react native web3modal<br># wagmi@1.4.13 - web3 react hooks (currently only supports v1)<br># viem@1.21.4 # js library for interacting with EVM (currently only support<br># @react-native-async-storage/async-storage - for local device storage<br># react-native-get-random-values - local random val generator<br># react-native-svg - native svg support<br># react-native-modal - modals support<br># @react-native-community/netinfo - api for network info for device<br># @walletconnect/react-native-compat - shims / polyfills for additional support<br># expo-application - for native app information<br># expo-linking - allows for external links to open the browser</pre><p>Let’s test that our app is working correctly — hint it won’t 😅.</p><blockquote><strong>Note:</strong> This is an issue specifically with pnpm. If you did everything with yarn then this won’t happen.</blockquote><pre># FROM: ./berachain-walletconnect-expo;<br><br>pnpm ios;<br><br># [Expected Output]:<br># </pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_6Y60takxUGveT3EJpGQLg.png" /><figcaption>Expo Not Working — Expected</figcaption></figure><p>⚠️ <strong>The PNPM Expo Fix</strong></p><p>If you’re using yarn you can still make these modifications and it’ll work for all package managers.</p><p>To fix this specific pnpm issue, we’ll need to make 3 modifications to our project.</p><p>1 — Install Babel Runtime Dependency</p><pre># FROM: ./berachain-walletconnect-expo;<br><br>pnpm add -D @babel/runtime;</pre><p>2 — Modify Package JSON App Entry</p><p><strong>File:</strong> ./package.json</p><pre>{<br>  &quot;name&quot;: &quot;berachain-walletconnect-expo&quot;,<br>  &quot;version&quot;: &quot;1.0.0&quot;,<br>-  &quot;main&quot;: &quot;node_modules/expo/AppEntry.js&quot;,<br>+ &quot;main&quot;: &quot;index.ts&quot;,<br>  &quot;scripts&quot;: {<br>    &quot;start&quot;: &quot;expo start&quot;,<br>    &quot;android&quot;: &quot;expo start --android&quot;,<br>    &quot;ios&quot;: &quot;expo start --ios&quot;,<br>    &quot;web&quot;: &quot;expo start --web&quot;<br>  },<br>  &quot;dependencies&quot;: {<br>    &quot;@react-native-async-storage/async-storage&quot;: &quot;^1.22.1&quot;,<br>    &quot;@react-native-community/netinfo&quot;: &quot;^11.3.0&quot;,<br>    &quot;@walletconnect/react-native-compat&quot;: &quot;^2.11.1&quot;,<br>    &quot;@web3modal/wagmi-react-native&quot;: &quot;^1.2.0&quot;,<br>    &quot;expo&quot;: &quot;~50.0.7&quot;,<br>    &quot;expo-application&quot;: &quot;^5.8.3&quot;,<br>    &quot;expo-status-bar&quot;: &quot;~1.11.1&quot;,<br>    &quot;react&quot;: &quot;18.2.0&quot;,<br>    &quot;react-native&quot;: &quot;0.73.4&quot;,<br>    &quot;react-native-get-random-values&quot;: &quot;^1.10.0&quot;,<br>    &quot;react-native-modal&quot;: &quot;^13.0.1&quot;,<br>    &quot;react-native-svg&quot;: &quot;^14.1.0&quot;,<br>    &quot;viem&quot;: &quot;1.21.4&quot;,<br>    &quot;wagmi&quot;: &quot;1.4.13&quot;<br>  },<br>  &quot;devDependencies&quot;: {<br>    &quot;@babel/core&quot;: &quot;^7.20.0&quot;,<br>    &quot;@types/react&quot;: &quot;~18.2.45&quot;,<br>    &quot;typescript&quot;: &quot;^5.1.3&quot;<br>  },<br>  &quot;private&quot;: true<br>}</pre><p>3 — Add New Entry File &amp; Move Our App.tsx</p><pre># FROM: ./berachain-walletconnect-expo;<br><br>touch index.ts;<br>mkdir app;<br>mv App.tsx app;</pre><p><strong>File:</strong> ./index.ts</p><pre>// Imports<br>// ========================================================<br>import { registerRootComponent } from &quot;expo&quot;;<br><br>// Main App<br>// ========================================================<br>import App from &quot;./app/App&quot;;<br><br>// registerRootComponent calls AppRegistry.registerComponent(&#39;main&#39;, () =&gt; App);<br>// It also ensures that whether you load the app in Expo Go or in a native build,<br>// the environment is set up appropriately<br>registerRootComponent(App);</pre><p>Let’s try this again, with pnpm ios and we should get the following working. This should also work with yarn or npm as well.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*I-DYSWn5KLP32jYwJ377Dw.png" /><figcaption>Expo iOS Simulator Working After PNPM Fix</figcaption></figure><h4>Styling Our Project</h4><p>For styling, we’re going to use <a href="https://tailwindcss.com/"><strong><em>Tailwind</em></strong></a> with <a href="https://www.nativewind.dev/"><strong><em>Nativewind</em></strong></a> to keep that same consistent styling with all of our app.</p><p>These next few steps, are a few but once it’s setup, it’ll make sure that we have Tailwind configured correctly.</p><pre># FROM: ./berachain-walletconnect-expo;<br><br>pnpm add nativewind@^4.0.1 tailwindcss react-native-css-interop;<br>npx tailwindcss init;<br><br># Move our main App.tsx to an app directory for better tailwind changes<br>mkdir app;<br>mv App.tsx app/;</pre><p>Make the appropriate modification to our newly generated tailwind.config.js file.</p><p><strong>File:</strong> ./tailwind.config.js</p><pre>/** @type {import(&#39;tailwindcss&#39;).Config} */<br>module.exports = {<br>  // NOTE: Update this to include the paths to all of your component files.<br>  content: [<br>    &quot;./app/**/*.{js,jsx,ts,tsx}&quot;, <br>    &quot;./components/**/*.{js,jsx,ts,tsx}&quot;<br>  ],<br>  presets: [require(&quot;nativewind/preset&quot;)],<br>  theme: {<br>    extend: {},<br>  },<br>  plugins: [],<br>}</pre><p>Create a new global.css and add Tailwind styles.</p><pre># FROM: ./berachain-walletconnect-expo;<br><br>touch global.css;</pre><p><strong>File:</strong> ./global.css</p><pre>@tailwind base;<br>@tailwind components;<br>@tailwind utilities;<br><br>@layer base {<br>  .App {<br>    @apply bg-[#F47226] text-[#2E1E1A] flex w-full h-full items-center justify-center;<br>  }<br><br>  .H1 {<br>    @apply text-lg mb-2 block font-semibold text-[#121312] text-center;<br>  }<br><br>  .Text {<br>    @apply mb-2 text-[#2E1E1A] block;<br>  }<br><br>  .TextInput {<br>    @apply bg-white text-base h-12 px-2 align-text-top rounded w-full mb-4;<br>  }<br><br>  .TextError {<br>    @apply text-red-800 bg-red-200 mb-2 text-base p-4;<br>  }<br><br>  .Button {<br>    @apply bg-[#2E1E1A] h-12 flex items-center justify-center rounded-lg mb-4 w-full;<br>  }<br><br>  .Code {<br>    @apply block bg-[#ff843d] whitespace-nowrap overflow-scroll mb-4 text-[#874c2a] text-base h-12 leading-[3rem] px-2 rounded w-full;<br>  }<br>  <br>  .Connect {<br>    @apply my-4 block;<br>  }<br><br>  .Balance {<br>    @apply block w-full px-8;<br>  }<br><br>  .SignMessage {<br>    @apply block w-full px-8;<br>  }<br><br>  .Deploy {<br>    @apply block w-full px-8;<br>  }<br>}</pre><p>Modify our babel.config.js to support nativewind.</p><p><strong>File:</strong> ./babel.config.js</p><pre>module.exports = (api) =&gt; {<br>  api.cache(true);<br>  return {<br>    presets: [<br>      [&quot;babel-preset-expo&quot;, { jsxImportSource: &quot;nativewind&quot; }],<br>      &quot;nativewind/babel&quot;,<br>    ],<br>  };<br>};</pre><p>Generate a new metro.config.js file which will help with build.</p><pre># FROM: ./berachain-walletconnect-expo;<br><br>npx expo customize metro.config.js;</pre><p>Make some modifications to that config file.</p><p><strong>File:</strong> ./metro.config.js</p><pre>// Learn more https://docs.expo.io/guides/customizing-metro<br>const { getDefaultConfig } = require(&#39;expo/metro-config&#39;);<br>+ const { withNativeWind } = require(&#39;nativewind/metro&#39;);<br><br>/** @type {import(&#39;expo/metro-config&#39;).MetroConfig} */<br>- const config = getDefaultConfig(__dirname);<br>+ const config = getDefaultConfig(__dirname, { isCSSEnabled: true })<br><br>- module.exports = config;<br>+ module.exports = withNativeWind(config, { input: &#39;./global.css&#39; });</pre><p>Let’s modify our main App.tsx and replace everything with the following code.</p><p><strong>File:</strong> ./app/App.tsx</p><pre>// Imports<br>// ========================================================<br>import { StatusBar } from &#39;expo-status-bar&#39;;<br>import { Text, View } from &#39;react-native&#39;;<br>import &#39;../global.css&#39;;<br><br>// Main App Component<br>// ========================================================<br>export default function App() {<br>  return (<br>    &lt;View className=&quot;App&quot;&gt;<br>      &lt;StatusBar style=&quot;auto&quot; /&gt;<br>      &lt;Text className=&quot;H1&quot;&gt;Berachain WalletConnect Expo Example&lt;/Text&gt;<br>      &lt;Text className=&quot;Text&quot;&gt;Demonstrating how to build mobile dApps&lt;/Text&gt;<br>    &lt;/View&gt;<br>  );<br>};</pre><p>Run our app again and we should see the following.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CugFT4gkbKNyH9LZ9D9veA.png" /><figcaption>Berachain Mobile iOS dApp Working With Tailwind</figcaption></figure><p>Let’s also add an SVG logo to our app as a separate component.</p><pre># FROM: ./berachain-walletconnect-expo;<br><br>mkdir components;<br>mkdir components/Icons;<br>touch components/Icons/index.tsx;</pre><p>Add the following code to our new icons file.</p><p><strong>File:</strong> ./components/Icons/index.tsx</p><pre>// Imports<br>// ========================================================<br>import Svg, { Path } from &quot;react-native-svg&quot;;<br><br>// Icons<br>// ========================================================<br>export const Logo = ({ className = &#39;&#39;, width = 128, height = 128  }) =&gt; &lt;Svg className={className} width={width} height={height} viewBox=&quot;0 0 1024 1024&quot; fill=&quot;none&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;<br>  &lt;Path d=&quot;M477.298 474.489C476.946 472.605 476.506 470.802 475.801 469.084C476.066 468.675 534.55 392.929 480.381 346.092C426.299 299.252 363.145 360.339 362.793 360.667C352.751 357.718 342.622 355.918 332.581 355.099C332.581 355.099 332.581 355.099 332.493 355.099C311.882 351.906 282.99 355.099 282.99 355.099C273.037 355.918 262.996 357.718 253.042 360.585C252.69 360.258 189.536 299.17 135.454 346.01C81.3722 392.847 139.77 468.675 140.034 469.002C139.418 470.802 138.889 472.605 138.537 474.407C132.724 506.833 92.8228 516.823 92.8228 573.325C92.8228 630.891 134.485 676.256 219.572 676.256H254.452C254.628 676.42 268.106 694.27 295.938 695.335C295.938 695.335 302.369 695.99 317.165 695.499C346.673 695.499 361.031 676.583 361.12 676.338H395.999C481.085 676.338 522.748 630.972 522.748 573.407C523.012 516.987 483.111 506.915 477.298 474.489Z&quot; fill=&quot;#F9F4D5&quot; /&gt;<br>  &lt;Path d=&quot;M692.83 628.84V584.622C720.048 575.287 739.867 546.3 739.867 511.99C739.867 477.679 720.048 448.61 692.83 439.355V395.137C718.463 386.376 737.577 360.092 739.69 328.319H708.51V341.83C708.51 352.229 702.167 361.4 692.83 365.986V359.682C692.83 350.429 684.726 342.894 674.773 342.894H673.188C663.234 342.894 655.133 350.429 655.133 359.682V365.986C645.796 361.4 639.453 352.311 639.453 341.83V328.319H608.272C610.386 360.092 629.5 386.376 655.133 395.137V439.355C628.003 448.61 608.096 477.598 608.096 511.99C608.096 546.382 627.915 575.369 655.133 584.622V628.84C629.5 637.602 610.386 663.888 608.272 695.658H639.453V682.148C639.453 671.748 645.796 662.577 655.133 657.992V664.297C655.133 673.55 663.234 681.083 673.188 681.083H674.773C684.726 681.083 692.83 673.55 692.83 664.297V657.992C702.167 662.577 708.51 671.666 708.51 682.148V695.658H739.69C737.577 663.888 718.463 637.602 692.83 628.84ZM639.453 531.315V492.583C639.453 482.183 645.796 473.012 655.133 468.427V474.73C655.133 483.983 663.234 491.518 673.188 491.518H674.773C684.726 491.518 692.83 483.983 692.83 474.73V468.427C702.167 473.012 708.51 482.101 708.51 492.583V531.315C708.51 541.714 702.167 550.885 692.83 555.471V549.165C692.83 539.912 684.726 532.38 674.773 532.38H673.188C663.234 532.38 655.133 539.912 655.133 549.165V555.471C645.884 550.885 639.453 541.796 639.453 531.315Z&quot; fill=&quot;#F9F4D5&quot; /&gt;<br>  &lt;Path d=&quot;M884.142 535.49V488.407C911.358 479.07 931.176 450.083 931.176 415.773C931.176 381.462 911.358 352.393 884.142 343.14V328.319H846.53V343.14C819.315 352.475 799.496 381.462 799.496 415.773C799.496 450.083 819.315 479.152 846.53 488.407V535.49C819.315 544.825 799.496 573.813 799.496 608.123C799.496 642.433 819.315 671.502 846.53 680.755V695.576H884.142V680.755C911.358 671.42 931.176 642.433 931.176 608.123C931.176 573.813 911.358 544.825 884.142 535.49ZM830.765 435.097V396.366C830.765 385.966 837.106 376.795 846.442 372.21V378.515C846.442 387.768 854.546 395.301 864.5 395.301H865.997C875.95 395.301 884.054 387.768 884.054 378.515V372.21C893.391 376.795 899.731 385.884 899.731 396.366V435.097C899.731 445.497 893.391 454.668 884.054 459.254V452.95C884.054 443.697 875.95 436.162 865.997 436.162H864.412C854.458 436.162 846.354 443.697 846.354 452.95V459.254C837.194 454.668 830.765 445.579 830.765 435.097ZM899.819 627.53C899.819 637.929 893.479 647.1 884.142 651.686V642.433C884.142 633.18 876.038 625.648 866.085 625.648H864.588C854.634 625.648 846.53 633.18 846.53 642.433V651.686C837.194 647.1 830.853 638.011 830.853 627.53V588.798C830.853 578.398 837.194 569.227 846.53 564.642V567.998C846.53 577.253 854.634 584.786 864.588 584.786H866.173C876.126 584.786 884.23 577.253 884.23 567.998V564.642C893.567 569.227 899.907 578.316 899.907 588.798V627.53H899.819Z&quot; fill=&quot;#F9F4D5&quot; /&gt;<br>&lt;/Svg&gt;</pre><p>Next we just need to modify our main App.tsx file to include the logo.</p><p><strong>File:</strong> ./app/App.tsx</p><pre>// Imports<br>// ========================================================<br>import { StatusBar } from &#39;expo-status-bar&#39;;<br>import { Text, View } from &#39;react-native&#39;;<br>import &#39;../global.css&#39;;<br>+ import { Logo } from &#39;../components/Icons&#39;;<br><br>// Main App Component<br>// ========================================================<br>export default function App() {<br>  return (<br>    &lt;View className=&quot;App&quot;&gt;<br>      &lt;StatusBar style=&quot;auto&quot; /&gt;<br>+       &lt;Logo className=&quot;w-auto h-10 mx-auto&quot; /&gt;<br>      &lt;Text className=&quot;H1&quot;&gt;Berachain WalletConnect Expo Example&lt;/Text&gt;<br>      &lt;Text className=&quot;Text&quot;&gt;Demonstrating how to build mobile dApps&lt;/Text&gt;<br>    &lt;/View&gt;<br>  );<br>};</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LGEY-4XgDEgxhIolA1SJyw.png" /><figcaption>Berachain Mobile Web3 Expo App With Berachain Logo</figcaption></figure><h4>WalletConnect Web3Modal</h4><p>The next step we’re going to do is add WalletConnect’s Web3Modal support into our Expo app.</p><p>The first step will be to configure our environment variables.</p><blockquote><strong>Note:</strong> Make sure not to commit this to our git repository</blockquote><pre># FROM: ./berachain-walletconnect-expo;<br><br>touch .env;</pre><p>Add the following contents and remember to replace the WALLET_CONNECT_PROJECT_ID with the newly created project from WalletConnect Cloud directly.</p><p><strong>File:</strong> ./.env</p><pre># Expo Metadata<br>EXPO_PUBLIC_METADATA_NAME=&quot;Berachain WalletConnect Expo&quot;<br>EXPO_PUBLIC_METADATA_DESCRIPTION=&quot;Berachain WalletConnect Expo Example&quot;<br>EXPO_PUBLIC_METADATA_URL=&quot;https://berachain.com&quot;<br>EXPO_PUBLIC_METADATA_ICONS=&quot;https://avatars.githubusercontent.com/u/96059542&quot;<br>EXPO_PUBLIC_METADATA_REDIRECT_NAME=&quot;YOUR_APP_SCHEME://&quot;<br>EXPO_PUBLIC_METADATA_REDIRECT_UNIVERSAL=&quot;YOUR_APP_UNIVERSAL_LINK.com&quot;<br><br># WalletConnect - See https://cloud.walletconnect.com<br>EXPO_PUBLIC_WALLET_CONNECT_PROJECT_ID=&quot;YOUR_PROJECT_ID&quot;<br><br># Chain<br>EXPO_PUBLIC_CHAIN_ID=80085<br>EXPO_PUBLIC_CHAIN_NAME=&quot;berachainTestnet&quot;<br>EXPO_PUBLIC_CHAIN_NETWORK=&quot;Berachain&quot;<br>EXPO_PUBLIC_CHAIN_NATIVECURRENCY_DECIMALS=18<br>EXPO_PUBLIC_CHAIN_NATIVECURRENCY_NAME=&quot;Bera Token&quot;<br>EXPO_PUBLIC_CHAIN_NATIVECURRENCY_SYMBOL=&quot;BERA&quot;<br>EXPO_PUBLIC_CHAIN_RPC_URL=&quot;https://rpc.ankr.com/berachain_testnet&quot;<br>EXPO_PUBLIC_CHAIN_BLOCKEXPLORER_NAME=&quot;Beratrail&quot;<br>EXPO_PUBLIC_CHAIN_BLOCKEXPLORER_URL=&quot;https://artio.beratrail.io&quot;</pre><p>Now that we have this setup, we’re going wrap our main App.tsx with some of the configured providers from WalletConnect that adds its own configuration to the wagmi library.</p><pre># FROM: ./berachain-walletconnect-expo;<br><br>mkdir providers;<br>touch providers/index.tsx;<br>touch providers/wagmi.tsx;</pre><p>First up is configuring our wagmi provider. This will ensure that we can take advantage of all of wagmi’s hooks but also some default functionality built into WalletConnet Web3Modal.</p><p><strong>File:</strong> ./providers/wagmi.tsx</p><pre>// Imports<br>// ========================================================<br>import &quot;@walletconnect/react-native-compat&quot;;<br>import {<br>  createWeb3Modal,<br>  defaultWagmiConfig,<br>} from &quot;@web3modal/wagmi-react-native&quot;;<br>import { defineChain } from &quot;viem&quot;;<br>import { WagmiConfig } from &quot;wagmi&quot;;<br><br>// Config<br>// ========================================================<br>// 1. Get projectId at https://cloud.walletconnect.com<br>const projectId = `${process.env.EXPO_PUBLIC_WALLET_CONNECT_PROJECT_ID}`;<br><br>if (!projectId) throw Error(&#39;Error: Missing `EXPO_PUBLIC_WALLET_CONNECT_PROJECT_ID`.&#39;);<br><br>// 2. Create config for our app - defined by our env vars<br>const metadata = {<br>  name: `${process.env.EXPO_PUBLIC_METADATA_NAME}`,<br>  description: `${process.env.EXPO_PUBLIC_METADATA_DESCRIPTION}`,<br>  url: `${process.env.EXPO_PUBLIC_METADATA_URL}`,<br>  icons: [`${process.env.EXPO_PUBLIC_METADATA_ICONS}`],<br>  redirect: {<br>    native: `${process.env.EXPO_PUBLIC_METADATA_REDIRECT_NATIVE}`,<br>    universal: `${process.env.EXPO_PUBLIC_METADATA_REDIRECT_UNIVERSAL}`,<br>  },<br>};<br><br>// 3. Configure our custom chain - Note this is needed for wagmi and viem v1<br>/**<br> * @dev Custom chain configuration<br> */<br>const chainConfiguration = defineChain({<br> id: parseInt(`${process.env.EXPO_PUBLIC_CHAIN_ID}`),<br> name:`${process.env.EXPO_PUBLIC_CHAIN_NAME}`,<br> network: `${process.env.EXPO_PUBLIC_CHAIN_NETWORK}`,<br> nativeCurrency: {<br>  decimals: parseInt(`${process.env.EXPO_PUBLIC_CHAIN_NATIVECURRENCY_DECIMALS}`),<br>  name: `${process.env.EXPO_PUBLIC_CHAIN_NATIVECURRENCY_NAME}`,<br>  symbol:`${process.env.EXPO_PUBLIC_CHAIN_NATIVECURRENCY_SYMBOL}`,<br> },<br> rpcUrls: {<br>  default: {<br>   http: [`${process.env.EXPO_PUBLIC_CHAIN_RPC_URL}`],<br>  },<br>  public: {<br>   http: [`${process.env.EXPO_PUBLIC_CHAIN_RPC_URL}`],<br>  },<br> },<br> blockExplorers: {<br>  default: { <br>      name: `${process.env.EXPO_PUBLIC_CHAIN_BLOCKEXPLORER_NAME}`,<br>      url: `${process.env.EXPO_PUBLIC_CHAIN_BLOCKEXPLORER_URL}` <br>    },<br> },<br>});<br><br>/**<br> * @dev supported chains<br> */<br>const chains = [chainConfiguration];<br><br>/**<br> * <br> */<br>const wagmiConfig = defaultWagmiConfig({ chains, projectId, metadata });<br><br>// 4. Create modal configuration<br>createWeb3Modal({<br>  projectId,<br>  chains,<br>  wagmiConfig,<br>});<br><br>// Provider<br>// ========================================================<br>export default function Wagmi({ children }: { children: React.ReactNode }) {<br>  return &lt;WagmiConfig config={wagmiConfig}&gt;{children}&lt;/WagmiConfig&gt;<br>};</pre><p>Next, to keep things clean, we’ll modify our main provider file that will wrap our entire application. This helps to keep our App.tsx file clean, and allows us to add more providers easily with our main provider wrapper.</p><p><strong>File:</strong> ./providers/index.tsx</p><pre>// Imports<br>// ========================================================<br>import WagmiProvider from &quot;./wagmi&quot;;<br><br>// Root Provider<br>// ========================================================<br>export default function RootProvider({ children }: { children: React.ReactNode }) {<br>  return &lt;WagmiProvider&gt;{children}&lt;/WagmiProvider&gt;<br>};</pre><p>Then we’ll want this root provider to wrap our App.tsx and we’ll also add our web3modal button.</p><p><strong>File:</strong> ./app/App.tsx</p><pre>// Imports<br>// ========================================================<br>import { StatusBar } from &quot;expo-status-bar&quot;;<br>import { Text, View } from &quot;react-native&quot;;<br>import &quot;../global.css&quot;;<br>import { Logo } from &quot;../components/Icons&quot;;<br>+ import RootProvider from &quot;../providers&quot;;<br>+ import { Web3Modal } from &quot;@web3modal/wagmi-react-native&quot;;<br><br>// Main App Component<br>// ========================================================<br>export default function App() {<br> return (<br>+   &lt;RootProvider&gt;<br>   &lt;View className=&quot;App&quot;&gt;<br>    &lt;StatusBar style=&quot;auto&quot; /&gt;<br>+     &lt;Web3Modal /&gt;<br>    &lt;Logo className=&quot;w-auto h-10 mx-auto&quot; /&gt;<br>    &lt;Text className=&quot;H1&quot;&gt;Berachain WalletConnect Expo Example&lt;/Text&gt;<br>    &lt;Text className=&quot;Text&quot;&gt;Demonstrating how to build mobile dApps&lt;/Text&gt;<br>   &lt;/View&gt;<br>+   &lt;/RootProvider&gt;<br> );<br>}</pre><h4>Connect Button</h4><p>Now that the app fully supports WalletConnect, we can now add support for a connect button. We’re going to put this in a separate file to make it easier for us to modify by itself.</p><pre># FROM: ./berachain-walletconnect-expo;<br><br>mkdir components/Connect;<br>touch components/Connect/index.tsx;</pre><p><strong>File:</strong> ./components/Connect/index.tsx</p><pre>// Imports<br>// ========================================================<br>import { W3mButton } from &quot;@web3modal/wagmi-react-native&quot;;<br>import { View } from &quot;react-native&quot;;<br><br>// Component<br>// ========================================================<br>export default function Connect() {<br> return (<br>  &lt;View className=&quot;Connect&quot;&gt;<br>   {/* Customizing the web3modal button requires passing it certain props */}<br>   &lt;W3mButton<br>    connectStyle={{<br>     backgroundColor: &quot;#2E1E1A&quot;,<br>    }}<br>    accountStyle={{<br>     backgroundColor: &quot;#2E1E1A&quot;,<br>    }}<br>   /&gt;<br>  &lt;/View&gt;<br> );<br>}</pre><p>Let’s add this button to our App.tsx file.</p><pre>// Imports<br>// ========================================================<br>import { StatusBar } from &quot;expo-status-bar&quot;;<br>import { Text, View } from &quot;react-native&quot;;<br>import &quot;../global.css&quot;;<br>import { Logo } from &quot;../components/Icons&quot;;<br>+ import Connect from &quot;../components/Connect&quot;;<br>import RootProvider from &quot;../providers&quot;;<br>import { Web3Modal } from &quot;@web3modal/wagmi-react-native&quot;;<br><br><br>// Main App Component<br>// ========================================================<br>export default function App() {<br> return (<br>  &lt;RootProvider&gt;<br>   &lt;View className=&quot;App&quot;&gt;<br>    &lt;StatusBar style=&quot;auto&quot; /&gt;<br>        &lt;Web3Modal /&gt;<br>    &lt;Logo className=&quot;w-auto h-10 mx-auto&quot; /&gt;<br>    &lt;Text className=&quot;H1&quot;&gt;Berachain WalletConnect Expo Example&lt;/Text&gt;<br>    &lt;Text className=&quot;Text&quot;&gt;Demonstrating how to build mobile dApps&lt;/Text&gt;<br>+     &lt;Connect /&gt;<br>   &lt;/View&gt;<br>  &lt;/RootProvider&gt;<br> );<br>}</pre><p>We should now have a our connect button supported, but you’ll quickly notice there isn’t a way to connect with our wallet on our mobile because MetaMask isn’t installed on Simulator.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qIHqpfVTMBSi4Iq31RNE0A.png" /><figcaption>Berachain WalletConnect Web3Modal Working</figcaption></figure><p>When you click the <strong><em>Connect</em></strong> button, we’ll see that there are zero wallets available.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2o5Qp47Oycxj8gX7StuaKA.png" /><figcaption>Berachain WalletConnect Web3Modal Cannot Connect To Wallet On Simulator</figcaption></figure><p>This is the part where we can take advantage of <a href="https://expo.dev/expo-go"><strong><em>Expo Go</em></strong></a> on our phone to connect with our existing wallets.</p><blockquote><strong>Note:</strong> Make sure that you have MetaMask Mobile installed on your phone and <a href="https://docs.berachain.com/developers/"><strong>configure your MetaMask mobile to have a new network with Berachain</strong></a>.</blockquote><p>If you notice when we run pnpm ios a QR code shows up. We should be able to use that with the <strong><em>Expo Go app</em></strong> to load the app directly into our phone.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-4QEz6MKbGhth38zFLna5A.png" /><figcaption>Warp Terminal Running Expo With QR Code</figcaption></figure><p>Now when we use our iPhone’s camera, we can connect and open up our app in Expo Go.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_TsWVHCZyWB1d43MR_siTg.png" /><figcaption>Connecting To Expo Go On With Your iPhone</figcaption></figure><p>When the app loads on our phone, we should be able to tap <strong><em>Connect</em></strong>, be presented with <strong><em>MetaMask</em></strong> as an option, select <strong><em>MetaMask</em></strong>, confirm our connection via the <strong><em>MetaMask</em></strong> app, and then be pushed back to the app to confirm that we’re connected.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rvgJSgtipb1Lt3E4hIjlsQ.jpeg" /><figcaption>Berachain Expo WalletConnect Successfully Connecting To MetaMask</figcaption></figure><h4>Display $BERA Balance</h4><p>Now that we have successfully connected our account with MetaMask, let’s add a basic component that displays our current balance on Berachain.</p><blockquote><strong>Note:</strong> Make sure to switch your MetaMask wallet to the Berachain Artio Testnet Network before hand.</blockquote><p>Our component will check if the account is already connected and the make a request to show the current balance.</p><pre># FROM: ./berachain-walletconnect-expo;<br><br>mkdir components/Balance;<br>touch components/Balance/index.tsx;</pre><p>Let’s add the following code for our new Balance component.</p><p><strong>File:</strong> ./components/Balance/index.tsx</p><pre>// Imports<br>// ========================================================<br>import { View, Text } from &quot;react-native&quot;;<br>import { useAccount, useBalance } from &quot;wagmi&quot;;<br><br>// Component<br>// ========================================================<br>export default function Balance() {<br>  // Hooks<br>  const { isConnected, address } = useAccount();<br>  const { data, isError, isLoading } = useBalance({<br>    address<br>  });<br><br>  // Return<br>  /**<br>   * If still loading, show a loading state<br>   */<br>  if (isLoading)<br>    return &lt;Text className=&quot;Text&quot;&gt;Fetching balance...&lt;/Text&gt;;<br><br><br>  /**<br>   * Show error if having a problem fetching the balance<br>   */<br>  if (isError)<br>    return (<br>      &lt;Text className=&quot;mText&quot;&gt;Error fetching balance&lt;/Text&gt;<br>    );<br><br>  /**<br>   * If not connected don&#39;t show anything<br>   */<br>  if (!isConnected) return null;<br><br><br>  /**<br>   * Successfully connected<br>   */<br>  return (<br>    &lt;View className=&quot;Balance&quot;&gt;<br>      &lt;Text className=&quot;Text&quot;&gt;Balance&lt;/Text&gt;<br>      &lt;Text className=&quot;Code&quot;&gt;{(parseInt((data?.value ?? &#39;&#39;).toString()) / 1000000000000000000).toFixed(2)} $BERA&lt;/Text&gt;<br>    &lt;/View&gt;<br>  );<br>}</pre><p>Then we’ll add the Balance component to our App.tsx.</p><p><strong>File:</strong> ./app/App.tsx</p><pre>// Imports<br>// ========================================================<br>import { StatusBar } from &quot;expo-status-bar&quot;;<br>import { Text, View } from &quot;react-native&quot;;<br>import &quot;../global.css&quot;;<br>import { Logo } from &quot;../components/Icons&quot;;<br>import Connect from &quot;../components/Connect&quot;;<br>+ import Balance from &quot;../components/Balance&quot;;<br>import RootProvider from &quot;../providers&quot;;<br>import { Web3Modal } from &quot;@web3modal/wagmi-react-native&quot;;<br><br>// Main App Component<br>// ========================================================<br>export default function App() {<br> return (<br>  &lt;RootProvider&gt;<br>   &lt;View className=&quot;App&quot;&gt;<br>    &lt;StatusBar style=&quot;auto&quot; /&gt;<br>        &lt;Web3Modal /&gt;<br>    &lt;Logo className=&quot;w-auto h-10 mx-auto&quot; /&gt;<br>    &lt;Text className=&quot;H1&quot;&gt;Berachain WalletConnect Expo Example&lt;/Text&gt;<br>    &lt;Text className=&quot;Text&quot;&gt;Demonstrating how to build mobile dApps&lt;/Text&gt;<br>    &lt;Connect /&gt;<br>+     &lt;Balance /&gt;<br>   &lt;/View&gt;<br>  &lt;/RootProvider&gt;<br> );<br>}</pre><p>Now when we connect with MetaMask, we should see our $BERA balance.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*L2yseYuEUWVhiLkWXlelRQ.jpeg" /><figcaption>Berachain WalletConnect Expo Showing $BERA Balance Functionality</figcaption></figure><h4>Wallet Sign Message</h4><p>On top of every basic RPC request, we also want to get some basic wallet interactions going. The simplest version would be signing a message with your MetaMask wallet and getting a signature.</p><p>We’re going to build an input that accepts a message, prompts the user’s MetaMask wallet to sign the message, and output the signature.</p><p>We’ll first create the file.</p><pre># FROM: ./berachain-walletconnect-expo;<br><br>mkdir components/SignMessage;<br>touch components/SignMessage/index.tsx;</pre><p>Add the functionality to it.</p><p><strong>File:</strong> ./components/SignMessage/index.tsx</p><pre>// Imports<br>// ========================================================<br>import { useState } from &quot;react&quot;;<br>import { View, Pressable, Text, TextInput } from &quot;react-native&quot;;<br>import { useAccount, useSignMessage } from &quot;wagmi&quot;;<br><br>// Component<br>// ========================================================<br>export default function SignMessage() {<br> // Hooks<br> const [message, setMessage] = useState(&quot;&quot;);<br> const [signature, setSignature] = useState(&quot;(Signature will show up here)&quot;);<br> const [error, setError] = useState(&quot;&quot;);<br> const { isConnected, address } = useAccount();<br> const { signMessageAsync } = useSignMessage();<br><br> // Functions<br>  /**<br>   * @dev Handles signing message<br>   */<br> const onPressSignMessage = async () =&gt; {<br>  console.group(&quot;onPressSignMessage&quot;);<br>  setError(&quot;&quot;);<br><br>  try {<br>   const signature = await signMessageAsync({<br>    message,<br>   });<br>   setSignature(signature);<br>  } catch (error: unknown) {<br>   console.error({ error });<br>   setError(&quot;Error signing message.&quot;);<br>  }<br>  console.groupEnd();<br> };<br><br> // Return<br>  /**<br>   * If not connected and no address, then don&#39;t show anything<br>   */<br> if (!isConnected || !address) return null;<br><br> return (<br>  &lt;View className=&quot;SignMessage&quot;&gt;<br>   &lt;Text className=&quot;Text&quot;&gt;Sign Message&lt;/Text&gt;<br>   &lt;TextInput<br>    className=&quot;TextInput&quot;<br>    placeholder=&quot;Message to sign&quot;<br>    onChangeText={setMessage}<br>    value={message}<br>   /&gt;<br>   &lt;Text className=&quot;Text&quot;&gt;Signature Generated&lt;/Text&gt;<br>   &lt;Text<br>    className=&quot;Code&quot;<br>   &gt;{signature}&lt;/Text&gt;<br>   &lt;Pressable<br>    className=&quot;Button&quot;<br>    onPress={onPressSignMessage}<br>   &gt;<br>    &lt;Text className=&quot;text-white text-base&quot;&gt;Sign Message&lt;/Text&gt;<br>   &lt;/Pressable&gt;<br><br>   {error ? (<br>    &lt;Text className=&quot;TextError&quot;&gt;<br>     {error}<br>    &lt;/Text&gt;<br>   ) : null}<br>  &lt;/View&gt;<br> );<br>}</pre><p>We’ll add the Sign Message functionality to our App.tsx.</p><p><strong>File:</strong> ./app/App.tsx</p><pre>// Imports<br>// ========================================================<br>import { StatusBar } from &quot;expo-status-bar&quot;;<br>import { Text, View } from &quot;react-native&quot;;<br>import &quot;../global.css&quot;;<br>import { Logo } from &quot;../components/Icons&quot;;<br>import Connect from &quot;../components/Connect&quot;;<br>import Balance from &quot;../components/Balance&quot;;<br>+ import SignMessage from &quot;../components/SignMessage&quot;;<br>import RootProvider from &quot;../providers&quot;;<br>import { Web3Modal } from &quot;@web3modal/wagmi-react-native&quot;;<br><br>// Main App Component<br>// ========================================================<br>export default function App() {<br> return (<br>  &lt;RootProvider&gt;<br>   &lt;View className=&quot;App&quot;&gt;<br>    &lt;StatusBar style=&quot;auto&quot; /&gt;<br>        &lt;Web3Modal /&gt;<br>    &lt;Logo className=&quot;w-auto h-10 mx-auto&quot; /&gt;<br>    &lt;Text className=&quot;H1&quot;&gt;Berachain WalletConnect Expo Example&lt;/Text&gt;<br>    &lt;Text className=&quot;Text&quot;&gt;Demonstrating how to build mobile dApps&lt;/Text&gt;<br>    &lt;Connect /&gt;<br>    &lt;Balance /&gt;<br>+     &lt;SignMessage /&gt;<br>   &lt;/View&gt;<br>  &lt;/RootProvider&gt;<br> );<br>}</pre><p>We should now see the functionality of inputting a message, prompting our wallet to sign the message, and seeing the generated signature.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tNMgE-k0qWAdQ_hjgQ68jg.jpeg" /><figcaption>Berachain WalletConnect Wallet Signature Working With Ooga Booga</figcaption></figure><h4>Deploy Contract</h4><p>The last piece of functionality I want to add to this app is the ability to deploy a contract’s bytecode directly from the mobile app itself. This would essentially prompt our wallet to initiate a transaction that would deploy a contract to Berachain.</p><p>To start, let’s create a new Deploy component.</p><pre># FROM: ./berachain-walletconnect-expo;<br><br>mkdir components/Deploy;<br>touch components/Deploy/index.tsx;</pre><p>We’ll add the following functionality to our Deploy component.</p><p><strong>File:</strong> ./components/Deploy/index.tsx</p><pre>// Imports<br>// ========================================================<br>import { useState } from &quot;react&quot;;<br>import { Pressable, Text } from &quot;react-native&quot;;<br>import { useAccount, useWaitForTransaction } from &quot;wagmi&quot;;<br>import { encodeAbiParameters } from &quot;viem&quot;;<br>import { openURL } from &quot;expo-linking&quot;;<br><br>// Constants<br>// ========================================================<br>/**<br> * @dev ByteCode for HelloWorld Contract see https://github.com/berachain/guides/blob/main/apps/hardhat-viem-helloworld/contracts/HelloWorld.sol<br> */<br>const CONTRACT_BYTECODE =<br>  &quot;0x60806040523480156200001157600080fd5b5060405162000da238038062000da283398181016040528101906200003791906200021e565b8060009081620000489190620004ba565b507fcbc299eeb7a1a982d3674880645107c4fe48c3227163794e48540a752272235433826040516200007c92919062000638565b60405180910390a1506200066c565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620000f482620000a9565b810181811067ffffffffffffffff82111715620001165762000115620000ba565b5b80604052505050565b60006200012b6200008b565b9050620001398282620000e9565b919050565b600067ffffffffffffffff8211156200015c576200015b620000ba565b5b6200016782620000a9565b9050602081019050919050565b60005b838110156200019457808201518184015260208101905062000177565b60008484015250505050565b6000620001b7620001b1846200013e565b6200011f565b905082815260208101848484011115620001d657620001d5620000a4565b5b620001e384828562000174565b509392505050565b600082601f8301126200020357620002026200009f565b5b815162000215848260208601620001a0565b91505092915050565b60006020828403121562000237576200023662000095565b5b600082015167ffffffffffffffff8111156200025857620002576200009a565b5b6200026684828501620001eb565b91505092915050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620002c257607f821691505b602082108103620002d857620002d76200027a565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620003427fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000303565b6200034e868362000303565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b60006200039b620003956200038f8462000366565b62000370565b62000366565b9050919050565b6000819050919050565b620003b7836200037a565b620003cf620003c682620003a2565b84845462000310565b825550505050565b600090565b620003e6620003d7565b620003f3818484620003ac565b505050565b5b818110156200041b576200040f600082620003dc565b600181019050620003f9565b5050565b601f8211156200046a576200043481620002de565b6200043f84620002f3565b810160208510156200044f578190505b620004676200045e85620002f3565b830182620003f8565b50505b505050565b600082821c905092915050565b60006200048f600019846008026200046f565b1980831691505092915050565b6000620004aa83836200047c565b9150826002028217905092915050565b620004c5826200026f565b67ffffffffffffffff811115620004e157620004e0620000ba565b5b620004ed8254620002a9565b620004fa8282856200041f565b600060209050601f8311600181146200053257600084156200051d578287015190505b6200052985826200049c565b86555062000599565b601f1984166200054286620002de565b60005b828110156200056c5784890151825560018201915060208501945060208101905062000545565b868310156200058c578489015162000588601f8916826200047c565b8355505b6001600288020188555050505b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620005ce82620005a1565b9050919050565b620005e081620005c1565b82525050565b600082825260208201905092915050565b600062000604826200026f565b620006108185620005e6565b93506200062281856020860162000174565b6200062d81620000a9565b840191505092915050565b60006040820190506200064f6000830185620005d5565b8181036020830152620006638184620005f7565b90509392505050565b610726806200067c6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063fe50cc7214610057575b600080fd5b610055600480360381019061005091906102ad565b610075565b005b61005f6100c1565b60405161006c9190610375565b60405180910390f35b806000908161008491906105ad565b507fcbc299eeb7a1a982d3674880645107c4fe48c3227163794e48540a752272235433826040516100b69291906106c0565b60405180910390a150565b6060600080546100d0906103c6565b80601f01602080910402602001604051908101604052809291908181526020018280546100fc906103c6565b80156101495780601f1061011e57610100808354040283529160200191610149565b820191906000526020600020905b81548152906001019060200180831161012c57829003601f168201915b5050505050905090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6101ba82610171565b810181811067ffffffffffffffff821117156101d9576101d8610182565b5b80604052505050565b60006101ec610153565b90506101f882826101b1565b919050565b600067ffffffffffffffff82111561021857610217610182565b5b61022182610171565b9050602081019050919050565b82818337600083830152505050565b600061025061024b846101fd565b6101e2565b90508281526020810184848401111561026c5761026b61016c565b5b61027784828561022e565b509392505050565b600082601f83011261029457610293610167565b5b81356102a484826020860161023d565b91505092915050565b6000602082840312156102c3576102c261015d565b5b600082013567ffffffffffffffff8111156102e1576102e0610162565b5b6102ed8482850161027f565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610330578082015181840152602081019050610315565b60008484015250505050565b6000610347826102f6565b6103518185610301565b9350610361818560208601610312565b61036a81610171565b840191505092915050565b6000602082019050818103600083015261038f818461033c565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806103de57607f821691505b6020821081036103f1576103f0610397565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026104597fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261041c565b610463868361041c565b95508019841693508086168417925050509392505050565b6000819050919050565b6000819050919050565b60006104aa6104a56104a08461047b565b610485565b61047b565b9050919050565b6000819050919050565b6104c48361048f565b6104d86104d0826104b1565b848454610429565b825550505050565b600090565b6104ed6104e0565b6104f88184846104bb565b505050565b5b8181101561051c576105116000826104e5565b6001810190506104fe565b5050565b601f82111561056157610532816103f7565b61053b8461040c565b8101602085101561054a578190505b61055e6105568561040c565b8301826104fd565b50505b505050565b600082821c905092915050565b600061058460001984600802610566565b1980831691505092915050565b600061059d8383610573565b9150826002028217905092915050565b6105b6826102f6565b67ffffffffffffffff8111156105cf576105ce610182565b5b6105d982546103c6565b6105e4828285610520565b600060209050601f8311600181146106175760008415610605578287015190505b61060f8582610591565b865550610677565b601f198416610625866103f7565b60005b8281101561064d57848901518255600182019150602085019450602081019050610628565b8683101561066a5784890151610666601f891682610573565b8355505b6001600288020188555050505b505050505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006106aa8261067f565b9050919050565b6106ba8161069f565b82525050565b60006040820190506106d560008301856106b1565b81810360208301526106e7818461033c565b9050939250505056fea264697066735822122051a137f3f2f370792efdafdfd52aa1721451dfaa2e804a5236730d97a26f237664736f6c63430008110033&quot;;<br><br><br>// Component<br>// ========================================================<br>export default function Deploy() {<br>  // Hooks<br>  const [isLoading, setIsLoading] = useState(false);<br>  const [error, setError] = useState(&#39;&#39;);<br>  const [transactionHash, setTransactionHash] = useState&lt;`0x${string}` | undefined&gt;();<br>  const { isConnected, address, connector } = useAccount();<br><br>  // Functions<br>  /**<br>   * @dev hook that waits for a transaction hash<br>   */<br>  const txResult = useWaitForTransaction({<br>    hash: transactionHash<br>  });<br><br>  /**<br>   * @dev handles deploying the contract<br>   */<br>  const onPressDeployContract = async () =&gt; {<br>    console.group(&#39;onPressDeployContract&#39;);<br>    setError(&#39;&#39;);<br>    setIsLoading(true);<br>    try {<br>      const provider = await connector?.getProvider(); // get&#39;s the provider from wagmi directly - needed for the walletconnection<br>      console.log({ provider });<br>      console.log({ request: provider?.request });<br><br>      // Based on constructor - constructor(string memory _greeting) {<br>      // encodes the function name and the input of `Hello World!`<br>      const encodedData = encodeAbiParameters(<br>        [{ name: &quot;_greeting&quot;, type: &quot;string&quot; }],<br>        [&quot;Hello World!&quot;]<br>      );<br><br>      // Need slide(2) to remove 0x from encodedData at the beginning<br>      const fullByteCode = `${CONTRACT_BYTECODE}${encodedData.slice(2)}`;<br><br>      // Send eth transsaction<br>      const tx = await provider.request({<br>        method: &quot;eth_sendTransaction&quot;,<br>        params: [<br>          {<br>            from: address,<br>            data: fullByteCode,<br>          },<br>        ],<br>      });<br>      console.log({ tx });<br><br>      // Set the state transaction hash for `useWaitForTransaction` to wait for it<br>      setTransactionHash(tx);<br>    } catch (error: unknown) {<br>      console.error(error);<br>      setError(&#39;Error could not deploy contract.&#39;)<br>    }<br>    setIsLoading(false);<br><br>    console.groupEnd();<br>  };<br><br>  /**<br>   * @dev function that handles opening url to the final transaction hash in a block explorer<br>   */<br>  const onPressSeeTransaction = () =&gt; {<br>    openURL(`${process.env.EXPO_PUBLIC_CHAIN_BLOCKEXPLORER_URL}/tx/${txResult?.data?.transactionHash}`);<br>  };<br><br>  /**<br>   * If not connected and no address, then don&#39;t show anything<br>   */<br>  if (!isConnected || !address) return null;<br><br>  return (<br>    &lt;&gt;<br>      &lt;Text className=&quot;Text&quot;&gt;Deploy Contract&lt;/Text&gt;<br>      &lt;Pressable<br>        disabled={isLoading}<br>        className={&quot;Button&quot;}<br>        onPress={onPressDeployContract}&gt;<br>        &lt;Text className=&quot;text-white text-base&quot;&gt;<br>          Deploy<br>        &lt;/Text&gt;<br>      &lt;/Pressable&gt;<br><br>      {isLoading &amp;&amp; &lt;Text className=&quot;Code&quot;&gt;Loading...&lt;/Text&gt;}<br><br>      {!isLoading &amp;&amp; txResult?.data?.transactionHash<br>        ? &lt;Pressable<br>          className=&quot;Button&quot;<br>          onPress={onPressSeeTransaction}&gt;<br>          &lt;Text className=&quot;text-white text-base&quot;&gt;<br>            See Successful Transaction<br>          &lt;/Text&gt;<br>        &lt;/Pressable&gt;<br>        : null}<br>      {error ? &lt;Text className=&quot;TextError&quot;&gt;{error}&lt;/Text&gt; : null}<br>    &lt;/&gt;<br>  );<br>}</pre><p>Now if we go through the process, we should be able to tap Deploy, be prompted by our wallet to confirm the transaction, wait for the transaction to complete and see the transaction on the block explorer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zFD4Ba_Op3wnGEzndlzpxQ.jpeg" /><figcaption>Berachain WalletConnect Successfully Deployed Contract</figcaption></figure><h3>🐻 Full Code Repository</h3><p>If you want to see the final code and see other guides, check out <a href="https://github.com/berachain/guides/tree/main/apps/walletconnect-expo"><strong><em>Berachain WalletConnect Expo Guide Code</em></strong></a>.</p><p><a href="https://github.com/berachain/guides/tree/main/apps/walletconnect-expo">guides/apps/walletconnect-expo at main · berachain/guides</a></p><h3>🛠️ Want To Build More?</h3><p>Want to build more on Berachain and see more examples. Take a look at our <a href="https://github.com/berachain/guides"><strong><em>Berachain GitHub Guides Repo</em></strong></a> for a wide variety of implementations that include NextJS, Hardhat, Viem, Foundry, and more.</p><p><a href="https://github.com/berachain/guides">GitHub - berachain/guides: A demonstration of different contracts, languages, and libraries that work with Berachain EVM.</a></p><p>If you’re looking to dive deeper into the details, take a look at our <a href="https://docs.berachain.com/"><strong><em>Berachain Docs</em></strong></a>.</p><p><a href="https://docs.berachain.com/">Berachain Docs</a></p><h4>Looking For Dev Support?</h4><p>Make sure to join our <a href="https://discord.com/invite/berachain"><strong><em>Berachain Discord</em></strong></a> server and check out our developer channels to ask questions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*1aH5owNqr3WwIh4sGfk9Gw.png" /><figcaption><a href="https://discord.com/invite/berachain">https://discord.com/invite/berachain</a></figcaption></figure><p><a href="https://discord.com/invite/berachain">Join the Berachain Discord Server!</a></p><p>❤️ Don’t forget to show some love for this article 👏🏼.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c5cde75dbac2" width="1" height="1" alt=""><hr><p><a href="https://medium.com/berachain-devs/build-a-berachain-mobile-dapp-with-walletconnect-expo-c5cde75dbac2">Build A Berachain Mobile dApp With WalletConnect &amp; Expo</a> was originally published in <a href="https://medium.com/berachain-devs">berachain-devs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>