<?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"><channel><title><![CDATA[Blog | Idris Olubisi]]></title><description><![CDATA[Articles written by Idris Olubisi]]></description><link>https://blog.idrisolubisi.com</link><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 21:14:01 GMT</lastBuildDate><atom:link href="https://blog.idrisolubisi.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Building Your First Token: A Solidity Speedrun]]></title><description><![CDATA[Every developer usually starts with a simple program: “Hello, World!” It’s that first step where you test if everything’s working. It doesn’t do much, but it proves your setup is good and your code can run. In blockchain, “Hello World” looks a little...]]></description><link>https://blog.idrisolubisi.com/building-your-first-token-a-solidity-speedrun</link><guid isPermaLink="true">https://blog.idrisolubisi.com/building-your-first-token-a-solidity-speedrun</guid><category><![CDATA[Web3]]></category><category><![CDATA[Solidity]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Fri, 01 Aug 2025 15:47:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/OBP4nCbDjIQ/upload/3a3294d96a4700cf5f10963d272084e8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Every developer usually starts with a simple program: <strong>“Hello, World!”</strong> It’s that first step where you test if everything’s working. It doesn’t do much, but it proves your setup is good and your code can run. In blockchain, “Hello World” looks a little different. It’s not just printing a message. It’s writing and deploying your first <a target="_blank" href="https://docs.openzeppelin.com/contracts/4.x/erc20"><strong>token contract</strong></a>.</p>
<p>If you've written JavaScript or Python, you already have the mental models needed for <a target="_blank" href="https://soliditylang.org/">Solidity</a>. The syntax will feel familiar, but the environment is completely different. Every line of code incurs a cost to execute. Every variable is permanently stored on thousands of computers worldwide. And once deployed, your code is immutable - bugs become features forever.</p>
<p>It might sound intimidating at first, but once you understand the fundamentals, it becomes much more approachable.</p>
<p>By the end of this tutorial, you'll understand <em>how</em> to write a token contract and <em>why</em> each piece works the way it does. We'll build a simplified <a target="_blank" href="https://docs.openzeppelin.com/contracts/4.x/erc20">ERC20</a> token that could be deployed on <a target="_blank" href="https://ethereum.org/en/">Ethereum</a>, <a target="_blank" href="https://www.monad.xyz/">Monad</a>, or any EVM-compatible chain. </p>
<h2 id="heading-setting-up-your-first-smart-contract">Setting Up Your First Smart Contract</h2>
<p>A smart contract is like a vending machine; it holds value, has rules, and executes automatically. The contract we're building today will create and manage tokens that could represent anything: loyalty points at your local coffee shop, shares in an investment fund, or coins in a game economy.</p>
<p>Before we can build this digital vending machine, we need a workspace. That's where Remix IDE comes in; think of it as your contract workshop.</p>
<p>We'll use <a target="_blank" href="http://remix.ethereum.org/">Remix IDE</a>, a powerful, web-based development environment for Solidity, to keep things simple and get you writing code right away. There's no need to install anything; open it in a new tab, and you'll be ready.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_073E6FABE28364727B32A35D952A635B963595143EDC69E737E3D092380C379B_1751467102047_Screenshot+2025-07-02+at+15.35.50.png" alt="Remix IDE Interface" /></p>
<p>Once Remix loads: </p>
<ol>
<li><p>Look for the contracts folder in the file explorer (left sidebar).</p>
</li>
<li><p>Right-click the file icon and create a new file called MyToken.sol.</p>
</li>
<li><p>Click on your new file to open it.</p>
</li>
</ol>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_073E6FABE28364727B32A35D952A635B963595143EDC69E737E3D092380C379B_1751467109683_Screenshot+2025-07-02+at+15.36.50.png" alt="Create a new file on Remix - MyToken.sol" /></p>
<p>Next, create the basic structure of your token.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>

<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.20;</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MyToken</span> </span>{
    <span class="hljs-comment">// Token Implementation here!</span>
}
</code></pre>
<p>That might look like a lot at first glance, but let’s break it down step-by-step:</p>
<ul>
<li><p><code>// SPDX-License-Identifier: MIT</code>: This comment specifies the contract's license. Including the comment is a best practice and helps build trust in the open-source community.</p>
</li>
<li><p><code>pragma solidity ^0.8.20;</code>: This line tells the compiler which version of Solidity to use. The ^ means it will accept version 0.8.20 or any newer <em>minor</em> version (like 0.8.21) but not major updates that could break compatibility (like 0.9.0).</p>
</li>
<li><p><code>contract MyToken { ... }</code>: This declares our contract. If you come from an object-oriented language like Python or JavaScript, you can think of a contract as a class. It's a blueprint for the logic and data that will live on the blockchain.</p>
</li>
</ul>
<p><strong>Giving Your Token an Identity</strong></p>
<p>Now, let's define what makes our token unique. Just like how the US Dollar has a name ("Dollar"), symbol ("$"), and can be divided into cents, our token needs these fundamental properties:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>

<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.20;</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MyToken</span> </span>{

    <span class="hljs-comment">// Token metadata - this is what makes your token unique</span>

    <span class="hljs-keyword">string</span> <span class="hljs-keyword">public</span> name <span class="hljs-operator">=</span> <span class="hljs-string">"MyToken"</span>;
    <span class="hljs-keyword">string</span> <span class="hljs-keyword">public</span> symbol <span class="hljs-operator">=</span> <span class="hljs-string">"MTK"</span>;
    <span class="hljs-keyword">uint8</span> <span class="hljs-keyword">public</span> decimals <span class="hljs-operator">=</span> <span class="hljs-number">18</span>; <span class="hljs-comment">// Standard for most tokens</span>
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> totalSupply; <span class="hljs-comment">// How many tokens exist in total</span>
}
</code></pre>
<p>In the code snippet above, we've just introduced a few core concepts:</p>
<ul>
<li><p><strong>State Variables</strong>: These variables (name, symbol, decimals, totalSupply) are stored permanently on the blockchain. Think of them as the properties of a class instance.</p>
</li>
<li><p><strong>Data Types</strong>: We're using string for text, uint8 for an 8-bit unsigned integer (perfect for decimals), and uint256for a 256-bit unsigned integer, the standard for token amounts.</p>
</li>
<li><p><strong>Visibility (public)</strong>: Marking a state variable as public has a significant impact. The Solidity compiler automatically creates a "getter" function for it. This means anyone can read its value from the blockchain for free. This is our first look at a <strong>view-only function</strong>.</p>
</li>
</ul>
<p>Now we have a token with an identity, but we're missing the most important part - a way to track who owns what. Let's build the ledger that makes this a real token.</p>
<h2 id="heading-the-token-ledger-who-owns-what">The Token Ledger: Who Owns What?</h2>
<p>At its core, a token contract has one fundamental job: answering the question, <strong>"How many tokens does this address have?"</strong> To keep track of this, we need a ledger. In traditional systems, a bank’s database manages account balances. In Solidity, the ideal tool for this job is a mapping.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MyToken</span> </span>{

    <span class="hljs-comment">// ... inside contract MyToken</span>

    <span class="hljs-comment">// A mapping from an address to their token balance.</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint256</span>) <span class="hljs-keyword">public</span> balances;
}
</code></pre>
<p>A mapping in Solidity is like a hash map or dictionary you might know from other programming languages. This particular mapping, called balances, links an address to a uint256 value. Think of it as a super-efficient dictionary: you give it an address, and it instantly tells you the token balance for that address. No searching or sorting needed; just instant lookups.</p>
<ul>
<li><p><code>address</code>: This is a special data type that holds a 20-byte Ethereum address. It's the unique identifier for a user's wallet or another smart contract.</p>
</li>
<li><p><code>balances[someAddress]</code>: When you query this, it returns the token balance for someAddress. If that address has never received tokens before, the balance defaults to 0.</p>
</li>
</ul>
<p>For example: </p>
<pre><code class="lang-solidity">balances[<span class="hljs-number">0x123</span>...] <span class="hljs-operator">=</span> <span class="hljs-number">1000</span>;  <span class="hljs-comment">// This address has 1000 tokens</span>

balances[<span class="hljs-number">0x456</span>...] <span class="hljs-operator">=</span> <span class="hljs-number">500</span>;   <span class="hljs-comment">// This one has 500</span>
</code></pre>
<p>Since we marked the balances mapping as public, we automatically get a <a target="_blank" href="https://docs.soliditylang.org/en/latest/contracts.html#getter-functions">getter function</a>. We can now create a more explicit balanceOf function that matches the <a target="_blank" href="https://docs.openzeppelin.com/contracts/4.x/erc20">ERC20 standard</a>.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// ... inside contract MyToken</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">balanceOf</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
    <span class="hljs-keyword">return</span> balances[account];
}
</code></pre>
<p>Notice the <strong>view</strong> keyword. This explicitly tells the <a target="_blank" href="https://ethereum.org/en/developers/docs/evm/">Ethereum Virtual Machine (EVM)</a> that this function only <em>reads</em> from the blockchain state and doesn't modify it. Calling view functions is free from the outside world because they don't require a transaction to be mined.</p>
<p>Perfect! We can track balances, but everyone's balance is zero. Time to create some tokens.</p>
<h2 id="heading-creating-tokens">Creating Tokens</h2>
<p>Currently, our token exists, but nobody currently holds any. It's like opening a bank with no money. Let's fix that by creating a minting function that can allow users to mint tokens:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MyToken</span> </span>{

    <span class="hljs-comment">// Previous code...</span>

    <span class="hljs-comment">// The address that deployed this contract (the creator)</span>
    <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> owner;

    <span class="hljs-comment">// This special function runs ONCE when the contract is deployed</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) </span>{
        owner <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>; <span class="hljs-comment">// Crown yourself as the owner!</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-comment">// Only the owner can create new tokens</span>
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> owner, <span class="hljs-string">"Nice try! Only the owner can mint."</span>);

        totalSupply <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount; <span class="hljs-comment">// Increase total supply</span>
        balances[to] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount; <span class="hljs-comment">// Give tokens to the recipient</span>
    }
}
</code></pre>
<p>Whoa, a lot just happened. Let's unpack it.</p>
<p> <code>msg.sender</code> is a global variable available in every function. It always contains the address of whoever called this function. It's unfakeable, unhackable, and always reliable, and it's how your contract identifies who is talking to it. Think of it as a caller ID that works.</p>
<p>In our constructor, we're using it to remember who deployed the contract. That person becomes the owner, the only one allowed to mint new tokens.</p>
<p>As you explore Solidity, you'll encounter tx.origin, a variable that seems helpful but hides a dangerous flaw. Let's explore why <code>msg.sender</code> is always the right choice:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// Dont do this</span>
<span class="hljs-built_in">require</span>(<span class="hljs-built_in">tx</span>.<span class="hljs-built_in">origin</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> owner, <span class="hljs-string">"Only owner"</span>);

<span class="hljs-comment">// Do this instead</span>
<span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> owner, <span class="hljs-string">"Only owner"</span>);
</code></pre>
<p>For example, using <code>tx.origin</code> for authorization is dangerous because it can make your contract vulnerable to phishing-style attacks. If User A calls <code>MaliciousContract</code> B, which then calls <code>YourContract C</code>, <code>msg.sender</code> in C will be B's address, but <code>tx.origin</code> will be User A's address.</p>
<p>If you authorize based on <code>tx.origin</code>, <code>MaliciousContract</code> B could trick User A into triggering an action on your contract that they never intended. Always use msg.sender for authorization.</p>
<p>Now our token can be minted, but there’s still a problem. How does the outside world know when tokens are created? </p>
<p>This touches on a core blockchain principle: transparency through observation. Unlike traditional systems where a server pushes updates to clients, blockchain works on a "pull" model. </p>
<p>Your wallet, Etherscan, and every DeFi protocol must actively watch for changes. Without a standardized way to signal "something important happened here," they'd have to scan every single storage change - an impossibly expensive and slow process. </p>
<p>Events solve this by creating an efficient notification layer on top of the blockchain.</p>
<h2 id="heading-events-in-your-smart-contract">Events in Your Smart Contract</h2>
<p>Events are the backbone of blockchain visibility. Block explorers use them to show transaction history, wallets listen for them to update your balance, and DeFi protocols track them for analytics. Plus, they're 8x cheaper than storing data.</p>
<p>To implement events in your contract, you declare the event, which is similar to defining a notification template, and then trigger it after your preferred function call or action, as shown in the following code.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MyToken</span> </span>{

    <span class="hljs-comment">// Previous code...</span>

    <span class="hljs-comment">// Declare an event</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">Transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> <span class="hljs-keyword">from</span>, <span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> to, <span class="hljs-keyword">uint256</span> value</span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{

        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> owner, <span class="hljs-string">"Only owner can mint"</span>);
        totalSupply <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;
        balances[to] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;

        <span class="hljs-comment">// Fire the event! Tell the world tokens were created</span>
        <span class="hljs-keyword">emit</span> Transfer(<span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), to, amount);
    }
}
</code></pre>
<p>When minting, we show tokens from address(0). This is the universal signal for "new tokens created."</p>
<p>Minting is great, but tokens that can't move aren't very useful. Let's add the ability to transfer tokens between addresses.</p>
<h2 id="heading-the-transfer-function">The Transfer Function</h2>
<p>Create the transfer function named transfer with the following code snippet:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{

    <span class="hljs-comment">// Check 1: Do you have enough tokens?</span>
    <span class="hljs-built_in">require</span>(balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> amount, <span class="hljs-string">"Not enough tokens!"</span>);

    <span class="hljs-comment">// Check 2: Are you sending to a real address?</span>
    <span class="hljs-built_in">require</span>(to <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), <span class="hljs-string">"Can't send to the zero address"</span>);


    <span class="hljs-comment">// The actual transfer (order matters for security!)</span>
    balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> amount; <span class="hljs-comment">// Take from sender</span>
    balances[to] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount; <span class="hljs-comment">// Give to recipient</span>

    <span class="hljs-comment">// Announce it to the world</span>
    <span class="hljs-keyword">emit</span> Transfer(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, to, amount);

    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; <span class="hljs-comment">// ERC20 standard says return true on success</span>
}
</code></pre>
<p>The code snippet above does the following:</p>
<ul>
<li><p>First, we checked if you're not trying to send more tokens than you have (no overdrafts in blockchain).</p>
</li>
<li><p>Next, we made sure you're not accidentally burning tokens by sending to the zero address.</p>
</li>
<li><p>Then we performed the actual transfer to subtract from the sender and add to the recipient.</p>
</li>
<li><p>We announced the transfer with an event (this is how MetaMask knows to update your balance).</p>
</li>
<li><p>Finally, we returned true because that's what the ERC20 standard expects on success.</p>
</li>
</ul>
<p>So far, only you can transfer your own tokens. But what if you want a <a target="_blank" href="https://www.coinbase.com/en-gb/learn/crypto-basics/what-is-a-dex">decentralized exchange (DEX)</a> like <a target="_blank" href="https://app.uniswap.org/">Uniswap</a> to be able to pull 100 of your tokens to swap them for another asset? You can't give the DEX your <a target="_blank" href="https://www.coinbase.com/en-gb/learn/crypto-basics/what-is-a-private-key">private key</a>. That’s where delegation and token approval come in; they let you authorize a third party to spend tokens on your behalf, without handing over full control.</p>
<h2 id="heading-the-token-approval-mechanism">The Token Approval Mechanism</h2>
<p>The token approval mechanism is a two-step process:</p>
<ul>
<li><p><strong>Approve</strong>: You (the owner) call the <code>approve</code> function to authorize another address (the spender) to withdraw up to a certain amount of your tokens.</p>
</li>
<li><p><strong>TransferFrom</strong>: The spender then calls <code>transferFrom</code> to move the tokens from your account to a destination.</p>
</li>
</ul>
<p>Let’s add this functionality to our contract.</p>
<p>To implement the <code>approve</code> function, add the following code snippet:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MyToken</span> </span>{

    <span class="hljs-comment">// Previous code...</span>

    <span class="hljs-comment">// Who is allowed to spend what: owner =&gt; spender =&gt; amount</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint256</span>)) <span class="hljs-keyword">public</span> allowance;

    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">Approval</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> owner,
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> spender,
        <span class="hljs-keyword">uint256</span> value
    </span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">approve</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> spender, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{

        <span class="hljs-built_in">require</span>(spender <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), <span class="hljs-string">"Can't approve zero address"</span>);

        <span class="hljs-comment">// "I allow this spender to use up to this amount of MY tokens"</span>
        allowance[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>][spender] <span class="hljs-operator">=</span> amount;

        <span class="hljs-keyword">emit</span> Approval(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, spender, amount);
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
}
</code></pre>
<p>Next, implement the <code>transferFrom</code> function:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transferFrom</span>(<span class="hljs-params">
    <span class="hljs-keyword">address</span> <span class="hljs-keyword">from</span>,
    <span class="hljs-keyword">address</span> to,
    <span class="hljs-keyword">uint256</span> amount
</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{

    <span class="hljs-comment">// Check 1: Does the owner have enough tokens?</span>
    <span class="hljs-built_in">require</span>(balances[<span class="hljs-keyword">from</span>] <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> amount, <span class="hljs-string">"Owner doesn't have enough tokens"</span>);

    <span class="hljs-comment">// Check 2: Are YOU allowed to move this many?</span>
    <span class="hljs-built_in">require</span>(
        allowance[<span class="hljs-keyword">from</span>][<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> amount,
        <span class="hljs-string">"You're not approved for that amount"</span>
    );

    <span class="hljs-comment">// Check 3: Valid recipient?</span>
    <span class="hljs-built_in">require</span>(to <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), <span class="hljs-string">"Can't send to zero address"</span>);

    <span class="hljs-comment">// Update the allowance FIRST (very important!)</span>
    allowance[<span class="hljs-keyword">from</span>][<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> amount;

    <span class="hljs-comment">// Then do the transfer</span>
    balances[<span class="hljs-keyword">from</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> amount;
    balances[to] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;

    <span class="hljs-keyword">emit</span> Transfer(<span class="hljs-keyword">from</span>, to, amount);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
</code></pre>
<p>With <code>approve</code> and <code>transferFrom</code>, our token is now composable. It can interact with other smart contracts in a secure, decentralized way. The nested mapping for allowance might look intimidating, but it's just a way to record that the owner has allowed this spender to use this amount.</p>
<p>In a real-world scenario using the Uniswap DEX we mentioned earlier, this is how it would look:</p>
<ol>
<li><p>You approve(uniswapRouter, 100) - "Uniswap can use 100 of my tokens".</p>
</li>
<li><p>You call Uniswap's swap function.</p>
</li>
<li><p>Uniswap calls transferFrom(you, liquidityPool, 100).</p>
</li>
<li><p>You get ETH back.</p>
</li>
</ol>
<p>It's like writing a check - you specify the amount and recipient, but they decide when to cash it.</p>
<p>This approval system seems bulletproof, right? You control who can spend your tokens and how much. What could go wrong?</p>
<p>Well, here's where things get spicy. This approval system has a hidden flaw. Imagine writing someone a check, then trying to write them a smaller check to replace it - they might cash both. This exact problem has been used to steal tokens from real projects.</p>
<p>For example:</p>
<ul>
<li><p>Alice approves Bob for 100 tokens.</p>
</li>
<li><p>Alice changes her mind and sends a transaction to reduce it to 50.</p>
</li>
<li><p>Bob sees Alice's pending transaction.</p>
</li>
<li><p>Bob quickly uses the current 100 approval.</p>
</li>
<li><p>Alice's new 50 approval goes through.</p>
</li>
<li><p>Bob uses the 50 approval, too.</p>
</li>
<li><p>Bob got 150 tokens instead of 50! 😱</p>
</li>
</ul>
<p>So, how do you avoid this scenario? The fix involves modifying the contract by adding increaseAllowance and decreaseAllowance functions, thereby making approval changes atomic and preventing race conditions.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">//...</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">increaseAllowance</span>(<span class="hljs-params">
    <span class="hljs-keyword">address</span> spender,
    <span class="hljs-keyword">uint256</span> addedValue
</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{

    allowance[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>][spender] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> addedValue;
    <span class="hljs-keyword">emit</span> Approval(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, spender, allowance[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>][spender]);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">decreaseAllowance</span>(<span class="hljs-params">
    <span class="hljs-keyword">address</span> spender,
    <span class="hljs-keyword">uint256</span> subtractedValue
</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{

    <span class="hljs-keyword">uint256</span> currentAllowance <span class="hljs-operator">=</span> allowance[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>][spender];
    <span class="hljs-built_in">require</span>(currentAllowance <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> subtractedValue, <span class="hljs-string">"Can't decrease below zero"</span>);

    allowance[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>][spender] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> subtractedValue;
    <span class="hljs-keyword">emit</span> Approval(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, spender, allowance[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>][spender]);
    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}
</code></pre>
<p>These functions fix the race condition by changing HOW we update approvals:</p>
<ul>
<li><p><code>increaseAllowance</code>: Adds to the current allowance instead of replacing it.</p>
</li>
<li><p><code>decreaseAllowance</code>: Subtracts from the current allowance (with a safety check).</p>
</li>
<li><p>Both are atomic operations - no window for attackers to exploit.</p>
</li>
<li><p>If Bob has 100 and you decrease by 50, he ends up with exactly 50.</p>
</li>
</ul>
<p>Our token is now secure, feature-complete, and ready for production. However, there's one important question we haven't answered: how will other smart contracts recognize that our token has these exact functions? When Uniswap tries to interact with our token, how does it know we have <code>transfer</code>, <code>approve</code>, and <code>transferFrom</code>?</p>
<p>This is where standards come in. Let's implement the IERC20 interface.</p>
<h2 id="heading-making-it-standard-the-ierc20-interface">Making It Standard: The IERC20 Interface</h2>
<p>Our token works great, but how do other contracts know what functions it has? This is where interfaces shine; they're like a contract's API specification that shows certain functions exist.</p>
<p>Let's implement the standard <a target="_blank" href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol">IERC20 interface</a>:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>

<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.20;</span>

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IERC20</span> </span>{

    <span class="hljs-comment">// Read functions</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">totalSupply</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">balanceOf</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">allowance</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> owner, <span class="hljs-keyword">address</span> spender</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)</span>;

    <span class="hljs-comment">// Write functions</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">approve</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> spender, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transferFrom</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">from</span>, <span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)</span>;

    <span class="hljs-comment">// Events</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">Transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> <span class="hljs-keyword">from</span>, <span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> to, <span class="hljs-keyword">uint256</span> value</span>)</span>;
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">Approval</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> owner, <span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> spender, <span class="hljs-keyword">uint256</span> value</span>)</span>;
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MyToken</span> <span class="hljs-keyword">is</span> <span class="hljs-title">IERC20</span> </span>{
    <span class="hljs-comment">// Our implementation...</span>
}
</code></pre>
<p>The Interface implementation above gives our contract:</p>
<ul>
<li><p>Composability: Any contract expecting IERC20 can work with your token.</p>
</li>
<li><p>Type Safety: The compiler ensures you implement every required function.</p>
</li>
<li><p>Documentation: Clear specification of what your contract can do.</p>
</li>
<li><p>Standards: Following ERC20 means instant compatibility with thousands of dApps.</p>
</li>
</ul>
<p>Congratulations! You've just built a functional, simplified ERC20 token from scratch. Here is the complete code for <code>MyToken.sol</code>.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>

<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.20;</span>

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IERC20</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">totalSupply</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">balanceOf</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">allowance</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> owner,
        <span class="hljs-keyword">address</span> spender
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">approve</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> spender, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)</span>;
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transferFrom</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">from</span>,
        <span class="hljs-keyword">address</span> to,
        <span class="hljs-keyword">uint256</span> amount
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">Transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> <span class="hljs-keyword">from</span>, <span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> to, <span class="hljs-keyword">uint256</span> value</span>)</span>;
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">Approval</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> owner,
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">indexed</span> spender,
        <span class="hljs-keyword">uint256</span> value
    </span>)</span>;
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">MyToken</span> <span class="hljs-keyword">is</span> <span class="hljs-title">IERC20</span> </span>{

    <span class="hljs-comment">// Token metadata</span>
    <span class="hljs-keyword">string</span> <span class="hljs-keyword">public</span> name <span class="hljs-operator">=</span> <span class="hljs-string">"MyToken"</span>;
    <span class="hljs-keyword">string</span> <span class="hljs-keyword">public</span> symbol <span class="hljs-operator">=</span> <span class="hljs-string">"MTK"</span>;
    <span class="hljs-keyword">uint8</span> <span class="hljs-keyword">public</span> decimals <span class="hljs-operator">=</span> <span class="hljs-number">18</span>;
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> totalSupply;

    <span class="hljs-comment">// Contract owner (can mint new tokens)</span>
    <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> owner;

    <span class="hljs-comment">// Balances ledger</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint256</span>) <span class="hljs-keyword">public</span> balances;

    <span class="hljs-comment">// Allowances ledger</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">&gt;</span> <span class="hljs-keyword">uint256</span>)) <span class="hljs-keyword">public</span> allowance;

    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"></span>) </span>{
        owner <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">balanceOf</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">return</span> balances[account];
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">mint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{

        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> owner, <span class="hljs-string">"Only owner can mint"</span>);
        <span class="hljs-built_in">require</span>(to <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), <span class="hljs-string">"Cannot mint to zero address"</span>);

        totalSupply <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;
        balances[to] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;

        <span class="hljs-keyword">emit</span> Transfer(<span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), to, amount);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{

        <span class="hljs-built_in">require</span>(balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> amount, <span class="hljs-string">"Insufficient balance"</span>);
        <span class="hljs-built_in">require</span>(to <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), <span class="hljs-string">"Cannot transfer to zero address"</span>);

        balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> amount;
        balances[to] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;
        <span class="hljs-keyword">emit</span> Transfer(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, to, amount);
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">approve</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> spender, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        <span class="hljs-built_in">require</span>(spender <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), <span class="hljs-string">"Cannot approve zero address"</span>);

        allowance[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>][spender] <span class="hljs-operator">=</span> amount;
        <span class="hljs-keyword">emit</span> Approval(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, spender, amount);
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transferFrom</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">from</span>,
        <span class="hljs-keyword">address</span> to,
        <span class="hljs-keyword">uint256</span> amount
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{

        <span class="hljs-built_in">require</span>(balances[<span class="hljs-keyword">from</span>] <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> amount, <span class="hljs-string">"Insufficient balance"</span>);
        <span class="hljs-built_in">require</span>(
            allowance[<span class="hljs-keyword">from</span>][<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> amount,
            <span class="hljs-string">"Insufficient allowance"</span>
        );

        <span class="hljs-built_in">require</span>(to <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), <span class="hljs-string">"Cannot transfer to zero address"</span>);

        allowance[<span class="hljs-keyword">from</span>][<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> amount;
        balances[<span class="hljs-keyword">from</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> amount;
        balances[to] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;

        <span class="hljs-keyword">emit</span> Transfer(<span class="hljs-keyword">from</span>, to, amount);
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">increaseAllowance</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> spender,
        <span class="hljs-keyword">uint256</span> addedValue
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        allowance[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>][spender] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> addedValue;
        <span class="hljs-keyword">emit</span> Approval(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, spender, allowance[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>][spender]);
        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">decreaseAllowance</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> spender,
        <span class="hljs-keyword">uint256</span> subtractedValue
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{

        <span class="hljs-keyword">uint256</span> currentAllowance <span class="hljs-operator">=</span> allowance[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>][spender];
        <span class="hljs-built_in">require</span>(
            currentAllowance <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> subtractedValue,
            <span class="hljs-string">"Decreased allowance below zero"</span>
        );

        allowance[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>][spender] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> subtractedValue;
        <span class="hljs-keyword">emit</span> Approval(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, spender, allowance[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>][spender]);

        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }
}
</code></pre>
<h2 id="heading-testing-your-token">Testing Your Token</h2>
<p>You can test your token step by step right in Remix:</p>
<ul>
<li><p><strong>Compile</strong>: Hit Ctrl+S or click the Solidity compiler tab.</p>
</li>
<li><p><strong>Deploy</strong>: Go to the "Deploy &amp; Run" tab, click "Deploy".</p>
</li>
<li><p><strong>Mint some tokens</strong>: Call mint with your address and 1000000000000000000000 (that's 1000 tokens with 18 decimals).</p>
</li>
<li><p><strong>Check your balance</strong>: Call balanceOf with your address.</p>
</li>
<li><p><strong>Send tokens</strong>: Try transferring to another address.</p>
</li>
<li><p><strong>Test approvals</strong>: Approve an address and test transferFrom.</p>
</li>
</ul>
<p>Something to note here is that when you set a balance in your mapping, Solidity performs complex cryptographic calculations to determine exactly where on the blockchain to store that data. And every storage operation has a different gas cost. Let's take a deeper look at storage and gas optimization</p>
<h2 id="heading-storage-and-gas-optimization">Storage and Gas Optimization</h2>
<p>Now that you understand the basics, let's take a closer look at how Solidity stores your token data and how to optimize for gas costs.</p>
<p><strong>How Storage Slots Work</strong></p>
<p>When you write:</p>
<pre><code class="lang-solidity">balances[<span class="hljs-number">0x123</span>...] <span class="hljs-operator">=</span> <span class="hljs-number">1000</span>;
</code></pre>
<p>Solidity doesn't just put this somewhere random. It computes:</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">bytes32</span> slot <span class="hljs-operator">=</span> <span class="hljs-built_in">keccak256</span>(<span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(<span class="hljs-keyword">address</span>(<span class="hljs-number">0x123</span>...), <span class="hljs-keyword">uint256</span>(<span class="hljs-number">1</span>)));

<span class="hljs-comment">// Where 1 is the storage slot of the balances mapping</span>
</code></pre>
<p>This addressing ensures:</p>
<ul>
<li><p>No collisions between different addresses</p>
</li>
<li><p>Predictable gas costs (SSTORE costs 20,000 gas for new values)</p>
</li>
<li><p>Infinite capacity without pre-allocation</p>
</li>
</ul>
<p><strong>Gas Optimization Tips</strong></p>
<p>1. Pack your variables:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// Expensive (uses 3 storage slots)</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Inefficient</span> </span>{
    <span class="hljs-keyword">uint256</span> a; <span class="hljs-comment">// Slot 0</span>
    <span class="hljs-keyword">uint128</span> b; <span class="hljs-comment">// Slot 1 (wastes 128 bits)</span>
    <span class="hljs-keyword">uint128</span> c; <span class="hljs-comment">// Slot 2 (wastes 128 bits</span>
}

<span class="hljs-comment">// Cheap (uses 2 storage slots)</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Efficient</span> </span>{
    <span class="hljs-keyword">uint256</span> a; <span class="hljs-comment">// Slot 0</span>
    <span class="hljs-keyword">uint128</span> b; <span class="hljs-comment">// Slot 1 (first half)</span>
    <span class="hljs-keyword">uint128</span> c; <span class="hljs-comment">// Slot 1 (second half)</span>
}
</code></pre>
<p>2. Use events instead of storage for historical data:</p>
<ul>
<li><p>Storage: 20,000 gas.</p>
</li>
<li><p>Event: 2,500 gas (8x cheaper).</p>
</li>
</ul>
<p>3. Short-circuit your requirements:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// Check cheap conditions first</span>

<span class="hljs-built_in">require</span>(spender <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), <span class="hljs-string">"Invalid spender"</span>); <span class="hljs-comment">// cheap check</span>
<span class="hljs-built_in">require</span>(balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">&gt;</span><span class="hljs-operator">=</span> amount, <span class="hljs-string">"Insufficient balance"</span>); <span class="hljs-comment">// expensive check</span>
</code></pre>
<h2 id="heading-common-pitfalls-and-security-considerations">Common Pitfalls and Security Considerations</h2>
<p>Now that you've built a token, let's talk about what could go wrong and how we've protected against it:</p>
<p><strong>1. Integer Overflow (Pre-Solidity 0.8)</strong> </p>
<p>Before Solidity 0.8, numbers could "wrap around" like a car odometer going from 999,999 to 000,000:</p>
<pre><code class="lang-solidity"><span class="hljs-keyword">uint256</span> balance <span class="hljs-operator">=</span> <span class="hljs-keyword">type</span>(<span class="hljs-keyword">uint256</span>).<span class="hljs-built_in">max</span>; <span class="hljs-comment">// Biggest possible number</span>

balance <span class="hljs-operator">+</span><span class="hljs-operator">=</span> <span class="hljs-number">1</span>; <span class="hljs-comment">// Would wrap to 0!</span>
</code></pre>
<p>Think of it like filling a glass of water, once it's full, adding more makes it overflow. Luckily, modern Solidity stops this automatically, but older contracts needed special SafeMath libraries to check every calculation.</p>
<p><strong>2. Reentrancy Protection</strong></p>
<p>To explain this, let’s say you're at an ATM that gives you cash before updating your balance. If you could somehow trigger it multiple times before it updates, you could drain the account. That's reentrancy.</p>
<p>Our token prevents this by always updating balances BEFORE doing anything else:</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// Good: Update state before external calls</span>
balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> amount;              <span class="hljs-comment">// 1. Update state</span>
balances[to] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;                      <span class="hljs-comment">// 2. Update state</span>
<span class="hljs-keyword">emit</span> Transfer(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, to, amount);       <span class="hljs-comment">// 3. Then emit event</span>


<span class="hljs-comment">// Bad: External call before state update</span>
<span class="hljs-keyword">emit</span> Transfer(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, to, amount);       <span class="hljs-comment">// If this calls external code...</span>
balances[<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>] <span class="hljs-operator">-</span><span class="hljs-operator">=</span> amount;              <span class="hljs-comment">// ...they could call transfer again!</span>
balances[to] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;
</code></pre>
<p><strong>3. Front-Running Protection</strong></p>
<p>Front-running is like someone cutting in line at the store because they saw what you're buying. On blockchain, bots can see your pending transaction and submit their own with higher gas fees to go first. </p>
<p>The approval race condition we fixed earlier is one example. Here are others:</p>
<ul>
<li><p><a target="_blank" href="https://chain.link/education-hub/maximal-extractable-value-mev"><strong>Maximal Extractable Value (MEV)</strong></a> <strong>Bots</strong>: Automated programs that watch for profitable trades and jump in front. Like ticket scalpers, but for blockchain transactions.</p>
</li>
<li><p><a target="_blank" href="https://www.coinbase.com/en-gb/learn/crypto-glossary/what-are-sandwich-attacks-in-crypto"><strong>Sandwich Attacks</strong></a>: A bot sees you trying to buy tokens on a DEX. They buy first (driving up the price), let your transaction go through at the higher price, then sell immediately after. You're the "meat" in their profit sandwich.</p>
</li>
<li><p><a target="_blank" href="https://www.mev.wiki/terms-and-concepts/priority-gas-auctions"><strong>Priority Gas Auctions</strong></a>: When multiple bots compete to front-run, they keep raising gas prices to go first, like an auction where everyone loses except miners.</p>
</li>
</ul>
<h2 id="heading-what-youve-accomplished">What You've Accomplished</h2>
<p>Take a moment to appreciate what you've built. This isn't just a toy, it's a real token contract that could be deployed on any EVM chain. </p>
<p>You now understand:</p>
<ul>
<li><p>State &amp; Storage: How data lives forever on the blockchain.</p>
</li>
<li><p>Access Control: Using msg.sender to secure functions.</p>
</li>
<li><p>Events: Broadcasting actions to the world.</p>
</li>
<li><p>View Functions: Free data reads for users.</p>
</li>
<li><p>The Approval Pattern: The foundation of all DeFi.</p>
</li>
<li><p>Security Best Practices: From Reentrancy to Race Conditions.</p>
</li>
<li><p>Interfaces: How contracts guarantee compatibility</p>
</li>
<li><p>Gas Optimization: Making your contracts efficient</p>
</li>
</ul>
<h2 id="heading-what-next">What Next?</h2>
<p>Your token is alive and functional, but why stop here? The real fun begins when you start adding features that production tokens use. Implement a burn function to allow users to destroy their tokens permanently, a powerful feature for <a target="_blank" href="https://cointelegraph.com/explained/how-do-inflationary-vs-deflationary-token-models-affect-market-liquidity">deflationary tokenomics</a>. Add a <strong>maximum supply cap</strong> to ensure only a fixed amount can ever exist. Develop a <a target="_blank" href="https://ethereum-blockchain-developer.com/022-pausing-destroying-smart-contracts/03-pausing-smart-contracts/">pausability</a> feature for emergencies, enabling temporary freezes on all transfers and related activities.</p>
<p>Advanced Extensions to Explore</p>
<ul>
<li><p><a target="_blank" href="https://eips.ethereum.org/EIPS/eip-2612">ERC20Permit</a>: Gasless approvals using signatures</p>
</li>
<li><p>Flash Minting: Create and destroy tokens within a single transaction</p>
</li>
<li><p>Rebase Tokens: Tokens that adjust all balances periodically</p>
</li>
<li><p>Fee-on-Transfer: Tokens that take a percentage on each transfer</p>
</li>
</ul>
<p>Once you're happy with the smart contract, it's time to make it accessible. Create a web interface using ethers.js or web3.js, allowing users to interact with your token without needing to write code. Deploy it to <a target="_blank" href="https://testnet.monad.xyz/">Monad's testnet</a> to experience blazing-fast transactions in a real blockchain environment.</p>
<h2 id="heading-resources-for-continued-learning">Resources for Continued Learning</h2>
<ul>
<li><p><a target="_blank" href="https://github.com/OpenZeppelin/openzeppelin-contracts">OpenZeppelin Contracts</a></p>
</li>
<li><p><a target="_blank" href="https://ethereum.github.io/yellowpaper/paper.pdf">Ethereum Yellow Paper</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Depth Over Trend]]></title><description><![CDATA[This isn't a typical blog I write, but I'm going to share some raw thoughts along with rhetorical questions that you might find useful and helpful.

It's interesting to see how fast the ecosystem moves today, which has made me think a lot over the pa...]]></description><link>https://blog.idrisolubisi.com/depth-over-trend</link><guid isPermaLink="true">https://blog.idrisolubisi.com/depth-over-trend</guid><category><![CDATA[Developer]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Founder]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Sun, 23 Mar 2025 10:00:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/0YQOOxNT2V4/upload/3c26856be5dc97cd3e70b34461d92523.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong><em>This isn't a typical blog I write, but I'm going to share some raw thoughts along with rhetorical questions that you might find useful and helpful.</em></strong></p>
</blockquote>
<p>It's interesting to see how fast the ecosystem moves today, which has made me think a lot over the past few months about what comes next. Yes, what comes after accomplishments?</p>
<p>What comes after reaching the goal you set a year or two ago?<br />What comes after overcoming your biggest challenge, whether in skills or leadership??</p>
<p><a target="_blank" href="https://x.com/olanetsoft/status/1900537308798919076"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742049833847/8df7a55c-bd98-4142-bcc6-07c5be093e6f.png" alt="Depth not trend" class="image--center mx-auto" /></a></p>
<p>Have you ever thought about the different phases of the internet we've experienced over the years and wondered what the developers from those times are doing today? Let me take you back a bit. You might know about our various internet phases: from <a target="_blank" href="https://www.investopedia.com/web-20-web-30-5208698">1995 to 2000 (Web1), 2000 to 2020 (Web2, which is still active), and now Web3</a> and Web5 up to the present.</p>
<p>Yes, Web5. If this is your first time hearing about <a target="_blank" href="https://youtu.be/Vw3i2LeVa_Y?t=128">Web5, you can learn about it with this breakdown from Adewale Abatti (Acekyd)</a>.</p>
<p>It's fascinating to see how things have changed over time. But can you guess what the different eras have in common? Please take a moment to think about it.</p>
<blockquote>
<p>The tech skill!</p>
</blockquote>
<p>Yes, tech skills are transferable skills you can own, nurture, and improve without worrying about the next iteration of the internet or trends. Before I stray too far, let me bring you back to why you're reading this: it's about valuing depth over trends or, simply put, Depth over Trend. However, you prefer to call it.</p>
<p>Let's talk about what's important, what you need, and why you need it. I will also share what I have learned from the past months of thinking about what truly matters, using the history I mentioned earlier. As you all know, data don’t lie.</p>
<h2 id="heading-depth-vs-trend">Depth vs Trend</h2>
<p><img src="https://images.pexels.com/photos/28795077/pexels-photo-28795077/free-photo-of-abstract-green-spiral-design-on-black-background.jpeg?auto=compress&amp;cs=tinysrgb&amp;dpr=1&amp;w=500" alt="Free Artistic 3D spiral structure in green hues against a solid black background, showcasing modern abstract design. Stock Photo" class="image--center mx-auto" /></p>
<p>To explain this concept the way I think about it, and how I believe everyone reading this should subconsciously think about it, is to use the idea of trade.</p>
<p>"Depth" refers to the volume and liquidity at different <strong>price levels</strong> in the order book, while "Trend" refers to the overall direction of <strong>price movement over time.</strong> Think of it this way: trends are what everyone can see. They're the apparent upward or downward movements that catch attention. People chase trends because they're visible and exciting - like jumping on the AI bandwagon or whatever’s hot on Twitter this week.</p>
<p>But depth? That's where the real value sits. It’s having deep knowledge or capability that persists regardless of market conditions. <strong>Trends come and go, but depth gives you staying power.</strong></p>
<p>What makes them similar is that both can lead to success. You can make quick wins following trends like day traders can profit from momentum. But the difference is <strong>sustainability</strong>.</p>
<p>Depth wins in the long run because it builds compounding value. While trend-chasers constantly restart with each new wave, depth-focused players build foundations that strengthen over time. When the trend inevitably shifts, those without depth get washed out, while those with substantive knowledge or skills remain valuable.</p>
<p>As <em>Warren Buffett says - when the tide goes out, you discover who’s been swimming naked.</em> Depth is your protection when trends reverse.</p>
<h2 id="heading-why-should-you-care">Why should you care?</h2>
<p>Even if you think all that matters is money, who doesn't like money? Understanding the difference between depth and trends isn’t just academic. It directly impacts where you invest your limited <strong>time and energy</strong>.</p>
<p>Chasing trends without depth is like buying into market momentum without understanding fundamentals. Sure, you might catch some upside, but you're essentially gambling. When the music stops, you're left without a chair.</p>
<p>Trends often shine a lot, and if you aren't careful as a builder, founder, or developer, it's very easy to get carried away with them. But then, I know what you might be thinking: ” Everyone is doing it”, ” It’s the next big thing,” “I don’t want to miss out,” and all that. But in reality, there are different phases of life, the same as tech and the tech ecosystem in general.</p>
<p>Depth, on the other hand, is <strong>compound interest</strong> for your career and business. Each layer of deep understanding builds on previous layers, creating compounding returns that trends can't can't.</p>
<p>Take developers who studied fundamental programming concepts versus those who just learned the trending framework of the month. When React inevitably gives way to the next big thing, guess who adapts faster? The ones with depth.</p>
<p>Or consider founders who deeply understand customer problems versus those chasing funding trends. When venture capital dried up in 2022-2023, companies with genuine market depth survived while trend-chasers ran out of runway.</p>
<p>The market eventually rewards depth not because it's virtuous but because it's viable. And in an increasingly noisy world where everyone chases the same trends, depth is your unfair advantage.</p>
<blockquote>
<p>Every person who created something different focused on depth, which often comes from a deep work state—a flow state of continuous, focused work. With trends, you stay at the top. It only requires shallow work to produce something of substance. - Blessing Adesiji</p>
</blockquote>
<p>What can you do differently?</p>
<p>Stop treating tech like a fashion show. Take a breath instead of <strong>reflexively jumping on every new framework, language, or platform that trends on X(Formerly Twitter)</strong>.</p>
<p>Ask yourself: "Does it solve a fundamental problem, or is it just shiny?"</p>
<p>It doesn’t mean you should isolate yourself and not keep abreast of what's going on around you.</p>
<p>Develop your Bulls***t detector. When everyone's hypineveryone's thing, that's your cue that's skeptical. The real opportunities often lie in areas others overlook because they're too busy following the crowd.</p>
<p>Allocate your learning time like an investment portfolio:</p>
<ul>
<li><p><strong>70% toward deepening your understanding of fundamentals that won't change.</strong></p>
</li>
<li><p><strong>20% tailoring adjacent skills that complement your core.</strong></p>
</li>
<li><p><strong>10% experimenting with trends.</strong></p>
</li>
</ul>
<p>Build relationships with people who prioritize depth. You become the average of the five people you spend the most time with, so surround yourself with depth-seekers who ask hard questions rather than trend-followers who chase easy answers.</p>
<p>Perhaps most importantly, be willing to be temporarily uncool. The paradox is that ignoring what's trendy positions you to catch more immense, meaningful waves later.</p>
<h2 id="heading-self-reflection">Self Reflection</h2>
<p>Take a moment to audit your recent decisions. How many were made because "everyone is doing it" versus a ”deep understanding of underlying value”?</p>
<p>Look at your skill set critically. If the tech landscape dramatically changed tomorrow, which of your abilities would remain valuable? Those are your depth areas.</p>
<p>Consider your heroes in tech. Are they known for riding trends or creating fundamental value regardless of market conditions? What can you learn from their approaches?</p>
<p>Ask yourself the uncomfortable question: "<strong>Am I building something that will matter in five years?</strong>" If not, you might be optimizing for trends over depth.</p>
<p>Finally, depth isn't just technical knowledge; it's understanding people, problems, and principles. The most profound insights often come from connecting dots across disciplines rather than narrowing down to what's happening.</p>
<p>The choice between depth and trend is not a career strategy. It's a philosophy about how you want to contribute to the world. Choose wisely.</p>
<p>Olanetsoft ✍️</p>
]]></content:encoded></item><item><title><![CDATA[How to Set Up Cross-Chain Messaging Between EVM and Cosmos]]></title><description><![CDATA[Cross-chain messaging allows seamless communication and interaction between different blockchain ecosystems, from Ethereum Virtual Machine (EVM)-based chains to Cosmos-based chains.
Axelar has long been the best way to connect EVM and Cosmos chains v...]]></description><link>https://blog.idrisolubisi.com/how-to-set-up-cross-chain-messaging-between-evm-and-cosmos</link><guid isPermaLink="true">https://blog.idrisolubisi.com/how-to-set-up-cross-chain-messaging-between-evm-and-cosmos</guid><category><![CDATA[Smart Contracts]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[cosmos]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Web3]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Thu, 28 Nov 2024 13:34:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1732800673844/b5203736-18ad-4ec5-a9d3-18982ba3c8f7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Cross-chain messaging allows seamless communication and interaction between different blockchain ecosystems, from Ethereum Virtual Machine (EVM)-based chains to Cosmos-based chains.</p>
<p>Axelar has long been the best way to connect EVM and Cosmos chains via bridged assets. With <a target="_blank" href="/dev/general-message-passing/overview/">General Message Passing</a>, that connection goes beyond bridging, supporting a new generation of cross-chain applications that combine the best of Cosmos and EVM.</p>
<p>In this tutorial, you will learn how to:</p>
<ul>
<li><p>Build and deploy an EVM smart contract on Avalanche</p>
</li>
<li><p>Build and deploy a CosmWasm contract on Osmosis</p>
</li>
<li><p>Send a message from a CosmWasm contract to Avalanche</p>
</li>
<li><p>Read a message from an EVM smart contract on Avalanche</p>
</li>
<li><p>Send a message from EVM to a CosmWasm contract on Osmosis</p>
</li>
<li><p>Read a message from a CosmWasm contract on Osmosis</p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li><p>Practical understanding of <a target="_blank" href="https://docs.cosmwasm.com/docs/getting-started/intro/">how to build a CosmWasm contract</a></p>
</li>
<li><p>Basic understanding of <a target="_blank" href="https://hacken.io/discover/create-smart-contract/">how to build EVM smart contract</a></p>
</li>
<li><p>Install <code>osmosisd</code> CLI</p>
<ul>
<li>Download and install the <code>osmosisd</code> CLI by following the instructions <a target="_blank" href="https://docs.osmosis.zone/osmosis-core/osmosisd">here</a>. If the installation wizard does not work, build from the source using the following commands:</li>
</ul>
</li>
</ul>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/osmosis-labs/osmosis.git
<span class="hljs-built_in">cd</span> osmosis
make build
</code></pre>
<ul>
<li><p>Create a Wallet</p>
<ul>
<li>If you don't have a wallet yet, create one using the following command:</li>
</ul>
</li>
</ul>
<pre><code class="lang-bash">osmosisd keys add wallet
</code></pre>
<ul>
<li><p>Obtain Test Tokens</p>
<ul>
<li>Get some test tokens from the <a target="_blank" href="https://faucet.testnet.osmosis.zone/">Osmosis Testnet Faucet</a>.</li>
</ul>
</li>
<li><p>Ensure you have <a target="_blank" href="https://www.docker.com/">Docker</a> installed to build the contract.</p>
</li>
<li><p>A <a target="_blank" href="https://metamask.io/">wallet</a> with an Avax token for testing. If you don’t have these tokens, you can get Avax from the <a target="_blank" href="https://docs.avax.network/build/dapp/smart-contracts/get-funds-faucet">Avalanche faucet</a>.</p>
</li>
</ul>
<h2 id="heading-what-is-a-cosmwasm-contract">What is a CosmWasm contract?</h2>
<p><a target="_blank" href="https://docs.cosmos.network/v0.46/CosmWasm/">CosmWasm</a> is a smart contracting platform designed for the Cosmos ecosystem. In simple terms, it utilizes WebAssembly (Wasm) in the Cosmos (Cosm) way.</p>
<p>CosmWasm contracts provide advanced smart contract capabilities within the Cosmos ecosystem, leveraging the performance and security advantages of WebAssembly and <a target="_blank" href="https://www.rust-lang.org/">Rust</a>. This allows developers to create complex, interoperable, and secure decentralized applications across various Cosmos-based blockchains.</p>
<h2 id="heading-what-is-axelar-cosmos-general-message-passing-gmp">What is Axelar Cosmos general message passing (GMP)</h2>
<p><a target="_blank" href="/dev/general-message-passing/overview/">General Message Passing (GMP)</a> empowers developers with the ability to build interchain-native applications that make cross-chain function calls and synchronize state in a way that is completely abstracted for the user.</p>
<p>In simpler terms, Axelar GMP enables developers to build applications that integrate functions (such as smart contracts) hosted on various connected chains, similar to using Lego bricks.</p>
<p>Axelar has expanded General Message Passing (GMP) to support Cosmos blockchains. With Axelar, you can now send and receive messages on EVM chains and Cosmos chains. Messages sent to Cosmos chains can be received by <a target="_blank" href="https://github.com/axelarnetwork/evm-cosmos-gmp-sample/tree/main/cosmwasm-integration/">CosmWasm smart contracts</a> (on blockchains with CosmWasm support), or those messages can be received <a target="_blank" href="https://github.com/axelarnetwork/evm-cosmos-gmp-sample/tree/main/native-integration">natively at the consensus layer as part of Go code</a>.</p>
<p>Cosmos GMP works by sending and receiving through <a target="_blank" href="https://medium.com/the-interchain-foundation/moving-beyond-simple-token-transfers-d42b2b1dc29b">IBC’s memo field</a>. Cosmos chains that support GMP should <a target="_blank" href="/dev/cosmos-gmp/overview/#chain-support">integrate the appropriate middleware</a> and <a target="_blank" href="/dev/cosmos-gmp/overview/#establishing-a-path-of-trust">verify the message source</a>.</p>
<h2 id="heading-project-setup-and-installation">Project setup and installation</h2>
<p>To start the project setup and installation quickly, clone this <a target="_blank" href="https://github.com/axelarnetwork/cross-chain-airdrop-dapp/tree/start"><strong>project on GitHub</strong></a> using the following command:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/axelarnetwork/send-message-from-cosmos-to-evm-example.git
</code></pre>
<p>Make sure you're on the <code>start</code> branch using the following command:</p>
<pre><code class="lang-bash">git checkout start
</code></pre>
<p>Next, change the directory into the cloned folder and install the project locally using npm with the following command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> send-message-from-cosmos-to-evm-example &amp;&amp; npm i
</code></pre>
<h3 id="heading-create-a-env-file">Create a <code>.env</code> file</h3>
<p>Run the following command to create an <a target="_blank" href="https://blog.bitsrc.io/a-gentle-introduction-to-env-files-9ad424cc5ff4"><code>.env</code> file</a>:</p>
<pre><code class="lang-bash">touch .env
</code></pre>
<p>Add your axl private key to <code>.env</code></p>
<p><a target="_blank" href="https://help.keplr.app/articles/how-to-view-your-private-key">Export your osmo prefix address private key</a> and add it to the <code>.env</code> file you just created:</p>
<pre><code class="lang-bash">PRIVATE_KEY= // Add your account private key here
</code></pre>
<h2 id="heading-build-and-deploy-a-cosmwasm-contract-on-osmosis">Build and deploy a CosmWasm contract on Osmosis</h2>
<p>The cloned project has the following folder structure that already contains the WASM contract; the next step you will be taking is to build and deploy the contract.</p>
<pre><code class="lang-markdown">├── wasm
│ ├── src
│ │ ├── contract.rs
│ │ ├── error.rs
│ │ ├── ibc.rs
| │ ├── lib.rs
│ │ ├── msg.rs
│ │ ├── state.rs
| │ ├── unit<span class="hljs-emphasis">_tests.rs
│ ├── cargo.lock
│ ├── corgo.toml
├── .env
├── node_</span>modules
├── package.json
├── package-lock.json
├── README.md
└── .gitignore
</code></pre>
<p>In the <a target="_blank" href="http://contract.rs"><code>contract.rs</code></a>, the following was implemented:</p>
<ul>
<li><p><strong>Initialization</strong>: The <code>instantiate</code> function sets up the contract by saving the initial configuration and a placeholder message into the contract's storage.</p>
</li>
<li><p><strong>Message Sending</strong>: The <code>execute</code> function handles various <code>ExecuteMsg</code> variants to send messages to EVM or Cosmos chains using Axelar GMP, constructing and dispatching messages with the necessary payload and metadata.</p>
</li>
<li><p><strong>Message Reception</strong>: The contract includes functions (<code>receive_message_evm</code> and <code>receive_message_cosmos</code>) to receive and store messages from EVM and Cosmos chains, decoding the payload and saving it in the contract's state.</p>
</li>
<li><p><strong>IBC Integration</strong>: It leverages Inter-Blockchain Communication (IBC) to send cross-chain messages, specifically designed to work with Axelar's GMP for transferring messages and funds across chains.</p>
</li>
<li><p><strong>Query Stored Messages</strong>: The <code>query</code> function enables retrieval of stored messages via the <code>GetStoredMessage</code> query, returning the sender and message details stored in the contract.</p>
</li>
</ul>
<h3 id="heading-build-the-cosmwasm-contract">Build the CosmWasm contract</h3>
<p>Navigate into the <code>wasm</code> folder and build the contract with the following command:</p>
<pre><code class="lang-bash">docker run --rm -v <span class="hljs-string">"<span class="hljs-subst">$(pwd)</span>"</span>:/code \
  --mount <span class="hljs-built_in">type</span>=volume,<span class="hljs-built_in">source</span>=<span class="hljs-string">"<span class="hljs-subst">$(basename <span class="hljs-string">"<span class="hljs-subst">$(pwd)</span>"</span>)</span>_cache"</span>,target=/code/target \
  --mount <span class="hljs-built_in">type</span>=volume,<span class="hljs-built_in">source</span>=registry_cache,target=/usr/<span class="hljs-built_in">local</span>/cargo/registry \
  cosmwasm/rust-optimizer:0.12.13
</code></pre>
<blockquote>
<p>Make sure you have Docker daemon running before running the command above.</p>
</blockquote>
<p>You should see something similar to what is displayed below on your terminal if the build is successful:</p>
<pre><code class="lang-bash">Info: RUSTC_WRAPPER=sccache
Info: sccache stats before build
Compile requests                      0
Compile requests executed             0
Cache hits                            0
Cache misses                          0
Cache timeouts                        0
Cache <span class="hljs-built_in">read</span> errors                     0
Forced recaches                       0
Cache write errors                    0
Compilation failures                  0
Cache errors                          0
Non-cacheable compilations            0
Non-cacheable calls                   0
Non-compilation calls                 0
Unsupported compiler calls            0
Average cache write               0.000 s
Average cache <span class="hljs-built_in">read</span> miss           0.000 s
Average cache <span class="hljs-built_in">read</span> hit            0.000 s
Failed distributed compilations       0
Cache location                  Local disk: <span class="hljs-string">"/root/.cache/sccache"</span>
Cache size                            0 bytes
Max cache size                       10 GiB
Building contract <span class="hljs-keyword">in</span> /code ...
    Finished release [optimized] target(s) <span class="hljs-keyword">in</span> 0.44s
Creating intermediate <span class="hljs-built_in">hash</span> <span class="hljs-keyword">for</span> send_receive.wasm ...
ebea0ee2e90b34fe4d55bd011051213938b95d596d6b56853c6e3e9bda8630ad  ./target/wasm32-unknown-unknown/release/send_receive.wasm
Optimizing send_receive.wasm ...
Creating hashes ...
c255d85938b647f59fcb77fe9d52ceefef5e510cd71364c522ce9ce25d3de8cc  send_receive.wasm
Info: sccache stats after build
Compile requests                      0
Compile requests executed             0
Cache hits                            0
Cache misses                          0
Cache timeouts                        0
Cache <span class="hljs-built_in">read</span> errors                     0
Forced recaches                       0
Cache write errors                    0
Compilation failures                  0
Cache errors                          0
Non-cacheable compilations            0
Non-cacheable calls                   0
Non-compilation calls                 0
Unsupported compiler calls            0
Average cache write               0.000 s
Average cache <span class="hljs-built_in">read</span> miss           0.000 s
Average cache <span class="hljs-built_in">read</span> hit            0.000 s
Failed distributed compilations       0
Cache location                  Local disk: <span class="hljs-string">"/root/.cache/sccache"</span>
Cache size                            0 bytes
Max cache size                       10 GiB
<span class="hljs-keyword">done</span>
</code></pre>
<h3 id="heading-upload-the-cosmwasm-contract">Upload the CosmWasm contract</h3>
<p>Next, you need to upload the contract using the following command:</p>
<pre><code class="lang-bash">osmosisd tx wasm store ./artifacts/send_receive.wasm --from wallet --gas-prices 0.4uosmo --gas auto --gas-adjustment 1.5 -y -b sync --output json --node https://rpc.osmotest5.osmosis.zone:443 --chain-id osmo-test-5
</code></pre>
<p>You should see something similar to what is displayed below on your terminal if the upload is successful:</p>
<pre><code class="lang-bash">gas estimate: 3150117
{
    <span class="hljs-string">"height"</span>:<span class="hljs-string">"0"</span>,
    <span class="hljs-string">"txhash"</span>:<span class="hljs-string">"339C8D4E8BB10E0DD337F79ACC26BB825C341E6DAFE803C5E8F8C2B42E9D5A33"</span>,
    <span class="hljs-string">"codespace"</span>:<span class="hljs-string">""</span>,<span class="hljs-string">"code"</span>:0,<span class="hljs-string">"data"</span>:<span class="hljs-string">""</span>,
    <span class="hljs-string">"raw_log"</span>:<span class="hljs-string">""</span>,<span class="hljs-string">"logs"</span>:[],
    <span class="hljs-string">"info"</span>:<span class="hljs-string">""</span>,<span class="hljs-string">"gas_wanted"</span>:<span class="hljs-string">"0"</span>,<span class="hljs-string">"gas_used"</span>:<span class="hljs-string">"0"</span>,<span class="hljs-string">"tx"</span>:null,
    <span class="hljs-string">"timestamp"</span>:<span class="hljs-string">""</span>,<span class="hljs-string">"events"</span>:[]
}
</code></pre>
<h3 id="heading-instantiate-the-cosmwasm-contract">Instantiate the CosmWasm contract</h3>
<p>To instantiate the CosmWasm contract, you will need a <code>CodeId</code>. To retrieve that, copy the transaction hash from the terminal response and paste it on <a target="_blank" href="https://www.mintscan.io/">Mintscan</a>; in the transaction details, you should see a <code>CodeId</code> similar to <a target="_blank" href="https://www.mintscan.io/osmosis-testnet/tx/339C8D4E8BB10E0DD337F79ACC26BB825C341E6DAFE803C5E8F8C2B42E9D5A33/?height=10285351#:~:text=osmo12qg7q97ny9yhqew3s2gf4h3mkzjnfxcdzvjuhs-,Code%20Id%3A,-9%2C726">this</a>.</p>
<p>Next, instantiate the contract with the following command:</p>
<pre><code class="lang-bash">osmosisd tx wasm instantiate &lt;codeId&gt; <span class="hljs-string">'{"channel":"channel-4118"}'</span> --from wallet --label <span class="hljs-string">"send_receive"</span> --gas-prices 0.1uosmo --gas auto --gas-adjustment 1.3 --no-admin -y -b sync --output json --node https://rpc.osmotest5.osmosis.zone:443 --chain-id osmo-test-5
</code></pre>
<p>Replace <code>&lt;codeId&gt;</code> with the actual code ID of your transaction. You should see something similar to what is displayed below on your terminal if the instantiation is successful:</p>
<pre><code class="lang-bash">gas estimate: 208330
{
    <span class="hljs-string">"height"</span>:<span class="hljs-string">"0"</span>,
    <span class="hljs-string">"txhash"</span>:<span class="hljs-string">"6F2FD21EF41267562826444DB29091CA163941BC31AB5FCC085A42B3F67E2317"</span>,
    <span class="hljs-string">"codespace"</span>:<span class="hljs-string">""</span>,<span class="hljs-string">"code"</span>:0,<span class="hljs-string">"data"</span>:<span class="hljs-string">""</span>,<span class="hljs-string">"raw_log"</span>:<span class="hljs-string">""</span>,<span class="hljs-string">"logs"</span>:[],
    <span class="hljs-string">"info"</span>:<span class="hljs-string">""</span>,<span class="hljs-string">"gas_wanted"</span>:<span class="hljs-string">"0"</span>,<span class="hljs-string">"gas_used"</span>:<span class="hljs-string">"0"</span>,
    <span class="hljs-string">"tx"</span>:null,<span class="hljs-string">"timestamp"</span>:<span class="hljs-string">""</span>,<span class="hljs-string">"events"</span>:[]
    }
</code></pre>
<p>You have successfully built, uploaded, and instantiated the CosmWasm contract. In the next section, you will build and deploy the EVM smart contract on Avalanche in this example and then interact with the EVM contract from the CosmWasm contract.</p>
<h3 id="heading-save-the-cosmwasm-contract-address">Save the CosmWasm contract address</h3>
<p>You will need the CosmWasm contract address later in this tutorial. You can find it in the contract details on Mintscan by pasting the transaction hash and saving it somewhere. In this example, the contract address is <code>osmo1vqgrchlfuymkjrzmrjznpam3xtzfemthzue43yt8l4ug046rtvwqarcl8r</code>.</p>
<h2 id="heading-build-and-deploy-an-evm-smart-contract-on-avalanche">Build and deploy an EVM smart contract on Avalanche</h2>
<p>In this session, you will build and deploy an EVM smart contract to Avalanche, a contract you will interact with from the CosmWasm you deployed.</p>
<p>To quickly build and deploy the EVM smart contract, you can use <a target="_blank" href="https://remix.ethereum.org/"><strong>https://remix.ethereum.org/</strong></a>, a powerful toolset for developing, deploying, debugging, and testing Ethereum and EVM-compatible smart contracts.</p>
<h3 id="heading-build-contract">Build contract</h3>
<p>Create a new file titled <code>SendReceive.sol</code> inside the <code>contracts</code> folder and copy the code from this <a target="_blank" href="https://gist.github.com/Olanetsoft/ede55a81d4953831de728f902a4280b2"><strong>gist</strong></a> into it.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.9;</span>

<span class="hljs-keyword">import</span> {<span class="hljs-title">AxelarExecutable</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">IAxelarGateway</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">IAxelarGasService</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">StringToAddress</span>, <span class="hljs-title">AddressToString</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/utils/AddressString.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">SendReceive</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AxelarExecutable</span> </span>{
    <span class="hljs-keyword">using</span> <span class="hljs-title">StringToAddress</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title"><span class="hljs-keyword">string</span></span>;
    <span class="hljs-keyword">using</span> <span class="hljs-title">AddressToString</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title"><span class="hljs-keyword">address</span></span>;

    IAxelarGasService <span class="hljs-keyword">public</span> <span class="hljs-keyword">immutable</span> gasService;
    <span class="hljs-keyword">string</span> <span class="hljs-keyword">public</span> chainName; <span class="hljs-comment">// name of the chain this contract is deployed to</span>

    <span class="hljs-keyword">struct</span> <span class="hljs-title">Message</span> {
        <span class="hljs-keyword">string</span> sender;
        <span class="hljs-keyword">string</span> message;
    }

    Message <span class="hljs-keyword">public</span> storedMessage; <span class="hljs-comment">// message received from _execute</span>

    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> gateway_,
        <span class="hljs-keyword">address</span> gasReceiver_,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> chainName_
    </span>) <span class="hljs-title">AxelarExecutable</span>(<span class="hljs-params">gateway_</span>) </span>{
        gasService <span class="hljs-operator">=</span> IAxelarGasService(gasReceiver_);
        chainName <span class="hljs-operator">=</span> chainName_;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">send</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> destinationChain,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> destinationAddress,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> message
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>, <span class="hljs-string">'Gas payment is required'</span>);

        <span class="hljs-comment">// 1. Generate GMP payload</span>
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> executeMsgPayload <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>.toString(), message);
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> payload <span class="hljs-operator">=</span> _encodePayloadToCosmWasm(executeMsgPayload);

        <span class="hljs-comment">// 2. Pay for gas</span>
        gasService.payNativeGasForContractCall{<span class="hljs-built_in">value</span>: <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>}(
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
            destinationChain,
            destinationAddress,
            payload,
            <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>
        );

        <span class="hljs-comment">// 3. Make GMP call</span>
        gateway.callContract(destinationChain, destinationAddress, payload);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_encodePayloadToCosmWasm</span>(<span class="hljs-params"><span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> executeMsgPayload</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-comment">//   Schema</span>
        <span class="hljs-comment">//   bytes4  version number (0x00000001)</span>
        <span class="hljs-comment">//   bytes   ABI-encoded payload, indicating function name and arguments:</span>
        <span class="hljs-comment">//   string                   CosmWasm contract method name</span>
        <span class="hljs-comment">//   dynamic array of string  CosmWasm contract argument name array</span>
        <span class="hljs-comment">//   dynamic array of string  argument abi type array</span>
        <span class="hljs-comment">//   bytes                    abi encoded argument values</span>

        <span class="hljs-comment">// contract call arguments for ExecuteMsg::receive_message_evm{ source_chain, source_address, payload }</span>
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> argValues <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(
            chainName,
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>).toString(),
            executeMsgPayload
        );

        <span class="hljs-keyword">string</span>[] <span class="hljs-keyword">memory</span> argumentNameArray <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">string</span>[](<span class="hljs-number">3</span>);
        argumentNameArray[<span class="hljs-number">0</span>] <span class="hljs-operator">=</span> <span class="hljs-string">"source_chain"</span>;
        argumentNameArray[<span class="hljs-number">1</span>] <span class="hljs-operator">=</span> <span class="hljs-string">"source_address"</span>;
        argumentNameArray[<span class="hljs-number">2</span>] <span class="hljs-operator">=</span> <span class="hljs-string">"payload"</span>;

        <span class="hljs-keyword">string</span>[] <span class="hljs-keyword">memory</span> abiTypeArray <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-keyword">string</span>[](<span class="hljs-number">3</span>);
        abiTypeArray[<span class="hljs-number">0</span>] <span class="hljs-operator">=</span> <span class="hljs-string">"string"</span>;
        abiTypeArray[<span class="hljs-number">1</span>] <span class="hljs-operator">=</span> <span class="hljs-string">"string"</span>;
        abiTypeArray[<span class="hljs-number">2</span>] <span class="hljs-operator">=</span> <span class="hljs-string">"bytes"</span>;

        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> gmpPayload;
        gmpPayload <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(
            <span class="hljs-string">"receive_message_evm"</span>,
            argumentNameArray,
            abiTypeArray,
            argValues
        );

        <span class="hljs-keyword">return</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encodePacked</span>(
            <span class="hljs-keyword">bytes4</span>(<span class="hljs-number">0x00000001</span>),
            gmpPayload
        );
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_execute</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> <span class="hljs-comment">/*sourceChain*/</span>,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> <span class="hljs-comment">/*sourceAddress*/</span>,
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">calldata</span> payload
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> </span>{
        (<span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> sender, <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> message) <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">decode</span>(payload, (<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>));
        storedMessage <span class="hljs-operator">=</span> Message(sender, message);
    }
}
</code></pre>
<p>In the contract above,</p>
<ul>
<li><p><strong>Contract Initialization</strong>: The <code>SendReceive</code> contract inherits from <code>AxelarExecutable</code> and initializes the Axelar gas service and chain name in its constructor</p>
</li>
<li><p><strong>Sending Messages</strong>: The <code>send</code> function allows users to send messages to a specified destination chain and address, requiring a gas payment. It generates a General Message Passing (GMP) payload, pays for the gas, and makes the call through the Axelar gateway</p>
</li>
<li><p><strong>Payload Encoding</strong>: The <code>_encodePayloadToCosmWasm</code> internal function encodes the message payload into a specific format required for CosmWasm contracts, including schema versioning and argument encoding</p>
</li>
<li><p><strong>Message Reception</strong>: The <code>_execute</code> function decodes the received message payload and stores the message in the contract's state, handling incoming messages from other chains</p>
</li>
</ul>
<h3 id="heading-compile-contract">Compile contract</h3>
<p>You can proceed to compile the smart contract. Click the compile icon, and then the compile buttons are shown below.</p>
<p><img src="https://docs.axelar.dev/images/cosmos/compile-contract.png" alt="Compile contract" /></p>
<h3 id="heading-deploy-contract">Deploy contract</h3>
<p>Deploying the smart contract to Avalanche testnets requires specifying the Axelar Gateway Service and Gas Service contracts in the argument. <a target="_blank" href="/resources/contract-addresses/testnet/">Here is the list</a> of Axelar Gas Service and Gateway contracts for all the chains currently supported by Axelar.</p>
<p>This contract you want to deploy requires the Gas Service, Gateway, and Chain Name, which will be passed on to the constructor before deployment, as shown below.</p>
<p>Click the deploy icon on Remix, as shown below.</p>
<p><img src="https://docs.axelar.dev/images/cosmos/deploy-contract.png" alt="Click the deploy icon on Remix, as shown below." /></p>
<p>Select the deployment target, Injected Provider - MetaMask.</p>
<p>Add the Axelar <code>Gateway</code>: <code>0xC249632c2D40b9001FE907806902f63038B737Ab</code> and the <code>Gas Service</code>: <code>0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6</code> contract address deployed on Avalanche and chain name: <code>Avalanche</code>.</p>
<p>Next, click the <code>transact</code> button.</p>
<p><img src="https://docs.axelar.dev/images/cosmos/transact.png" alt="click the transact button." /></p>
<h3 id="heading-copy-contract-address">Copy contract address</h3>
<p>Copy the contract address and save it somewhere; you will need it in the following section to send a message from the Coswasm contract to Avalanche.</p>
<p><img src="https://docs.axelar.dev/images/cosmos/copy-address.png" alt="Copy contract address" /></p>
<p>Address <a target="_blank" href="https://testnet.snowtrace.io/address/0x113BD07720a5Ae9104C5d54fBDfA83F792afc8e0">0x113BD07720a5Ae9104C5d54fBDfA83F792afc8e0</a> Details - Avalanche Testnet.</p>
<h2 id="heading-send-a-message-from-a-cosmwasm-contract-to-avalanche">Send a message from a CosmWasm contract to Avalanche</h2>
<p>You are all set to send a message from the CosmWasm contract you deployed to Avalanche. Create a new file with the name <code>index.js</code> in the root directory.</p>
<h3 id="heading-import-dependencies">Import dependencies</h3>
<p>To import the required dependencies add the following code snippet.</p>
<pre><code class="lang-js"><span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config();
<span class="hljs-keyword">const</span> { GasPrice } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"@cosmjs/stargate"</span>);
<span class="hljs-keyword">const</span> { SigningCosmWasmClient } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"@cosmjs/cosmwasm-stargate"</span>);
<span class="hljs-keyword">const</span> { AxelarQueryAPI } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"@axelar-network/axelarjs-sdk"</span>);
<span class="hljs-keyword">const</span> { DirectSecp256k1Wallet } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"@cosmjs/proto-signing"</span>);
<span class="hljs-keyword">const</span> { fromHex } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"@cosmjs/encoding"</span>);
</code></pre>
<ul>
<li><p>The script uses <code>dotenv</code> to load environment variables and imports essential modules from <code>@cosmjs/stargate</code>, <code>@cosmjs/cosmwasm-stargate</code>, <code>@axelar-network/axelarjs-sdk</code>, and <code>@cosmjs/proto-signing</code> to interact with Cosmos and Axelar networks</p>
</li>
<li><p>The <code>fromHex</code> function from <code>@cosmjs/encoding</code> is imported for decoding hex strings, which is crucial for handling private keys and other hexadecimal data formats</p>
</li>
</ul>
<h3 id="heading-set-up-the-environment-api-settings-token-and-contract-details">Set up the environment, API settings, token, and contract details</h3>
<p>You need to define a few variables to be used in the script for the environment, API settings, token, and contract details. To do that, add the following code snippet.</p>
<pre><code class="lang-js"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Environment and API settings</span>
<span class="hljs-keyword">const</span> privateKey = process.env.PRIVATE_KEY;
<span class="hljs-keyword">const</span> rpcEndpoint = <span class="hljs-string">"https://rpc.osmotest5.osmosis.zone"</span>;
<span class="hljs-keyword">const</span> chainId = <span class="hljs-string">"osmosis-7"</span>;
<span class="hljs-keyword">const</span> testnetEnvironment = <span class="hljs-string">"testnet"</span>;

<span class="hljs-comment">// Token and contract details</span>
<span class="hljs-keyword">const</span> aUSDC =
  <span class="hljs-string">"ibc/1587E7B54FC9EFDA2350DC690EC2F9B9ECEB6FC31CF11884F9C0C5207ABE3921"</span>; <span class="hljs-comment">// aUSDC IBC address</span>
<span class="hljs-keyword">const</span> osmoDenom = <span class="hljs-string">"uosmo"</span>;
<span class="hljs-keyword">const</span> gasPriceString = <span class="hljs-string">`0.4<span class="hljs-subst">${osmoDenom}</span>`</span>;
<span class="hljs-keyword">const</span> wasmContractAddress =
  <span class="hljs-string">"osmo1vqgrchlfuymkjrzmrjznpam3xtzfemthzue43yt8l4ug046rtvwqarcl8r"</span>;
</code></pre>
<h3 id="heading-add-evm-contract-details">Add EVM contract details</h3>
<pre><code class="lang-js"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Message details</span>
<span class="hljs-keyword">const</span> destinationChain = <span class="hljs-string">"Avalanche"</span>;
<span class="hljs-keyword">const</span> destinationAddress = <span class="hljs-string">"0x113BD07720a5Ae9104C5d54fBDfA83F792afc8e0"</span>; <span class="hljs-comment">// Replace with the Avalanche address you deployed</span>
<span class="hljs-keyword">const</span> messageToSend = <span class="hljs-string">"Hello world from Osmosis!"</span>;
</code></pre>
<p>Replace <code>0x113BD07720a5Ae9104C5d54fBDfA83F792afc8e0</code> with the contract address you copied from Remix earlier when you deployed on Avalanche.</p>
<h3 id="heading-decode-the-private-key-and-create-a-wallet">Decode the Private Key and Create a Wallet</h3>
<p>Now, decode your private key and create a wallet:</p>
<pre><code class="lang-js"><span class="hljs-comment">//...</span>

(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Decode the private key from hex</span>
    <span class="hljs-keyword">const</span> decodedPrivateKey = fromHex(privateKey);

    <span class="hljs-comment">// Create a wallet from the private key</span>
    <span class="hljs-keyword">const</span> wallet = <span class="hljs-keyword">await</span> DirectSecp256k1Wallet.fromKey(
      decodedPrivateKey,
      <span class="hljs-string">"osmo"</span>,
    );
    <span class="hljs-keyword">const</span> [{ address }] = <span class="hljs-keyword">await</span> wallet.getAccounts();
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"An error occurred:"</span>, error);
  }
})();
</code></pre>
<h3 id="heading-connect-to-the-client">Connect to the Client</h3>
<p>Set up the client to interact with the blockchain:</p>
<pre><code class="lang-js"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Connect to the client</span>
<span class="hljs-keyword">const</span> gasPrice = GasPrice.fromString(gasPriceString);
<span class="hljs-keyword">const</span> client = <span class="hljs-keyword">await</span> SigningCosmWasmClient.connectWithSigner(
  rpcEndpoint,
  wallet,
  { gasPrice },
);
</code></pre>
<h3 id="heading-retrieve-and-log-balances">Retrieve and Log Balances</h3>
<p>Retrieve the balances of aUSDC and OSMO tokens and log them:</p>
<pre><code class="lang-js"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Retrieve balances</span>
<span class="hljs-keyword">const</span> balanceUsdc = <span class="hljs-keyword">await</span> client.getBalance(address, aUSDC);
<span class="hljs-keyword">const</span> balanceOsmo = <span class="hljs-keyword">await</span> client.getBalance(address, osmoDenom);

<span class="hljs-comment">// Log wallet information</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"----- Wallet Info -----"</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Wallet address: <span class="hljs-subst">${address}</span>`</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`aUSDC balance: <span class="hljs-subst">${balanceUsdc.amount / <span class="hljs-number">1e6</span>}</span> aUSDC`</span>);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Osmo balance: <span class="hljs-subst">${balanceOsmo.amount / <span class="hljs-number">1e6</span>}</span> OSMO\\n`</span>);
</code></pre>
<h3 id="heading-estimate-gas-fee">Estimate Gas Fee</h3>
<p>Estimate the gas fee for sending the message:</p>
<pre><code class="lang-js"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Estimate gas fee</span>
<span class="hljs-keyword">const</span> api = <span class="hljs-keyword">new</span> AxelarQueryAPI({ <span class="hljs-attr">environment</span>: testnetEnvironment });
<span class="hljs-keyword">const</span> gasAmount = <span class="hljs-keyword">await</span> api.estimateGasFee(
  chainId,
  destinationChain,
  <span class="hljs-number">100000</span>,
  <span class="hljs-string">"auto"</span>,
  <span class="hljs-string">"aUSDC"</span>,
);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Estimated gas fee: <span class="hljs-subst">${<span class="hljs-built_in">parseInt</span>(gasAmount) / <span class="hljs-number">1e6</span>}</span> aUSDC`</span>);
</code></pre>
<h3 id="heading-check-for-sufficient-balances">Check for Sufficient Balances</h3>
<p>Ensure you have enough balances to cover the gas fees:</p>
<pre><code class="lang-js"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Check for sufficient balances</span>
<span class="hljs-keyword">if</span> (balanceUsdc.amount &lt; gasAmount) {
  <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Insufficient aUSDC balance to pay for gas fee"</span>);
  <span class="hljs-keyword">return</span> process.exit(<span class="hljs-number">0</span>);
}

<span class="hljs-keyword">if</span> (balanceOsmo.amount &lt; <span class="hljs-number">1e6</span>) {
  <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Insufficient OSMO balance to pay for gas fee"</span>);
  <span class="hljs-keyword">return</span> process.exit(<span class="hljs-number">0</span>);
}
</code></pre>
<h3 id="heading-query-message-from-the-osmosis-contract">Query Message from the Osmosis Contract</h3>
<p>Retrieve a stored message from the Osmosis contract:</p>
<pre><code class="lang-js"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Query message from the osmosis contract</span>
<span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> client.queryContractSmart(wasmContractAddress, {
  <span class="hljs-attr">get_stored_message</span>: {},
});
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message from Osmosis contract:"</span>, response.message);
</code></pre>
<h3 id="heading-prepare-and-send-the-message">Prepare and Send the Message</h3>
<p>Prepare the payload and send the message to the Osmosis contract:</p>
<pre><code class="lang-js"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Prepare payload to send message to osmosis contract</span>
<span class="hljs-keyword">const</span> payload = {
  <span class="hljs-attr">send_message_evm</span>: {
    <span class="hljs-attr">destination_chain</span>: destinationChain,
    <span class="hljs-attr">destination_address</span>: destinationAddress,
    <span class="hljs-attr">message</span>: messageToSend,
  },
};

<span class="hljs-keyword">const</span> fee = {
  <span class="hljs-attr">amount</span>: gasAmount,
  <span class="hljs-attr">denom</span>: aUSDC,
};

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Sending message to Osmosis contract..."</span>);

<span class="hljs-comment">// Execute transaction</span>
<span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> client.execute(
  address,
  wasmContractAddress,
  payload,
  <span class="hljs-string">"auto"</span>,
  <span class="hljs-literal">undefined</span>,
  [fee],
);

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Sent:"</span>, result.transactionHash);
</code></pre>
<h3 id="heading-test-sending-a-message-from-coswasm-contract-to-avalanche">Test sending a message from Coswasm contract to Avalanche</h3>
<p>You have successfully implemented sending messages from the CosmWasm contract you deployed earlier. It's time to test the implementation. Use the following command to run the script and ensure you are in the project's root directory.</p>
<pre><code class="lang-bash">node index.js
</code></pre>
<p>You should see something similar to what is displayed below on your terminal if the test is successful:</p>
<pre><code class="lang-bash">----- Wallet Info -----
Wallet address: osmo16m62wcd7dyednttjgayc08n22z509a70vcekuu
aUSDC balance: 48.553691 aUSDC
Osmo balance: 109.698386 OSMO

Estimated gas fee: 0.344874 aUSDC
Message from Osmosis contract: none
Sending message to Osmosis contract...
Sent: F19AB19C94794CF5BD2E480E1CEFD893D1E74E7CC709ADC8260736BCC253AD27
</code></pre>
<p>In case you run into an error like the following:</p>
<pre><code class="lang-bash">Error: Client network socket disconnected before secure TLS connection was established
    at connResetException (node:internal/errors:705:14)
    at TLSSocket.onConnectEnd (node:_tls_wrap:1594:19)
    at TLSSocket.emit (node:events:525:35)
    at endReadableNT (node:internal/streams/readable:1358:12)
    at processTicksAndRejections (node:internal/process/task_queues:83:21) {
    code: <span class="hljs-string">'ECONNRESET'</span>,
    path: null,
    host: <span class="hljs-string">'rpc.osmotest5.osmosis.zone'</span>,
    port: 443,
    localAddress: undefined
}
</code></pre>
<p>Wait a bit and retry.</p>
<p>If you encounter the error <code>"Insufficient aUSDC balance to pay for gas fee,"</code> please proceed to the <a target="_blank" href="https://discord.com/invite/axelar">Axelar Discord server</a>. In the faucet channel, kindly paste your axl wallet address in this format: <code>!faucet axelar16m62wcd7dyednttjgayc08n22z509a70qduwp0</code>, and then conduct an IBC transfer to your osmo wallet address.</p>
<p>Check transaction on Axelarscan testnet.</p>
<p>If you do not have any errors, you can copy the transaction hash logged on the console, head over to the <a target="_blank" href="https://testnet.axelarscan.io/">Axelarscan testnet</a>, and paste it; you should be able to see how the message is sent from Osmosis to Avalanche via Axelar. You can find an example of the transaction <a target="_blank" href="https://testnet.axelarscan.io/gmp/F19AB19C94794CF5BD2E480E1CEFD893D1E74E7CC709ADC8260736BCC253AD27">here</a>.</p>
<h2 id="heading-read-a-message-from-an-evm-smart-contract-on-avalanche">Read a message from an EVM smart contract on Avalanche</h2>
<p>You have successfully sent a message from your CosmWasm contract to Avalanche; let's confirm that the message was actually sent and arrived on Avalanche.</p>
<p>Head back to <a target="_blank" href="https://remix.ethereum.org/">https://remix.ethereum.org/</a>, find the contract you deployed earlier, and click on the <code>storedMessage</code> button, as shown below. You should see "Hello world from Osmosis!" logged, which indicates that your message was successfully sent from the CosmWasm contract and received on the Avalanche contract.</p>
<p><img src="https://docs.axelar.dev/images/cosmos/read-message-from-evm.png" alt="Read a message from an EVM smart contract on Avalanche" /></p>
<h2 id="heading-send-a-message-from-evm-to-a-cosmwasm-contract-on-osmosis">Send a message from EVM to a CosmWasm contract on Osmosis</h2>
<p>You have been able to send the message successfully in the previous step; now, proceed to send a message from Avalanche to the same CosmWasm contract on Osmosis. To do that, on Remix, click on the arrow icon beside the “Send” button and enter the following details.</p>
<pre><code class="lang-bash">destinationChain: osmosis-7

destinationAddress: osmo1vqgrchlfuymkjrzmrjznpam3xtzfemthzue43yt8l4ug046rtvwqarcl8r

message: Hello from Avalanche
</code></pre>
<p>Make sure to replace <code>osmo1vqgrchlfuymkjrzmrjznpam3xtzfemthzue43yt8l4ug046rtvwqarcl8r</code> with your contract address on Osmosis.</p>
<p><img src="https://docs.axelar.dev/images/cosmos/contract-address.png" alt /></p>
<p>Next, pass a gas value in Gwei, in this example we passed 10000000 Gwei.</p>
<p><img src="https://docs.axelar.dev/images/cosmos/insert-gas.png" alt /></p>
<p><img src="https://docs.axelar.dev/images/cosmos/click-transact.png" alt="Click the transact button" /></p>
<p>After confirming the transaction on the MetaMask popup, you can proceed to verify the transaction onchain on the Axelarscan testnet by copying the transaction hash and pasting it. Here is an <a target="_blank" href="https://testnet.axelarscan.io/gmp/0x181b558f4ae74812b8ab0cacbf5b2cf4abe51dee713e15fcf1038fe441f722c0">example</a>.</p>
<h2 id="heading-read-a-message-from-a-cosmwasm-contract-on-osmosis">Read a message from a CosmWasm contract on Osmosis</h2>
<p>In the previous step, you have successe=fully sent a message from Avalanche to Osmosis, in this step you will read the message from Osmosi to confirm it was truly received on Osmosis. To do that, create a new file, <code>read.js</code>, in the root folder of your project and add the following code snippet.</p>
<pre><code class="lang-js"><span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config();
<span class="hljs-keyword">const</span> { GasPrice } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"@cosmjs/stargate"</span>);
<span class="hljs-keyword">const</span> { SigningCosmWasmClient } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"@cosmjs/cosmwasm-stargate"</span>);
<span class="hljs-keyword">const</span> { DirectSecp256k1Wallet } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"@cosmjs/proto-signing"</span>);
<span class="hljs-keyword">const</span> { fromHex } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"@cosmjs/encoding"</span>);

<span class="hljs-comment">// Environment and API settings</span>
<span class="hljs-keyword">const</span> privateKey = process.env.PRIVATE_KEY;
<span class="hljs-keyword">const</span> rpcEndpoint = <span class="hljs-string">"https://rpc.osmotest5.osmosis.zone"</span>;

<span class="hljs-comment">// Token and contract details</span>
<span class="hljs-keyword">const</span> aUSDC =
  <span class="hljs-string">"ibc/1587E7B54FC9EFDA2350DC690EC2F9B9ECEB6FC31CF11884F9C0C5207ABE3921"</span>;
<span class="hljs-keyword">const</span> osmoDenom = <span class="hljs-string">"uosmo"</span>;
<span class="hljs-keyword">const</span> gasPriceString = <span class="hljs-string">`0.4<span class="hljs-subst">${osmoDenom}</span>`</span>;
<span class="hljs-keyword">const</span> wasmContractAddress =
  <span class="hljs-string">"osmo1vqgrchlfuymkjrzmrjznpam3xtzfemthzue43yt8l4ug046rtvwqarcl8r"</span>;

(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Decode the private key from hex</span>
    <span class="hljs-keyword">const</span> decodedPrivateKey = fromHex(privateKey);

    <span class="hljs-comment">// Create a wallet from the private key</span>
    <span class="hljs-keyword">const</span> wallet = <span class="hljs-keyword">await</span> DirectSecp256k1Wallet.fromKey(
      decodedPrivateKey,
      <span class="hljs-string">"osmo"</span>,
    );
    <span class="hljs-keyword">const</span> [{ address }] = <span class="hljs-keyword">await</span> wallet.getAccounts();

    <span class="hljs-comment">// Connect to the client</span>
    <span class="hljs-keyword">const</span> gasPrice = GasPrice.fromString(gasPriceString);
    <span class="hljs-keyword">const</span> client = <span class="hljs-keyword">await</span> SigningCosmWasmClient.connectWithSigner(
      rpcEndpoint,
      wallet,
      { gasPrice },
    );

    <span class="hljs-comment">// Retrieve balances</span>
    <span class="hljs-keyword">const</span> balanceUsdc = <span class="hljs-keyword">await</span> client.getBalance(address, aUSDC);
    <span class="hljs-keyword">const</span> balanceOsmo = <span class="hljs-keyword">await</span> client.getBalance(address, osmoDenom);

    <span class="hljs-comment">// Log wallet information</span>
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"----- Wallet Info -----"</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Wallet address: <span class="hljs-subst">${address}</span>`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`aUSDC balance: <span class="hljs-subst">${balanceUsdc.amount / <span class="hljs-number">1e6</span>}</span> aUSDC`</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Osmo balance: <span class="hljs-subst">${balanceOsmo.amount / <span class="hljs-number">1e6</span>}</span> OSMO\n`</span>);

    <span class="hljs-comment">// Query message from the osmosis contract</span>
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> client.queryContractSmart(wasmContractAddress, {
      <span class="hljs-attr">get_stored_message</span>: {},
    });
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message from Osmosis contract:"</span>, response.message);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"An error occurred:"</span>, error);
  }
})();
</code></pre>
<p>You should see something similar to what is displayed below on your terminal if the test is successful:</p>
<pre><code class="lang-bash">----- Wallet Info -----
Wallet address: osmo16m62wcd7dyednttjgayc08n22z509a70vcekuu
aUSDC balance: 48.208817 aUSDC
Osmo balance: 109.58592 OSMO

Message from Osmosis contract: Hello from Avalanche
</code></pre>
<p>Woohoo! If you made it this far, congratulations.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you have learned how to build and deploy an EVM smart contract on Avalanche, build and deploy a CosmWasm contract on Osmosis, send a message from a CosmWasm contract to Avalanche, read a message from an EVM smart contract on Avalanche, send a message from EVM to a CosmWasm contract on Osmosis, and read a message from a CosmWasm contract on Osmosis.</p>
<p>By mastering these steps, you can effectively create interoperable decentralized applications that leverage the strengths of both EVM-based and Cosmos-based blockchain networks.</p>
<h2 id="heading-reference">Reference</h2>
<ul>
<li><p><a target="_blank" href="/dev/cosmos-gmp/overview/">Axelar Cosmos General Message Passing</a></p>
</li>
<li><p><a target="_blank" href="https://testnet.axelarscan.io/">Axelarscan Testnet</a></p>
</li>
<li><p><a target="_blank" href="https://faucet.testnet.osmosis.zone/">Osmosis Testnet Faucet</a></p>
</li>
<li><p><a target="_blank" href="https://mintscan.io/osmosis-testnet">Osmosis Testnet Explorer</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How Merkle Proofs Work]]></title><description><![CDATA[You have millions of unique images in your gallery, each representing a piece of private or personal data stored on your phone. After an incident, you lost your device, but it was returned to you after many months, with claims that the images hadn't ...]]></description><link>https://blog.idrisolubisi.com/how-merkle-proofs-work</link><guid isPermaLink="true">https://blog.idrisolubisi.com/how-merkle-proofs-work</guid><category><![CDATA[merkle tree]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Cryptocurrency]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Fri, 31 May 2024 09:00:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1717104802886/35626d42-4ac8-4076-853e-e0def6846a78.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You have millions of unique images in your gallery, each representing a piece of private or personal data stored on your phone. After an incident, you lost your device, but it was returned to you after many months, with claims that the images hadn't been tampered with.</p>
<p>Verifying the authenticity of each image in this gallery could be difficult, right? How can they prove the images haven't been manipulated, or how can you confirm everything is as it should be? That's where <strong>Merkle's proofs</strong> come into play, as they offer a solution to verify the integrity of large datasets without the need to inspect each item individually.</p>
<p>In this tutorial, you will learn about Merkle proofs, how to create them using a <a target="_blank" href="https://en.wikipedia.org/wiki/Merkle_tree">Merkle Tree</a>, and how to implement Merkle proofs for whitelisting email addresses using JavaScript.</p>
<p>To understand how Merkle proofs help verify the authenticity and integrity of your data without the need to check each piece individually, such as your image gallery, as discussed earlier, you first need to understand the structure that underpins them: the <strong>Merkle Tree</strong>.</p>
<h2 id="heading-what-is-a-merkle-tree">What is a Merkle Tree?</h2>
<p>A <a target="_blank" href="https://en.wikipedia.org/wiki/Merkle_tree">Merkle Tree</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Merkle_tree">also known</a> as a hash tree, is a binary tree structure used to verify a data set's integrity effectively. It was a concept named after the computer scientist <a target="_blank" href="https://en.wikipedia.org/wiki/Ralph_Merkle">Ralph Merkle</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Ralph_Merkle">who patented</a> it in 1979.</p>
<p>This binary t<a target="_blank" href="https://en.wikipedia.org/wiki/Merkle_tree">ree structu</a>re has each leaf node representing a block of data or a piece of information. Instead of containing the data directly, the internal nodes hold a cryptographic h<a target="_blank" href="https://en.wikipedia.org/wiki/Ralph_Merkle">ash of their</a> child nodes. The tree is built by repeatedly hashing pairs of child nodes until a single root hash is achieved.</p>
<h2 id="heading-components-of-merkle-tree">Components of Merkle Tree</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715416558091/c9877802-d859-47c2-b5e2-9e218e5565b9.jpeg" alt=" Merkle Tree image by Teemu Kanstrén" class="image--center mx-auto" /></p>
<p><em>Merkle Tree image by Teemu Kanstrén</em></p>
<p>A Merkle tree has three different components, as shown in the image above Merkle root, Merkle branches, and Merkle leaves. Let's take a look at what they are.</p>
<ul>
<li><p><strong>Merkle root</strong> is derived from hashing together the child hashes beneath it and down to the leaves. It is a single hash on its own that represents the top of the Merkle tree, as shown in the image above and is often used to store block headers in <a target="_blank" href="https://en.wikipedia.org/wiki/Blockchain">blockchain</a> content without downloading the entire block.</p>
</li>
<li><p>In a Merkle tree, we have <strong>Merkle branches</strong>, intermediate nodes between Merkle roots and Merkle leaves. Each branch node is created by hashing together the hashes of its child nodes. These branches form the connections between the leaves (where the data resides) and the Merkle root, making it easier to ensure that the Merkle tree can be efficiently tra<a target="_blank" href="https://en.wikipedia.org/wiki/Blockchain">versed and</a> verified.</p>
</li>
<li><p><strong>Merkle leaves</strong> are the nodes at the bottom layer of the Merkle tree. They contain hashes of the actual data stored. The leaves are the foundation of the Merkle tree, as their hashes are combined and rehashed to produce the hashes of the nodes above them, ultimately leading to the Merkle root.</p>
</li>
</ul>
<p>Additionally, we have the <strong>Data nodes</strong>, a layer representing how data is supplied to start the process before it hashed in the next layer(Merkle leaves), which is the Merkle leaves, as shown in the image.</p>
<h2 id="heading-what-is-a-merkle-proof">What is a Merkle Proof?</h2>
<p>A Merkle proof is a method used to verify the presence and integrity of specific data within a dataset using a Merkle tree. It comprises a single data block (leaf), a series of hashes from the tree (branches), and the Merkle root.</p>
<p>While Merkle proof is used to verify the presence of specific data within a dataset using a Merkle tree, here are some areas where Merkle proof can be applied.</p>
<ul>
<li><p>In a distributed system for data verification</p>
</li>
<li><p>Secure communication protocols</p>
</li>
<li><p>Data storage solution</p>
</li>
<li><p>Cryptocurrencies and blockchain</p>
</li>
</ul>
<h2 id="heading-implementing-a-merkle-proof-for-whitelisting-email-addresses">Implementing a Merkle Proof for Whitelisting Email Addresses</h2>
<p>Let's implement a Merkle proof for whitelisting email addresses in this section.</p>
<h3 id="heading-prerequisite">Prerequisite</h3>
<ul>
<li><p><a target="_blank" href="https://nodejs.org/en/">Node.js</a> and its package manager NPM, version 18. Verify Node.js is installed by running the followi<a target="_blank" href="https://nodejs.org/en/">ng term</a>inal command: <code>node -v &amp;&amp; npm -v</code></p>
</li>
<li><p>A basic understanding of <a target="_blank" href="https://www.w3schools.com/js/default.asp">JavaScript</a></p>
</li>
</ul>
<h3 id="heading-project-setup-and-installation">Project Setup and Installation</h3>
<p>Navigate to any directory of <a target="_blank" href="https://nodejs.org/en/">your c</a>hoice, and then r<a target="_blank" href="https://www.w3schools.com/js/default.asp">un the fol</a>lowing commands to create a new folder and change the directory into the folder:</p>
<pre><code class="lang-bash">mkdir merkle-proof-tutorial
<span class="hljs-built_in">cd</span> merkle-proof-tutorial
</code></pre>
<p><a target="_blank" href="https://www.w3schools.com/js/default.asp">Next,</a> you need to install the <code>merkletreejs</code> and <code>crypto-js</code> libraries, which will be needed to create a Merkle tree and hash data using the following command:</p>
<pre><code class="lang-bash">npm i merkletreejs crypto-js
</code></pre>
<p>Create a new file <code>proof.js</code> feel free to name it whatever you want, but for this tutorial, you will name it <code>proof.js</code>.</p>
<h3 id="heading-import-libraries">Import Libraries</h3>
<p>You will be using the <code>merkletreejs</code> and <code>crypto-js</code> libraries in this example to create a Merkle tree and hash the data, respectively.</p>
<p>Navigate into the <code>proof.js</code> file and add the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { MerkleTree } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'merkletreejs'</span>)
<span class="hljs-keyword">const</span> SHA256 = <span class="hljs-built_in">require</span>(<span class="hljs-string">'crypto-js/sha256'</span>)
</code></pre>
<h3 id="heading-create-a-list-of-emails-to-be-whitelisted">Create a List of Emails to Be Whitelisted</h3>
<p>You need to create a list of emails to be whitelisted. In this example, you will add three emails, but it could be millions of emails, depending on the data you want to test with. Add the following code snippet to create an array of three email addresses:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// List of email addresses to be whitelisted</span>
<span class="hljs-keyword">const</span> emails = [<span class="hljs-string">"example1@mail.com"</span>, <span class="hljs-string">"example2@mail.com"</span>, <span class="hljs-string">"example3@mail.com"</span>];
</code></pre>
<h3 id="heading-convert-emails-to-hashes-and-build-the-merkle-tree">Convert Emails to Hashes and Build the Merkle Tree</h3>
<p>Next, you need to convert each email into a hash and create the Merkle tree using the hashed emails with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Convert each email into a hash</span>
<span class="hljs-keyword">const</span> leaves = emails.map(<span class="hljs-function"><span class="hljs-params">email</span> =&gt;</span> SHA256(email));

<span class="hljs-comment">// Create the Merkle Tree using the hashed emails</span>
<span class="hljs-keyword">const</span> tree = <span class="hljs-keyword">new</span> MerkleTree(leaves, SHA256);

<span class="hljs-comment">// Get the root and convert it to a hexadecimal string</span>
<span class="hljs-keyword">const</span> root = tree.getRoot().toString(<span class="hljs-string">'hex'</span>);
</code></pre>
<h3 id="heading-add-function-to-verify-whitelisted-emails">Add Function to Verify Whitelisted Emails</h3>
<p>In the previous step, you created a tree for the addresses; next, you must create a function to prove if an email is part of the whitelisted emails.</p>
<p>Create a function <code>verifyEmail</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Function to verify if an email is whitelisted</span>
<span class="hljs-keyword">const</span> verifyEmail = <span class="hljs-function">(<span class="hljs-params">email</span>) =&gt;</span> {
  <span class="hljs-comment">// Hash the email to be verified</span>
  <span class="hljs-keyword">const</span> hashedEmail = SHA256(email);

  <span class="hljs-comment">// Get the proof for the hashed email from the tree</span>
  <span class="hljs-keyword">const</span> proof = tree.getProof(hashedEmail);

  <span class="hljs-comment">// Verify the proof against the root of the tree; returns true if valid, false otherwise</span>
  <span class="hljs-keyword">const</span> verified = tree.verify(proof, hashedEmail, root);

  <span class="hljs-comment">// Log the result to the console</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${email}</span> is <span class="hljs-subst">${verified ? <span class="hljs-string">"whitelisted"</span> : <span class="hljs-string">"not whitelisted"</span>}</span>.`</span>);
};
</code></pre>
<p>In the code snippet, you created a function verifying whether an email is whitelisted. To do this, you:</p>
<ul>
<li><p>Hashed the email to be verified using SHA256</p>
</li>
<li><p>Got the proof for the hashed email using the <code>getProof</code> method</p>
</li>
<li><p>Verified the proof against the root of the tree</p>
</li>
</ul>
<p>Here is what the complete code looks like:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { MerkleTree } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"merkletreejs"</span>);
<span class="hljs-keyword">const</span> SHA256 = <span class="hljs-built_in">require</span>(<span class="hljs-string">"crypto-js/sha256"</span>);

<span class="hljs-comment">// List of email addresses to be whitelisted</span>
<span class="hljs-keyword">const</span> emails = [<span class="hljs-string">"example1@mail.com"</span>, <span class="hljs-string">"example2@mail.com"</span>, <span class="hljs-string">"example3@mail.com"</span>];

<span class="hljs-comment">// Convert each email into a hash</span>
<span class="hljs-keyword">const</span> leaves = emails.map(<span class="hljs-function">(<span class="hljs-params">email</span>) =&gt;</span> SHA256(email));

<span class="hljs-comment">// Create the Merkle Tree using the hashed emails</span>
<span class="hljs-keyword">const</span> tree = <span class="hljs-keyword">new</span> MerkleTree(leaves, SHA256);

<span class="hljs-comment">// Get the root and convert it to a hexadecimal string</span>
<span class="hljs-keyword">const</span> root = tree.getRoot().toString(<span class="hljs-string">"hex"</span>);

<span class="hljs-comment">// Function to verify if an email is whitelisted</span>
<span class="hljs-keyword">const</span> verifyEmail = <span class="hljs-function">(<span class="hljs-params">email</span>) =&gt;</span> {
  <span class="hljs-comment">// Hash the email to be verified</span>
  <span class="hljs-keyword">const</span> hashedEmail = SHA256(email);

  <span class="hljs-comment">// Get the proof for the hashed email from the tree</span>
  <span class="hljs-keyword">const</span> proof = tree.getProof(hashedEmail);

  <span class="hljs-comment">// Verify the proof against the root of the tree; returns true if valid, false otherwise</span>
  <span class="hljs-keyword">const</span> verified = tree.verify(proof, hashedEmail, root);

  <span class="hljs-comment">// Log the result to the console</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${email}</span> is <span class="hljs-subst">${verified ? <span class="hljs-string">"whitelisted"</span> : <span class="hljs-string">"not whitelisted"</span>}</span>.`</span>);
};
</code></pre>
<h3 id="heading-test-the-verification-function">Test the Verification Function</h3>
<p>In this section, you will test the verification function with a whitelisted and non-whitelisted email.</p>
<p>Test with a whitelisted email address by calling the <code>verifyEmail</code> function inside the script file.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

verifyEmail(<span class="hljs-string">"example2@mail.com"</span>);  <span class="hljs-comment">// Expected output: "example2@mail.com is whitelisted."</span>
</code></pre>
<p>To run the script, use the following command:</p>
<pre><code class="lang-bash">node proof.js
</code></pre>
<p>The result printed on the console will return a response as shown below, indicating the email address is whitelisted because it is part of the emails we added to the email array.</p>
<p>Next, test with an email that is not whitelisted.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

verifyEmail(<span class="hljs-string">"x@mail.com"</span>); 
<span class="hljs-comment">// Expected output: "x@mail.com is not whitelisted."</span>
</code></pre>
<p>You should see a response indicating the email is not whitelisted, as shown below. This is because it wasn't part of the emails whitelisted, meaning there is no proof for the email address to indicate it was part of the tree.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you learned about Merkle proofs, how they can be used to ensure the integrity of datasets in applications, how to create them using a Merkle Tree, and how to implement Merkle proofs for whitelisting email addresses using JavaScript.</p>
<h2 id="heading-references">References</h2>
<ul>
<li><p><a target="_blank" href="https://en.wikipedia.org/wiki/Merkle_tree">Merkle Tree</a></p>
</li>
<li><p><a target="_blank" href="https://www.npmjs.com/package/merkletreejs">Merkletreejs SDK</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Celebrating One Year Working on Axelar: Building the Interoperability Future]]></title><description><![CDATA[gm builders!
It's been a while since I published my last piece of content here. I'm back—not to dwell on the gap but to share my excitement for what lies ahead. Above all, I'm celebrating a year as a Developer Advocate working on Axelar with the best...]]></description><link>https://blog.idrisolubisi.com/celebrating-one-year-working-on-axelar-building-the-interoperability-future</link><guid isPermaLink="true">https://blog.idrisolubisi.com/celebrating-one-year-working-on-axelar-building-the-interoperability-future</guid><category><![CDATA[axelar]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Career]]></category><category><![CDATA[community]]></category><category><![CDATA[development]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Thu, 04 Apr 2024 10:36:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1712055615780/e777de7f-8a6e-4e9d-8654-2202b8aab7bb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>gm builders!</p>
<p>It's been a while since I published my last piece of content here. I'm back—not to dwell on the gap but to share my excitement for what lies ahead. Above all, I'm celebrating a year as a Developer Advocate working on Axelar with the best engineers and teams in web3. Woohoo 🥳</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711968713969/136a7ba9-a122-42b5-bd6b-330b30fdb246.jpeg" alt="Idris speaking at Web3 Afrika event" class="image--center mx-auto" /></p>
<p>As I sit down to pen this reflection, I'm reminded of the countless stories where individuals embark on journeys filled with unknowns, armed with nothing but a heart full of dreams and a relentless drive to explore. This narrative resonates universally, mirroring the essence of human curiosity and our innate desire to push beyond the familiar confines of our world.</p>
<p>Exactly one year ago, I found myself at the threshold of such an adventure with Axelar. Much like the protagonist of a story who steps into a new realm, I was filled with a blend of excitement and uncertainty.</p>
<p>In this blog post, I invite you to join me on a retrospective voyage through my first year at Axelar. It's a story of growth, learning, and the relentless pursuit of building bridges in the digital world.</p>
<h2 id="heading-the-motivation">The Motivation</h2>
<p>In the early days, we had <a target="_blank" href="https://bitcoin.org/en/">Bitcoin</a>, <a target="_blank" href="https://en.wikipedia.org/wiki/Vitalik_Buterin">Vitalik</a> and his team take significant steps to enrich the developer ecosystem by <a target="_blank" href="https://www.youtube.com/watch?v=l9dpjN3Mwps">enabling applications to leverage the blockchain through smart contracts</a>. This sparked immense excitement in the "crypto" space, particularly among builders and the curious. It means that whether you were actively involved in the space or not, you couldn't ignore the buzz about NFTs, haha.</p>
<p>Fast forward to late 2021, I became really curious about what powers NFTs. At that time, the space saw an unprecedented boom, and it was everywhere. However, as a backend developer, I used my curiosity to focus on learning about the technology rather than the "hype." Discovering blockchain and its amazing features that could be leveraged made me dive deep into the "Rabbit Hole," and the rest was history.</p>
<p><strong><em>But there was a problem; wait, what?</em></strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712053448125/ad1e1349-61df-4b43-b457-8cb53c4a972a.png" alt="There was a problem" class="image--center mx-auto" /></p>
<p>Yes, I'll discuss the problem in one of the sections of this post; keep reading.</p>
<p>Back to my motivations, Axelar wasn't just another company; it promised a quest toward building the future of interoperability—a concept as vast and uncharted as the deepest oceans or the farthest galaxies in our collective imagination.</p>
<p>This journey at Axelar became my canvas, on which I've painted days of rigorous challenges, moments of unprecedented innovation, and the unyielding pursuit of something truly groundbreaking. It's a tale not unlike those of explorers of old, who set sail to discover new worlds or scientists on the cusp of breakthroughs that could redefine the boundaries of what we believe is possible.</p>
<h2 id="heading-first-year-milestone">First-Year Milestone</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711983138672/8448a28c-daa1-44fc-8aee-217be9e4b855.jpeg" alt="Idris Olubisi speaking at Osmocon conference in Paris" class="image--center mx-auto" /></p>
<p>The list is looooooooooooong!</p>
<p>One of my greatest achievements so far has been collaborating with incredibly talented, brilliant, and passionate engineers and leaders under the guidance of my manager, Stephen Fluin, and the DevRel Team. We've made significant improvements to the current system, focusing on developer experience, supporting developers and partners, and fostering community and leadership, among many other areas. It's already been a year, but it still feels like day one. ;)</p>
<p>During this period, I've learned a great deal about Axelar. I've assisted partners with integration, enabling them to launch on the mainnet. I've delivered <a target="_blank" href="https://www.youtube.com/playlist?list=PLaZ7cT8J_HZbyPjlfLgFCCpA_rAbKaaqg">numerous talks and workshops</a> internationally and locally, created <a target="_blank" href="https://github.com/axelarnetwork/foundry-axelar-gmp-example">boilerplate projects</a> for building and testing cross-chain transactions locally or on testnets using <a target="_blank" href="https://book.getfoundry.sh/">Foundry</a>, hosted and judged several hackathons, enhanced <a target="_blank" href="https://docs.axelar.dev/">developer documentation</a> to support developer success, and worked with top industry leaders, projects, and products.</p>
<p>Additionally, I've built strong relationships, increased developer engagement, gathered feedback to enhance our products, and contributed significantly to developing our developer community, among many other activities.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>It's just day 0, with many more exciting updates to come.</strong></div>
</div>

<h2 id="heading-building-the-interoperability-future">Building the Interoperability Future</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712054075511/f2b4c972-0c96-4b3d-a8eb-66e7ede3d63e.png" alt="Visualize a humorous scenario highlighting the evolution from isolated technological systems to a future of seamless interoperability, without using text on the image. Picture a series of panels or a single scene that progresses from left to right. On the left, depict an individual struggling to connect two ancient, bulky computers with a mess of cables and adapters. In the center, transition to a slightly more modern setup where the individual looks slightly less frustrated but still faces compatibility issues, represented by mismatched devices trying to connect. On the right, show the future of interoperability: the same individual now effortlessly interacts with a diverse array of sleek, modern devices that are all seamlessly connected through glowing, ethereal links. The devices float in harmony, symbolizing the ease and connectivity of the interoperability future. The entire scene should be imbued with a playful tone, using visual cues to convey the transition from frustration to effortless connectivity, all without the need for textual explanation." class="image--center mx-auto" /></p>
<p>In the previous step, I mentioned there was a problem, and I promised to discuss it. The issue is well-known in the blockchain space, where all blockchain ecosystems, including both EVM and non-EVM chains, operate in isolation. These are great solutions that many products use, but there isn't a way to connect these ecosystems together in a decentralized manner without compromising security, decentralization, or the developer experience.</p>
<p>Guess what? We have an answer, and that's <a target="_blank" href="https://axelar.network/">Axelar</a>, connecting over 60+ chains, improving developer experience, security through decentralization, and much more.</p>
<p>That's not all; developing with <a target="_blank" href="https://axelar.network/blog/axelar-virtual-machine-future-of-interoperability">Axelar Virtual Machine</a> elevates the whole process of connectivity, supporting Interchain Maestro and Interchain Amplifier.</p>
<p>What does this mean for the future of interoperability?</p>
<p>With the Interchain Amplifier, developers can deploy and manage their multi-chain dApp instances using the Interchain Token Service, which went live on the mainnet in January. Additionally, <a target="_blank" href="https://docs.axelar.dev/dev/amplifier/introduction">the Interchain Amplifier</a>, recently launched, offers a permissionless model and service. This allows anyone to easily create a connection to the Axelar network and all its interconnected chains.</p>
<h2 id="heading-why-im-excited">Why I'm Excited</h2>
<p>Everything, YES, everything. One of my greatest aspirations in life and as a professional is always to make an impact and provide solutions to help humanity.</p>
<blockquote>
<p><em>Tiny changes, Remarkable Results</em> - <em>JamesClear</em></p>
</blockquote>
<p>If you're also working on Axelar and reading this, thank you for being amazing and for all the support so far.</p>
<p>To the tech community, tech twitter, <a target="_blank" href="http://developerdao.com">Developer DAO</a>, and all the builders, a big thank you for your support. It means a lot to me.</p>
<p>Gracias!</p>
]]></content:encoded></item><item><title><![CDATA[How to Build a Cross-chain Airdrop Dapp With Solidity, NextJs, and Axelar]]></title><description><![CDATA[Airdrops are part of a strategy for distributing coins or tokens to wallet addresses. In Web3, airdrop serve as a method to reward community members for their contributions and promote adoption, which involves distributing newly minted tokens to thou...]]></description><link>https://blog.idrisolubisi.com/how-to-build-a-cross-chain-airdrop-dapp-with-solidity-nextjs-and-axelar</link><guid isPermaLink="true">https://blog.idrisolubisi.com/how-to-build-a-cross-chain-airdrop-dapp-with-solidity-nextjs-and-axelar</guid><category><![CDATA[Solidity]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[axelar]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Web3]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Thu, 28 Sep 2023 14:24:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1695910899770/4fac3769-e7c8-47ea-80b6-9a93938ed421.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Airdrops are part of a strategy for distributing coins or tokens to wallet addresses. In Web3, airdrop serve as a method to reward community members for their contributions and promote adoption, which involves distributing newly minted tokens to thousands of distinct wallet addresses simultaneously. While this has typically been done on a single blockchain in the past, you will learn how to execute a cross-chain airdrop that extends this process across multiple chains.</p>
<p>In this tutorial, you will learn how to build a cross-chain airdrop decentralized application (dApp) using Solidity, Next.js, and <a target="_blank" href="https://dub.sh/N3LzdKr">Axelar General Message Passing (GMP)</a> for distributing tokens across multiple chains.</p>
<p>What are we building? This application guides you through a simple four-step process that empowers users to:</p>
<ul>
<li><p>Connect their wallet.</p>
</li>
<li><p>Authorize the airdrop token amount for spending.</p>
</li>
<li><p>Add wallet addresses.</p>
</li>
<li><p>Distribute tokens from Polygon to Avalanche testnet via airdrop.</p>
</li>
</ul>
<p>To get started quickly, you'll find the entire code for this tutorial on <a target="_blank" href="https://github.com/axelarnetwork/cross-chain-airdrop-dapp">GitHub</a>. This way, you can explore the application's inner workings as you follow along.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695909709886/d2d9eefd-a967-4b6f-8493-72955dfa2769.png" alt="Cross-chain Airdrop DApp with Solidity, Next.js &amp; Axelar" /></p>
<h2 id="heading-prerequisite">Prerequisite</h2>
<p>Before getting started, you need the following prerequisites:</p>
<ul>
<li><p><a target="_blank" href="https://nodejs.org/en/">Node.js</a> and its package manager NPM, version 18. Verify Node.js is installed by running the following terminal command: <code>node -v &amp;&amp; npm -v</code></p>
</li>
<li><p>A basic understanding of <a target="_blank" href="https://www.w3schools.com/js/default.asp">JavaScript</a>, <a target="_blank" href="https://www.tutorialspoint.com/solidity/index.htm">Solidity</a>, and <a target="_blank" href="https://www.w3schools.com/REACT/DEFAULT.ASP">React/Next.js</a>.</p>
</li>
</ul>
<h2 id="heading-project-setup-and-installation">Project Setup and Installation</h2>
<p>To start the project setup and installation quickly, clone this <a target="_blank" href="https://github.com/axelarnetwork/cross-chain-airdrop-dapp/tree/start">project on GitHub</a> using the following command:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/axelarnetwork/cross-chain-airdrop-dapp.git
</code></pre>
<p>Make sure you're on the <code>start</code> branch using the following command:</p>
<pre><code class="lang-bash">git checkout starter
</code></pre>
<p>Next, change the directory into the cloned folder and install the project locally using npm with the following command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> cross-chain-airdrop-dapp &amp;&amp; npm i &amp;&amp; npm run dev
</code></pre>
<p>The <code>npm run dev</code> will start a Next.js hot-reloading development environment accessible by default at <a target="_blank" href="http://localhost:3000">http://localhost:3000</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695909844171/39fe24fe-e761-4b77-bea9-a23c44e5bb7c.png" alt="How to Build a Cross-chain Airdrop DApp with Solidity, Next.js &amp; Axelar" /></p>
<p>To successfully create a smart contract for an airdrop using Axelar's general message passing, it's important to understand how it enables cross-chain interaction. The following section will explain how it works.</p>
<h2 id="heading-getting-started-with-axelar-general-message-passing-gmp">Getting Started with Axelar General Message Passing (GMP)</h2>
<p><a target="_blank" href="https://dub.sh/N3LzdKr">Axelar's General Message Passing (GMP)</a> feature empowers developers to call any function on interconnected chains seamlessly.</p>
<p>With GMP, developers gain the ability to:</p>
<ol>
<li><p>Call a contract on chain A and interact with a contract on chain B.</p>
</li>
<li><p>Execute cross-chain transactions by calling a contract on chain A and sending tokens to chain B.</p>
</li>
</ol>
<h2 id="heading-building-a-smart-contract-using-hardhat-and-axelar-gmp">Building a smart contract using Hardhat and Axelar GMP</h2>
<p>In this section, you will build the smart contract leveraging Axelar GMP to airdrop tokens from the Polygon testnet to the Avalanche testnet.</p>
<p>Navigate to the project's root folder you cloned in the previous step, and then run the following commands to create a new Hardhat project.</p>
<pre><code class="lang-bash">mkdir hardhat <span class="hljs-built_in">cd</span> hardhat npm install --save-dev hardhat
</code></pre>
<p>Get a sample project by running the command below:</p>
<pre><code class="lang-bash">npx hardhat
</code></pre>
<p>Accept the following options:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695909926118/ff4c9294-cc3a-41f8-ba93-de7cf5d2397e.png" alt="Accept the following hardhat options" /></p>
<p>The <code>@nomicfoundation/hardhat-toolbox</code> plugin includes all the commonly used packages and recommended Hardhat plugins for starting development with Hardhat.</p>
<p>In case it wasn't installed automatically, install this additional requirement using the following command:</p>
<pre><code class="lang-bash">npm i @nomicfoundation/hardhat-toolbox@3.0.0
</code></pre>
<p>Next, install <code>@axelar-network/axelar-gmp-sdk-solidity</code> for Axelar General Message Passing SDK in Solidity and <code>dotenv</code> with the following command:</p>
<pre><code class="lang-bash">npm i @axelar-network/axelar-gmp-sdk-solidity@3.6.1 dotenv
</code></pre>
<p>To ensure everything functions properly, execute the following command within the <code>hardhat</code> directory.</p>
<pre><code class="lang-bash">npx hardhat <span class="hljs-built_in">test</span>
</code></pre>
<p>You will see a passed test result in your console.</p>
<p>To start building from scratch, it's important to clean up the directory. To accomplish this task, delete <code>Lock.js</code> from the test folder and remove <code>deploy.js</code> from the <code>scripts</code> directory. After that, navigate to the <code>contracts</code> folder and delete Lock.sol.</p>
<p><img src="https://images.ctfassets.net/mjqoq33y05of/5ycScC5yUgXPPhltKDAOMs/62e2424e496bf037da341ac4a6d518b0/62c05341-ba68-41bd-b55f-d9d22886197a.png" alt="Folder setup for cross-chain-dapp" class="image--center mx-auto" /></p>
<p>Delete lock.js file</p>
<blockquote>
<p>The folders themselves should not be deleted!</p>
</blockquote>
<p>Create an <code>Airdrop.sol</code> file inside the <code>contracts</code> directory and update it with the following code snippet. When using Hardhat, file organization is crucial, so pay attention!</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.9;</span>

<span class="hljs-keyword">import</span> {<span class="hljs-title">AxelarExecutable</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">IAxelarGateway</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">IERC20</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol"</span>;
<span class="hljs-keyword">import</span> {<span class="hljs-title">IAxelarGasService</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol"</span>;

<span class="hljs-comment">// Airdrop contract that inherits from AxelarExecutable</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Airdrop</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AxelarExecutable</span> </span>{
    <span class="hljs-comment">// Immutable reference to the gas service contract</span>
    IAxelarGasService <span class="hljs-keyword">public</span> <span class="hljs-keyword">immutable</span> gasService;

    <span class="hljs-comment">// Variables to track airdrop details</span>
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> amountReceived;
    <span class="hljs-keyword">address</span>[] <span class="hljs-keyword">public</span> airdropRecipients;

    <span class="hljs-comment">// Constructor to initialize the contract</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> gateway_, <span class="hljs-keyword">address</span> gasReceiver_</span>) <span class="hljs-title">AxelarExecutable</span>(<span class="hljs-params">gateway_</span>) </span>{
        <span class="hljs-comment">// Initialize the gas service contract</span>
        gasService <span class="hljs-operator">=</span> IAxelarGasService(gasReceiver_);
    }

    <span class="hljs-comment">// Function to initiate airdrop to multiple recipients on another chain</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendToMany</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> destinationChain,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> destinationAddress,
        <span class="hljs-keyword">address</span>[] <span class="hljs-keyword">calldata</span> destinationAddresses,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> symbol,
        <span class="hljs-keyword">uint256</span> amount
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
        <span class="hljs-comment">// Require a gas payment for the transaction</span>
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>, <span class="hljs-string">"Gas payment is required"</span>);

        <span class="hljs-comment">// Get the token address associated with the provided symbol</span>
        <span class="hljs-keyword">address</span> tokenAddress <span class="hljs-operator">=</span> gateway.tokenAddresses(symbol);

        <span class="hljs-comment">// Transfer tokens from sender to this contract</span>
        IERC20(tokenAddress).transferFrom(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), amount);

        <span class="hljs-comment">// Approve the gateway to spend tokens on behalf of this contract</span>
        IERC20(tokenAddress).approve(<span class="hljs-keyword">address</span>(gateway), amount);

        <span class="hljs-comment">// Encode the recipient addresses into a payload</span>
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> payload <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(destinationAddresses);

        <span class="hljs-comment">// Pay for native gas using the gas service contract</span>
        gasService.payNativeGasForContractCallWithToken{<span class="hljs-built_in">value</span>: <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>}(
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
            destinationChain,
            destinationAddress,
            payload,
            symbol,
            amount,
            <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>
        );

        <span class="hljs-comment">// Initiate a contract call on the gateway</span>
        gateway.callContractWithToken(
            destinationChain,
            destinationAddress,
            payload,
            symbol,
            amount
        );
    }

    <span class="hljs-comment">// Function to retrieve the list of airdrop recipients</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getRecipients</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">address</span>[] <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-keyword">return</span> airdropRecipients;
    }

    <span class="hljs-comment">// Internal function to execute airdrop on the current chain</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_executeWithToken</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span>,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span>,
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">calldata</span> payload,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> tokenSymbol,
        <span class="hljs-keyword">uint256</span> amount
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> </span>{
        <span class="hljs-comment">// Decode the payload to get the recipient addresses</span>
        <span class="hljs-keyword">address</span>[] <span class="hljs-keyword">memory</span> recipients <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">decode</span>(payload, (<span class="hljs-keyword">address</span>[]));

        <span class="hljs-comment">// Get the token address associated with the provided symbol</span>
        <span class="hljs-keyword">address</span> tokenAddress <span class="hljs-operator">=</span> gateway.tokenAddresses(tokenSymbol);

        <span class="hljs-comment">// Set amountReceived and airdropRecipients variables</span>
        amountReceived <span class="hljs-operator">=</span> amount;
        airdropRecipients <span class="hljs-operator">=</span> recipients;

        <span class="hljs-comment">// Calculate the amount of tokens to send to each recipient</span>
        <span class="hljs-keyword">uint256</span> sentAmount <span class="hljs-operator">=</span> amount <span class="hljs-operator">/</span> recipients.<span class="hljs-built_in">length</span>;

        <span class="hljs-comment">// Transfer tokens to each recipient</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint256</span> i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> recipients.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
            IERC20(tokenAddress).<span class="hljs-built_in">transfer</span>(recipients[i], sentAmount);
        }
    }
}
</code></pre>
<p>In the code snippet above:</p>
<ul>
<li><p>It defines a Solidity contract named <code>Airdrop</code> that extends the <code>AxelarExecutable</code> contract.</p>
</li>
<li><p>The contract imports several Solidity interfaces and contracts from the <code>@axelar-network/axelar-gmp-sdk-solidity</code> package.</p>
</li>
<li><p>The constructor of the contract takes two parameters: <code>gateway_</code> and <code>gasReceiver_</code>. It initializes the <code>gasService</code> variable with the <code>gasReceiver_</code> address and calls the constructor of the <code>AxelarExecutable</code> contract with the <code>gateway_</code> address.</p>
</li>
<li><p>The contract has a function name<code>sendToMany</code> that is external and payable. It takes several parameters, including <code>destination chain</code>, <code>destination address</code>, <code>destination addresses (array)</code>, <code>symbol</code> and <code>amount</code>. It requires that the message value (attached Ether) is greater than 0, transfers tokens from the sender to the contract, approves the transfer to the gateway, and performs a native gas payment using the <code>gasService</code> contract. It then calls the <code>callContractWithToken</code> function of the <code>gateway</code> contract.</p>
</li>
<li><p>The contract has a public function name and returns the array of airdrop recipients.</p>
</li>
<li><p>The contract has an internal function name <code>_executeWithToken</code> that is called by the<code>AxelarExecutable</code> contract. It takes parameters including a payload (an array of addresses, which we have chosen in this tutorial but it can store any other data types) and a token symbol.</p>
</li>
<li><p>It decodes the payload, transfers tokens to the recipients, and updates the <code>amountReceived</code> and <code>airdropRecipients</code> variables.</p>
</li>
</ul>
<h3 id="heading-set-up-deployment-script">Set up deployment script</h3>
<p>Create a <code>deploy.js</code> file in the <code>scripts</code> folder and add the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> hre = <span class="hljs-built_in">require</span>(<span class="hljs-string">"hardhat"</span>);

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> Airdrop = <span class="hljs-keyword">await</span> hre.ethers.deployContract(<span class="hljs-string">"Airdrop"</span>, [
    <span class="hljs-string">""</span>,
    <span class="hljs-string">""</span>,
  ]);

  <span class="hljs-keyword">await</span> Airdrop.waitForDeployment();

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Airdrop contract deployed to <span class="hljs-subst">${<span class="hljs-keyword">await</span> Airdrop.getAddress()}</span>`</span>);
}

<span class="hljs-comment">// We recommend this pattern to be able to use async/await everywhere</span>
<span class="hljs-comment">// and properly handle errors.</span>
main().catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.error(error);
  process.exitCode = <span class="hljs-number">1</span>;
});
</code></pre>
<p>In the code snippet above:</p>
<ul>
<li><p>The <code>main</code> function has the <code>Airdrop</code> contract deployed using the <code>deployContract,</code> a method with two strings as arguments.</p>
</li>
<li><p>The <code>await Airdrop.waitForDeployment()</code> statement ensures that the deployment is completed before moving forward.</p>
</li>
<li><p>The deployed contract's address is logged into the console.</p>
</li>
</ul>
<h3 id="heading-set-up-remote-procedure-call-rpc-to-testnet">Set up remote procedure call (RPC) to testnet</h3>
<p>A remote procedure call (RPC) is a protocol used for communication between client and server systems in a network or blockchain environment. It enables clients to execute procedures or functions on remote servers and receive the results. RPC abstracts the underlying network details and allows clients to invoke methods on servers as if they were local.</p>
<p>Before you proceed to set up RPC, create a <code>.env</code> file using the command below:</p>
<pre><code class="lang-bash">touch .env
</code></pre>
<blockquote>
<p>Ensure you are in the hardhat directory before running the command above.</p>
</blockquote>
<p>Inside the <code>.env</code> file you just created, add the following key:</p>
<pre><code class="lang-bash">PRIVATE_KEY= // Add your account private key here
</code></pre>
<p>Getting your private account key is easy. If you use MetaMask, take a look at this <a target="_blank" href="https://support.metamask.io/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key">post</a>. Keep in mind that exporting the private key can differ for other wallet providers.</p>
<p>Next, set up RPC for Polygon and Avalanche test networks by updating the <code>hardhat.config.js</code> file with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">require</span>(<span class="hljs-string">"@nomicfoundation/hardhat-toolbox"</span>);
<span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config({ <span class="hljs-attr">path</span>: <span class="hljs-string">".env"</span> });
<span class="hljs-built_in">require</span>(<span class="hljs-string">"solidity-coverage"</span>);

<span class="hljs-keyword">const</span> PRIVATE_KEY = process.env.PRIVATE_KEY;

<span class="hljs-comment">// This is a sample Hardhat task. To learn how to create your own go to</span>
<span class="hljs-comment">// &lt;https://hardhat.org/guides/create-task.html&gt;</span>
task(<span class="hljs-string">"accounts"</span>, <span class="hljs-string">"Prints the list of accounts"</span>, <span class="hljs-keyword">async</span> (taskArgs, hre) =&gt; {
  <span class="hljs-keyword">const</span> accounts = <span class="hljs-keyword">await</span> hre.ethers.getSigners();

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> account <span class="hljs-keyword">of</span> accounts) {
    <span class="hljs-built_in">console</span>.log(account.address);
  }
});

<span class="hljs-comment">// You need to export an object to set up your config</span>
<span class="hljs-comment">// Go to &lt;https://hardhat.org/config/&gt; to learn more</span>

<span class="hljs-comment">/** @type import('hardhat/config').HardhatUserConfig */</span>
<span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">solidity</span>: <span class="hljs-string">"0.8.9"</span>,
  <span class="hljs-attr">networks</span>: {
    <span class="hljs-attr">mumbai</span>: {
      <span class="hljs-attr">url</span>: <span class="hljs-string">"https://rpc.ankr.com/polygon_mumbai"</span>,
      <span class="hljs-attr">chainId</span>: <span class="hljs-number">80001</span>,
      <span class="hljs-attr">accounts</span>: [PRIVATE_KEY],
    },
    <span class="hljs-attr">avalancheFujiTestnet</span>: {
      <span class="hljs-attr">url</span>: <span class="hljs-string">"https://avalanche-fuji-c-chain.publicnode.com"</span>,
      <span class="hljs-attr">chainId</span>: <span class="hljs-number">43113</span>,
      <span class="hljs-attr">accounts</span>: [PRIVATE_KEY],
    },
  },
};
</code></pre>
<p>You have successfully configured the RPC for Polygon and Avalanche test networks. In the next step, you will deploy smart contracts to these networks.</p>
<h3 id="heading-deploy-smart-contract-to-polygon-and-avalanche-networks">Deploy smart contract to Polygon and Avalanche networks</h3>
<p>In this section, you will deploy the smart contract to Polygon and Avalanche testnets. However, before you proceed, you need to specify the Axelar <code>Gateway Service</code> and the <code>Gas Service</code> contract in the <code>hre.ethers.deployContract()</code> method within the <code>deploy.js</code> file you created earlier.</p>
<p>You can find the list of Axelar Gas Service and Gateway contracts for all the chains currently supported by Axelar <a target="_blank" href="https://dub.sh/wzbLWsT">here</a>.</p>
<p>To ensure successful contract deployment, you also need a faucet for your Polygon and Avalanche testnet accounts. To get the Polygon faucet, visit this <a target="_blank" href="https://dub.sh/rEUXrYy">link</a>; and for the Avalanche faucet, access it <a target="_blank" href="https://dub.sh/Oxz9PGj">here</a>.</p>
<h3 id="heading-deploy-to-polygon-testnet">Deploy to Polygon testnet</h3>
<p>Update the deploy.js file inside the scripts folder to deploy to Polygon testnet with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{

  <span class="hljs-comment">// Update arguments with the Axelar gateway and</span>
  <span class="hljs-comment">// gas service on Polygon testnet</span>
  <span class="hljs-keyword">const</span> Airdrop = <span class="hljs-keyword">await</span> hre.ethers.deployContract(<span class="hljs-string">"Airdrop"</span>, [
    <span class="hljs-string">"0xBF62ef1486468a6bd26Dd669C06db43dEd5B849B"</span>,
    <span class="hljs-string">"0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6"</span>,
  ]);

  <span class="hljs-comment">//...</span>
}

<span class="hljs-comment">//..</span>
</code></pre>
<p>To deploy the contract on the Polygon testnet, run the following command:</p>
<pre><code class="lang-bash">npx hardhat run scripts/deploy.js --network mumbai
</code></pre>
<p>For example, the contract address will be displayed in your console: <code>0xe66f6e95E3edECe3567290751c024B19DEebAACd</code>.</p>
<h3 id="heading-deploy-to-avalanche-fuji-testnet">Deploy to Avalanche Fuji testnet</h3>
<p>Update the <code>deploy.js</code> file inside the <code>scripts</code> folder to deploy to Avalanche testnet with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Update arguments with the Axelar gateway and</span>
  <span class="hljs-comment">// gas service on Avalanche testnet</span>
  <span class="hljs-keyword">const</span> Airdrop = <span class="hljs-keyword">await</span> hre.ethers.deployContract(<span class="hljs-string">"Airdrop"</span>, [
    <span class="hljs-string">"0xC249632c2D40b9001FE907806902f63038B737Ab"</span>,
    <span class="hljs-string">"0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6"</span>,
  ]);

  <span class="hljs-comment">//...</span>
}

<span class="hljs-comment">//..</span>
</code></pre>
<p>To deploy the contract on the Avalanche testnet, run the following command:</p>
<pre><code class="lang-bash">npx hardhat run scripts/deploy.js --network avalancheFujiTestnet
</code></pre>
<p>The contract address will be displayed on your console; for example, <code>0x86bE218aD2CC1Dc3270c4A594E7BA52Fd03d6a46</code>. Save both deployed contract addresses, as you will need them for frontend integration.</p>
<h2 id="heading-integrating-a-nextjs-frontend-application-with-smart-contract">Integrating a Next.js frontend application with smart contract</h2>
<p>In the previous steps, you successfully built and deployed the smart contract. Now, it's time to interact with it from the frontend, just as you would typically engage with dApps on the web.</p>
<p>Having already cloned the Next.js frontend project and set up the configuration for <code>WAGMI</code> and <code>Rainbowkit</code>, you can now move forward with updating the existing application and connecting your smart contract for testing, enabling interaction with it as you would with decentralized web applications.</p>
<h3 id="heading-implementing-smart-contract-write-functionality">Implementing smart-contract write functionality</h3>
<p>Interacting with our contract is relatively straightforward from the frontend application, thanks to <code>WAGMI</code>, <code>RainbowKit</code>, and <code>Ethers</code>.</p>
<p>To interact between the Polygon and Avalanche testnets, you will need the Avalanche Fuji testnet RPC URL, the Polygon contract address and the Avalanche contract address. Create a <code>.env.local</code> file in the root directory by using the command below:</p>
<pre><code class="lang-bash">touch .env.local
</code></pre>
<blockquote>
<p>Ensure you are in the root directory before running the command above.</p>
</blockquote>
<p>Inside the <code>.env.local</code> file you just created, add the following:</p>
<pre><code class="lang-bash">NEXT_PUBLIC_AVALANCHE_RPC_URL=https://avalanche-fuji-c-chain.publicnode.com 
NEXT_PUBLIC_POLYGON_CONTRACT_ADDRESS=&lt;POLYGON_CONTRACT_ADDRESS&gt; 
NEXT_PUBLIC_AVALANCHE_CONTRACT_ADDRESS=&lt;AVALANCHE_CONTRACT_ADDRESS&gt;
</code></pre>
<p>Replace <code>&lt;POLYGON_CONTRACT_ADDRESS&gt;</code> with the contract address, you deployed to the Polygon testnet and replace <code>&lt;AVALANCHE_CONTRACT_ADDRESS&gt;</code> with the contract address you deployed to the Avalanche Fuji testnet earlier in this tutorial.</p>
<p>Next, you need to implement the write functionality for the smart contract. In this case, you must specify the airdrop amount and approve it by granting the contract permission to spend it. Only then can you input the wallet addresses to receive the airdrop and send it to them.</p>
<p>To enable the approval and airdrop feature, simply add this code snippet into the pages directory's <code>index.js</code> file. Be sure to import all essential functions from <code>WAGMI</code>, including the <code>@axelar-network/axelarjs-sdk</code>, <code>Polygon</code>, Avalanche Fuji testnet contract addresses, Airdrop contract and Avalanche Fuji testnet RPC URL.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

<span class="hljs-keyword">import</span> {
  useContractWrite,
  useContractRead,
  usePrepareContractWrite,
  useWaitForTransaction,
  erc20ABI,
  useAccount,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"wagmi"</span>;
<span class="hljs-keyword">import</span> { ethers } <span class="hljs-keyword">from</span> <span class="hljs-string">"ethers"</span>;
<span class="hljs-keyword">import</span> {
  AxelarQueryAPI,
  Environment,
  EvmChain,
  GasToken,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@axelar-network/axelarjs-sdk"</span>;

<span class="hljs-keyword">import</span> AirdropContract <span class="hljs-keyword">from</span> <span class="hljs-string">"../hardhat/artifacts/contracts/Airdrop.sol/Airdrop.json"</span>;

<span class="hljs-keyword">const</span> POLYGON_CONTRACT_ADDRESS =
  process.env.NEXT_PUBLIC_POLYGON_CONTRACT_ADDRESS;
<span class="hljs-keyword">const</span> AVALANCHE_CONTRACT_ADDRESS =
  process.env.NEXT_PUBLIC_AVALANCHE_CONTRACT_ADDRESS;
<span class="hljs-keyword">const</span> AVALANCHE_RPC_URL = process.env.NEXT_PUBLIC_AVALANCHE_RPC_URL;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-comment">//...</span>
}
</code></pre>
<p>Next, create the following state variables and functions to interact with the smart contract you created earlier.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [darkMode, setDarkMode] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> [amount, setAmount] = useState(<span class="hljs-number">0</span>);
  <span class="hljs-keyword">const</span> [Addresses, setAddresses] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> { address } = useAccount();
  <span class="hljs-keyword">const</span> [isSendButtonVisible, setIsSendButtonVisible] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> [isApproveButtonVisible, setIsApproveButtonVisible] = useState(<span class="hljs-literal">true</span>);
  <span class="hljs-keyword">const</span> [isTextareaVisible, setIsTextareaVisible] = useState(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">const</span> api = <span class="hljs-keyword">new</span> AxelarQueryAPI({ <span class="hljs-attr">environment</span>: Environment.TESTNET });
  <span class="hljs-keyword">const</span> [gasFee, setGasFee] = useState(<span class="hljs-number">0</span>);

<span class="hljs-keyword">const</span> toastOptions = {
    <span class="hljs-attr">position</span>: <span class="hljs-string">"top-right"</span>,
    <span class="hljs-attr">autoClose</span>: <span class="hljs-number">8000</span>,
    <span class="hljs-attr">closeOnClick</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">pauseOnHover</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">draggable</span>: <span class="hljs-literal">true</span>,
  };

  <span class="hljs-comment">// Approve aUSDC to be spent by the contract</span>
  <span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: useContractWriteUSDCData, <span class="hljs-attr">write</span>: approveWrite } =
    useContractWrite({
      <span class="hljs-attr">address</span>: <span class="hljs-string">"0x2c852e740B62308c46DD29B982FBb650D063Bd07"</span>, <span class="hljs-comment">// Address of the aUSDC contract</span>
      <span class="hljs-attr">abi</span>: erc20ABI,
      <span class="hljs-attr">functionName</span>: <span class="hljs-string">"approve"</span>,
      <span class="hljs-attr">args</span>: [
        POLYGON_CONTRACT_ADDRESS,
        ethers.utils.parseUnits(amount.toString(), <span class="hljs-number">6</span>),
      ],
    });

  <span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: useWaitForTransactionUSDCData, <span class="hljs-attr">isSuccess</span>: isUSDCSuccess } =
    useWaitForTransaction({
      <span class="hljs-attr">hash</span>: useContractWriteUSDCData?.hash,
    });

  <span class="hljs-comment">// Check Allowance</span>
  <span class="hljs-keyword">const</span> {
    <span class="hljs-attr">data</span>: readAllowance,
    <span class="hljs-attr">isError</span>: isAllowanceError,
    <span class="hljs-attr">isLoading</span>: isAllowanceLoading,
  } = useContractRead({
    <span class="hljs-attr">address</span>: <span class="hljs-string">"0x2c852e740B62308c46DD29B982FBb650D063Bd07"</span>, <span class="hljs-comment">// Address of the USDC contract</span>
    <span class="hljs-attr">abi</span>: erc20ABI,
    <span class="hljs-attr">functionName</span>: <span class="hljs-string">"allowance"</span>,
    <span class="hljs-attr">args</span>: [address, POLYGON_CONTRACT_ADDRESS],
  });

  <span class="hljs-comment">// Estimate Gas</span>
  <span class="hljs-keyword">const</span> gasEstimator = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> gas = <span class="hljs-keyword">await</span> api.estimateGasFee(
      EvmChain.POLYGON,
      EvmChain.AVALANCHE,
      GasToken.MATIC,
      <span class="hljs-number">700000</span>,
      <span class="hljs-number">2</span>
    );
    setGasFee(gas);
  };

  <span class="hljs-comment">// Send Airdrop</span>
  <span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: useContractWriteData, write } = useContractWrite({
    <span class="hljs-attr">address</span>: POLYGON_CONTRACT_ADDRESS,
    <span class="hljs-attr">abi</span>: AirdropContract.abi,
    <span class="hljs-attr">functionName</span>: <span class="hljs-string">"sendToMany"</span>,
    <span class="hljs-attr">args</span>: [
      <span class="hljs-string">"Avalanche"</span>,
      AVALANCHE_CONTRACT_ADDRESS,
      Addresses.split(<span class="hljs-string">","</span>),
      <span class="hljs-string">"aUSDC"</span>,
      ethers.utils.parseUnits(amount.toString(), <span class="hljs-number">6</span>),
    ],
    <span class="hljs-attr">value</span>: gasFee,
  });

  <span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: useWaitForTransactionData, isSuccess } = useWaitForTransaction({
    <span class="hljs-comment">// Calling a hook to wait for the transaction to be mined</span>
    <span class="hljs-attr">hash</span>: useContractWriteData?.hash,
  });

<span class="hljs-comment">//...</span>
}
</code></pre>
<p>In the code above,</p>
<ul>
<li><p>The <code>useState</code> hook was utilized to create several state variables, including <code>darkMode</code>, <code>amount</code>, <code>Addresses</code>, <code>isSendButtonVisible</code>, <code>isApproveButtonVisible</code>, <code>isTextareaVisible</code> and <code>gasFee</code>.</p>
</li>
<li><p>The component utilizes the <code>useAccount</code> hook to get the <code>address</code> variable.</p>
</li>
<li><p>An instance of <code>AxelarQueryAPI</code> is created with the <code>TESTNET</code> environment and assigned to the <code>api</code> variable.</p>
</li>
<li><p>The component sets up a <code>toastOptions</code> object used for displaying toast notifications.</p>
</li>
<li><p>The code uses the <code>useContractWrite</code> hook twice, first to <code>Approve</code> aUSDC to be spent by the contract and then to <code>sendToMany</code> in the Airdrop contract with various arguments.</p>
</li>
<li><p>It also uses the <code>useWaitForTransaction</code> hook to wait for the transactions to be mined, checking for success in both cases.</p>
</li>
</ul>
<p>Next, you can create a function to handle sending the airdrop, managing the <code>Approve</code> functionality, and utilizing the <code>useEffect</code> hook.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-comment">//...</span>

<span class="hljs-comment">// Handle send airdrop button</span>
  <span class="hljs-keyword">const</span> handleSendAirdrop = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">if</span> (!(amount &amp;&amp; Addresses)) {
      toast.error(<span class="hljs-string">"Please enter amount and addresses"</span>, toastOptions);
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">if</span> (isAllowanceError) {
      toast.error(<span class="hljs-string">"Error checking allowance"</span>, toastOptions);
      <span class="hljs-keyword">return</span>;
    }

    write();
    toast.info(<span class="hljs-string">"Sending Airdrop..."</span>, {
      ...toastOptions,
    });
  };

  <span class="hljs-comment">// Handle Approval</span>
  <span class="hljs-keyword">const</span> handleApprove = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!amount) {
      toast.error(<span class="hljs-string">"Please enter amount"</span>, toastOptions);
      <span class="hljs-keyword">return</span>;
    }
    approveWrite();

    toast.info(<span class="hljs-string">"Approving..."</span>, toastOptions);
  };

 useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">//...</span>

    <span class="hljs-comment">// The gas estimator</span>
    gasEstimator();

    isSuccess
      ? toast.success(<span class="hljs-string">"Airdrop sent!"</span>, {
          toastOptions,
        })
      : useWaitForTransactionData?.error || useContractWriteData?.error
      ? toast.error(<span class="hljs-string">"Error sending message"</span>)
      : <span class="hljs-literal">null</span>;

    <span class="hljs-keyword">if</span> (isUSDCSuccess) {
      toast.success(<span class="hljs-string">"USDC Approved!"</span>, { toastOptions });
      setIsApproveButtonVisible(<span class="hljs-literal">false</span>);
      setIsSendButtonVisible(<span class="hljs-literal">true</span>);
      setIsTextareaVisible(<span class="hljs-literal">true</span>);
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (
      useWaitForTransactionUSDCData?.error ||
      useContractWriteUSDCData?.error
    ) {
      toast.error(<span class="hljs-string">"Error approving USDC"</span>, { toastOptions });
    }
  }, [
    <span class="hljs-comment">//...</span>
    useContractWriteData,
    useWaitForTransactionData,
    useContractWriteUSDCData,
    useWaitForTransactionUSDCData,
  ]);

<span class="hljs-comment">//...</span>

  <span class="hljs-keyword">return</span> (
    <span class="hljs-comment">//...</span>
  )
}
</code></pre>
<p>Update the <code>Approve</code>, <code>Send</code> button and <code>textarea</code> with the following code snippet to approve and send the airdrop cross-chain.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-comment">//...</span>

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container mx-auto px-4 flex flex-col min-h-screen"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"py-4"</span>&gt;</span>
         {/* ... */}
      <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex-grow flex flex-col items-center justify-center"</span>&gt;</span>

            {/* ... */}

            {isTextareaVisible &amp;&amp; (
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col mb-4"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-semibold mb-2"</span>&gt;</span>Addresses<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span>
                  <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter addresses (separate with a comma)"</span>
                  <span class="hljs-attr">className</span>=<span class="hljs-string">"border border-gray-300 rounded-lg p-2 h-32"</span>
                  <span class="hljs-attr">onChange</span>=<span class="hljs-string">{(e)</span> =&gt;</span> setAddresses(e.target.value)}
                /&gt;
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            )}
            {isApproveButtonVisible &amp;&amp; (
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-blue-500 hover:bg-blue-600 text-white py-2 px-6 rounded-full mr-5"</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> handleApprove()}
                display="none"
              &gt;
                Approve
              <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            )}
            {isSendButtonVisible &amp;&amp; (
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-blue-500 hover:bg-blue-600 text-white py-2 px-6 rounded-full"</span>
                <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleSendAirdrop}</span>
              &gt;</span>
                Send
              <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            )}

          {/* . */}

      <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ToastContainer</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">footer</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex justify-center items-center py-8 border-t border-gray-300"</span>&gt;</span>
        {/* . */}
      <span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>You can test the send functionality to see what you have so far, but you won't be able to retrieve it on the destination chain because the retrieval functionality hasn't been implemented yet.</p>
<p>The image below illustrates this by showing a <code>waiting for response...</code> message. Don't worry; you'll implement the retrieval functionality in the next step.</p>
<p><img src="https://images.ctfassets.net/mjqoq33y05of/5t14wMpJydUGHpUTUyWfgg/0928cc0ed39427d1b65633477f0fb9de/d6b914f8-6125-4bac-871e-6a342a041589.png" alt="Integrating a Next.js Frontend Application with Smart Contract" /></p>
<h3 id="heading-implementing-smart-contract-read-functionality">Implementing smart-contract read functionality</h3>
<p>In the previous step, you learned how to write to a smart contract from the frontend, and now this section will guide you through implementing the functionality to read data from a smart contract.</p>
<p>Update the <code>index.js</code> with the following code snippet to read the airdrop details, including the recipient's addresses and amount.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">//...</span>
 <span class="hljs-keyword">const</span> [amountReceived, setAmountReceived] = useState(<span class="hljs-number">0</span>);
 <span class="hljs-keyword">const</span> [airdropRecipients, setAirdropRecipients] = useState([]);

<span class="hljs-comment">//...</span>

<span class="hljs-comment">// Read data from Avalanche</span>
  <span class="hljs-keyword">const</span> provider = <span class="hljs-keyword">new</span> ethers.providers.JsonRpcProvider(AVALANCHE_RPC_URL);
  <span class="hljs-keyword">const</span> contract = <span class="hljs-keyword">new</span> ethers.Contract(
    AVALANCHE_CONTRACT_ADDRESS,
    AirdropContract.abi,
    provider
  );

  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readDestinationChainVariables</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> amountReceived = <span class="hljs-keyword">await</span> contract.amountReceived();

      <span class="hljs-keyword">const</span> airdropRecipients = <span class="hljs-keyword">await</span> contract.getRecipients();

      setAmountReceived(amountReceived.toString());

      setAirdropRecipients(airdropRecipients);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.log(error);
    }
  }

 useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">//...</span>
  readDestinationChainVariables();

 }, [ <span class="hljs-comment">//...</span>
]);

<span class="hljs-comment">//...</span>
}
</code></pre>
<p>In the code above,</p>
<ul>
<li><p>Two state variables, <code>amountReceived</code> and <code>airdropRecipients</code> , were set up using the <code>useState</code> hook to store the amount and recipients.</p>
</li>
<li><p>An instance of <code>ethers.providers.JsonRpcProvider</code> was created to connect to the Avalanche blockchain.</p>
</li>
<li><p>Defines a contract instance using <code>ethers.Contract</code> with the specified Avalanche contract address and ABI for the <code>AirdropContract</code>.</p>
</li>
<li><p>The function <code>readDestinationChainVariables</code> is defined to read data from the Avalanche contract, including the amount received and the list of airdrop recipients.</p>
</li>
<li><p>Inside <code>useEffect</code>, the <code>readDestinationChainVariables</code> function is called to fetch and update the state variables when the component mounts and when other dependencies change.</p>
</li>
</ul>
<p>Next, update the UI to be rendered.</p>
<pre><code class="lang-javascript"> <span class="hljs-comment">//...</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{

&lt;main className=<span class="hljs-string">"flex-grow flex flex-col items-center justify-center"</span>&gt;

    {<span class="hljs-comment">/* ... */</span>}

          &lt;div className=<span class="hljs-string">"border border-gray-300 rounded-lg p-8 m-2 "</span>&gt;
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-2xl font-bold mb-4"</span>&gt;</span>Airdrop Status 🎉<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>
            {airdropRecipients.length &gt; <span class="hljs-number">0</span> ? (
              <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-semibold mb-2"</span>&gt;</span>
                    Total Amount:{" "}
                    <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-normal text-gray-500"</span>&gt;</span>
                      {amountReceived / 1000000}
                    <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-semibold mb-2"</span>&gt;</span>
                    Total Addresses:{" "}
                    <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-normal text-gray-500"</span>&gt;</span>
                      {airdropRecipients.length}
                    <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

                  {airdropRecipients.map((recipient, index) =&gt; (
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex flex-col"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-semibold mb-2"</span>&gt;</span>
                        Address:{" "}
                        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-normal text-gray-500"</span>&gt;</span>
                          {recipient}
                        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-semibold mb-2"</span>&gt;</span>
                        Amount Received:{" "}
                        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"font-normal text-gray-500"</span>&gt;</span>
                          {amountReceived / airdropRecipients.length / 1000000}
                        <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                  ))}
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;/&gt;</span></span>
            ) : (
            <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-red-500"</span>&gt;</span>Waiting for response...<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>
            )}
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/main&gt;

{<span class="hljs-comment">/* . */</span>}

}
</code></pre>
<h2 id="heading-trying-the-application">Trying the application</h2>
<p>Hurray 🥳 , you have successfully built a cross-chain airdrop dApp with Solidity, Next.js &amp; Axelar General Message Passing.</p>
<p><img src="https://images.ctfassets.net/mjqoq33y05of/Duk9yXAXU6vKif14B7ZTV/2fc9fa62933c9cb2b372f4b36fd5973f/d3619e93-3096-4c7a-9818-0da75b66aa13.png" alt="Testing the cross-chain airdrop dapp" /></p>
<p>You can find the complete code for this project on <a target="_blank" href="https://github.com/Olanetsoft/cross-chain-airdrop-dapp">GitHub</a>.</p>
<h2 id="heading-what-next">What Next?</h2>
<p>This post covered the utilization of Axelar GMP with <code>callContractWithToken</code>, but that's not all General Message Passing can do.</p>
<p>You can always explore other functionalities like <a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/gmp-tokens-with-messages"><code>callContractWithToken</code></a>, <a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/overview"><code>SendToken</code></a>, <a target="_blank" href="https://axelar.network/blog/,https://docs.axelar.dev/dev/send-tokens/overview#get-a-deposit-address"><code>Deposit addresses</code></a>, <a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/examples#nft-linker"><code>NFT Linker</code></a>, <a target="_blank" href="https://docs.axelar.dev/dev/axelarjs-sdk/intro"><code>JavaScript SDK</code></a>, etc.</p>
<p>If you've made it this far, you're fantastic! You can <a target="_blank" href="https://twitter.com/intent/tweet?url=https%3A%2F%2Faxelar.network%2Fblog%2Fcross-chain-airdrop-dapp-tutorial%2F&amp;text=Thank%20you%2C%20@olanetsoft%2C%20for%20writing%20this%20helpful%20article.%0A%0AHow%20to%20Build%20an%20Airdrop%20dApp%20with%20@axelarcore,%20Solidity%20,and%20NextJs%20%0A%0A">post about your experience</a> building or following along with this tutorial to show your support to the author and tag <a target="_blank" href="https://twitter.com/axelarcore">@axelarcore</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, this tutorial demonstrated how to create a cross-chain airdrop dApp using Solidity, Next.js and Axelar GMP. You learned how to deploy a smart contract, interact with multiple blockchains, and build a frontend application to facilitate token distribution.</p>
<p>As a result, you now better understand how to leverage Axelar's powerful features to develop cross-chain dApps.</p>
<h2 id="heading-reference">Reference</h2>
<ul>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/overview">Axelar General Message Passing</a></p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/">Axelar Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://hardhat.org/">Hardhat</a></p>
</li>
<li><p><a target="_blank" href="https://www.rainbowkit.com/">RainbowKit</a></p>
</li>
<li><p><a target="_blank" href="https://nextjs.org/docs">Next.js</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to Create an Interchain Token with Axelar in 4 Steps]]></title><description><![CDATA[Interchain Tokens are a special kind of token that allows users to transfer value across different blockchains.
Existing solutions, like cross-chain bridges, create problems like fragmented fungibility (bridged tokens are nonfungible with versions on...]]></description><link>https://blog.idrisolubisi.com/how-to-create-an-interchain-token-with-axelar-in-4-steps</link><guid isPermaLink="true">https://blog.idrisolubisi.com/how-to-create-an-interchain-token-with-axelar-in-4-steps</guid><category><![CDATA[axelar]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[ERC20]]></category><category><![CDATA[Solidity]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Tue, 15 Aug 2023 23:53:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1692143580968/96c6ca14-f592-447c-84de-a35b9159d4da.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Interchain Tokens are a special kind of token that allows users to transfer value across different blockchains.</p>
<p>Existing solutions, like <a target="_blank" href="https://axelar.network/blog/cross-chain-bridges-benefits-limitations-risks">cross-chain bridges</a>, create problems like fragmented fungibility (bridged tokens are nonfungible with versions on other chains) and loss of custom functionality. Interchain Tokens solve that problem, extending tokens' fungibility and custom functionality into deployments on multiple chains.</p>
<p>Interchain Tokens are a groundbreaking development in the world of blockchain, creates a truly interoperable ecosystem.</p>
<p>The <a target="_blank" href="https://testnet.interchain.axelar.dev/">Axelar Interchain Token Portal</a> is a helpful tool that simplifies the process of creating and deploying ERC-20 tokens, providing support for standardized and canonical tokens.</p>
<p>This tutorial will walk you through the step-by-step process of creating, registering, and deploying an Interchain Token using the Axelar Interchain Token Portal and interacting with the token across multiple blockchains.</p>
<p>You will need Avalanche Fuji testnet faucet tokens; you can get some <a target="_blank" href="https://core.app/tools/testnet-faucet/?subnet=c&amp;token=c">here</a> if you don't have them.</p>
<h2 id="heading-step-1-create-and-deploy-an-erc0-20-token"><strong>Step 1: Create and deploy an ERC0-20 token</strong></h2>
<p>In this step, you will create and deploy an ERC-20 token on a testnet environment. The tutorial will walk you through the process of deploying it on the Avalanche Fuji testnet using the <a target="_blank" href="https://testnet.its.axelar.dev/">Axelar Interchain Token Portal</a> testnet. However, you can deploy it on any supported chain without limitation; it doesn't necessarily have to be on Avalanche.</p>
<p>Go to <a target="_blank" href="https://testnet.interchain.axelar.dev/">https://testnet.interchain.axelar.dev/</a> to create and deploy a new token. Click the <code>Deploy a new Interchain Token</code> button.</p>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2F5vsPM89zEuTxjtUHrySZSo%2F2cc5be07ac2dd3643ee20f9194a54099%2FScreenshot_2023-07-25_at_23.43.04.png&amp;w=3840&amp;q=50" alt="How to Create an Interchain Token with Axelar in 4 Steps" /></p>
<p>Provide the necessary token information in the fields: <code>Token Name</code>, <code>Symbol</code>, <code>Decimals</code> and preferred <code>Amount to mint</code>.</p>
<blockquote>
<p><strong><em>Please be aware that the default for</em></strong> <code>Amount to mint</code> in the user interface is set to 0, but it should not be left at 0. If you do not select advanced settings and change <code>Amount to mint</code> to a nonzero number, the token will remain stuck, and to mint later won’t be allowed. I recommend adding a default token based on your preference but ensure it is not set to 0.</p>
</blockquote>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2F16iRxbj9QXgjztojfI5VBO%2F93fa6aebcf6d5cf5f4e1692b7409a179%2FScreenshot_2023-07-25_at_23.46.27.png&amp;w=3840&amp;q=50" alt="How to Create an Interchain Token with Axelar in 4 Steps" /></p>
<p>Next, click on the <code>Deploy</code> button.</p>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2F68TKxib2aH11b4lFCgyhTd%2F928ef462bece340482ac0b0f91232d6f%2FScreenshot_2023-07-25_at_23.57.56.png&amp;w=3840&amp;q=50" alt="Deploy and Register - How to Create an Interchain Token with Axelar in 4 Steps" /></p>
<p>Hooray! You have successfully <a target="_blank" href="https://testnet.snowtrace.io/token/0xa4EC4897d831ec6b1F2fca2287aaA86940A3Efbb">deployed and registered your token successfully</a>. Next, click on <code>Go to the token page!</code></p>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2F2UwThkYlgVEvwes8qBotqy%2F3028b0820a77833d12333bcce1866794%2FScreenshot_2023-07-26_at_00.01.14.png&amp;w=3840&amp;q=50" alt="How to Create an Interchain Token with Axelar in 4 Steps" /></p>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2F4Vd8E5ymqZLLxxb3yNgvpg%2F4e24f37ae324e135f72b67aebead4bfa%2FScreenshot_2023-07-26_at_00.05.37.png&amp;w=3840&amp;q=50" alt="Register - How to Create an Interchain Token with Axelar in 4 Steps" /></p>
<h2 id="heading-step-2-register-and-deploy-an-erc-20-token-as-an-interchain-token-on-polygon-and-moonbase"><strong>Step 2: Register and deploy an ERC-20 token as an Interchain Token on Polygon and Moonbase</strong></h2>
<p>Choose the blockchain on which you want to deploy remote tokens. In this tutorial, you will deploy to Polygon and Moonbase testnet, respectively.</p>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2F12cXJANGqTizM7IeWFTGXx%2Ffe9208b326eeb03849f907ffde07e903%2FScreenshot_2023-07-26_at_00.14.36.png&amp;w=2048&amp;q=50" alt="Deploy Remote Token - How to Create an Interchain Token with Axelar in 4 Steps" /></p>
<p>Next, you should see a display similar to the one shown below, indicating that the token has been registered and is currently being deployed to the selected remote chains, in this case, Polygon and Moonbase testnet.</p>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2F6r73zP84ZqcdSPsAgkRjHA%2F562a6b0da78472479b2be08132cf8803%2FScreenshot_2023-07-26_at_00.17.07.png&amp;w=3840&amp;q=50" alt="Deploy Remote Token - How to Create an Interchain Token with Axelar in 4 Steps" /></p>
<p>Once successfully deployed, which may take a few minutes, you should see something similar to what is displayed below.</p>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2FMhAlYTRFUs4HAIGyvK50g%2F5043e76d52f3cbec2618ca9e5e7ec6d2%2FScreenshot_2023-07-26_at_00.22.37.png&amp;w=3840&amp;q=50" alt="How to Create an Interchain Token with Axelar in 4 Steps" /></p>
<h2 id="heading-step-4-interact-with-the-interchain-token"><strong>Step 4: Interact with the Interchain Token</strong></h2>
<p>In this section, you will interact with the interchain token you just deployed via the Axelar Interchain Token Portal user interface.</p>
<p>To interact with this, you can send balances across these networks, and that's precisely where the magic happens.</p>
<h3 id="heading-send-token-from-avalanche-fuji-testnet-to-polygon-testnet"><strong>Send Token from Avalanche Fuji Testnet to Polygon Testnet</strong></h3>
<p>To send tokens from the Avalanche Fuji testnet to the Polygon testnet, click the <code>send</code> button and enter the desired amount of tokens you want to send, as shown below.</p>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2F66cdX2lAK4LeakO6zfYfHW%2F5b9055ae4cbff7140ed83c73c56e68be%2FScreenshot_2023-07-26_at_00.29.03.png&amp;w=3840&amp;q=50" alt="Send Token from Avalanche Fuji Testnet to Polygon Testnet" /></p>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2F7dxBmQcfFHOqarKUgH5IC8%2F967ae1dc5b2b066da6d461e9c12b94a3%2FScreenshot_2023-07-26_at_00.31.09.png&amp;w=3840&amp;q=50" alt="Send Token from Avalanche Fuji Testnet to Polygon Testnet" /></p>
<p>The token was sent successfully, and the balance on Polygon is now updated, as shown below.</p>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2F6VRuhQHsQegRq4CuN7BGJ5%2F8fab057db18e1f8e1563f1e4a2b66240%2FScreenshot_2023-07-26_at_00.35.08.png&amp;w=3840&amp;q=50" alt="How to Create an Interchain Token with Axelar in 4 Steps" /></p>
<h3 id="heading-send-token-from-avalanche-fuji-testnet-to-moonbase-testnet"><strong>Send token from Avalanche Fuji testnet to Moonbase testnet</strong></h3>
<p>In the previous step, you successfully sent 200 units of your ERC-20 token to the Polygon testnet. Now you will do a similar process to send the token to Moonbase.</p>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2F3PGqLpnUqsDyLq4zPvgWSI%2Fd3567908f2ad0550180efc6b337246fe%2FScreenshot_2023-07-26_at_00.38.30.png&amp;w=3840&amp;q=50" alt="Send Token from Avalanche Fuji Testnet to Moonbase Testnet" /></p>
<p>The token was sent successfully, and the balance on Moonbase is now updated, as shown below.</p>
<p><img src="https://axelar.network/_next/image?url=https%3A%2F%2Fimages.ctfassets.net%2Fmjqoq33y05of%2F43onnhRdlsjOS7AJvKB8HL%2F0fbcca48644d09cafe3510e5d9121fdd%2FScreenshot_2023-07-26_at_00.48.05.png&amp;w=3840&amp;q=50" alt="Send Token from Avalanche Fuji Testnet to Moonbase Testnet" /></p>
<p>Hooray 🥳 With Axelar, you have successfully created, registered and deployed an interchain token using the Axelar Interchain Token Portal and interacting with the token across multiple blockchains.</p>
<h2 id="heading-whats-next"><strong>What's next?</strong></h2>
<p>You can learn more about <a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/interchain-tokens">Interchain Tokens</a> and how they are created and managed by the new <a target="_blank" href="https://axelar.network/its">Interchain Token Service</a>. It allows you to send tokens cross-chain, build asset bridges, build asset transfers into your Interchain dApp, and take on many other use cases.</p>
<p>If you've made it this far, you're fantastic! You can <a target="_blank" href="https://twitter.com/intent/tweet?url=https%3A%2F%2Faxelar.network%2Fblog%2Fhow-to-create-an-interchain-token-with-axelar-in-4-steps%2F&amp;text=Thank%20you%2C%20@olanetsoft%2C%20for%20writing%20this%20helpful%20article.%0A%0A%20How%20to%20Create%20an%20Interchain%20Token%20with%20@axelarcore%20in%204%20Steps%20%0A%0A">post about your experience</a> building or following along with this tutorial to show your support to the author and tag <a target="_blank" href="https://twitter.com/axelarcore">@axelarcore</a>.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>This post covered the step-by-step process of creating, registering, and deploying an interchain token using the Axelar Interchain Token Portal and interacting with the token across multiple blockchains.</p>
<h2 id="heading-reference"><strong>Reference</strong></h2>
<ul>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/interchain-tokens">Axelar Interchain Tokens</a></p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/">Axelar Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://testnet.its.axelar.dev/">Axelar Interchain Token Portal</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Solving the TypeError: no matching function Error in Hardhat]]></title><description><![CDATA[It's a bug-fix day. I encountered an error while attempting to deploy my contract to the testnet using Hardhat with the command below.
npx hardhat run scripts/deploy.js --network <testnet>

After spending a couple of hours debugging, I realized that ...]]></description><link>https://blog.idrisolubisi.com/typeerror-no-matching-function-argumentkey-valueaddress-codeinvalidargument-version662</link><guid isPermaLink="true">https://blog.idrisolubisi.com/typeerror-no-matching-function-argumentkey-valueaddress-codeinvalidargument-version662</guid><category><![CDATA[hardhat]]></category><category><![CDATA[Solidity]]></category><category><![CDATA[Smart Contracts]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Web3]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Tue, 11 Jul 2023 13:33:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1689081296310/931dbfc8-0ee0-488e-909f-7d4adbea202b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It's a bug-fix day. I encountered an error while attempting to deploy my contract to the testnet using Hardhat with the command below.</p>
<pre><code class="lang-bash">npx hardhat run scripts/deploy.js --network &lt;testnet&gt;
</code></pre>
<p>After spending a couple of hours debugging, I realized that I had followed a similar process to deploy the contract just last week, and it worked perfectly. However, it is no longer working now.</p>
<p>I figured this error was due to the changes/upgrades in <code>@nomicfoundation/hardhat-toolbox</code> to version 3.0.0 when you create a new hardhat project.</p>
<p><strong>The old way of writing the deployment script that caused the error:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> hre = <span class="hljs-built_in">require</span>(<span class="hljs-string">"hardhat"</span>);

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> Contract = <span class="hljs-keyword">await</span> hre.ethers.getContractFactory(<span class="hljs-string">"Contract"</span>);
  <span class="hljs-keyword">const</span> contract = <span class="hljs-keyword">await</span> Contract.deploy(
    <span class="hljs-string">"&lt;Your constructor argument here&gt;"</span>
  );

  <span class="hljs-keyword">await</span> contract.deployed();

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Contract deployed to <span class="hljs-subst">${contract.address}</span>`</span>);
}

main().catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.error(error);
  process.exitCode = <span class="hljs-number">1</span>;
});
</code></pre>
<p><strong>How to write the deployment script to fix the error:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> hre = <span class="hljs-built_in">require</span>(<span class="hljs-string">"hardhat"</span>);

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> Contract = <span class="hljs-keyword">await</span> hre.ethers.deployContract(<span class="hljs-string">"Contract"</span>, 
    [<span class="hljs-string">"&lt;Your constructor argument here&gt;"</span>]
  );

  <span class="hljs-keyword">await</span> Contract.waitForDeployment();

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Contract deployed to <span class="hljs-subst">${<span class="hljs-keyword">await</span> Contract.getAddress()}</span>`</span>);
}

main().catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.error(error);
  process.exitCode = <span class="hljs-number">1</span>;
});
</code></pre>
<p>That's it 🥳🥳🥳</p>
<p>This post explained and fixed the error in deployment caused by the hardhat tools upgrade to version 3.0.0 when deploying a contract to testnet.</p>
<p>I'd love to connect with you on <a target="_blank" href="https://twitter.com/olanetsoft"><strong>Twitter</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/olubisi-idris-ayinde-05727b17a/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://github.com/Olanetsoft"><strong>GitHub</strong></a> | <a target="_blank" href="https://idrisolubisi.com/"><strong>Portfolio</strong></a></p>
<p>See you in my next blog article. Take care!!!</p>
]]></content:encoded></item><item><title><![CDATA[Build a Full Stack Interchain dApp with Next.js, Solidity & Axelar]]></title><description><![CDATA[Today's blockchain ecosystem is characterized by many blockchain networks operating independently, each with unique features and functionalities. However, this fragmentation presents challenges regarding seamless communication and collaboration betwe...]]></description><link>https://blog.idrisolubisi.com/build-a-full-stack-interchain-dapp-with-nextjs-solidity-axelar</link><guid isPermaLink="true">https://blog.idrisolubisi.com/build-a-full-stack-interchain-dapp-with-nextjs-solidity-axelar</guid><category><![CDATA[Solidity]]></category><category><![CDATA[axelar]]></category><category><![CDATA[dapp]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Wed, 05 Jul 2023 15:16:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1688559190167/78c2fee7-53ea-4896-af97-10466eb6b3c2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today's blockchain ecosystem is characterized by many blockchain networks operating independently, each with unique features and functionalities. However, this fragmentation presents challenges regarding seamless communication and collaboration between these networks. To overcome these barriers, a vital element that has emerged is a programmable blockchain interoperability layer.</p>
<p>The programmable blockchain interoperability layer bridges different blockchain networks, facilitating the exchange of information and assets securely and efficiently. It enables smooth interaction by providing a standardized framework for cross-chain communication, allowing various blockchain networks to interoperate seamlessly.</p>
<p>In this tutorial, you will learn how to build a full-stack interchain decentralized application with Next.js, Solidity, and <a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/overview">Axelar General message passing</a> to send messages from one blockchain to another.</p>
<p>For a quick start, you can find the complete code for this tutorial on <a target="_blank" href="https://github.com/axelarnetwork/fullstack-interchain-dapp">GitHub</a>. However, in the video provided below, you can see the completed app that offers users the ability to:</p>
<ul>
<li><p>Connect their wallet</p>
</li>
<li><p>Enter their desired message for cross-chain interaction</p>
</li>
<li><p>Send the message from Binance to Avalanche</p>
</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/o-OrYvyN38M">https://youtu.be/o-OrYvyN38M</a></div>
<p> </p>
<h2 id="heading-getting-started-with-axelar-general-message-passing">Getting Started with Axelar General Message Passing</h2>
<p><a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/overview">Axelar's General Message Passing (GMP)</a> feature empowers developers by enabling them to call any function on interconnected chains seamlessly.</p>
<p>With GMP, developers gain the ability to:</p>
<ol>
<li><p>Call a contract on chain A and interact with a contract on chain B.</p>
</li>
<li><p>Execute cross-chain transactions by calling a contract on chain A and sending tokens to chain B.</p>
</li>
</ol>
<h2 id="heading-prerequisite">Prerequisite</h2>
<p>Before getting started, you need the following prerequisites:</p>
<ul>
<li><p><a target="_blank" href="https://nodejs.org/en/"><strong>Node.js</strong></a> and its package manager NPM, version 18*. Verify Node.js is installed by running the following terminal command: <code>node -v &amp;&amp; npm -v</code></p>
</li>
<li><p>A basic understanding of <a target="_blank" href="https://www.w3schools.com/js/default.asp">JavaScript</a>, <a target="_blank" href="https://www.tutorialspoint.com/solidity/index.htm">Solidity</a>, and <a target="_blank" href="https://www.w3schools.com/REACT/DEFAULT.ASP">React/Next.js</a></p>
</li>
</ul>
<h2 id="heading-project-setup-and-installation">Project Setup and Installation</h2>
<p>To start the project setup and installation quickly, clone this <a target="_blank" href="https://github.com/Olanetsoft/fullstack-interchain-dapp/tree/starter"><strong>project on GitHub</strong></a>. Make sure you're on the <code>starter</code> branch using the following command:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> &lt;https://github.com/axelarnetwork/fullstack-interchain-dapp&gt;
</code></pre>
<p>Next, install the project locally after cloning it using the following command in your terminal.</p>
<p>Here's how you can install the project using <code>npm</code>:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> fullstack-interchain-dapp &amp;&amp; npm i &amp;&amp; npm run dev
</code></pre>
<p>Next.js will start a hot-reloading development environment accessible by default at <a target="_blank" href="http://localhost:3000">http://localhost:3000</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686054110807/41e991f5-c25d-4e68-ba91-27b067becc23.png" alt="Build a Full Stack Interchain dApp with Next.js, Solidity &amp; Axelar" /></p>
<h2 id="heading-building-a-smart-contract-with-hardhat-and-axelar-gmp">Building a Smart Contract with Hardhat and Axelar GMP</h2>
<p>In this section, you will build an interchain smart contract leveraging the Axelar GMP feature to send messages from one chain to another.</p>
<p>Navigate to the project's root folder you cloned in the previous step, and then run the following commands to create a new Hardhat project.</p>
<pre><code class="lang-bash">mkdir hardhat
<span class="hljs-built_in">cd</span> hardhat
npm install --save-dev hardhat
</code></pre>
<p>Let's get a sample project by running the command below:</p>
<pre><code class="lang-bash">npx hardhat
</code></pre>
<p>We'll go with the following options:</p>
<p><code>What do you want to do?</code></p>
<p><code>✔ Create A JavaScript Project</code></p>
<p><code>✔ Hardhat project root:</code></p>
<p><code>? Do you want to add a .gitignore? (Y/n) › y</code></p>
<p><code>? Do you want to install this sample project's dependencies with npm (hardhat @nomicfoundation/hardhat-toolbox)? (Y/n) › y</code></p>
<p>The <code>@nomicfoundation/hardhat-toolbox</code> plugin bundles all the commonly used packages and Hardhat plugins recommended to start developing with Hardhat.</p>
<p>Just in case it didn't install automatically, install this other requirement with the following command:</p>
<pre><code class="lang-apache"><span class="hljs-attribute">npm</span> i @nomicfoundation/hardhat-toolbox
</code></pre>
<p>Next, install <code>@axelar-network/axelar-gmp-sdk-solidity</code> for Axelar General Message Passing SDK in Solidity and <code>dotenv</code> with the following command:</p>
<pre><code class="lang-apache"><span class="hljs-attribute">npm</span> i @axelar-network/axelar-gmp-sdk-solidity dotenv
</code></pre>
<p>To ensure everything works, run the command below in the <code>hardhat</code> directory.</p>
<pre><code class="lang-apache"><span class="hljs-attribute">npx</span> hardhat test
</code></pre>
<p>You will see a passed test result in our console.</p>
<p>Delete <code>Lock.js</code> from the test folder and delete <code>deploy.js</code> from the <code>scripts</code> directory. After that, go to contracts and delete <code>Lock.sol.</code></p>
<blockquote>
<p>The folders themselves should not be deleted!</p>
</blockquote>
<p>Create a <code>SendMessage.sol</code> file inside the <code>contracts</code> directory and update it with the following code snippet. When using Hardhat, file layout is crucial, so pay attention!</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-comment">// SPDX license identifier specifies which open-source license is being used for the contract</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> 0.8.9;</span>

<span class="hljs-comment">// Importing external contracts for dependencies</span>
<span class="hljs-keyword">import</span> { <span class="hljs-title">AxelarExecutable</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">IAxelarGateway</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">IAxelarGasService</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title">IERC20</span> } <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">'@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol'</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">SendMessage</span> <span class="hljs-keyword">is</span> <span class="hljs-title">AxelarExecutable</span> </span>{

    <span class="hljs-keyword">string</span> <span class="hljs-keyword">public</span> value;
    <span class="hljs-keyword">string</span> <span class="hljs-keyword">public</span> sourceChain;
    <span class="hljs-keyword">string</span> <span class="hljs-keyword">public</span> sourceAddress;

    IAxelarGasService <span class="hljs-keyword">public</span> <span class="hljs-keyword">immutable</span> gasService;

    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> gateway_, <span class="hljs-keyword">address</span> gasReceiver_</span>) <span class="hljs-title">AxelarExecutable</span>(<span class="hljs-params">gateway_</span>) </span>{
        <span class="hljs-comment">// Sets the immutable state variable to the address of gasReceiver_</span>
        gasService <span class="hljs-operator">=</span> IAxelarGasService(gasReceiver_);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendMessage</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> destinationChain,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> destinationAddress,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> value_
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{

        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">memory</span> payload <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">encode</span>(value_);

        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>) {
            gasService.payNativeGasForContractCall{ <span class="hljs-built_in">value</span>: <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> }(
                <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
                destinationChain,
                destinationAddress,
                payload,
                <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>
            );
        }
        <span class="hljs-comment">// Calls the Axelar gateway contract with the specified destination chain and address and sends the payload along with the call</span>
        gateway.callContract(destinationChain, destinationAddress, payload);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_execute</span>(<span class="hljs-params">
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> sourceChain_,
        <span class="hljs-keyword">string</span> <span class="hljs-keyword">calldata</span> sourceAddress_,
        <span class="hljs-keyword">bytes</span> <span class="hljs-keyword">calldata</span> payload_
    </span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">override</span></span> </span>{
        <span class="hljs-comment">// Decodes the payload bytes into the string value and sets the state variable for this contract</span>
        (value) <span class="hljs-operator">=</span> <span class="hljs-built_in">abi</span>.<span class="hljs-built_in">decode</span>(payload_, (<span class="hljs-keyword">string</span>));

sourceChain <span class="hljs-operator">=</span> sourceChain_;
        sourceAddress <span class="hljs-operator">=</span> sourceAddress_;
    }
}
</code></pre>
<p>In the code snippet above we:</p>
<ul>
<li><p>Create a <code>SendMessage</code> contract that extends the <code>AxelarExecutable</code> contract</p>
</li>
<li><p>Import <code>AxelarExecutable</code>, <code>IAxelarGateway</code>, <code>IAxelarGasService</code> from the <code>@axelar-network/axelar-gmp-sdk-solidity</code> library.</p>
</li>
<li><p>Define <code>four</code> state variables: <code>value</code>, <code>sourceChain</code>, <code>sourceAddress</code>, and <code>gasService</code>. The <code>gasService</code> state variable is immutable and can only be set during contract deployment.</p>
</li>
<li><p>Initialize the <code>gasService</code> variable with the provided <code>gasReceiver_</code> address.</p>
</li>
<li><p>Create a <code>sendMessage</code> function that takes three string parameters: <code>destinationChain</code>, <code>destinationAddress</code>, <code>value_</code> and it utilizes <code>gasService.payNativeGasForContractCall</code> with native gas (Ether).</p>
</li>
<li><p>Utilized the <code>gateway</code> contract's <code>callContract</code> function with the specified <code>destinationChain</code>, <code>destinationAddress</code>, and <code>payload</code> parameters.</p>
</li>
<li><p>The <code>_execute</code> function decodes the payload bytes into the <code>value</code> string and updates the state variables <code>sourceChain</code> and <code>sourceAddress</code>.</p>
</li>
</ul>
<h3 id="heading-setup-deployment-script">Setup Deployment Script</h3>
<p>Next, create a <code>deploy.js</code> file in the <code>scripts</code> folder and add the following code snippet:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// We require the Hardhat Runtime Environment explicitly here. This is optional</span>
<span class="hljs-comment">// but useful for running the script in a standalone fashion through `node &lt;script&gt;`.</span>
<span class="hljs-comment">//</span>
<span class="hljs-comment">// You can also run a script with `npx hardhat run &lt;script&gt;`. If you do that, Hardhat</span>
<span class="hljs-comment">// will compile your contracts, add the Hardhat Runtime Environment's members to the</span>
<span class="hljs-comment">// global scope, and execute the script.</span>
<span class="hljs-keyword">const</span> hre = <span class="hljs-built_in">require</span>(<span class="hljs-string">"hardhat"</span>);

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> SendMessage = <span class="hljs-keyword">await</span> hre.ethers.getContractFactory(<span class="hljs-string">"SendMessage"</span>);
  <span class="hljs-keyword">const</span> sendMessage = <span class="hljs-keyword">await</span> SendMessage.deploy(
    <span class="hljs-string">""</span>,
    <span class="hljs-string">""</span>
  );

  <span class="hljs-keyword">await</span> sendMessage.deployed();

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`SendMessage contract deployed to <span class="hljs-subst">${sendMessage.address}</span>`</span>);
}

<span class="hljs-comment">// We recommend this pattern to be able to use async/await everywhere</span>
<span class="hljs-comment">// and properly handle errors.</span>
main().catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.error(error);
  process.exitCode = <span class="hljs-number">1</span>;
});
</code></pre>
<p>In the code snippet above:</p>
<ul>
<li><p>The <code>main</code> function has the <code>SendMessage</code> contract factory obtained using <code>hre.ethers.getContractFactory</code>.</p>
</li>
<li><p>The <code>sendMessage</code> contract is deployed using the <code>SendMessage.deploy</code> method with two strings as arguments.</p>
</li>
<li><p><code>await sendMessage.deployed()</code> statement ensures that the deployment is completed before moving forward.</p>
</li>
<li><p>The deployed contract's address is logged into the console.</p>
</li>
</ul>
<h3 id="heading-setup-remote-procedure-call-rpc-to-testnet">Setup Remote Procedure Call (RPC) to Testnet</h3>
<p>Remote Procedure Call (RPC) is a protocol used for communication between client and server systems in a network or blockchain environment. It enables clients to execute procedures or functions on remote servers and receive the results. RPC abstracts the underlying network details and allows clients to invoke methods on servers as if they were local.</p>
<p>Before you proceed to set up RPC, create a <code>.env</code> file using the command below:</p>
<pre><code class="lang-apache"><span class="hljs-attribute">touch</span> .env
</code></pre>
<blockquote>
<p>Ensure you are in the hardhat directory before running the command above.</p>
</blockquote>
<p>Inside the <code>.env</code> file you just created, add the following key:</p>
<pre><code class="lang-apache"><span class="hljs-attribute">PRIVATE_KEY</span>= // Add your account private key here
</code></pre>
<p>Getting your private account key is easy. Check out this <a target="_blank" href="https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key"><strong>post</strong></a>.</p>
<p>Next, set up RPC for Binance and Avalanche networks by updating the <code>hardhat.config.js</code> file with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">require</span>(<span class="hljs-string">"@nomicfoundation/hardhat-toolbox"</span>);
<span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config({ <span class="hljs-attr">path</span>: <span class="hljs-string">".env"</span> });
<span class="hljs-built_in">require</span>(<span class="hljs-string">"solidity-coverage"</span>);

<span class="hljs-keyword">const</span> PRIVATE_KEY = process.env.PRIVATE_KEY;

<span class="hljs-comment">// This is a sample Hardhat task. To learn how to create your own go to</span>
<span class="hljs-comment">// &lt;https://hardhat.org/guides/create-task.html&gt;</span>
task(<span class="hljs-string">"accounts"</span>, <span class="hljs-string">"Prints the list of accounts"</span>, <span class="hljs-keyword">async</span> (taskArgs, hre) =&gt; {
  <span class="hljs-keyword">const</span> accounts = <span class="hljs-keyword">await</span> hre.ethers.getSigners();

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> account <span class="hljs-keyword">of</span> accounts) {
    <span class="hljs-built_in">console</span>.log(account.address);
  }
});

<span class="hljs-comment">// You need to export an object to set up your config</span>
<span class="hljs-comment">// Go to &lt;https://hardhat.org/config/&gt; to learn more</span>

<span class="hljs-comment">/** @type import('hardhat/config').HardhatUserConfig */</span>
<span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">solidity</span>: <span class="hljs-string">"0.8.9"</span>,
  <span class="hljs-attr">networks</span>: {
    <span class="hljs-attr">bsc</span>: {
      <span class="hljs-attr">url</span>: <span class="hljs-string">"&lt;https://data-seed-prebsc-1-s1.binance.org:8545&gt;"</span>,
      <span class="hljs-attr">chainId</span>: <span class="hljs-number">97</span>,
      <span class="hljs-attr">accounts</span>: [PRIVATE_KEY],
    },
    <span class="hljs-attr">avalancheFujiTestnet</span>: {
      <span class="hljs-attr">url</span>: <span class="hljs-string">"&lt;https://avalanche-fuji-c-chain.publicnode.com&gt;"</span>,
      <span class="hljs-attr">chainId</span>: <span class="hljs-number">43113</span>,
      <span class="hljs-attr">accounts</span>: [PRIVATE_KEY],
    },
  },
  <span class="hljs-attr">mocha</span>: {
    <span class="hljs-attr">timeout</span>: <span class="hljs-number">10000000000</span>,
  },
};
</code></pre>
<p>You have successfully configured RPC for Binance and Avalanche test networks, you will proceed with the smart contract deployment to those networks in the following step.</p>
<h3 id="heading-deploy-smart-contract-to-binance-and-avalanche-network">Deploy Smart Contract to Binance and Avalanche Network</h3>
<p>In this section, you will deploy the smart contract to Binance and Avalanche Testnet. However, before you proceed, you need to specify the Axelar <code>Gateway Service</code> and the <code>Gas Service</code> Contract in the <code>SendMessage.deploy()</code> method within the <code>deploy.js</code> file you created earlier.</p>
<p>You can find the Axelar Gas Service and Gateway contracts list for all the chains Axelar currently supports <a target="_blank" href="https://docs.axelar.dev/resources/testnet">here</a>.</p>
<p>You also need a faucet for your Binance and Avalanche accounts to ensure successful contract deployment. To obtain the Binance faucet, visit this <a target="_blank" href="http://discord.gg/bnbchain">link</a>, and for the Avalanche faucet, access it <a target="_blank" href="https://faucet.avax.network/">here</a>.</p>
<h3 id="heading-deploy-to-binance-testnet">Deploy to Binance Testnet</h3>
<p>Update the <code>deploy.js</code> file inside the <code>scripts</code> folder to deploy to Binance testnet with the following code snippet:</p>
<pre><code class="lang-apache">//...

<span class="hljs-attribute">async</span> function main() {
  //...

  // <span class="hljs-attribute">Update</span> arguments with the Axelar gateway and
  // <span class="hljs-attribute">gas</span> service <span class="hljs-literal">on</span> Binance testnet
  <span class="hljs-attribute">const</span> sendMessage = await SendMessage.deploy(
    "<span class="hljs-attribute">0x4D147dCb984e6affEEC47e44293DA442580A3Ec0</span><span class="hljs-string">",
    "</span><span class="hljs-number">0</span>xbE<span class="hljs-number">406</span>F<span class="hljs-number">0189</span>A<span class="hljs-number">0</span>B<span class="hljs-number">4</span>cf<span class="hljs-number">3</span>A<span class="hljs-number">05</span>C<span class="hljs-number">286473</span>D<span class="hljs-number">23791</span>Dd<span class="hljs-number">44</span>Cc<span class="hljs-number">6</span><span class="hljs-string">"
  );

  //...
}

//..</span>
</code></pre>
<p>To deploy the contract on the Binance testnet, run the following command:</p>
<pre><code class="lang-apache"><span class="hljs-attribute">npx</span> hardhat run scripts/deploy.js --network bsc
</code></pre>
<p>For example, the contract address will be displayed in your console: <code>0xC1b8fC9208E51aC997895626b0f384153E94f2A7</code>.</p>
<h3 id="heading-deploy-to-avalanche-fuji-testnet">Deploy to Avalanche Fuji Testnet</h3>
<p>Update the <code>deploy.js</code> file inside the <code>scripts</code> folder to deploy to Avalanche testnet with the following code snippet:</p>
<pre><code class="lang-apache">//...

<span class="hljs-attribute">async</span> function main() {
  //...

  // <span class="hljs-attribute">Update</span> arguments with the Axelar gateway and
  // <span class="hljs-attribute">gas</span> service <span class="hljs-literal">on</span> Avalanche testnet
  <span class="hljs-attribute">const</span> sendMessage = await SendMessage.deploy(
    "<span class="hljs-attribute">0xC249632c2D40b9001FE907806902f63038B737Ab</span><span class="hljs-string">",
    "</span><span class="hljs-number">0</span>xbE<span class="hljs-number">406</span>F<span class="hljs-number">0189</span>A<span class="hljs-number">0</span>B<span class="hljs-number">4</span>cf<span class="hljs-number">3</span>A<span class="hljs-number">05</span>C<span class="hljs-number">286473</span>D<span class="hljs-number">23791</span>Dd<span class="hljs-number">44</span>Cc<span class="hljs-number">6</span><span class="hljs-string">"
  );

  //...
}

//..</span>
</code></pre>
<p>To deploy the contract on the Avalanche testnet, run the following command:</p>
<pre><code class="lang-apache"><span class="hljs-attribute">npx</span> hardhat run scripts/deploy.js --network avalancheFujiTestnet
</code></pre>
<p>The contract address will be displayed on your console; for example, <code>0x2a03DCB9B24431d02839822209D58262f5e5df52</code>. Make sure to save both deployed contract addresses, as you will need them for front-end integration.</p>
<h2 id="heading-integrating-a-nextjs-frontend-application-with-smart-contract">Integrating a Nextjs Frontend Application with Smart Contract</h2>
<p>In the previous steps, you successfully built and deployed the smart contract. Now, it's time to interact with it from the front end, just as you would typically interact with decentralized applications on the web.</p>
<p>You already have the Next.js frontend project cloned, and the configuration for <code>WAGMI</code> and <code>Rainbowkit</code> is set up. This means you can proceed to update the existing application and connect your smart contract for testing.</p>
<h3 id="heading-implementing-write-smart-contract-functionality">Implementing Write Smart Contract Functionality</h3>
<p>Interacting with our contract is quite simple from the front-end application, thanks to <code>WAGMI</code>, <code>RainbowKit</code>, and <code>ethers</code>.</p>
<p>Create a <code>.env.local</code> file in the root directory using the command below:</p>
<pre><code class="lang-apache"><span class="hljs-attribute">touch</span> .env.local
</code></pre>
<blockquote>
<p>Ensure you are in the root directory before running the command above.</p>
</blockquote>
<p>Inside the <code>.env.local</code> file you just created, add the following key:</p>
<pre><code class="lang-apache"><span class="hljs-attribute">NEXT_PUBLIC_AVALANCHE_RPC_URL</span>=https://avalanche-fuji-c-chain.publicnode.com
<span class="hljs-attribute">NEXT_PUBLIC_BSC_CONTRACT_ADDRESS</span>=&lt;BSC_CONTRACT_ADDRESS&gt;
<span class="hljs-attribute">NEXT_PUBLIC_AVALANCHE_CONTRACT_ADDRESS</span>=&lt;AVALANCHE_CONTRACT_ADDRESS&gt;
</code></pre>
<p>Replace <code>&lt;BSC_CONTRACT_ADDRESS&gt;</code> with the contract address, you deployed to the Binance testnet and replace <code>&lt;AVALANCHE_CONTRACT_ADDRESS&gt;</code> with the contract address, you deployed to the Avalanche Fuji Testnet earlier in this tutorial.</p>
<p>Next, implement the write functionality for the smart contract, add the following code snippet to the <code>index.js</code> file located in the <code>pages</code> directory.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

<span class="hljs-keyword">const</span> BSC_CONTRACT_ADDRESS = process.env.NEXT_PUBLIC_BSC_CONTRACT_ADDRESS;
<span class="hljs-keyword">const</span> AVALANCHE_CONTRACT_ADDRESS =
  process.env.NEXT_PUBLIC_AVALANCHE_CONTRACT_ADDRESS;
<span class="hljs-keyword">const</span> AVALANCHE_RPC_URL = process.env.NEXT_PUBLIC_AVALANCHE_RPC_URL;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-comment">//...</span>

<span class="hljs-keyword">const</span> [message, setMessage] = useState(<span class="hljs-string">""</span>); 
<span class="hljs-keyword">const</span> [sourceChain, setSourceChain] = useState(<span class="hljs-string">""</span>); 

<span class="hljs-keyword">const</span> { config } = usePrepareContractWrite({ <span class="hljs-comment">// Calling a hook to prepare the contract write configuration</span>
  <span class="hljs-attr">address</span>: BSC_CONTRACT_ADDRESS, <span class="hljs-comment">// Address of the BSC contract</span>
  <span class="hljs-attr">abi</span>: SendMessageContract.abi, <span class="hljs-comment">// ABI (Application Binary Interface) of the contract</span>
  <span class="hljs-attr">functionName</span>: <span class="hljs-string">"sendMessage"</span>, <span class="hljs-comment">// Name of the function to call on the contract</span>
  <span class="hljs-attr">args</span>: [<span class="hljs-string">"Avalanche"</span>, AVALANCHE_CONTRACT_ADDRESS, message], <span class="hljs-comment">// Arguments to pass to the contract function</span>
  <span class="hljs-attr">value</span>: ethers.utils.parseEther(<span class="hljs-string">"0.01"</span>), <span class="hljs-comment">// Value to send along with the contract call for gas fee</span>
});

<span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: useContractWriteData, write } = useContractWrite(config); 

<span class="hljs-keyword">const</span> { <span class="hljs-attr">data</span>: useWaitForTransactionData, isSuccess } = useWaitForTransaction({ 
  <span class="hljs-attr">hash</span>: useContractWriteData?.hash, <span class="hljs-comment">// Hash of the transaction obtained from the contract write data</span>
});

<span class="hljs-keyword">const</span> handleSendMessage = <span class="hljs-function">() =&gt;</span> {
  write(); <span class="hljs-comment">// Initiating the contract call</span>

  toast.info(<span class="hljs-string">"Sending message..."</span>, {
    <span class="hljs-attr">position</span>: <span class="hljs-string">"top-right"</span>,
    <span class="hljs-attr">autoClose</span>: <span class="hljs-number">5000</span>,
    <span class="hljs-attr">hideProgressBar</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">closeOnClick</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">pauseOnHover</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">draggable</span>: <span class="hljs-literal">true</span>,
  });
};

useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> body = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"body"</span>);
    darkMode ? body.classList.add(<span class="hljs-string">"dark"</span>) : body.classList.remove(<span class="hljs-string">"dark"</span>);

    isSuccess
      ? toast.success(<span class="hljs-string">"Message sent!"</span>, {
          <span class="hljs-attr">position</span>: <span class="hljs-string">"top-right"</span>,
          <span class="hljs-attr">autoClose</span>: <span class="hljs-number">7000</span>,
          <span class="hljs-attr">closeOnClick</span>: <span class="hljs-literal">true</span>,
          <span class="hljs-attr">pauseOnHover</span>: <span class="hljs-literal">false</span>,
          <span class="hljs-attr">draggable</span>: <span class="hljs-literal">true</span>,
        })
      : useWaitForTransactionData?.error || useContractWriteData?.error
      ? toast.error(<span class="hljs-string">"Error sending message"</span>)
      : <span class="hljs-literal">null</span>;
  }, [darkMode, useContractWriteData, useWaitForTransactionData]);

<span class="hljs-keyword">return</span> (
    <span class="hljs-comment">//..</span>
   )
}
</code></pre>
<p>In the code snippet above:</p>
<ol>
<li><p>Two state variables, <code>message</code> and <code>sourceChain</code>, are declared using the <code>useState</code> hook to hold the message content and source chain, respectively.</p>
</li>
<li><p>The <code>usePrepareContractWrite</code> hook is called to prepare the configuration for a contract write operation. It takes several parameters, such as the BSC contract address, ABI, function name, arguments, and value.</p>
</li>
<li><p><code>useContractWrite</code> hook retrieves the contract write data and the write function based on the configuration obtained from the previous step.</p>
</li>
<li><p><code>useWaitForTransaction</code> hook is called to wait for the transaction to be mined. It takes the hash of the transaction obtained from the contract write data.</p>
</li>
<li><p><code>handleSendMessage</code> function is defined, which initiates the contract call by invoking the <code>write</code> function.</p>
</li>
<li><p><code>useEffect</code> hook performs actions when certain dependencies change to display toast notifications for successful or failed message sending.</p>
</li>
</ol>
<p>Update the <code>Send</code> button and <code>textarea</code> with the following code snippet to send messages and retrieve the data to be sent.</p>
<pre><code class="lang-apache">//...

<span class="hljs-attribute">return</span> (
    //...
    <span class="hljs-section">&lt;div className=<span class="hljs-string">"border border-gray-300 rounded-lg p-8 m-2 "</span>&gt;</span>
        <span class="hljs-section">&lt;h2 className=<span class="hljs-string">"text-2xl font-bold mb-4"</span>&gt;</span><span class="hljs-attribute">Send</span> Message 📓 &lt;/h<span class="hljs-number">2</span>&gt;
        <span class="hljs-section">&lt;textarea
            //...
            onChange={(e) =&gt;</span> <span class="hljs-attribute">setMessage</span>(e.target.value)}
        /&gt;
        <span class="hljs-section">&lt;button
            //...
            onClick={() =&gt;</span> <span class="hljs-attribute">handleSendMessage</span>()}
         &gt;
            <span class="hljs-attribute">Send</span>
        <span class="hljs-section">&lt;/button&gt;</span>
     <span class="hljs-section">&lt;/div&gt;</span>
    //...
  );
}
</code></pre>
<h3 id="heading-implementing-read-smart-contract-functionality">Implementing Read Smart Contract Functionality</h3>
<p>In the previous step, you implemented the functionality for writing to a smart contract from the front end. This section will teach you how to implement the functionality for reading data from a smart contract.</p>
<p>Update the <code>index.js</code> with the following code snippet:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//...</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Home</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">//...</span>

  <span class="hljs-keyword">const</span> [value, setValue] = useState(<span class="hljs-string">""</span>);

  <span class="hljs-keyword">const</span> provider = <span class="hljs-keyword">new</span> ethers.providers.JsonRpcProvider(AVALANCHE_RPC_URL); <span class="hljs-comment">// Create an instance of JsonRpcProvider with Avalanche RPC URL</span>

  <span class="hljs-keyword">const</span> contract = <span class="hljs-keyword">new</span> ethers.Contract(
    AVALANCHE_CONTRACT_ADDRESS, 
    SendMessageContract.abi,

    provider
  );

  <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readDestinationChainVariables</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> value = <span class="hljs-keyword">await</span> contract.value(); 
      <span class="hljs-keyword">const</span> sourceChain = <span class="hljs-keyword">await</span> contract.sourceChain();

      setValue(value.toString()); <span class="hljs-comment">// Convert the value to a string and store it</span>
      setSourceChain(sourceChain); <span class="hljs-comment">// Store the source chain</span>
    } <span class="hljs-keyword">catch</span> (error) {
      toast.error(<span class="hljs-string">"Error reading message"</span>); <span class="hljs-comment">// Display an error toast if reading fails</span>
    }
  }

  useEffect(<span class="hljs-function">() =&gt;</span> {
    readDestinationChainVariables(); <span class="hljs-comment">// Call the function to read destination chain variables</span>

    <span class="hljs-comment">//...</span>
  }, [darkMode, useContractWriteData, useWaitForTransactionData]);

  <span class="hljs-keyword">return</span> (
    <span class="hljs-comment">//...</span>

        {value ? ( <span class="hljs-comment">// Add value here</span>
              <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
                //...
              <span class="hljs-tag">&lt;/&gt;</span></span>
            ) : (
              <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"text-red-500 "</span>&gt;</span>waiting for response...<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>
         )}
  );
}
</code></pre>
<p>In the code above,</p>
<ol>
<li><p>An instance of the <code>JsonRpcProvider</code> class from the ethers.js library is created using the Avalanche RPC URL (<code>AVALANCHE_RPC_URL</code>) as the parameter.</p>
</li>
<li><p>An instance of the <code>Contract</code> class from the ethers.js library is created, representing a contract on the Avalanche network. It takes parameters such as the contract address (<code>AVALANCHE_CONTRACT_ADDRESS</code>), ABI (<code>SendMessageContract.abi</code>), and provider.</p>
</li>
<li><p>An asynchronous function named <code>readDestinationChainVariables</code> is defined. It attempts to read the contract's value and source chain variables using the <code>value()</code> and <code>sourceChain()</code> functions, respectively.</p>
</li>
<li><p>If an error occurs during the reading process, a toast notification with the message "Error reading message" is displayed.</p>
</li>
<li><p>The <code>useEffect</code> hook calls the <code>readDestinationChainVariables</code> function when certain dependencies change.</p>
</li>
</ol>
<h2 id="heading-trying-the-application">Trying the Application</h2>
<p>Hurray 🥳 , you have successfully built and deployed a full-stack interchain decentralized application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1686152491196/0f6c1be9-75b5-4dc8-bb28-fe9b77cb0f84.png" alt="Build a Full Stack Interchain dApp with Next.js, Solidity &amp; Axelar" /></p>
<p>You can find the GMP transaction on Axelarscan Testnet <a target="_blank" href="https://testnet.axelarscan.io/gmp/0x2fa441ef701ee830cd2e8d16fd78e5943e0d67af0787050edb68eacda18f3651">here</a> and the complete code for this project on <a target="_blank" href="https://github.com/Olanetsoft/fullstack-interchain-dapp">GitHub</a>.</p>
<h2 id="heading-what-next">What Next?</h2>
<p>This post covered the utilization of Axelar's General Message Passing with <code>callContract</code>, but that's not all the General Message Passing can do.</p>
<p>You can always explore other functionalities like <a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/gmp-tokens-with-messages"><code>callContractWithToken</code></a>, <a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/overview"><code>SendToken</code></a>, <a target="_blank" href="https://docs.axelar.dev/dev/send-tokens/overview#get-a-deposit-address"><code>Deposit addresses</code></a>, <a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/examples#nft-linker"><code>NFT Linker</code></a>, <a target="_blank" href="https://docs.axelar.dev/dev/axelarjs-sdk/intro"><code>JavaScript SDK</code></a>, etc.</p>
<p>If you've made it this far, you're awesome! You can also tweet about your experience building or following along with this tutorial to show your support to the author and tag <a target="_blank" href="https://twitter.com/axelarcore">@axelarcore</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This tutorial taught you how to build a full-stack interchain decentralized application using Next.js, Solidity, and Axelar's General Message Passing. You learned how to deploy and send messages from Binance to Avalanche test networks and interact with them through a Next.js frontend application.</p>
<h2 id="heading-reference">Reference</h2>
<ul>
<li><p><a target="_blank" href="https://docs.axelar.dev/dev/general-message-passing/overview">Axelar General Message Passing</a></p>
</li>
<li><p><a target="_blank" href="https://youtu.be/htMVIYzGA34">Axelar General Message Passing Video Tutorial</a></p>
</li>
<li><p><a target="_blank" href="https://docs.axelar.dev/">Axelar Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://hardhat.org/">Hardhat</a></p>
</li>
<li><p><a target="_blank" href="https://www.rainbowkit.com/">RainbowKit</a></p>
</li>
<li><p><a target="_blank" href="https://nextjs.org/docs">Next.js</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Create Better Content with These AI Tools]]></title><description><![CDATA[Creating compelling content that resonates with your audience is challenging, especially in the ever-changing digital landscape of 2023. However, you don't have to go alone as a content creator. By using cutting-edge tools, technology, and artificial...]]></description><link>https://blog.idrisolubisi.com/create-better-content-with-these-ai-tools-in-2023</link><guid isPermaLink="true">https://blog.idrisolubisi.com/create-better-content-with-these-ai-tools-in-2023</guid><category><![CDATA[writing]]></category><category><![CDATA[content]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[AI]]></category><category><![CDATA[technology]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Thu, 02 Mar 2023 16:08:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677678447915/e7e61ed3-670f-404c-b79a-144f157e24eb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Creating compelling content that resonates with your audience is challenging, especially in the ever-changing digital landscape of 2023. However, you don't have to go alone as a content creator. By using cutting-edge tools, technology, and artificial intelligence (AI), you can streamline your content creation process and take it to new heights.</p>
<p>This article will examine some of the top tools available to content creators today. If you're a seasoned blogger or a business owner looking to up your content game, read on to discover the AI tools to help you create content that truly stands out.</p>
<h2 id="heading-content-ai-tools">Content AI Tools ✍️</h2>
<h3 id="heading-article-idea-generator">Article Idea Generator</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677671581001/7cd8deab-3672-4f34-bad7-34dd7db585cd.png" alt="Article Idea Generator" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://www.articleideagenerator.com/">Article Idea Generator</a> is an open-source tool powered by AI technology designed to help writers overcome the frustration of writer's block. Whether you're a seasoned writer or just starting, it's the perfect solution for generating new article ideas.</p>
<h3 id="heading-copy-ai">Copy AI</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677671658935/a0ede5cf-932c-4d60-a31b-37ed9a81533a.png" alt class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://www.copy.ai/">Copy.a</a>i is an AI tool that creates content to help boost conversion rates. <a target="_blank" href="http://Copy.ai">Copy.ai</a> makes it easy for marketers and copywriters to test the app. If you're new to Copy.ai, you'll get a 7-day free trial of the Pro plan and 2,000 words to use each month - no strings attached! We won't ask for any credit card information until you're ready to upgrade your account.</p>
<h3 id="heading-grammarly">Grammarly</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677674998457/739aa808-0792-4226-aa49-f3c6e7928dbc.png" alt="Grammarly" class="image--center mx-auto" /></p>
<p><a target="_blank" href="http://grammarly.com">Grammarly</a> is an AI-powered writing assistant that checks grammar, spelling, and punctuation errors.</p>
<h3 id="heading-headline-analyzer">Headline Analyzer</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677675120111/75ea1e13-6f7a-45ec-abbb-72fea31b8b35.png" alt="Headline Analyzer" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://www.monsterinsights.com/headline-analyzer/">Headline Analyzer</a> is an AI tool that analyzes headlines for emotional appeal, word choice, and length.</p>
<h3 id="heading-puzzle">Puzzle</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677672005867/e961eb35-4754-45ca-a42c-0f77b05316fc.png" alt="Puzzle Labs" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://puzzlelabs.ai/">Puzzle</a> is an AI tool for building a knowledge base for your team and customers. Puzzle Labs believe understanding complex information should be easy and enjoyable, especially when managing your glossary. This enables you to provide the most effective customer instruction experience possible.</p>
<h3 id="heading-hashnode-ai-powered-writing-assistance-beta">Hashnode AI-powered Writing Assistance (Beta)</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677672766196/003d0444-bef6-4e12-885c-a7a6d53cbdce.png" alt="Hashnode AI-powered Writing Assistance" class="image--center mx-auto" /></p>
<p>This AI-powered writing assistance offers the following features:</p>
<ul>
<li><p>Paraphrasing, to improves the natural flow and readability of your content.</p>
</li>
<li><p>Automated creation of outlines, summaries, and code blocks.</p>
</li>
<li><p>Access to an AI-powered chatbot that assists with a wide range of writing and editing tasks, akin to GitHub's co-pilot for technical writing.</p>
</li>
</ul>
<h3 id="heading-articoolo">Articoolo</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677675637454/b96176ac-f5ef-4f7a-b4d4-4bbeaf43c194.png" alt="Articoolo" class="image--center mx-auto" /></p>
<p><a target="_blank" href="http://articoolo.com/">Articoolo</a> is an AI content generation tool that creates unique articles from scratch using natural language processing.</p>
<h3 id="heading-unbounce">Unbounce</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677672300540/a2bd9251-129a-4544-8808-805ac3ea7805.png" alt class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://unbounce.com/">Unbounce</a> is an AI-powered landing page builder with intelligent features that let you create beautiful, high-performing marketing campaigns in just a few minutes.</p>
<h3 id="heading-phrasee">Phrasee</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677676209883/9f223741-ace9-4444-a927-f195b9aa3cc4.png" alt="Phrasee" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://phrasee.co/">Phrasee</a> is an AI-powered email marketing tool that uses natural language generation to optimize email subject lines, body text, and calls-to-action.</p>
<h3 id="heading-marketmuse">MarketMuse</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677675484130/6d4db76d-d49a-48de-9152-4ce37edbda7f.png" alt="MarketMuse" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://www.marketmuse.com/">MareketMuse</a> is an AI-driven content optimization platform that uses natural language processing to identify gaps in content and suggest improvements.</p>
<h2 id="heading-audio-and-video-ai-tools">Audio and Video AI Tools 📸</h2>
<h3 id="heading-lumen5">Lumen5</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677675239827/45a12582-aadd-4100-bcc1-8f7b524e49ef.png" alt="Lumen5" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://lumen5.com/">Lumen5</a> is an AI-powered video creation platform that converts text-based content into engaging videos with images, music, and animations.</p>
<h3 id="heading-voicepen-ai">VoicePen AI</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677672514933/d4cf7434-5979-4d88-b680-6dcbbf16fb05.png" alt class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://voicepen.ai">VoicePen</a> AI helps you convert audio content into blog posts using AI in minutes.</p>
<h3 id="heading-vidyo">Vidyo</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677673116436/b3c8bf6c-daf1-4787-8025-9ca3d9b0d10c.png" alt="Vidyo" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://vidyo.ai/">Vidyo</a> is an AI tool for making short-form videos from long-form content. It uses AI to help you create shorter, socially ready clips from your long videos, saving you 90% of the time and effort.</p>
<h3 id="heading-podcastle">Podcastle</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677673340197/146d16a5-a0b7-42a9-a954-f0db6e440d78.png" alt="Podcastle" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://podcastle.ai/">Podcastle</a> is an AI tool for studio-quality recording from your computer. Podcastle help builds next-generation audio content creation and editing tools.</p>
<h3 id="heading-otter">Otter</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677673523713/821195df-9f18-4182-8f27-d3910c733196.png" alt="Otter" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://otter.ai/">Otter</a> helps pilot your meetings with AI using a meeting assistant that records audio, writes notes, automatically captures slides, and generates summaries.</p>
<h3 id="heading-cleanvoice">Cleanvoice</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677673786263/898abd66-0827-4ccf-aaa0-a3c1ada1bb89.png" alt="Cleanvoice" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://cleanvoice.ai/">Cleanvoice</a> is an artificial intelligence which removes filler sounds, stuttering, and mouth sounds from your podcast or audio recording.</p>
<h3 id="heading-soundraw">Soundraw</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677674219098/2fbe9786-45ba-4f45-9418-d8562c7181da.png" alt="Soundraw" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://soundraw.io/"><br />Soundraw</a> is an AI tool for creating original music content. If you've found a song that can't be used because of its long introduction or is too loud for a quiet scene in your video, Soundraw is the solution. You can edit the song with a few clicks to fit your needs.</p>
<h2 id="heading-design-ai-tools">Design AI Tools 🏝️</h2>
<h3 id="heading-illustroke">illustroke</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677674537879/9f1d9a52-8752-44a4-97dd-81f9c7acc9c2.png" alt class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://illustroke.com/">illustroke</a> is an AI tool for creating stunning and unique vector illustrations from text prompts.</p>
<h3 id="heading-flair">Flair</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677674412839/4ac5e435-e0b5-4eb9-a4f3-6d37ce318bc9.png" alt="Flair" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://flair.ai/">Flair</a> is an AI tool for designing branded content.</p>
<h3 id="heading-stockimg">Stockimg</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677674843875/0f405e27-f792-4e6c-bc5e-16d5880582c4.png" alt class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://stockimg.ai/">Stockimg</a> is an AI tool for generating the perfect stock photo, for example, a book cover, wallpaper, poster, logo, illustration etc.</p>
<h3 id="heading-canva">Canva</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677675784681/c37a88e4-ee38-4bfa-8616-6b5dfb51f27a.png" alt="Canva" class="image--center mx-auto" /></p>
<p><a target="_blank" href="http://canva.com">Canva</a> is an AI-powered design tool that provides templates, images, and graphics for creating visual content.</p>
<h3 id="heading-lucidpress">Lucidpress</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677675882108/f1db0b6a-83f5-4ab4-b4f1-ecb1997d0bbf.png" alt="Lucidpress" class="image--center mx-auto" /></p>
<p><a target="_blank" href="https://www.marq.com/">Lucidpress</a> is an AI-powered design tool that allows the creation of engaging presentations, brochures, and flyers with drag and drops editor.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>As a content creator, the journey to crafting compelling content can be a daunting task. But in this ever-evolving digital era, numerous tools and resources are available to help you streamline your content creation process and make it more effective.</p>
<p>This post highlights several tools essential for content creators to improve their productivity while AI does the other heavy lifting.</p>
<p>I'd love to connect with you on <a target="_blank" href="https://twitter.com/olanetsoft"><strong>Twitter</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/olubisi-idris-ayinde-05727b17a/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://github.com/Olanetsoft"><strong>GitHub</strong></a> | <a target="_blank" href="https://idrisolubisi.com/"><strong>Portfolio</strong></a></p>
<p>See you in my next blog article. Take care!!!</p>
]]></content:encoded></item><item><title><![CDATA[How to Fix React Hydration Error in Nextjs - Practical Guide]]></title><description><![CDATA[Are you struggling with the React Hydration Error in Nextjs? Don't worry; you're not alone! Many developers face this error when rendering their React components on the server and client sides. It can be frustrating, but let's fix it.
This is a stand...]]></description><link>https://blog.idrisolubisi.com/how-to-fix-react-hydration-error-in-nextjs-practical-guide</link><guid isPermaLink="true">https://blog.idrisolubisi.com/how-to-fix-react-hydration-error-in-nextjs-practical-guide</guid><category><![CDATA[DebuggingFeb]]></category><category><![CDATA[Developer]]></category><category><![CDATA[React]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Fri, 24 Feb 2023 14:08:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1677246823016/2191ed93-e9a6-46e8-b85a-e12af156bdef.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Are you struggling with the React Hydration Error in Nextjs? Don't worry; you're not alone! Many developers face this error when rendering their React components on the server and client sides. It can be frustrating, but let's fix it.</p>
<p>This is a standard error; you might find a solution online, but I tried most of them all, it didn't work for me. This article will provide a simple and practical guide on fixing the React Hydration Error in Nextjs with examples of my errors and how I set them.</p>
<p>Whether you're a beginner or an experienced developer, this guide will help you understand errors causes and provide practical solutions to fix them.</p>
<p>So, let's dive in and solve this problem once and for all!</p>
<h2 id="heading-understanding-react-hydration">Understanding React Hydration</h2>
<p>It's essential to understand React hydration as a developer who wants to build efficient and reliable web applications using React and Nextjs.</p>
<h3 id="heading-what-is-a-react-hydration">What is a React Hydration?</h3>
<p>The React hydration process involves attaching event handlers and states to the server-side markup during Server-Side Rendering (SSR). As a page loads, React reconciles the server-generated markup with the client-side markup and attaches event handlers and states.</p>
<p>The web application must behave correctly and interact with the end user during this process. The application might throw an error if the React Hydration process fails or behave unexpectedly if the operation fails.</p>
<p>Therefore, it's crucial to understand how React Hydration works and how to fix any issues that arise during the process.</p>
<h3 id="heading-causes-of-react-hydration-error-in-nextjs">Causes of React Hydration Error in Nextjs</h3>
<p>React Hydration Errors in Nextjs can be caused by <strong>inconsistencies between server and client-rendered markup</strong> and <strong>mismatched component states</strong>.</p>
<p>When the markup generated on the server side differs from what is generated on the client side, or when the state of a component on the server side doesn't match the state on the client side, the application can throw errors or behave unexpectedly.</p>
<p>Identifying and fixing these issues can be challenging, but understanding their causes is essential to improving web application performance and reliability.</p>
<h2 id="heading-a-practical-guide-to-fix-react-hydration-error-in-nextjs">A Practical Guide to Fix React Hydration Error in Nextjs</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1677250788019/e117d265-02aa-421b-a5c5-0d064865266c.png" alt class="image--center mx-auto" /></p>
<p>There are a couple of ways to fix the Reactjs hydration error, but I will share the standard and the hydration error I encountered while working on this decentralized identity project.</p>
<h3 id="heading-error">Error 🪲</h3>
<p>I needed to check if the browser window had a valid <code>ethereum</code> object.</p>
<pre><code class="lang-javascript">{connection.status === <span class="hljs-string">"connected"</span> ? (

    {<span class="hljs-comment">/* condition when its connected*/</span>}

    ) : <span class="hljs-keyword">typeof</span> <span class="hljs-built_in">window</span> !== <span class="hljs-string">"undefined"</span> &amp;&amp; <span class="hljs-string">"ethereum"</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span> ? (

    {<span class="hljs-comment">/* condition when ethereum is available */</span>}

    ) : (

    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
     An injected Ethereum provider such as MetaMask
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
)}
</code></pre>
<h3 id="heading-how-to-fix-it">How to Fix It 🛠️</h3>
<p>In the problem above, adding <code>typeof window !== "undefined"</code> caused the hydration error, which occurs if the server-rendered HTML does not match the client-rendered HTML.</p>
<p>Here's an example of how you can modify the code to avoid a hydration error:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [isEthereumAvailable, setIsEthereumAvailable] =     useState(<span class="hljs-literal">false</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">window</span> !== <span class="hljs-string">'undefined'</span> &amp;&amp; <span class="hljs-string">'ethereum'</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span>) {
      setIsEthereumAvailable(<span class="hljs-literal">true</span>);
    }
  }, []);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
    {connection.status === "connected" ? (

        {/* condition when its connected*/}
      ) : isEthereumAvailable ? (

        {/* condition when ethereum is available */}

      ) : (
       {/* condition when ethereum is not available */}
      )
    }
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
}
</code></pre>
<h3 id="heading-error-1">Error 🪲</h3>
<pre><code class="lang-javascript">{connection.status === <span class="hljs-string">"connected"</span> &amp;&amp; record &amp;&amp; record.content &amp;&amp; (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        {/* condition when ethereum is not available */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
     ) : (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>No profile found.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
)}
</code></pre>
<p>In the code snippet above, <code>connection</code> and <code>record</code> is an object; meanwhile, the record is fetched asynchronously, leading to hydration.</p>
<h3 id="heading-how-to-fix-it-1">How to Fix It 🛠️</h3>
<pre><code class="lang-javascript">{connection.status === <span class="hljs-string">"connected"</span> &amp;&amp; record &amp;&amp; record.content ? (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        {/* condition when ethereum is not available */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
     ) : (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>No profile found.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
)}
</code></pre>
<p><code>record.content</code> It is fetched asynchronously and can differ between the server and client rendering; the initial server-rendered HTML may not match the client-rendered HTML. Changing the last <code>&amp;&amp;</code> operator to a ternary <code>?</code> fixed the problem.</p>
<p>I hope you find this helpful post and fix any React hydration error within 3 minutes.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, this post teaches us how a hydration error can occur in Next.js when the server-rendered HTML output doesn't match the client-rendered HTML output. This can happen when client-side-only code, such as code that depends on the window object, is executed during server rendering.</p>
<p>Additionally, you can ensure that the data used to render your components is consistent between the server and client, especially when the data is asynchronously fetched.</p>
<p>By following these best practices, you can ensure that your Next.js application renders correctly without any hydration errors. Always test your application thoroughly to catch any issues before deploying to production.</p>
<h2 id="heading-reference">Reference</h2>
<ul>
<li><p><a target="_blank" href="https://nextjs.org/docs/messages/react-hydration-error">Nextjs React Hydration Error</a></p>
</li>
<li><p><a target="_blank" href="https://www.netlify.com/blog/fix-next-js-react-hydration-error/">Fix Next.js: "Text content does not match server-rendered HTML.</a>"</p>
</li>
</ul>
<p>I'd love to connect with you on <a target="_blank" href="https://twitter.com/olanetsoft"><strong>Twitter</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/olubisi-idris-ayinde-05727b17a/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://github.com/Olanetsoft"><strong>GitHub</strong></a> | <a target="_blank" href="https://idrisolubisi.com/"><strong>Portfolio</strong></a></p>
<p>See you in my next blog article. Take care!!!</p>
]]></content:encoded></item><item><title><![CDATA[Say Goodbye to Writers Block with the New Article Idea Generator]]></title><description><![CDATA[Writer's Block can be temporary or persistent. Still, it can be overcome using different techniques, such as brainstorming, freewriting, taking breaks, changing surroundings, using the relevant tools to get article topic inspiration, and seeking insp...]]></description><link>https://blog.idrisolubisi.com/say-goodbye-to-writers-block-with-the-new-article-idea-generator</link><guid isPermaLink="true">https://blog.idrisolubisi.com/say-goodbye-to-writers-block-with-the-new-article-idea-generator</guid><category><![CDATA[technology]]></category><category><![CDATA[openai]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[Technical writing ]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Thu, 09 Feb 2023 15:20:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/xG8IQMqMITM/upload/5a4a5027f3d8e451badbddcfaa8f3b75.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Writer's Block can be temporary or persistent. Still, it can be overcome using different techniques, such as brainstorming, freewriting, taking breaks, changing surroundings, using the <a target="_blank" href="https://www.articleideagenerator.com/">relevant tools to get article topic inspiration</a>, and seeking inspiration from various sources. It's essential to be patient with oneself and remember that writing is a creative process that requires time and perseverance to produce meaningful work.</p>
<p>The <a target="_blank" href="https://articleideagenerator.com">Article Idea Generator</a> is an open-source tool powered by <a target="_blank" href="https://openai.com/">AI technology</a> designed to help writers overcome the frustration of writer's Block.</p>
<p>Whether you're a seasoned writer or just starting, this generator is the perfect solution for generating new and unique article ideas. It uses advanced algorithms to analyze your topic and suggest a wide range of opinions, from the most straightforward to the most imaginative.</p>
<p>This post will help you understand writer's Block and also introduce you to the new tool called <a target="_blank" href="https://articleideagenerator.com/"><mark>Article Idea Generator</mark></a>.</p>
<h2 id="heading-inspiration">Inspiration ✨</h2>
<p>I ran a pool late last year; find the tweet <a target="_blank" href="https://twitter.com/olanetsoft/status/1606650175799365632?s=20&amp;t=cWtpDx1NFiAx3Lzo3RBSzw">here</a> called the Article Streak challenge, specifically to encourage content creators to discover their strengths and consistently produce quality articles.</p>
<p>I often get questions like; <code>I don't know what to write</code>, <code>How can I find a topic to write about</code>, <code>I think I can't do this because it's tough getting a topic</code>, <code>How can I get inspiration for what to write about</code></p>
<p>However, I came across <a target="_blank" href="https://twitter.com/nutlope">Hassan El Mghari's</a> project <a target="_blank" href="https://www.twitterbio.com/"><code>Twitterbio Generator</code></a> then I got the inspiration to help solve the writer's issue I mentioned earlier using the approach that leverages OpenAI, giving birth to <a target="_blank" href="https://www.articleideagenerator.com/"><code>Article Idea Generator</code></a><code>.</code></p>
<h2 id="heading-understanding-writers-block">Understanding Writer's Block ✍️</h2>
<h3 id="heading-causes-of-writers-block">Causes of Writer's Block ✅</h3>
<ol>
<li><p>Lack of inspiration or ideas - <code>Article Idea Generator fix this</code></p>
</li>
<li><p>Overwhelming self-doubt or negative self-criticism</p>
</li>
<li><p>Fear of failure or not meeting expectations and perfectionism or pressure to produce perfect work</p>
</li>
<li><p>Excessive stress or burnout &amp; difficulty balancing work and personal life</p>
</li>
<li><p>Distractions or lack of focus or discipline</p>
</li>
<li><p>Burnout or fatigue from excessive writing.</p>
</li>
</ol>
<p>It is crucial to remember that every writer has a different experience with writer's Block, and other people may have various causes.</p>
<h3 id="heading-effects-of-writers-block-on-the-writing-process">Effects of writer's Block on the writing process ✅</h3>
<ol>
<li><p>Delay in completing writing projects and meeting deadlines</p>
</li>
<li><p>Decreased productivity, creativity, frustration, and dissatisfaction with one's writing</p>
</li>
<li><p>Increased stress and anxiety and loss of confidence in one's writing abilities</p>
</li>
<li><p>Difficulty generating new ideas or finding inspiration</p>
</li>
<li><p>Stagnation in personal and professional growth as a writer</p>
</li>
<li><p>Financial loss, in case the writer is unable to deliver work on time</p>
</li>
</ol>
<p>It's essential to address writer's Block promptly, as it can cause long-term damage to a writer's career and personal well-being.</p>
<h3 id="heading-common-strategies-to-overcome-writers-block">Common strategies to overcome writer's Block ✅</h3>
<ul>
<li><p>Concentrating on frequently writing, even if that means setting modest objectives initially.</p>
</li>
<li><p>Taking breaks and caring for oneself</p>
</li>
<li><p>Altering the context or atmosphere for writing</p>
</li>
<li><p>Brainstorming or free writing to come up with new ideas</p>
</li>
<li><p>Trying out new writing prompts or activities</p>
</li>
<li><p>Working with other authors or asking for critiques from others.</p>
</li>
<li><p>Reassessing the writing project's objectives and priorities.</p>
</li>
<li><p>Dividing the writing process into more manageable, smaller segments.</p>
</li>
<li><p>Refusing to be critical of oneself and adopting a growth mentality</p>
</li>
<li><p>Trying out various writing types or styles</p>
</li>
</ul>
<p>Finding what works best for each writer is crucial, as is persevering in attempting several methods until the Block is removed.</p>
<h2 id="heading-introduction-to-the-article-idea-generator">Introduction to the Article Idea Generator ⭐️</h2>
<h3 id="heading-what-is-the-article-idea-generator">What is the Article Idea Generator ✅</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1675686364186/d3103c7f-6f71-4892-b64e-47d34d90f3ba.png" alt class="image--center mx-auto" /></p>
<p>The <a target="_blank" href="https://www.articleideagenerator.com/">Article Idea Generator's</a> user-friendly interface makes it easy to get started, regardless of your technical expertise. Enter a few keywords related to your topic and hit <code>Enter</code>. The generator will then produce a list of potential article ideas you can use to inspire your writing.</p>
<p>The open-source nature of the Article Idea Generator ensures that it's always up-to-date and constantly improving, so you can be confident that you're getting the best possible results. The tool is also highly customizable, allowing you to refine your results and generate ideas that are explicitly tailored to your needs.</p>
<p>Whether you're a <code>blogger</code>, <code>content marketer,</code> <code>freelance writer</code>It is the perfect solution for anyone looking to improve their writing. So, if you're struggling with writer's Block, why not try it out today and discover the power of AI-driven inspiration? With the Article Idea Generator, you'll always have ideas!</p>
<h3 id="heading-how-article-idea-generator-works">How Article Idea Generator works ✅</h3>
<ol>
<li><p>Enter anything you may want to write about</p>
</li>
<li><p>Click Enter</p>
</li>
<li><p>Optionally, you can check the "Enable SEO and Clickbait Feature.". This feature would help tailor your idea to relevant search and make it SEO-compatible and a Clickbait approach to driving more traffic to your blog.</p>
</li>
<li><p>That's it 🥳</p>
</li>
</ol>
<h3 id="heading-key-features-and-benefits-of-the-article-idea-generator">Key features and benefits of the Article Idea Generator ✅</h3>
<p>By coming up with fresh and original ideas for articles, blog posts, and other writing assignments, the Article Idea Generator is a tool that assists writers in getting over writer's Block.</p>
<p>Some key features and benefits of the Article Idea Generator include:</p>
<ul>
<li><p><strong>Quick and easy idea generation:</strong> The Article Idea Generator provides a list of potential article topics, saving writers time and effort in brainstorming.</p>
</li>
<li><p><strong>Diverse ideas:</strong> The Article Idea Generator offers a wide selection of views across various industries and hobbies by drawing from millions of datasets used to train the AI model of prospective article ideas.</p>
</li>
<li><p><strong>Customization:</strong> Allowing users to filter their results based on particular SEO keywords or categories would help them find more ideas pertinent to their writing tasks.</p>
</li>
<li><p><strong>Inspiration:</strong> The Article Idea Generator helps to spark inspiration and creativity by presenting ideas that writers may not have thought of on their own.</p>
</li>
<li><p><strong>Overcoming writer's Block:</strong> By providing a steady stream of new and unique article ideas, the Article Idea Generator helps writers overcome writer's Block and maintain their productivity.</p>
</li>
<li><p><strong>Time-saving:</strong> The Article Idea Generator saves writers necessary time and allows them to concentrate on the writing process by removing the need for lengthy brainstorming sessions.</p>
</li>
</ul>
<h2 id="heading-using-the-article-idea-generator-to-overcome-writers-block">Using the Article Idea Generator to Overcome Writer's Block 🔥</h2>
<p>To use the Article Idea Generator to overcome writer's Block, follow these steps:</p>
<ol>
<li><p>Choose a reliable and reputable <a target="_blank" href="https://www.articleideagenerator.com/">Article Idea Generator</a>.</p>
</li>
<li><p>Enter keywords or phrases related to your writing project.</p>
</li>
<li><p>Review the list of ideas generated by the tool and select one that interests you.</p>
</li>
<li><p>Use the concept as a springboard to develop more concepts or modify the concept to suit your writing project.</p>
</li>
<li><p>Start your article, blog post, or other writing assignments using the topic as a guide.</p>
</li>
</ol>
<p>It's crucial to remember that numerous tools are available for overcoming writer's Block, and the Article Idea Generator is simply one of them. Additionally, it's critical to be flexible and open to the tool's suggestions.</p>
<p>The Article Idea Generator can be used with other techniques like taking breaks, trying various writing styles, and adopting a development mindset to help authors get over writer's Block and continue to be productive.</p>
<h2 id="heading-how-article-idea-generator-has-helped-writers-overcome-writers-block">How <code>Article Idea Generator</code> has helped writers overcome writer's Block. 💙</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/jideabdqudus/status/1619989897124913157?s=20&amp;t=cWtpDx1NFiAx3Lzo3RBSzw">https://twitter.com/jideabdqudus/status/1619989897124913157?s=20&amp;t=cWtpDx1NFiAx3Lzo3RBSzw</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/nutlope/status/1619389909156134913?s=20&amp;t=cWtpDx1NFiAx3Lzo3RBSzw">https://twitter.com/nutlope/status/1619389909156134913?s=20&amp;t=cWtpDx1NFiAx3Lzo3RBSzw</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/Anita_ihuman/status/1619654788605685761?s=20&amp;t=cWtpDx1NFiAx3Lzo3RBSzw">https://twitter.com/Anita_ihuman/status/1619654788605685761?s=20&amp;t=cWtpDx1NFiAx3Lzo3RBSzw</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/codesamurai_/status/1619362017802092547?s=20&amp;t=cWtpDx1NFiAx3Lzo3RBSzw">https://twitter.com/codesamurai_/status/1619362017802092547?s=20&amp;t=cWtpDx1NFiAx3Lzo3RBSzw</a></div>
<p> </p>
<p>I wish I could share all the feedback, but check this <a target="_blank" href="https://twitter.com/olanetsoft/status/1619355130041864193?s=20&amp;t=cWtpDx1NFiAx3Lzo3RBSzw">tweet</a> reply and quote retweet to see how this tool is changing lives, helping people to be more creative, and overcoming writer's Block easily.</p>
<h2 id="heading-the-tech-stack">The Tech Stack 🛠️</h2>
<p><a target="_blank" href="https://nextjs.org/"><strong>NextJS</strong></a> - React application framework</p>
<p><a target="_blank" href="https://tailwindcss.com/docs/guides/nextjs">TailwindCSS</a> - For styling the project</p>
<p><a target="_blank" href="https://www.typescriptlang.org/">TypeScript</a> - A strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.</p>
<p><a target="_blank" href="https://vercel.com/docs/concepts/functions/edge-functions/streaming">Vercel Function</a> - For streaming responses from OPEN AI</p>
<p><a target="_blank" href="https://github.com/"><strong>GitHub</strong></a> - To host the <a target="_blank" href="https://github.com/Olanetsoft/article-idea-generator">code</a></p>
<p><a target="_blank" href="https://vercel.com/"><strong>Vercel</strong></a> - To deploy and host the project</p>
<h2 id="heading-contributing">Contributing 🤝</h2>
<p>Please read the <a target="_blank" href="https://github.com/Olanetsoft/article-idea-generator/blob/develop/CONTRIBUTING.md">contributing guide</a> if you want to contribute to this project. If you have any ideas or suggestions, feel free to open an issue or a pull request.</p>
<blockquote>
<p>If you like <a target="_blank" href="https://github.com/Olanetsoft/article-idea-generator/">this project</a>, please give it a star ⭐️</p>
</blockquote>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/Olanetsoft/article-idea-generator/">https://github.com/Olanetsoft/article-idea-generator/</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This post teaches us about writer's Block, its causes, and shared strategies to overcome it. It also introduces you to the <a target="_blank" href="https://www.articleideagenerator.com/">Article Idea Generator tool,</a> how it works, how to overcome writer's Block using it, and feedback on how it has helped writers.</p>
<h2 id="heading-reference">Reference</h2>
<ul>
<li><p><a target="_blank" href="https://www.articleideagenerator.com/">Article Idea Generator</a></p>
</li>
<li><p><a target="_blank" href="https://www.twitterbio.com/">Twitterbio Generator</a></p>
</li>
<li><p><a target="_blank" href="https://openai.com/">OpenAI</a></p>
</li>
<li><p><a target="_blank" href="http://vercel.com/">Vercel</a></p>
</li>
</ul>
<p>I'd love to connect with you on <a target="_blank" href="https://twitter.com/olanetsoft"><strong>Twitter</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/olubisi-idris-ayinde-05727b17a/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://github.com/Olanetsoft"><strong>GitHub</strong></a> | <a target="_blank" href="https://idrisolubisi.com/"><strong>Portfolio</strong></a></p>
<p>See you in my next blog article. Take care!!!</p>
]]></content:encoded></item><item><title><![CDATA[Master the Cosmos: A Beginner's Guide to Building and Deploying Smart Contracts]]></title><description><![CDATA[The Cosmos network is one of the most promising blockchain networks that enable interoperability between different blockchain platforms, and it's becoming increasingly important for developers to understand how to build and deploy smart contracts on ...]]></description><link>https://blog.idrisolubisi.com/master-the-cosmos-a-beginners-guide-to-building-and-deploying-smart-contracts</link><guid isPermaLink="true">https://blog.idrisolubisi.com/master-the-cosmos-a-beginners-guide-to-building-and-deploying-smart-contracts</guid><category><![CDATA[Cosmos ecosystem]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Solidity]]></category><category><![CDATA[hardhat]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Thu, 02 Feb 2023 13:29:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1675334053337/b81a774e-c74d-413e-a197-6a1db16bfd32.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The <a target="_blank" href="https://docs.cosmos.network/main">Cosmos network</a> is one of the most promising blockchain networks that enable interoperability between different blockchain platforms, and it's becoming increasingly important for developers to understand how to build and deploy smart contracts on this network.</p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Smart_contract">Smart contracts</a> are self-executing contracts with the terms of the agreement written directly into code. They are a vital component of decentralized applications and are crucial for creating trustless and transparent systems. As the demand for decentralized applications rises, understanding and using smart contracts is a prerequisite skill for developers building and developing applications in Web3.</p>
<p>Does the cosmos support smart contracts? Yes. In this tutorial, we will learn about the Cosmos ecosystem and how to build and deploy a smart contract on the cosmos network.</p>
<h2 id="heading-understanding-the-cosmos-network">Understanding the Cosmos Network</h2>
<p>The <a target="_blank" href="https://blog.cosmos.network/tendermint-explained-bringing-bft-based-pos-to-the-public-blockchain-domain-f22e274a0fdb">Tendermint Core consensus</a> engine powers the independent, parallel blockchains that make up the decentralized Cosmos Network. The Cosmos Network aims to build a decentralized network of interconnected blockchains that can expand and cooperate, facilitating the exchange of data and value between various blockchain platforms.</p>
<p>Tendermint is a Byzantine Fault Tolerant (BFT) consensus engine that enables fast and secure transaction processing. It allows a group of <a target="_blank" href="https://www.pcmag.com/encyclopedia/term/blockchain-validator">validators</a> to agree on the state of the network through a voting procedure. Tendermint enables quicker transaction processing than conventional proof-of-work consensus methods, such as those employed by Bitcoin and Ethereum (Now Proof of Stake).</p>
<p>The Cosmos Network's use of the Inter-Blockchain Communication (IBC) protocol is crucial. Interoperability across several blockchain systems is made possible by IBC, which enables the transfer of value and data between various blockchains in the Cosmos Network.</p>
<p>Additionally, the Cosmos Network features a hub-and-spoke architecture that enables the development of standalone blockchains (spokes) that can communicate with the Cosmos Hub (the hub). Data and currency can be exchanged between the various blockchains in the network thanks to the Cosmos Hub, which acts as the network's hub.</p>
<p>Scalability, security, and interoperability are just a few of the Cosmos Network's benefits over other blockchain platforms. It is an intriguing and promising blockchain network overall.</p>
<p>It is a desirable alternative for developers looking to create decentralized applications due to its capacity to handle colossal throughput and connect several blockchains.</p>
<h2 id="heading-why-cosmos">Why Cosmos?</h2>
<p>The Inter-Blockchain Communication (IBC) protocol and the Tendermint Core consensus engine form the Cosmos network's foundation, enabling the exchange of value and data between various blockchains within the Cosmos Network. This was covered in more detail in the previous section when we discussed the Cosmos ecosystem.</p>
<p>The Cosmos Network's main traits include the following:</p>
<ul>
<li><p><strong>Tendermint Core Consensus Engine:</strong> A Byzantine Fault Tolerant consensus engine, Tendermint provides quick and secure transaction processing.</p>
</li>
<li><p><strong>Inter-Blockchain Communication (IBC) protocol:</strong> IBC enables communication across several blockchains inside the Cosmos Network, allowing for the exchange of value and data.</p>
</li>
<li><p>The Cosmos Network provides support for custom token creation. These tokens can be used in decentralized apps to represent digital assets or as payment.</p>
</li>
<li><p><strong>Scalability:</strong> Using independent blockchains with Tendermint Core enables quicker transaction processing times and the capacity to process many transactions per second.</p>
</li>
<li><p><strong>Interoperability:</strong> The Cosmos Network's interoperability feature enables developers to create decentralized applications that communicate with many blockchain systems, including Bitcoin, Ethereum, and others.</p>
</li>
<li><p><strong>Hub-and-spoke architecture:</strong> The Cosmos Network's hub-and-spoke architecture enables the development of separate blockchains that can communicate with the Cosmos Hub. The network's central node, the Cosmos Hub, facilitates the exchange of money and information among its several blockchains.</p>
</li>
</ul>
<p>In the following section, let's dive deeply into the practical aspect of building and deploying smart contracts on the cosmos network.</p>
<h2 id="heading-prerequisite">Prerequisite</h2>
<p>Let's make sure Node/NPM is set up on our computer. <a target="_blank" href="https://nodejs.org/en/">Here</a> is a guide if we don't already have it installed.</p>
<h2 id="heading-project-setup-and-installation">Project Setup and Installation</h2>
<p>Let's navigate to the terminal. We'll need to <code>cd</code> into any directory of our choice and then run the following commands:</p>
<pre><code class="lang-bash">mkdir cosmos-project
<span class="hljs-built_in">cd</span> cosmos-project 
npm init -y 
npm install --save-dev hardhat
</code></pre>
<p>Let's create a sample project by using the following command:</p>
<pre><code class="lang-bash">npx hardhat
</code></pre>
<p>The above command will check if we have hardhat installed globally; if not, it will download it from the npm registry and run the command using the downloaded version.</p>
<p>Accept the following options.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673904656862/2b35f1b5-4477-4774-bd3a-4e86de1d927c.png" alt class="image--center mx-auto" /></p>
<p>Let's run the command below to verify that everything is operating as it should.</p>
<pre><code class="lang-bash">npx hardhat <span class="hljs-built_in">test</span>
</code></pre>
<p>A passing test result will appear in our console.</p>
<p>Now, <code>Lock.js</code> may be removed from the <code>test</code> directory and <code>deploy.js</code> the scripts directory. After that, delete <code>Lock.sol</code> in the <code>contracts</code> directory.</p>
<p><strong><em><mark>The folders themselves should not be deleted!</mark></em></strong></p>
<h2 id="heading-create-a-greeter-smart-contract">Create a <code>Greeter</code> Smart Contract</h2>
<p>This section will create a <code>Greeter.sol</code> file in the contract directory with the following code snippet.</p>
<pre><code class="lang-solidity"><span class="hljs-comment">// SPDX-License-Identifier: UNLICENSED</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.9;</span>

<span class="hljs-comment">// Define a smart contract called "Greeter"</span>
<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Greeter</span> </span>{
    <span class="hljs-comment">// Define a public variable called "greeting" of type string</span>
    <span class="hljs-keyword">string</span> <span class="hljs-keyword">public</span> greeting;

    <span class="hljs-comment">// Define a constructor that takes in a string and assigns it to the "greeting" variable</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _greeting</span>) </span>{
        greeting <span class="hljs-operator">=</span> _greeting;
    }

    <span class="hljs-comment">// Define a function called "setGreeting" that allows the "greeting" variable to be changed</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setGreeting</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _greeting</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        greeting <span class="hljs-operator">=</span> _greeting;
    }

    <span class="hljs-comment">// Define a function called "greet" that returns the current "greeting" variable</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-keyword">return</span> greeting;
    }
}
</code></pre>
<p>In the code snippet above, it's important to note that the line <code>SPDX-License-Identifier: UNLICENSED</code> serves as a unique identifier to signify that the code is unlicensed and available for anybody.</p>
<h2 id="heading-testing-the-smart-contract">Testing the Smart Contract</h2>
<p>Create a new file called <code>Greeter-test.js</code> inside the <code>test</code> directory and update it with the following code snippet.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { expect } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"chai"</span>);
<span class="hljs-keyword">const</span> { ethers } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"hardhat"</span>);

describe(<span class="hljs-string">"Greeter"</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  it(<span class="hljs-string">"Should deploy the Greeter contract"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Get the contract factory for the "Greeter" contract</span>
    <span class="hljs-keyword">const</span> Greeter = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">"Greeter"</span>);
    <span class="hljs-comment">// Deploy the contract to the blockchain</span>
    <span class="hljs-keyword">const</span> greeter = <span class="hljs-keyword">await</span> Greeter.deploy(<span class="hljs-string">"Hello, world!"</span>);

    <span class="hljs-comment">// Wait until the contract is deployed</span>
    <span class="hljs-keyword">await</span> greeter.deployed();

    <span class="hljs-comment">// Check that the contract's greet() method returns the expected greeting</span>
    expect(<span class="hljs-keyword">await</span> greeter.greet()).to.equal(<span class="hljs-string">"Hello, world!"</span>);
  });

  it(<span class="hljs-string">"Should return the new greeting once it's changed"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Get the contract factory for the "Greeter" contract</span>
    <span class="hljs-keyword">const</span> Greeter = <span class="hljs-keyword">await</span> ethers.getContractFactory(<span class="hljs-string">"Greeter"</span>);
    <span class="hljs-comment">// Deploy the contract to the blockchain</span>
    <span class="hljs-keyword">const</span> greeter = <span class="hljs-keyword">await</span> Greeter.deploy(<span class="hljs-string">"Hello, world!"</span>);

    <span class="hljs-comment">// Wait until the contract is deployed</span>
    <span class="hljs-keyword">await</span> greeter.deployed();

    <span class="hljs-comment">// Check that the contract's greet() method returns the expected greeting</span>
    expect(<span class="hljs-keyword">await</span> greeter.greet()).to.equal(<span class="hljs-string">"Hello, world!"</span>);

    <span class="hljs-comment">// call the setGreeting method</span>
    <span class="hljs-keyword">const</span> setGreetingTx = <span class="hljs-keyword">await</span> greeter.setGreeting(<span class="hljs-string">"Hola, mundo!"</span>);

    <span class="hljs-comment">// wait until the transaction is mined</span>
    <span class="hljs-keyword">await</span> setGreetingTx.wait();

    <span class="hljs-comment">// Check that the contract's greet() method returns the new greeting</span>
    expect(<span class="hljs-keyword">await</span> greeter.greet()).to.equal(<span class="hljs-string">"Hola, mundo!"</span>);
  });
});
</code></pre>
<p>Next, run the following command in the terminal to compile test cases.</p>
<pre><code class="lang-bash"> npx hardhat <span class="hljs-built_in">test</span>
</code></pre>
<p>We should have something similar to what is shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674085298659/93adaeec-b0ba-4d24-a8b6-2aa3a70fb784.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-compile-and-deploy-the-greeter-smart-contract-to-the-cosmos-network">Compile and Deploy the Greeter Smart Contract to the Cosmos Network</h2>
<p>To compile the smart contract, we will need to create a new file <code>deploy.js</code> inside the <code>scripts</code> folder and update it with the following code snippet.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> main = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-comment">// Get the contract factory for the "Greeter" contract</span>
  <span class="hljs-keyword">const</span> greeterContractFactory = <span class="hljs-keyword">await</span> hre.ethers.getContractFactory(<span class="hljs-string">"Greeter"</span>);

  <span class="hljs-comment">// Deploy the contract to the blockchain</span>
  <span class="hljs-keyword">const</span> greeterContract = <span class="hljs-keyword">await</span> greeterContractFactory.deploy(
    <span class="hljs-string">"Hello, Hardhat!"</span>
  );

  <span class="hljs-comment">// Wait until the contract is deployed</span>
  <span class="hljs-keyword">await</span> greeterContract.deployed();

  <span class="hljs-comment">// Log the address of the deployed contract</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Greeter Contract deployed to: "</span>, greeterContract.address);
};

<span class="hljs-keyword">const</span> runMain = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Call the main function</span>
    <span class="hljs-keyword">await</span> main();
    process.exit(<span class="hljs-number">0</span>);
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-comment">// Log any errors that occur</span>
    <span class="hljs-built_in">console</span>.log(error);
    process.exit(<span class="hljs-number">1</span>);
  }
};

<span class="hljs-comment">// Run the main function</span>
runMain();
</code></pre>
<p>In the code snippet above,</p>
<ul>
<li><p>This script deploys a smart contract called <code>Greeter</code> to the blockchain using the hre.ethers library.</p>
</li>
<li><p>The <code>greeterContractFactory.deploy()</code> method deploys a new contract instance to the blockchain.</p>
</li>
<li><p><code>await greeterContract.deployed()</code> method is used to await the contract deployment.</p>
</li>
<li><p>The address of the deployed contract is then logged into the console, and then <code>runMain()</code> function is a wrapper function that runs the main function and catches any possible errors.</p>
</li>
</ul>
<p>Next, create <code>.env</code> on the project's root directory to store the private key, which we will use in the <code>hardhat.config.js</code> file during deployment.</p>
<pre><code class="lang-bash">PRIVATE_KEY=
</code></pre>
<p>Navigate to the <code>hardhat.config.js</code> file and then add the following code snippet.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">require</span>(<span class="hljs-string">"@nomicfoundation/hardhat-toolbox"</span>);
<span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config();

<span class="hljs-comment">/** @type import('hardhat/config').HardhatUserConfig */</span>
<span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-comment">// Specify version of solidity compiler</span>
  <span class="hljs-attr">solidity</span>: <span class="hljs-string">"0.8.17"</span>,

  <span class="hljs-comment">// Define networks to be used for testing and deployment</span>
  <span class="hljs-attr">networks</span>: {
    <span class="hljs-comment">// Hardhat network is a built-in development network in Hardhat</span>
    <span class="hljs-attr">hardhat</span>: {
    },
    <span class="hljs-comment">// Local network is a network running on localhost</span>
    <span class="hljs-attr">local</span> : {
      <span class="hljs-attr">url</span>: <span class="hljs-string">"http://localhost:8545"</span>,
    },
    <span class="hljs-comment">// evmos network is a network hosted by evmos</span>
    <span class="hljs-attr">evmos</span>: {
      <span class="hljs-attr">url</span>: <span class="hljs-string">"https://eth.bd.evmos.dev:8545"</span>,
      <span class="hljs-comment">// Use the private key specified in the .env file</span>
      <span class="hljs-attr">accounts</span>:[process.env.PRIVATE_KEY],
    },
  },
};
</code></pre>
<p>This is a configuration file for the Hardhat development environment.</p>
<p>We will deploy the smart contract in the next step, but we need to ensure we fund our wallet with a test EVMOS (<strong>A decentralized proof of stake blockchain in the Cosmos ecosystem)</strong> token. <a target="_blank" href="https://docs.evmos.org/users/wallets/metamask.html">Set up evmos on MetaMask</a> and fund the wallet using this evmos <a target="_blank" href="https://faucet.evmos.dev/">faucet site</a>.</p>
<p>After requesting a faucet, we should have something similar to what is shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674085951417/3c69bad1-ce45-49a3-a842-0ba428f7134f.png" alt class="image--center mx-auto" /></p>
<p>Now we can deploy the smart contract on the Cosmos network using the following command.</p>
<pre><code class="lang-bash">npx hardhat run --network evmos scripts/deploy.js
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674086546952/e06111b5-9b83-4d9c-9712-7fcf8c4d9f71.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-verify-contract-deployment-on-evm-explorer">Verify Contract Deployment on EVM Explorer</h2>
<p>Let’s view this block in the EVM Explorer <a target="_blank" href="https://evm.evmos.dev/"><code>https://evm.evmos.dev</code></a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674087019344/64466ba5-db6e-4203-8596-48d9310b8dbe.png" alt class="image--center mx-auto" /></p>
<p>To follow up, you can find the entire code for this project <a target="_blank" href="https://github.com/Olanetsoft/cosmos-project-demo"><strong>here</strong></a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This article provided a beginner-friendly guide to building and deploying smart contracts on the Cosmos network. Using the Hardhat development environment, we also demonstrated how to deploy a smart contract to the Cosmos network.</p>
<p>I'd love to connect with you on <a target="_blank" href="https://twitter.com/olanetsoft"><strong>Twitter</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/olubisi-idris-ayinde-05727b17a/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://github.com/Olanetsoft"><strong>GitHub</strong></a> | <a target="_blank" href="https://idrisolubisi.com/"><strong>Portfolio</strong></a></p>
<p>See you in my next blog article. Take care!!!</p>
]]></content:encoded></item><item><title><![CDATA[The Ultimate Guide to Debugging Smart Contracts: Tips and Tools for Web3 Developers]]></title><description><![CDATA[Smart contract development is vital to building decentralized applications on the blockchain. However, as with any software development, debugging smart contracts can be challenging but can quickly determine the cause of a single transaction or contr...]]></description><link>https://blog.idrisolubisi.com/the-ultimate-guide-to-debugging-smart-contracts-tips-and-tools-for-web3-developers</link><guid isPermaLink="true">https://blog.idrisolubisi.com/the-ultimate-guide-to-debugging-smart-contracts-tips-and-tools-for-web3-developers</guid><category><![CDATA[Smart Contracts]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Web3]]></category><category><![CDATA[debugging]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Wed, 25 Jan 2023 14:20:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/szrJ3wjzOMg/upload/29d8ad3300075a1958d65ad8ac2f8a48.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Smart contract development is vital to building decentralized applications on the blockchain. However, as with any software development, debugging smart contracts can be challenging but can quickly determine the cause of a single transaction or contract execution failure with an advanced tool for debugging Solidity smart contracts.</p>
<p>We can implement a suitable solution once we identify the error that led to a specific issue and learn in-depth details about the error's nature.</p>
<p>This guide will provide tips and tools for debugging smart contracts to help Web3 developers ensure their contracts work as intended.</p>
<h2 id="heading-debugging-smart-contracts">Debugging Smart Contracts</h2>
<p>Smart contract debugging is identifying and fixing errors in smart contracts. It is essential in developing any decentralized application as it ensures the contracts function as intended.</p>
<p>Contract development can run into several problems, including unpredictable behaviour, coding errors, and security flaws. Debugging can assist in resolving these problems and preventing more serious ones from developing later.</p>
<p>Implementation, testing, and deployment are only a few processes in developing a smart contract. A crucial phase in each of these steps is debugging. After deploying the contract, debugging helps find and correct flaws in the code introduced during the writing phase.</p>
<p>Debugging assists in finding and correcting issues that might have gone unnoticed during the writing stage during the testing phase. Debugging also ensures that the contract is deployed correctly and interacts with the blockchain as intended during deployment.</p>
<h3 id="heading-debugging-tips">Debugging Tips</h3>
<p>Writing smart contracts that are easy to debug is a crucial step in development. Below are some tips for writing smart contracts that are easy to debug:</p>
<ul>
<li><p>Use simple, evocative names for your variables and functions so that anyone can quickly grasp what each one does and spot mistakes.</p>
</li>
<li><p>Utilize the built-in solidity function called <code>require</code> to ensure that a particular condition is satisfied before the contract can continue executing. It's a valuable tool for debugging because it halts contract execution when the need is unmet, enabling programmers to locate the problem quickly.</p>
</li>
<li><p>The <a target="_blank" href="https://trufflesuite.com/docs/truffle/how-to/debug-test/use-the-truffle-debugger/">Truffle Debugger</a> is a powerful tool that you can use to debug contracts during the testing stage. It allows developers to review the code, inspect variable values, and revert to previous states.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674482687832/0cb03efa-4451-43f3-be4d-3cdd90bfa63d.png" alt="The Truffle Debugger" class="image--center mx-auto" /></p>
<ul>
<li>The <a target="_blank" href="https://remix.ethereum.org/">Remix IDE</a> is a popular online code editor for Solidity. It contains an integrated debugging function that enables programmers to browse the code and check the values of variables.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674482824748/93ad34de-d99e-4186-b694-2d7ed8e07933.png" alt="Remix IDE" class="image--center mx-auto" /></p>
<h2 id="heading-categories-of-ethereum-smart-contract-errors">Categories of Ethereum Smart Contract Errors</h2>
<p>Syntax, runtime, and logic errors are the most frequent problems engineers face while writing or running code for Solidity contracts.</p>
<h3 id="heading-syntax-error">Syntax Error</h3>
<p>A syntax error in a smart contract is a mistake in the code that prevents the computer from understanding it. Simple errors like omitting a semicolon or misusing a term can constitute a syntax fault.</p>
<h3 id="heading-logical-error">Logical Error</h3>
<p>A logical error in a smart contract refers to a mistake in the code that doesn't prevent it from being executed but causes it to produce unexpected or incorrect results.</p>
<p>For instance, a contract transfers money to the incorrect address when sending money from one account to another.</p>
<p>An <a target="_blank" href="https://cointelegraph.com/blockchain-for-beginners/what-is-a-smart-contract-security-audit-a-beginners-guide">audit</a> of a smart contract can find logical problems since, sometimes, from the developer's perspective, everything is going according to plan. Even though there might not be a bug in the code, an auditor can still execute a smart contract to look for security vulnerabilities, examine the business logic, and find loopholes.</p>
<h3 id="heading-runtime-error">Runtime Error</h3>
<p>Any error during the execution of a contract is called a runtime error. This may occur if a contract fails to handle unexpected inputs or conditions correctly or attempts to carry out an operation prohibited by the underlying blockchain.</p>
<p>For instance, a contract that tries to transfer more money than is allowed in an account would result in a runtime error.</p>
<p>Runtime problems are more challenging to diagnose than syntax faults since they are not known before being deployed on a blockchain and can only occur when a smart contract's state changes.</p>
<h2 id="heading-common-runtime-errors">Common Runtime Errors</h2>
<p>Let's look at the most common runtime errors when developing smart contracts for the Ethereum network.</p>
<h3 id="heading-stack-overflow">Stack Overflow</h3>
<p>In Solidity, a stack can only hold 1024 frames, meaning a function can only call itself 1024 times before a stack overflow happens. If there is an attempt to execute a function recursively and there is no condition to stop it, stack overflow will occur.</p>
<pre><code class="lang-solidity"><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Overflow</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">count</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> num</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
    <span class="hljs-keyword">return</span> count(num <span class="hljs-operator">+</span> <span class="hljs-number">1</span>);
  }
}

Overflow o <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Overflow();
o.count(<span class="hljs-number">1</span>); <span class="hljs-comment">// This will cause a Stack Overflow error as the function keeps calling itself infinitely.</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678196085364/060026b4-0742-4e9c-8844-4b1d3028a764.png" alt="Stack Overflow Error in Solidity" class="image--center mx-auto" /></p>
<h3 id="heading-stack-underflow">Stack Underflow</h3>
<p>When there is an attempt to pop a nonexistent variable in assembly language, a stack underflow happens.</p>
<p>Solidity doesn't have a stack-based execution model like some other programming languages, such as C, so it's impossible to cause a Stack Underflow error in Solidity the same way it is in those languages.</p>
<p>However, Solidity does have some exceptions that can be thrown if a contract runs out of gas, which can be thought of as a similar concept to Stack Underflow. Here's an example of Solidity code that can potentially cause an Out of Gas error:</p>
<pre><code class="lang-solidity"><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Underflow</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">loop</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> num</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint256</span> i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&lt;</span> num; i<span class="hljs-operator">-</span><span class="hljs-operator">-</span>) {
      <span class="hljs-comment">// Do some operation</span>
    }
    <span class="hljs-keyword">return</span> num;
  }
}

Underflow u <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Underflow();
u.loop(<span class="hljs-number">1</span>); <span class="hljs-comment">// This code may run out of gas as the for loop condition will always be true and the loop will continue indefinitely, potentially causing an Out of Gas error.</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678196266979/c050a4a7-19de-4ef8-a076-7aa4830cb066.png" alt="Stack Underflow Error in Solidity" class="image--center mx-auto" /></p>
<h3 id="heading-execution-reverted">Execution Reverted</h3>
<p>When a contract stops the execution of a transaction that deviates from its business logic, revert errors happen. Contracts usually include checks for various required criteria. The contract deems a transaction invalid and halts execution if it doesn't meet all requirements.</p>
<p>It's vital to remember that a transaction will only be reverted if it was attempted to be completed but could not be executed based on the smart contract's logic; in this case, the EVM will return an error, and the transaction will be reverted.</p>
<pre><code class="lang-solidity"><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">Revert</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> recipient, <span class="hljs-keyword">uint256</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
    <span class="hljs-built_in">require</span>(amount <span class="hljs-operator">&gt;</span> <span class="hljs-number">0</span>, <span class="hljs-string">"Amount must be greater than zero"</span>);
    recipient.<span class="hljs-built_in">transfer</span>(amount);
  }
}

Revert r <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Revert();
r.<span class="hljs-built_in">transfer</span>(<span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), <span class="hljs-number">0</span>); <span class="hljs-comment">// This code will cause an Execution Reverted error as the `require` statement will fail since the amount is zero, causing the function to revert its execution.</span>
</code></pre>
<h3 id="heading-out-of-gas">Out-of-Gas</h3>
<p>Out-of-gas error occurs when you don't provide enough gas to execute a transaction or gas is insufficient to complete a transaction.</p>
<pre><code class="lang-solidity"><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">OutOfGas</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">consumeGas</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) {
            <span class="hljs-comment">// Do some computation that consumes gas</span>
        }
    }
}

OutOfGas o <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> OutOfGas();
o.consumeGas(); <span class="hljs-comment">// This code may run out of gas as the while loop runs indefinitely, consuming all available gas.</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678196585484/929b3364-6d4d-49f5-b2c1-b4b536411604.png" alt="Out-of-Gas error in solidity" class="image--center mx-auto" /></p>
<h3 id="heading-invalid-opcode">Invalid Opcode</h3>
<p>The Invalid opcode errors occur when <a target="_blank" href="https://ethereum.org/en/developers/docs/evm/">EVM</a> encounters an incompatibility with a contract. For instance, when the contract was compiled with an unsupported compiler.</p>
<h3 id="heading-jump-errors">JUMP Errors</h3>
<p>The invalid <code>jump</code> happens when you try to call a function that doesn't exist, such as when you call a function of one contract through another contract that doesn't exist. A similar issue can happen when you use assembly language and point to false memory.</p>
<pre><code class="lang-solidity"><span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">JumpError</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">jump</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
    <span class="hljs-keyword">uint256</span> x <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;
    <span class="hljs-keyword">if</span> (x <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">1</span>) {
      <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">return</span> <span class="hljs-number">2</span>;
    }
    <span class="hljs-keyword">return</span> <span class="hljs-number">3</span>; <span class="hljs-comment">// This code is unreachable and can cause a "JUMP" error.</span>
  }
}

JumpError j <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> JumpError();
j.jump(); <span class="hljs-comment">// This code may cause a "JUMP" error as the final return statement is unreachable.</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1678196925665/b10faabc-9d0a-4179-a837-7e6bc8527a9f.png" alt="JUMP Errors in Solidity" class="image--center mx-auto" /></p>
<h2 id="heading-debugging-tools">Debugging Tools</h2>
<p>This previous section taught us about common errors in building and deploying smart contracts. Now, we will check out the tools for debugging smart contracts.</p>
<h3 id="heading-hardhat-andamp-truffle">Hardhat &amp; Truffle</h3>
<p><a target="_blank" href="https://hardhat.org/">Hardhat</a> is an open-source development environment for Ethereum. It includes tools for developing, testing, and deploying smart contracts. Hardhat also has a built-in debugger allowing developers to review the code and inspect variable values.</p>
<p><a target="_blank" href="https://trufflesuite.com/">Truffle</a> is a popular development framework for Ethereum. It includes a suite of tools for developing, testing, and deploying smart contracts. Truffle also consists of the Truffle Debugger, a powerful tool for debugging contracts during the testing stage.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674486756798/bf5d099a-3e36-4eb6-b50b-3689f11b9faa.png" alt="Hardhat" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674486811095/780174f9-9217-46d0-ae7d-86d7247c3db9.png" alt="Trufflesuite" class="image--center mx-auto" /></p>
<h3 id="heading-remix">Remix</h3>
<p>Remix is a popular online code editor for Solidity. It has a built-in debugging feature lets developers scan the code and inspect variable values.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674487090252/8bf83951-f1ad-4d1f-b820-14282d4d6192.png" alt="Remix IDE" class="image--center mx-auto" /></p>
<h3 id="heading-etherscan">EtherScan</h3>
<p>Etherscan is a blockchain explorer for Ethereum. It allows developers to inspect and debug contracts deployed on the Ethereum blockchain.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1674487142081/89057d16-926c-44ac-9ec5-bac159e41ee9.png" alt="Etherscan" class="image--center mx-auto" /></p>
<p>The stage of development and the project's particular requirements will determine the best tool to use for debugging contracts.</p>
<p>Remix and EtherScan are better suited for the deployment stage, while Truffle and Hardhat are better suited for testing. Truffle and Hardhat offer more sophisticated debugging tools, such as stepping code and returning to earlier states. Remix and Etherscan, on the other hand, provide additional visibility and transparency into the deployed contract.</p>
<p>Testing various tools to determine which best suits the project's demands is crucial.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Debugging smart contracts is a critical stage in creating decentralized apps for the blockchain. Web3 developers can ensure that their contracts operate as intended by following the advice and using the resources described in this guide.</p>
<p>As technology and best practices advance, it's critical to keep learning and experimenting with new tools and strategies for debugging contracts.</p>
<h2 id="heading-resources">Resources</h2>
<ul>
<li><p><a target="_blank" href="https://github.com/ConsenSys/ethereum-developer-tools-list#developing-smart-contracts">Ethereum Developers Tools list</a></p>
</li>
<li><p><a target="_blank" href="https://betterprogramming.pub/top-10-smart-contract-developer-tools-you-need-for-2022-b763f5df689a">Smart Contract tools you need to know</a></p>
</li>
<li><p><a target="_blank" href="https://www.myhsts.org/blog/ultimate-guide-to-ethereum-developer-tools.html">Guide to Ethereum Developer Tools</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/quillhash/how-to-debug-a-smart-contract-transaction-e76aa625c782">How to Debug Smart Contract Transactions</a></p>
</li>
</ul>
<p>I'd love to connect with you on <a target="_blank" href="https://twitter.com/olanetsoft"><strong>Twitter</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/olubisi-idris-ayinde-05727b17a/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://github.com/Olanetsoft"><strong>GitHub</strong></a> | <a target="_blank" href="https://idrisolubisi.com/"><strong>Portfolio</strong></a></p>
<p>See you in my next blog article. Take care!!!</p>
]]></content:encoded></item><item><title><![CDATA[Easily Create An NFT App Using The New Infura NFT SDK TypeScript]]></title><description><![CDATA[If you know typescript, it’s easy to add the ability to create, mint, and manage non-fungible tokens (NFTs) to your app. The Infura NFT SDK wraps REST calls to Ethereum nodes, abstracting away the technical compilations and making it possible to work...]]></description><link>https://blog.idrisolubisi.com/easily-create-an-nft-app-using-the-new-infura-nft-sdk-typescript</link><guid isPermaLink="true">https://blog.idrisolubisi.com/easily-create-an-nft-app-using-the-new-infura-nft-sdk-typescript</guid><category><![CDATA[NFT]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[infura]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[sdk]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Thu, 19 Jan 2023 14:22:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1674138061986/230905b4-5d67-4c96-8626-55ffdccbdd16.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you know typescript, it’s easy to add the ability to create, mint, and manage non-fungible tokens (NFTs) to your app. The <a target="_blank" href="https://docs.infura.io/infura/infura-custom-apis/nft-sdk">Infura NFT SDK</a> wraps REST calls to Ethereum nodes, abstracting away the technical compilations and making it possible to work with NFTs with just an Infura account, some configuration, and a few lines of code. The Infura NFT SDK also doesn’t require the overhead of learning Solidity, importing ABIs, etc. Whether you are new to web3 or highly experienced, Infura NFT SDK makes NFTs easy.</p>
<p>Let’s jump in, build, and deploy an ERC721 NFT to see how it works.</p>
<h2 id="heading-what-is-the-infura-nft-sdk">What is the Infura NFT SDK?</h2>
<p>The <a target="_blank" href="https://docs.infura.io/infura/infura-custom-apis/nft-sdk">Infura NFT SDK</a> is an SDK that allows you to build and interact with NFTs easily.  It’s implemented in TypeScript, a programming language that is a strict superset of JavaScript. The SDK includes the ability to create, mint, and manage NFTs and query information about them. </p>
<p>The significant part is that it abstracts away the technical details so you can focus on the core functionality of your dApp instead of the (often difficult) details. It’s all about ease of use with Infura SDKs!</p>
<p>Supported chains include:</p>
<p><strong>Write</strong></p>
<ul>
<li><p>Ethereum: Mainnet, Goerli, Sepolia</p>
</li>
<li><p>Polygon: Mainnet, Mumbai</p>
</li>
</ul>
<p><strong>Read</strong></p>
<ul>
<li><p>Ethereum: Mainnet, Goerli, Sepolia</p>
</li>
<li><p>Polygon: Mainnet, Mumbai</p>
</li>
<li><p>BSC: Mainnet</p>
</li>
</ul>
<p>By using the Infura NFT SDK, you also get access to Infura's core functionality and infrastructure, which provides access to Ethereum (and other blockchains) without requiring you to run a full node. With the SDK, you can leverage many capabilities, making it easier to build and scale your dApps.</p>
<p>So let’s build an NFT and see what the SDK can do.</p>
<h2 id="heading-building-and-deploying-erc721-nft">Building and Deploying ERC721 NFT</h2>
<p>We will build a dApp and smart contract on Ethereum and use the SDK to create a new NFT. We’ll do all this on the Ethereum Goerli testnet, so we don’t have to worry about defects or the cost of deploying to the mainnet.</p>
<p><strong>Prerequisite</strong></p>
<p>Before getting started, you need the following prerequisites:</p>
<ul>
<li><a target="_blank" href="https://nodejs.org/en/">Node.js</a> and its package manager NPM. Verify you have Node.js installed by using the following terminal command: node -v &amp;&amp; npm -v</li>
</ul>
<ul>
<li><p><a target="_blank" href="https://www.npmjs.com/package/typescript">TypeScript</a> installed</p>
</li>
<li><p><a target="_blank" href="https://docs.infura.io/infura/getting-started">An Infura account</a></p>
</li>
<li><p>A basic understanding of TypeScript and JavaScript</p>
</li>
<li><p><a target="_blank" href="https://consensys.net/docs/consensys-nft/en/latest/tutorials/tuto_1/tuto_1_4/">MetaMask</a></p>
</li>
</ul>
<h2 id="heading-infura"><strong>Infura</strong></h2>
<p>The Infura NFT SDK is really simple to use. In fact, most of this tutorial is just the setup and configuration needed to create a dApp. Let’s start by <a target="_blank" href="https://infura.io/login">logging in</a> to your Infura account. You should be on your dashboard, where you can create a new key, as shown below. We’ll create a new key for this project.</p>
<p><img src="https://lh4.googleusercontent.com/q-sh4QfIwxBueeyIhF1aWpKfSPA50RMhbn23-LnepDzNk_ssh3WIiKfTeR_iG9m7c9CoIRYOjoIFbzDqcUqeE9Ph4XKO4hCjeborZMN3h43PLaGYjC-gAvmXQOXZoT1hoqwC7KAO0OXNri__VuIZ13EP9S8uzkTIR0eoSmWUMFAUoRZnS67MmMCwpRiSgg" alt /></p>
<p>Click the “Create a New Key” button and fill in the required information.</p>
<p><img src="https://lh5.googleusercontent.com/uDpugcXEr6hZ5bnIpQJCHhlfMy-4Xgby8Fz-9yVCTW3Cmn5_9PC4PnO9HZ3_5eumpcS4YoxHGLZxBpTAm8sAyChyLBV2kvgRV5ACXrksen9CHnEOklZBOZJa6sKWcnfWlbwgkLQWNaQ5nwFIFYHkUpD8GdNLfpTtfaNITSwTtCH69K9tJZxpIRwfdypAcg" alt /></p>
<p>After creating your key, your project ID will be visible on your dashboard under the API KEY section, as shown below. Copy and keep it somewhere; you’ll need it later in this tutorial.</p>
<p><img src="https://lh4.googleusercontent.com/XMy1EC7RYsua8V0y8USVdLAPiOqIiYNVi68FGeK1WQWYSWReSUK_vEM64NG39LRvYDKxYB1R-vTdLllr-dqmLyCf4eSDUE7nt9EX-ha1hSTBHgXFKtdcwD5LWy1IgaFCFjxeSqAQZw2t0YsS_YlWr8QHymMFnkByOSeNwAUdOE9Wk8x5br4h_eo69egc2g" alt /></p>
<h2 id="heading-set-up-ipfs-project-on-infura-dashboard">Set up IPFS project on Infura Dashboard</h2>
<p>Now, let’s create an IPFS project. <a target="_blank" href="https://ipfs.tech/">IPFS</a> is a P2P distributed file system for storing and accessing files (and other data). It works well with blockchain. We’ll need IPFS (and these credentials) to upload and store the metadata of our NFT project. </p>
<p>Head to your dashboard and create another new key by clicking “Create a Key”, as shown below.</p>
<p><img src="https://lh4.googleusercontent.com/q-sh4QfIwxBueeyIhF1aWpKfSPA50RMhbn23-LnepDzNk_ssh3WIiKfTeR_iG9m7c9CoIRYOjoIFbzDqcUqeE9Ph4XKO4hCjeborZMN3h43PLaGYjC-gAvmXQOXZoT1hoqwC7KAO0OXNri__VuIZ13EP9S8uzkTIR0eoSmWUMFAUoRZnS67MmMCwpRiSgg" alt /></p>
<p>This time we’ll choose IPFS as the network. This project will work on the mainnet and (what we will use it for) testnet.</p>
<p><img src="https://lh3.googleusercontent.com/NudbLlKMFtAmhPX_eiLcJmXmb3Vd0qhW7eJZuBaPpZNXFgdsThfqBwNn13nE1B_iIseds-IDl10ST9CYyqf8WEmWSJoySKYg7VxIWFvYEP32snBTn7NVaTHkyhOX4FkAk_w_-WdClJHj1VAJJ_NFGQOpUedodxJADSXU0uv9n_ff3ZymY7gIJyUeG1tK6Q" alt /></p>
<p>After creating your key, you’ll see your project ID and API key secret under the API KEY section of your dashboard. You’ll need this later as well, so copy it and keep it somewhere safe.</p>
<p><img src="https://lh4.googleusercontent.com/5uAFoPoLW6t2KgxvLYiWM5yHNcbrrOuNNPhuzFDrGQYkx4cF4K9tQldKDzvBjNCtbzJJCmWh9LG3T2SgfsISCIUFHmeKipeu0fglYMbs9JNkMowiqb_3j6DZELINfsCOMnh9euG3Ceo0BuFBUZLYoLeqjO9YDyfDX4e5mh7At4l0LyEWrm3DznZhUxtthg" alt /></p>
<h3 id="heading-project-setup-and-installation">Project Setup and Installation</h3>
<p>Next, we’ll set up and initialize a node.js Typescript project. Use the following commands in your console:</p>
<pre><code class="lang-bash">mkdir typescript-nft-demo &amp;&amp; <span class="hljs-built_in">cd</span> typescript-nft-demo

npm init -y

npm install -D typescript ts-node

npx tsc --init
</code></pre>
<p>Open the project in your preferred development environment. For example, if you are using Visual Studio Code, use the following command to open the project automatically:</p>
<pre><code class="lang-bash">code .
</code></pre>
<h3 id="heading-install-the-project-libraries">Install the Project Libraries</h3>
<p>Next, we need to install the Infura SDK and dotenv library for reading the environment variables.</p>
<p>Use the following command: </p>
<pre><code class="lang-bash">npm install @infura/sdk dotenv
</code></pre>
<p>Your project should have something similar to what is shown below:</p>
<p><img src="https://lh6.googleusercontent.com/PfZkuIF_9pNmH7bD_Cqc4kgcMz2sGyXSfAi_NNkkC7YU5lCQZDL3D5Z-yV_0NrimcbuB9qfkTOlfD1NeDa-fokELlRqR3Ct1jBjVlEiGsj3aWeNWjyg_GuL7TepNuIZbQvJR4_OK3fYz0TP6_NXtiA3H4esnYkmJx9DZK3jlvpjmXXdVCAY4gO0V0WWGEw" alt /></p>
<p>Create a <code>.env</code> file at your project's root and add the following variables to it:</p>
<pre><code class="lang-bash">INFURA_PROJECT_ID=&lt;YOUR-INFURA-PROJECT-ID&gt;

INFURA_PROJECT_SECRET=&lt;YOUR-INFURA-PROJECT-API-KEY&gt;

WALLET_PRIVATE_KEY=&lt;YOUR-WALLET-MNEMONIC/PRIVATE-KEY&gt;

EVM_RPC_URL=https://goerli.infura.io/v3/&lt;YOUR-PROJECT-API-KEY&gt;

INFURA_IPFS_PROJECT_ID=&lt;YOUR-INFURA-IPFS-PROJECT-ID&gt;

INFURA_IPFS_PROJECT_SECRET=&lt;YOUR-INFURA-IPFS-PROJECT-SECRET-KEY&gt;

WALLET_PUBLIC_ADDRESS=&lt;YOUR-WALLET-ADDRESS&gt;
</code></pre>
<ul>
<li><p>Replace <code>&lt;YOUR-INFURA-PROJECT-ID&gt;</code> and <code>&lt;YOUR-INFURA-PROJECT-API-KEY&gt;</code> with the <code>ID</code> and <code>API</code> key from the Infura project created earlier in this tutorial.</p>
</li>
<li><p>Replace <code>&lt;YOUR-INFURA-IPFS-PROJECT-ID&gt;</code> and <code>&lt;YOUR-INFURA-IPFS-PROJECT-SECRET-KEY&gt;</code> with the <code>ID</code> and <code>API</code> key from the <em>IPFS</em>  project created earlier in this tutorial.</p>
</li>
<li><p>On the line starting with <code>EVM_RPC_URL</code>, replace <code>&lt;YOUR-PROJECT-API-KEY&gt;</code> with your <code>Infura API key</code>.</p>
</li>
<li><p><code>&lt;YOUR-WALLET-ADDRESS&gt;</code> should be replaced with your public blockchain address.</p>
</li>
<li><p><code>&lt;YOUR-WALLET-MNEMONIC/PRIVATE-KEY&gt;</code> is your wallet's private key. <strong><em>Note: Never share your private keys</em></strong> <em>(mnemonic)</em> <strong><em>with anyone, and keep them secure.</em></strong>  </p>
</li>
</ul>
<p>You can find your wallet address and private key to your wallet on MetaMask in the following steps:</p>
<ul>
<li>Open MetaMask by clicking on the browser extension icon or visiting the MetaMask website.</li>
</ul>
<p><img src="https://lh4.googleusercontent.com/rrqxtgalFtL34J4t-9iWMVRhNyEJr5JVTq7s7yi-OlYzezXGn3OykDWDcJ-VlRATYvEyLpLhmHhEVSXriFiQczkZ2OT3wo4Sv9SXSixJN3A0hBc88lKW5eHgbQYkZisUsOLzLnv-mBgc-zUxk6g_5PqKRKm29QQXW_Cj3jyXtJOTLEqLC3ASfcXKT7n0mA" alt /></p>
<ul>
<li>Click on the three dots in the top right corner of the MetaMask window.</li>
</ul>
<p><img src="https://lh5.googleusercontent.com/3KTNepuUGplfK7tuwF0Dn4YSXQcOPjaujOr7mNe6njESgG9toj-FIJzOvKzhzdMWVeioVDuTQaUmFg_dpnDp-APzfckXiiwLwfFfW_6e_S8PPreZxtw_GtEerGycPftwfILnCes0XCI16XYGQPa7aBTIan7VqPUjepjvAhGQArOZpOodCUmZq87vWtou_Q" alt /></p>
<ul>
<li>Select “Account Details” from the drop-down menu, and click on the “Export Private Key” button.</li>
</ul>
<p><img src="https://lh5.googleusercontent.com/PX68aXVy76z_RDUj0q23qkukWFk9NvTmqR_psvYkJSp50jIsGgRsnZoQTD4Yvj-TzAbsRSTqrHOfAWPB1hFFQken6kyeN8zcD2NoJZKIp4TNQjY1LsGXO5iJq7TCpld8Dvozyid3dKdGbE7ty9DAhrYfsvfHbAclr2Egtk86EOxJd_5ema0IcVM9PyZYdA" alt /></p>
<ul>
<li><p>A pop-up window will appear, asking you to enter your password. Enter your password and click on the “Unlock” button.</p>
</li>
<li><p>Once your account is unlocked, you can see your private key. </p>
</li>
</ul>
<p><mark>Remember: keep your private key safe and </mark> <em><mark>never </mark></em> <mark>share your private key with anyone else. Also, be sure you're connected to the Goerli testnet, not the mainnet, as shown in the image below.</mark></p>
<p><img src="https://lh3.googleusercontent.com/F4Txkf7w3MEpjDOlykttZoki5SHSt6MPc_o72gABfWr-059wTseIBFHxDiufN2O4HMNDs_tCxds2Sx58RSwOTlYEgE00IpPzCtysLeU7TGUQKVf0Zz4Hwy3T1BKZt1-tMi7yzmrUPLuMWCPvKdolgdmWv3-Fdsy-uVaV4K96mDQSDm0ZZy7T4PzfBrHMUg" alt /></p>
<p>Now that we’ve successfully configured our project, create a new TypeScript file <code>nft.ts</code> at the root level.</p>
<p>Your project structure should look similar to the one below.</p>
<p><img src="https://lh5.googleusercontent.com/oLkILZoQrfzCWFH5_hN-35ctAT3jZ5cWSW1wLujRK2JFaBsKlTJP-81b4Xjz-AE1MFKPnqtG7NtoSW4bf_wO3f3S4fIrGy8OO2jHlXKRz4lX_hcvaHC10mS7IAoen5ZP2Jy3t5xO0YDa_VKlVS7smZZt0LZW6mwsCpEb4_BZyG5cS_5atrfgYNx5fkdOSw" alt /></p>
<h2 id="heading-setup-infura-authentication">Setup Infura Authentication</h2>
<p>Authentication from inside our dApp requires our PROJECT_ID and PROJECT_SECRET. We’ll load these from our new .env file.</p>
<p>Create an auth object inside the <code>nft.ts</code> using the following code snippet:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { config <span class="hljs-keyword">as</span> loadEnv } <span class="hljs-keyword">from</span> <span class="hljs-string">"dotenv"</span>;
<span class="hljs-keyword">import</span> { SDK, Auth, Metadata, TEMPLATES } <span class="hljs-keyword">from</span> <span class="hljs-string">"@infura/sdk"</span>;

<span class="hljs-comment">// load environment variables from .env file</span>
loadEnv();

<span class="hljs-comment">// Create an instance of the Auth class </span>
<span class="hljs-keyword">const</span> auth = <span class="hljs-keyword">new</span> Auth({

  <span class="hljs-comment">// set the projectId taken from the INFURA_PROJECT_ID environment variable </span>
  projectId: process.env.INFURA_PROJECT_ID,

  <span class="hljs-comment">// set the secretId taken from the INFURA_PROJECT_SECRET environment variable </span>
  secretId: process.env.INFURA_PROJECT_SECRET,

  <span class="hljs-comment">// set the private key taken from the WALLET_PRIVATE_KEY environment variable </span>
  privateKey: process.env.WALLET_PRIVATE_KEY,

  <span class="hljs-comment">// set the rpcUrl taken from the EVM_RPC_URL environment variable </span>
  rpcUrl: process.env.EVM_RPC_URL,

  <span class="hljs-comment">// set the chainId for the Goerli testnet</span>
  chainId: <span class="hljs-number">5</span>, <span class="hljs-comment">// Goerli</span>

  <span class="hljs-comment">// set the options for IPFS</span>
  ipfs: {

    <span class="hljs-comment">// set the project Id taken from the INFURA_IPFS_PROJECT_ID environment variable</span>
    projectId: process.env.INFURA_IPFS_PROJECT_ID,

    <span class="hljs-comment">// set the API key secret taken from the INFURA_IPFS_PROJECT_SECRET environment variable</span>
    apiKeySecret: process.env.INFURA_IPFS_PROJECT_SECRET,
  },
});

<span class="hljs-comment">// Instantiate the SDK</span>
<span class="hljs-keyword">const</span> sdk = <span class="hljs-keyword">new</span> SDK(auth);
</code></pre>
<p>Configure the <code>tsconfig.json</code> file as shown. (You might get an error but keep going.) <code>tsconfig.json</code> is a configuration file for TypeScript projects. It’s used to specify the compiler options and files that should be included in the project.</p>
<p><img src="https://lh6.googleusercontent.com/m3K_y890hR2T8kAOI_d__ucqAH-DgiN8QbKxM-wRf8POCeQXPHl3nnVSmQDLjMzoAKTBl70woRjSE0TTna8N0Ry1xCocNcF8yWMTzV64wJXhIh8bySHMxmVMeeSEuh8tp0zPSKCTYdOE6Z-Pf87sg8DSBkKMTPtgBwesbKONxkgwZU3FVmbsKkerjtvtTA" alt /></p>
<p>Configure your <code>tsconfig.json</code> with the following code snippet:</p>
<pre><code class="lang-json">{
        <span class="hljs-attr">"compilerOptions"</span>: {

          <span class="hljs-attr">"target"</span>: <span class="hljs-string">"ESNext"</span>, <span class="hljs-comment">/* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */</span>

          <span class="hljs-attr">"module"</span>: <span class="hljs-string">"ES2022"</span>, <span class="hljs-comment">/* Specify what module code is generated. */</span>

          <span class="hljs-comment">// "rootDir": "./",                                  /* Specify the root folder within your source files. */</span>

          <span class="hljs-attr">"moduleResolution"</span>: <span class="hljs-string">"node"</span>, <span class="hljs-comment">/* Specify how TypeScript looks up a file from a given module specifier. */</span>

          <span class="hljs-attr">"esModuleInterop"</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">/* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */</span>

          <span class="hljs-attr">"forceConsistentCasingInFileNames"</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">/* Ensure that casing is correct in imports. */</span>

          <span class="hljs-comment">/* Type Checking */</span>

          <span class="hljs-attr">"strict"</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">/* Enable all strict type-checking options. */</span>

          <span class="hljs-attr">"skipLibCheck"</span>: <span class="hljs-literal">true</span> <span class="hljs-comment">/* Skip type checking all .d.ts files. */</span>
      }
}
</code></pre>
<p>Next, add the <code>type</code> module to the <code>package.json</code> file using the following code snippet:</p>
<pre><code class="lang-json"><span class="hljs-comment">//...</span>

<span class="hljs-string">"type"</span>: <span class="hljs-string">"module"</span>,
<span class="hljs-string">"scripts"</span>: {},

<span class="hljs-comment">//...</span>
</code></pre>
<h2 id="heading-create-token-metadata">Create Token Metadata</h2>
<p>Now we’re done configuring. Let’s get to the exciting stuff!</p>
<p>First, we’ll create the token metadata. </p>
<p>Token metadata refers to additional information or data associated with a token (typically an ERC-721 or ERC-1155 token on the Ethereum blockchain). This metadata can include information such as the token's name, symbol, image, and other attributes that describe the token or give it context.</p>
<p>The metadata is stored on the blockchain and is typically represented as a URI or a URL that points to a JSON file containing the metadata.</p>
<p>Inside the <code>nft.ts file</code>, add the following code snippet. It will create and store the token metadata. The metadata class is from the Infura NFT SDK.</p>
<p>(Note: The <a target="_blank" href="http://consensys.net">consensys.net</a> external_url is just for demo purposes here and can be replaced.)  </p>
<pre><code class="lang-typescript"><span class="hljs-comment">// Define the properties of the token, including its description, external URL, image, name, and attributes</span>
<span class="hljs-keyword">const</span> tokenMetadata = Metadata.openSeaTokenLevelStandard({

  description: <span class="hljs-string">"Fantastic creature of different emojis"</span>,

  external_url: <span class="hljs-string">"https://consensys.net/"</span>,

  image: <span class="hljs-keyword">await</span> sdk.storeFile({

    <span class="hljs-comment">// Store the image from the given URL</span>
    metadata: <span class="hljs-string">"https://res.cloudinary.com/olanetsoft/image/upload/c_pad,b_auto:predominant,fl_preserve_transparency/v1672327921/demo.jpg"</span>,

  }),
  name: <span class="hljs-string">"Kandy Jane"</span>,
  attributes: [],
});

<span class="hljs-comment">// Log the token metadata object to the console</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Token Metadata: "</span>, tokenMetadata);


<span class="hljs-comment">// Store the token metadata and log the result</span>
<span class="hljs-keyword">const</span> storeTokenMetadata = <span class="hljs-keyword">await</span> sdk.storeMetadata({ metadata: tokenMetadata });

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Store Token Metadata: "</span>, storeTokenMetadata);
</code></pre>
<h2 id="heading-create-the-contract-metadata">Create the Contract Metadata</h2>
<p>Contract metadata refers to additional information or data associated with a smart contract on a blockchain network. This metadata can include information such as the contract's name, symbol, version, and other attributes that describe the contract or give it context.</p>
<p>The metadata is stored on the blockchain and is typically represented as a URI or a URL that points to a JSON file containing the metadata.</p>
<p>Create contract metadata using the following code snippet:  </p>
<pre><code class="lang-typescript"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Define the properties of the collection, including its description, external URL, image, name, and attributes</span>
<span class="hljs-keyword">const</span> collectionMetadata = Metadata.openSeaCollectionLevelStandard({

  name: <span class="hljs-string">"Emojis collection"</span>, <span class="hljs-comment">// Sets the name of the collection to "Emojis collection"</span>

  description:
    <span class="hljs-string">"A small digital image or icon used to express an idea or emotion in electronic communication. Emoji's come in many forms, such as smiley faces, animals, food, and activities. "</span>, <span class="hljs-comment">// Sets the description of the collection</span>
  image: <span class="hljs-keyword">await</span> sdk.storeFile({

    <span class="hljs-comment">// Sets the image property of the collection using the storeFile method</span>
    metadata:
<span class="hljs-string">"https://res.cloudinary.com/olanetsoft/image/upload/c_pad,b_auto:predominant,fl_preserve_transparency/v1672327921/demo.jpg"</span>, <span class="hljs-comment">// The URL of the image file</span>
  }),

  external_link: <span class="hljs-string">"https://google.com/"</span>, <span class="hljs-comment">// Sets the external link property of the collection</span>
});

<span class="hljs-comment">// Logs the collection metadata to the console</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Collection Metadata:- "</span>, collectionMetadata); 

<span class="hljs-comment">// stores the metadata using the storeMetadata method</span>
<span class="hljs-keyword">const</span> storeMetadata = <span class="hljs-keyword">await</span> sdk.storeMetadata({ metadata: collectionMetadata }); 

<span class="hljs-comment">// Logs the store metadata to the console</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Store Metadata: "</span>, storeMetadata);
</code></pre>
<p>This code snippet above creates an object <code>collectionMetadata</code> using the <code>openSeaCollectionLevelStandard</code> method from the Metadata class. The <code>openSeaCollectionLevelStandard</code> method creates standard collection-level metadata compatible with <a target="_blank" href="https://opensea.io/">OpenSea</a>, a leading marketplace for NFTs. It sets the collection's name, description, image, and external link properties; stores the metadata using the <code>storeMetadata</code> method; then logs it and stores it in the console for debugging.</p>
<h2 id="heading-create-a-new-contract-and-mint-an-nft">Create a New Contract and Mint an NFT</h2>
<p>Add the following code to create a new contract and mint an NFT using the Infura NFT SDK. Most of this functionality comes to us from our new NFT SDK!</p>
<pre><code class="lang-typescript"><span class="hljs-comment">//...</span>

<span class="hljs-comment">// Create a new contract</span>
<span class="hljs-keyword">const</span> newContract = <span class="hljs-keyword">await</span> sdk.deploy({   <span class="hljs-comment">// deploys a new contract using the sdk.deploy method</span>

  template: TEMPLATES.ERC721Mintable,     <span class="hljs-comment">// sets the template for the contract to ERC721Mintable</span>
  params: {
    name: <span class="hljs-string">"1507Contract"</span>,                  <span class="hljs-comment">// sets the name of the contract as "1507Contract"</span>
    symbol: <span class="hljs-string">"EMOJI"</span>,                        <span class="hljs-comment">// sets the symbol of the contract as "EMOJI"</span>
    contractURI: storeMetadata,             <span class="hljs-comment">// sets the contract URI with the storeMetadata</span>
  },
});

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Contract Address: \n"</span>, newContract.contractAddress);  <span class="hljs-comment">// logs the contract address to the console</span>

<span class="hljs-comment">// mint an NFT</span>
<span class="hljs-keyword">const</span> mint = <span class="hljs-keyword">await</span> newContract.mint({  <span class="hljs-comment">// mints a new NFT using the mint method from the new contract</span>

  publicAddress:
    process.env.WALLET_PUBLIC_ADDRESS ??

    <span class="hljs-string">"0x510e5EA32386B7C48C4DEEAC80e86859b5e2416C"</span>, <span class="hljs-comment">// sets the public address of the wallet, if not set it will use the given address</span>

  tokenURI: storeTokenMetadata,                <span class="hljs-comment">// sets the token URI with the storeTokenMetadata</span>

});

<span class="hljs-keyword">const</span> minted = <span class="hljs-keyword">await</span> mint.wait();            <span class="hljs-comment">// waits for the minting process to complete</span>

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Minted: "</span>, minted);               <span class="hljs-comment">// logs the minted NFT to the console</span>
</code></pre>
<p>This code creates a new contract using the <code>sdk.deploy</code> method and sets the template for the contract to <code>ERC721Mintable</code>. Then it sets the contract's name, symbol, and contract URI. The contract address is logged for debugging.</p>
<p>It then mints a new NFT using the <code>mint</code> method from the new contract and sets the wallet's public address. If not specified, it uses the given address and then sets the token URI with the <code>storeTokenMetadata</code>.</p>
<p>Finally, it waits for the minting process to complete and logs the minted NFT to the console.</p>
<p>Let’s test it out!</p>
<pre><code class="lang-bash">ts-node-esm nft.ts
</code></pre>
<p>You should see something similar to what is shown below:</p>
<p><img src="https://lh5.googleusercontent.com/bcAOFivZ81CLYvT8Cnum8St24rGH7q1eNilgVuW8vhwTqhmO3QWCI25HNhvJPyoqZT3-Tp_wLdLdLsu5B0-xwIfObeH-IffGqrFSRVd4dPETXmup1N_-54DlDSIWhUPvr50wsCKLwzRO0rf7kYdXo6NopMtgDCPfUgYp5P3jw4UDNebQHRB0vi3_KO_omw" alt /></p>
<h2 id="heading-verify-contract-on-account-and-goerli-etherscan">Verify Contract on Account and Goerli Etherscan</h2>
<p>Finally, let’s verify the contract using a blockchain explorer on the <a target="_blank" href="https://goerli.etherscan.io/">Goerli Etherscan</a>. Go to the <a target="_blank" href="https://goerli.etherscan.io/">Goerli Ethereum testnet site</a> and paste the transaction hash from your output above (as shown below).</p>
<p><img src="https://lh6.googleusercontent.com/DQmHhg8WVXeDHoQ6TeiVgqgv3sBTJ7L3bVpGkWbkF1W1wswrHX8zPfqh1BiYRJEXDBMnaAgS0qR1xYlqUX8GXKVjOacrXZezCAIcG2-y0E2q3QiOm6c2Bk6oUN7HvazFS42FXKgHrykhFr9GHWSjvz-1U6HLk2GXHfB0XOCYW_29uD5ZlW6RvOaZmNI1gQ" alt /></p>
<p>You should see the details.</p>
<p><img src="https://lh4.googleusercontent.com/n5mTSEW6_G3Hg-rtD6Ng3Lq30p7NspF_3f7u6mFKiga03OQmsTZ2iJcQSXTI_PjQYune1BJzuvTeJKWviMKZ6clvt5o3u9v4ycRiECWp-gp5zh4Cr_W0d_uzHMh-E67sUkoR0Gw-fa28bFmc7cPku2sKPACguQ0lj977qnA2hIYtkAaGn7295GBDkBBp7w" alt /></p>
<p>That was easy! We successfully utilized the Infura NFT SDK to build, deploy, and mint an NFT on the Goerli testnet.</p>
<h2 id="heading-import-token-on-metamask">Import token on MetaMask</h2>
<p>Let’s look at our new NFT from a front-end perspective using MetaMask. First, we have to import our wallet to MetaMask. Click “Import Tokens”, as shown in MetaMask. (Be sure you are connected to the Goerli Testnet as shown.)</p>
<p><img src="https://lh3.googleusercontent.com/Nw8e3QWqdUBNS71_SfdUdGSVvhNeCgky7MEK0A1HhJkSrOiIWZklUZG-ySFXx7h6mmI6uObI3TVLCtZ5EJPUaH1ZELGcHsSI3R0wNl_46NxDqfzVXWbXhB3tV0AfUsld8hS60VKOLSZEqkNRLQPAW3e6Z4me34HDJuxpz4x0LKC7BNslfcSMpsnpo9q7UA" alt /></p>
<p><img src="https://lh3.googleusercontent.com/9UZocvQnZ866WmwRvH0f8Bj3iuVD0hGESziyGQxCJ7kJ83NOIolJSy0e2y0V1pahk36QQBxQ1Na0Ts1ZEYahxCurYLjbpnnGFBt0Xj5tHx0uCBHn2Q3TRIxGZuuq-jSvFRjIhP309sMr8xWJC9jQ5sgQuddwYQ0Ke0dh2qE4mmpaVe95jSgxpICbtIUy9g" alt /></p>
<p>Copy and paste the contract address to import your token on MetaMask, as shown below.</p>
<p><img src="https://lh3.googleusercontent.com/cZIm0jbz_xYA6_hGq7p5GH-aZZeeJwxziPMoasmrfhscbB2YvPN4vUL-UY6it2QNk2JgnSBNAAZEJR8JtOXGI2t7t__NGCnd31m4ryJShRIeth8KHr6UR_Uz6AHq2ImRyg-GrIqiV7z5zWhaDhzqAjlDJuMLS38ysxjyhDIATlDABDBFhocMGTg6rbgN0g" alt /></p>
<p>And there it is! An easy and fast way to add NFTs to your dApps. You can use the SDK now to manage the NFTs and more (<a target="_blank" href="https://docs.infura.io/infura/infura-custom-apis/nft-sdk">see the docs for current capabilities</a>).</p>
<h2 id="heading-verify-minted-nft-on-opensea">Verify Minted NFT on OpenSea</h2>
<p>We’ve successfully imported the minted NFT on MetaMask, but now let’s verify on <a target="_blank" href="https://testnets.opensea.io/">OpenSea tesnet</a>. Connect your wallet and view your new NFT. You should have something similar to what is shown below.</p>
<p><img src="https://lh4.googleusercontent.com/G5wUmb6mX588wWBv6gvwZIAJsjY6qHftXZWqcUrMgSYFezsVMO41guJS7XJllrHq-DkFPyC5FomNxz_ru0RQTT3wcDmIVxwSy0LABO_jEyZaSRmAdjUJN5kDUoSEoXw1YtnvrS1cgPgloScNU7P_wYgcz2DCpzrHAqq3k94QLEGjgq8KbaWYbBLhBOUY-Q" alt /></p>
<p>For reference, <a target="_blank" href="https://testnets.opensea.io/assets/goerli/0x7d29d142ca8e60139d14fe2ebf1e353e579ed8f6/0">here’s the OpenSea link</a> to the NFT created. You can find the complete code on a GitHub repository <a target="_blank" href="https://github.com/Olanetsoft/nft-demo-with-typescript">here</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, the new Infura NFT SDK for TypeScript is a powerful tool for developers looking to incorporate NFTs into their dApps. With its easy-to-use functions and comprehensive features, this SDK makes it simple to deploy, mint, and manage NFTs on the Ethereum blockchain. <a target="_blank" href="https://www.npmjs.com/package/@infura/sdk">Sign up and start building</a>!</p>
<p>I'd love to connect with you on <a target="_blank" href="https://twitter.com/olanetsoft"><strong>Twitter</strong></a> | <a target="_blank" href="https://www.linkedin.com/in/olubisi-idris-ayinde-05727b17a/"><strong>LinkedIn</strong></a> | <a target="_blank" href="https://github.com/Olanetsoft"><strong>GitHub</strong></a> | <a target="_blank" href="https://idrisolubisi.com/"><strong>Portfolio</strong></a></p>
<p>See you in my next blog article. Take care!!!</p>
]]></content:encoded></item><item><title><![CDATA[Get Started with DAOs: A Step-by-Step Guide Using Boardroom]]></title><description><![CDATA[DAOs (Decentralized Autonomous Organizations) are the next generation of organizational structures. A community of like-minded people collaborates on a common goal without the guidance of a central authority figure.
On the other hand, the boardroom p...]]></description><link>https://blog.idrisolubisi.com/get-started-with-daos-a-step-by-step-guide-using-boardroom</link><guid isPermaLink="true">https://blog.idrisolubisi.com/get-started-with-daos-a-step-by-step-guide-using-boardroom</guid><category><![CDATA[Web3]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[DAO]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Tue, 10 Jan 2023 12:49:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/CJBCaMkLP_U/upload/v1649255236377/xWAOfgrIE.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>DAOs (Decentralized Autonomous Organizations) are the next generation of organizational structures. A community of like-minded people collaborates on a common goal without the guidance of a central authority figure.</p>
<p>On the other hand, the boardroom platform makes discovering, transacting, and improving distributed decision-making across crypto networks a breeze.</p>
<p>In this post, we will learn about DAOs, Boardroom, how to discover DAOs, Boardroom features, and projects.</p>
<h2 id="heading-what-is-a-dao">What is a DAO?</h2>
<p>DAOs (decentralized autonomous organizations) are organizations that were created to be automated and decentralized. The community is managed by rules enforced on a blockchain, and decisions are made from the bottom up.</p>
<p>The use of blockchain technology to establish a secure digital ledger to trace digital activities across the internet, toughened against forgery by trustworthy timestamping and the dispersion of a distributed database, is typified by decentralized autonomous organizations.</p>
<p>A decentralized autonomous organization (DAO) operates without the need for hierarchical management and can serve a variety of objectives. These groups can create freelancer networks where contracts pool their funds to pay for software subscriptions, philanthropic organizations where members approve payments, and venture capital businesses run by a group.</p>
<h2 id="heading-what-is-boardroom">What is Boardroom?</h2>
<p>The Boardroom is a protocol governance and management software designed to help crypto networks make better-distributed decisions.</p>
<p>In exchange for their efforts, the Boardroom allows DAOs to reward users with a direct ownership position in the platform, aligning their success with the forums.</p>
<h2 id="heading-boardroom-features">Boardroom Features</h2>
<p>The Boardroom allows stakeholder-owned platforms to scale while maintaining the interests of all stakeholders. </p>
<p>This section will go through some of the key features it comes with out of the box.</p>
<h3 id="heading-adding-a-dao">Adding a DAO</h3>
<p>Adding a DAO to Boardroom is a relatively painless and straightforward process. First, we will click the <code>Add a DAO</code> button in the top right corner of the page, as shown below.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647559418437_Screenshot+2022-03-18+at+00.22.40.png" alt="Boardroom - Homepage" /></p>
<p>Then, as shown below, we'll be redirected to a new page where we can fill in all of the necessary information about the DAO.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647559616245_Screenshot+2022-03-18+at+00.26.29.png" alt="Boardroom - DAO" /></p>
<p>Voila 🥳, our DAO integration is completed.</p>
<h3 id="heading-profile-management">Profile Management</h3>
<p>Boardroom provides us with vital information about each connected wallet, allowing us to see how active they are and how they voted. Let's look at how we can make changes to our profile.</p>
<p>Let's connect our wallet by clicking on the <code>Connect Wallet</code> button on the top-right of the page, as shown below.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647560034994_Screenshot+2022-03-18+at+00.33.02.png" alt="Boardroom - wallet" /></p>
<p>Next, we will see a pop-up to select our favorite wallet provider to connect our wallet successfully.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647560348191_Screenshot+2022-03-18+at+00.34.46.png" alt="Boardroom - Wallet Provider" /></p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647560348252_Screenshot+2022-03-18+at+00.37.32.png" alt="Boardroom - Profile" /></p>
<p>We will be redirected to a new page by selecting the profile option from the dropdown menu shown in the image above. </p>
<p>We can view our profile information, including our wallet address, activities in all projects (including voting history and proposals), voting power, and edit and share profile buttons.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647561020480_Screenshot+2022-03-18+at+00.41.00.png" alt="Boardroom - Profile Information" /></p>
<p>Then, by clicking the edit profile button, we'll see how to update our profile information.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647561449166_Screenshot+2022-03-18+at+00.54.37.png" alt="Boardroom - Profile Update" /></p>
<h3 id="heading-voting">Voting</h3>
<p>This section will teach us how to vote on the Boardroom application. We'll go to the <a target="_blank" href="https://boardroom.io/projects">DAO page</a>, where we'll be able to vote.</p>
<p>There are numerous methods for locating the DAO where we want to vote. We can either navigate through graphic cards for each DAO or filter by DAO category in the Boardroom.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647602898805_Screenshot+2022-03-18+at+12.27.26.png" alt="Boardroom - Vote" /></p>
<p>We'll choose the Developer DAO project for this article because that's where our associated wallet can vote.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647603137690_Screenshot+2022-03-18+at+12.31.38.png" alt="Boardroom - DAO" /></p>
<p>Next, we'll click on the Total Proposals number and see all of the proposals for the Developer DAO, which we can then filter to see only the Active ones.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647603438154_Screenshot+2022-03-18+at+12.34.43.png" alt="Boardroom - Projects" /></p>
<p>We'll end up with something similar to what's shown below after filtering only the active ones.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647603536634_Screenshot+2022-03-18+at+12.35.54.png" alt="Boardroom - DAO" /></p>
<p>We can now read the proposal's background information, see the current voting results, and vote by clicking as shown below.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647603806085_Screenshot+2022-03-18+at+12.42.34.png" alt="Boardroom - Vote" /></p>
<h3 id="heading-delegation">Delegation</h3>
<p>A user may be too busy or choose to have a proxy vote on their behalf, which is simple to set up in the Boardroom application.</p>
<p>As shown below, let's head over to any DAO page to set up Delegation.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647604355611_Screenshot+2022-03-18+at+12.49.50.png" alt="Boardroom - Delegation" /></p>
<p>When we click on Set Up Delegation, a page will appear asking us to select a delegation type, and there may be a charge for gas.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647604452186_Screenshot+2022-03-18+at+12.50.37.png" alt="Boardroom - Delegation Vote" /></p>
<p>A new pop-up window will appear, asking us to input the Ethereum address we want to delegate. We can also use Boardroom to look for delegates on a leaderboard.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647604535518_Screenshot+2022-03-18+at+12.51.40.png" alt="Boardroom - Delegation Vote" /></p>
<h2 id="heading-boardroom-projects-and-dao-discovery">Boardroom Projects and DAO Discovery</h2>
<p>DAOs can scale much faster than corporations since they are more internationally accessible and have fewer entry restrictions.</p>
<p>The Boardroom main page is a great place to look for freshly developed or added DOAs. We can also view all projects by clicking on the Explore Dao tab below.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647604887963_Screenshot+2022-03-18+at+12.57.14.png" alt="Boardroom - DAO" /></p>
<p>We can filter by protocol, social services, etc.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647605317219_Screenshot+2022-03-18+at+13.04.23.png" alt="Boardroom - Projects" /></p>
<p>We can also read additional information, check the treasury, vote, and view the calendar by clicking on each DAO.</p>
<p><img src="https://paper-attachments.dropbox.com/s_E474D86845AF2231A193AAB99DF4BF8FBDAEF326FE95625C4BD57A8D317CFF75_1647612734661_Screenshot+2022-03-18+at+15.11.07.png" alt="Boardroom - DAO Information" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>This post explores how to discover DAOs on the Boardroom platform and other essential features such as Projects, Voting, Delegation, and profile maintenance.</p>
<h2 id="heading-reference">Reference</h2>
<ul>
<li><a target="_blank" href="https://boardroom.io/">Boardroom</a></li>
<li><a target="_blank" href="https://boardroom.io/projects">Boardroom Projects</a></li>
</ul>
<p>I'd love to connect with you at <a target="_blank" href="https://twitter.com/olanetsoft">Twitter</a> | <a target="_blank" href="https://www.linkedin.com/in/olubisi-idris-ayinde-05727b17a/">LinkedIn</a> | <a target="_blank" href="https://github.com/Olanetsoft">GitHub</a> | <a target="_blank" href="https://idrisolubisi.com/">Portfolio</a></p>
<p>See you in my next blog article. Take care!!!</p>
]]></content:encoded></item><item><title><![CDATA[Dev Retro 2022: The Highs and Lows of a Year to Remember]]></title><description><![CDATA[louAs the end of 2022 approaches, it's natural to reflect on the year, and all that has happened. This year has been a rollercoaster of emotions from the highs and lows, the joys and struggles, the laughter and tears.
As we take stock of all that has...]]></description><link>https://blog.idrisolubisi.com/dev-retro-2022-the-highs-and-lows-of-a-year-to-remember</link><guid isPermaLink="true">https://blog.idrisolubisi.com/dev-retro-2022-the-highs-and-lows-of-a-year-to-remember</guid><category><![CDATA[#DevRetro2022]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[#DevRetro2022 #hashnode]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Career]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Thu, 29 Dec 2022 14:35:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1672095909230/a14ab128-5ba5-47e6-a936-dec8cd94a732.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>louAs the end of 2022 approaches, it's natural to reflect on the year, and all that has happened. This year has been a rollercoaster of emotions from the highs and lows, the joys and struggles, the laughter and tears.</p>
<p>As we take stock of all that has happened, it's easy to feel overwhelmed by the sheer magnitude of it all. But as we look back on the year, we must remember that we are not alone in this journey. We have shared these experiences, and in doing so, we have forged a bond that will carry us forward into the future.</p>
<p>So as I approach the end of the year, I will take a moment to honour all that I have been through and all that I have achieved. Let's embrace the emotions that come with looking back on a year filled with so much. And let's look ahead to the future with hope and determination, knowing that we will face it no matter what comes our way.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672097352688/eb9ed25c-6ae6-4e64-bd1e-78bf2ad1c3a2.jpeg" alt="Idris Olubisi at a Dinner" /></p>
<p>I wrote an "End of the Year" review last year, and I got quite a lot of feedback regarding how some folks are being inspired, so let's do this again. You can find the 2021 review <a target="_blank" href="https://blog.idrisolubisi.com/2021-in-review-the-good-the-bad-and-the-ugly">here</a>.</p>
<h2 id="heading-highlights">Highlights</h2>
<ul>
<li><p>I got a new role with a UK-based company as a Backend Developer</p>
</li>
<li><p>Transitioned into Web3 full-time, securing a role as a <a target="_blank" href="https://blog.idrisolubisi.com/how-i-landed-a-developer-relations-role-in-web3-after-6-months">Developer Relations Engineer</a></p>
</li>
<li><p>Made thousands of $$$ from technical writing</p>
</li>
<li><p>I bought a new phone Samsung S22+, and Samsung watch5 Pro.</p>
</li>
<li><p>Travelled to 3 different countries (Let's do more)</p>
</li>
<li><p>I moved to my new Home (sharing some incredible photos and video soon)</p>
</li>
<li><p>Invested in real estate</p>
</li>
<li><p>Spoke at over 50+ tech conf (In-person events, Webinars, Twitter space, podcast etc.)</p>
</li>
<li><p>Wrote over 40+ technical contents</p>
</li>
<li><p>Founded <a target="_blank" href="https://twitter.com/web3afrika">Web3 Afrika</a></p>
<p>  I'll start with a list of things I expected to get done but didn't.</p>
</li>
</ul>
<blockquote>
<p><em>Failure is simply the opportunity to begin again, this time more intelligently. — Henry Ford</em></p>
</blockquote>
<h2 id="heading-challenges">Challenges</h2>
<p>In this section, I will discuss some challenges I faced. Although I felt so sad about it, but we move !!!</p>
<ul>
<li><p>I got over 50+ rejections, which is way lesser than last year, maybe because I stopped applying to roles at some point. Although I tailored my application to a specific position, I wasn't just applying to roles blindly.</p>
</li>
<li><p>"Hiring freeze" is what they told me after finalizing the five stages of the interview process (I wish I could mention the company name). I was so pained, but after several interactions with HR, she made me realize it was due to the economic crisis in Europe at the time.</p>
</li>
<li><p>I got rejected by three giant Web3 companies at stage 3 or 4 after a smooth interview process. I think one of the reasons I figured was because of my location (sad).</p>
</li>
<li><p>I thought I would write more since I am now in the web3 space full time, but the attention was split between speaking and writing. I failed.</p>
</li>
<li><p>Invited to speak at CMfest22 and Gdg Ikorodu but didn't make it down. 🥲</p>
<hr />
<p>  Life is full of challenges, and it's natural to feel overwhelmed or discouraged when faced with difficulties. But it's important to remember that challenges are a normal and necessary part of life and can help us grow and become stronger.</p>
<p>  So if you're feeling weighed down by challenges, here are a few tips to help you stay motivated and keep moving forward:</p>
<ol>
<li><p><strong>Remember that challenges are temporary:</strong> No matter how difficult a challenge may seem, it will eventually end. Remember this as you work through your struggles, and remind yourself that things will improve.</p>
</li>
<li><p><strong>Please focus on the things you can control:</strong> It's easy to get caught up in the things that are out of our control, but this only leads to frustration and stress. Instead, focus on the things you can control, like your attitude and actions.</p>
</li>
<li><p><strong>Seek support:</strong> No one has to face challenges alone. Whether it's a friend, a family member, or a professional, reach out to someone you trust for support and guidance.</p>
</li>
<li><p><strong>Take care of yourself:</strong> Don't forget to prioritise your physical and emotional well-being. This might mean getting enough rest, eating healthy, or relaxing and de-stressing.</p>
</li>
<li><p><strong>Find the silver lining:</strong> It can be hard to see the bright side when you're going through a tough time but try to look for the small moments of joy and positivity. These can help lift your spirits and motivate you to keep going.</p>
</li>
</ol>
</li>
</ul>
<p><mark>Remember, challenges are a natural part of life and can help us grow and become stronger. So don't let them weigh you down – use them as an opportunity to learn and grow.</mark></p>
<h2 id="heading-accomplishment">Accomplishment</h2>
<p>it's a good time to reflect on our actions and achievements over the past 12 months. Whether it's a significant career milestone, a personal achievement, or something small but meaningful, it's essential to take a moment to celebrate our successes and reflect on our progress.</p>
<ul>
<li>Built a web3 tool: Twitter bot to simplify web3 terms</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1512389126796066817?s=20&amp;t=YgduYyEugQLWliZaSgqMGA">https://twitter.com/olanetsoft/status/1512389126796066817?s=20&amp;t=YgduYyEugQLWliZaSgqMGA</a></div>
<p> </p>
<ul>
<li>I contributed significantly in my little way to folks within my network to get gigs, full-time roles, advice, guides, writing, understanding blockchain concepts from my talks etc. Here are a few ones I can get my hands on right now.</li>
</ul>
<details>
<summary>Click here to view feedbacks</summary>
<p>Tiny changes, remarkable result</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672219765024/9fa5ff9f-85af-46bd-b77b-2be598d2eaa1.png" />
<p>Tiny changes, remarkable result</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672315212566/fed7ec94-2478-4a42-8b8e-b5b3ae3bedba.png" />
<p>Tiny changes, remarkable result</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672315202261/60611269-20a9-4c83-82f1-d5a580f068dc.png" />
<p>Tiny changes, remarkable result</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672315186432/3dc5d4fa-ccdb-4cb8-8c00-d9a3ecbdb7e2.png" />
<p>Tiny changes, remarkable result</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672315176140/0bc44a5a-5c04-4d3d-8abd-584faec6206e.png" />
<p>Tiny changes, remarkable result</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672315152605/466988ea-16af-469a-91b8-590aa78d2179.png" />
<p>Tiny changes, remarkable result</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672315099883/050877fe-3bc4-4923-8bb1-e813d1e5cd0e.jpeg" />
<p>Tiny changes, remarkable result</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672315467620/c86fc43e-bd6d-4405-9cf1-194a4f2046c8.png" />
<p>Tiny changes, remarkable result</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672315453628/e55151ef-2245-47b0-a88a-fe7fdbdaf37a.png" />
<p>Tiny changes, remarkable result</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672315439339/639f8a3f-4d44-4e8c-a8e1-fefa416791dd.pn" />
</details>

<p>I know I might not be able to connect with everyone, but there is a quote that resonates with me every time, which I would like to share with everyone reading this piece.</p>
<blockquote>
<p>Tiny changes, remarkable result - James Clear</p>
</blockquote>
<ul>
<li>Donated a token to support those in need of laptops and also several data giveaway to support those learning in tech.</li>
</ul>
<h3 id="heading-content">Content</h3>
<ul>
<li><p>Made thousands of $$$ from technical writing. Interested to know how? <a target="_blank" href="https://twitter.com/olanetsoft/status/1606650175799365632?s=20&amp;t=5ZJS8iMFJcSyeP5KQzAviA">Check this</a>, let's go on a ride in 2023.</p>
</li>
<li><p>My Hashnode blog crossed 220,000 views, having over 1.2 milion+ views across all platforms.</p>
</li>
<li><p>Started writing content for <a target="_blank" href="https://cloudinary.com/">Cloudinary</a>(<a target="_blank" href="https://mediajams.dev">Media Jam</a>) - <a target="_blank" href="https://mediajams.dev/author/idris-olubisi">profile</a>, <a target="_blank" href="https://web3.hashnode.com/members">Web3 Hashnode</a>, Moralis, Alchemy, Better Programming, and LogRocket.</p>
<p>  <a target="_blank" href="https://linktr.ee/olanetsoft"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1672147169947/5c801aa0-b10f-406e-80b9-25ca5340f544.png" alt class="image--center mx-auto" /></a></p>
<h3 id="heading-travel">Travel</h3>
</li>
<li><p>I travelled out of the country for the first time in my life.</p>
</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1539543506959613952?s=20&amp;t=54f5HtlvYI4NMt_ALN6uyQ">https://twitter.com/olanetsoft/status/1539543506959613952?s=20&amp;t=54f5HtlvYI4NMt_ALN6uyQ</a></div>
<p> </p>
<ul>
<li>Trip to Ghana.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1601928029336662023?s=20&amp;t=5ZJS8iMFJcSyeP5KQzAviA">https://twitter.com/olanetsoft/status/1601928029336662023?s=20&amp;t=5ZJS8iMFJcSyeP5KQzAviA</a></div>
<p> </p>
<h3 id="heading-speaking-engagement">Speaking Engagement</h3>
<ul>
<li>My first-ever in-person speaking event got approved by OSCAFRICA for OscaFest.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1496458485315379207?s=20&amp;t=RJZnJzHP_C-AeeJb_-DD5A">https://twitter.com/olanetsoft/status/1496458485315379207?s=20&amp;t=RJZnJzHP_C-AeeJb_-DD5A</a></div>
<p> </p>
<p>During the Oscafest event after my talk, I got a lot of exciting feedback and started feeling like doing more what people were saying (picking a few).</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/iamCynthiaPeter/status/1507374823093243907?s=20&amp;t=JDqbywNnlRUwnvyNWhyhRA">https://twitter.com/iamCynthiaPeter/status/1507374823093243907?s=20&amp;t=JDqbywNnlRUwnvyNWhyhRA</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/reetahUzoma/status/1507433614761463810?s=20&amp;t=JDqbywNnlRUwnvyNWhyhRA">https://twitter.com/reetahUzoma/status/1507433614761463810?s=20&amp;t=JDqbywNnlRUwnvyNWhyhRA</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/Shittu_Olumide_/status/1507374100649492487?s=20&amp;t=JDqbywNnlRUwnvyNWhyhRA">https://twitter.com/Shittu_Olumide_/status/1507374100649492487?s=20&amp;t=JDqbywNnlRUwnvyNWhyhRA</a></div>
<p> </p>
<ul>
<li>Met <a class="user-mention" href="https://hashnode.com/@dabit3">Nader Dabit</a> at OSCAFEST after connecting online for several years. Thanks for all you do in the community, ser!!</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/developer_dao/status/1507313402368122892?s=20&amp;t=JDqbywNnlRUwnvyNWhyhRA">https://twitter.com/developer_dao/status/1507313402368122892?s=20&amp;t=JDqbywNnlRUwnvyNWhyhRA</a></div>
<p> </p>
<ul>
<li>I was invited to speak at Decode Web3 Series alongside experienced speakers and community builders in the Web3 ecosystem.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/theVatsal_eth/status/1536007937222508545?s=20&amp;t=UYN4Y3N8tZD6hkIb7ciGBg">https://twitter.com/theVatsal_eth/status/1536007937222508545?s=20&amp;t=UYN4Y3N8tZD6hkIb7ciGBg</a></div>
<p> </p>
<ul>
<li>Allowing someone to speak at a web3 Twitter space is not just about giving them a platform – it's about giving them a voice and the chance to share their insights and ideas with the world. Thank you <a class="user-mention" href="https://hashnode.com/@FrancescoCiulla">Francesco Ciulla</a> 💙</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/FrancescoCiull4/status/1581188624606842881?s=20&amp;t=3r0pfdr1tD5oE3kkhPAyTQ">https://twitter.com/FrancescoCiull4/status/1581188624606842881?s=20&amp;t=3r0pfdr1tD5oE3kkhPAyTQ</a></div>
<p> </p>
<ul>
<li>"The Web3 Stack" gave another exciting talk at the Web3 Lagos event, where attendees learnt about the core Web3 stack and how to build a decentralized application.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1578672862201643009?s=20&amp;t=BYl-AEqwOcVnz-kBQ3xk5A">https://twitter.com/olanetsoft/status/1578672862201643009?s=20&amp;t=BYl-AEqwOcVnz-kBQ3xk5A</a></div>
<p> </p>
<ul>
<li>I gave a hands-on technical session about "The Power of Circle APIs + Building &amp; Deploying a USDC-based Smart Contract" in Lagos and Nairobi at the <a target="_blank" href="https://twitter.com/hashtag/Web3Dev22?src=hashtag_click">#Web3Dev22</a> Roadshow.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1584149314192175106?s=20&amp;t=j6C7L53wn4X9R9GYJ4bGjA">https://twitter.com/olanetsoft/status/1584149314192175106?s=20&amp;t=j6C7L53wn4X9R9GYJ4bGjA</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1586724615409262592?s=20&amp;t=eerUbCOEjyfTDwPzjaTAJQ">https://twitter.com/olanetsoft/status/1586724615409262592?s=20&amp;t=eerUbCOEjyfTDwPzjaTAJQ</a></div>
<p> </p>
<ul>
<li>Web3 has come a long way since its inception, and it's clear that it has the potential to revolutionize the way we interact with the internet and each other. At the I4GHACKFEST2022, I gave another talk about building a decentralized application using the appropriate stack.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1591779147260768256?s=20&amp;t=AzdHV394u6XoUd-GyVia2w">https://twitter.com/olanetsoft/status/1591779147260768256?s=20&amp;t=AzdHV394u6XoUd-GyVia2w</a></div>
<p> </p>
<ul>
<li>Speaking at a developer conference is not just an opportunity to share your knowledge and ideas – it's a chance to inspire and motivate others to pursue their passions and positively impact the world. Thank you, DevFest Lagos, DevFest Nairobi, DevFest Ajah and DevFest Ibadan, for the vast opportunity.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1597561915869646848?s=20&amp;t=z1oy1czs0iLzrVcgMM7Eaw">https://twitter.com/olanetsoft/status/1597561915869646848?s=20&amp;t=z1oy1czs0iLzrVcgMM7Eaw</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1602653438323605505?s=20&amp;t=z1oy1czs0iLzrVcgMM7Eaw">https://twitter.com/olanetsoft/status/1602653438323605505?s=20&amp;t=z1oy1czs0iLzrVcgMM7Eaw</a></div>
<p> </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1595110719380684802?s=20&amp;t=EFS3JljVBSwhY5a5YdMKLQ">https://twitter.com/olanetsoft/status/1595110719380684802?s=20&amp;t=EFS3JljVBSwhY5a5YdMKLQ</a></div>
<p> </p>
<ul>
<li>It was an inspiring moment for me during Devfest Nairobi when I gave a talk about leveraging blockchain technology to build software applications.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1589271478184599556?s=20&amp;t=Cq06TYGDSm167lwqkvUPuw">https://twitter.com/olanetsoft/status/1589271478184599556?s=20&amp;t=Cq06TYGDSm167lwqkvUPuw</a></div>
<p> </p>
<ul>
<li>Another exciting moment at the Federal university of technology Owerri.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1606312523677966337?s=20&amp;t=Pn6N2oA1aqIBLUVNl87Tvg">https://twitter.com/olanetsoft/status/1606312523677966337?s=20&amp;t=Pn6N2oA1aqIBLUVNl87Tvg</a></div>
<p> </p>
<p><strong>I wish to list all of the presentations I gave this year. Recall that I stated it's 50+? Knowing that one of my primary goals for 2022 was to speak more was fascinating.</strong></p>
<p>Speaking at a tech conference is a huge accomplishment, and it's natural to feel a sense of pride and accomplishment after such an achievement. But it's important to remember that success is not about resting on your laurels – it's about pushing yourself and striving for even greater things.</p>
<p>If you're feeling overwhelmed or uncertain about what to do next after speaking at a tech conference, here are a few tips to help you stay motivated and keep moving forward:</p>
<p><em><mark>Remember that success is a journey, not a destination: Success is not about reaching a certain point and then stopping – it's about continuously striving to improve and grow. Keep this in mind as you look ahead to your following goals and challenges.</mark></em></p>
<h3 id="heading-community-engagement">Community Engagement</h3>
<ul>
<li>Became <a target="_blank" href="https://www.showwcase.com/">Showwcase</a> Community lead focusing on blogging, Javascript and Technical writing community.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1531951579565277184?s=20&amp;t=7pMxGbivv1tCvvLZqZIp9A">https://twitter.com/olanetsoft/status/1531951579565277184?s=20&amp;t=7pMxGbivv1tCvvLZqZIp9A</a></div>
<p> </p>
<ul>
<li>Became Freecodecamp's 2022 top contributor. I love this, and I hope to do more in 2023.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1601582225400557568?s=20&amp;t=zGhXkvT9HI4AzUouuFjkhA">https://twitter.com/olanetsoft/status/1601582225400557568?s=20&amp;t=zGhXkvT9HI4AzUouuFjkhA</a></div>
<p> </p>
<ul>
<li>I was invited to be a judge in a hackathon at Microsoft garage by Africa hack.</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/uchiuchibeke/status/1578089522763530247?s=20&amp;t=ha6xPwnv6DQGzcXf47UYiA">https://twitter.com/uchiuchibeke/status/1578089522763530247?s=20&amp;t=ha6xPwnv6DQGzcXf47UYiA</a></div>
<p> </p>
<ul>
<li><p>Joined the <a target="_blank" href="https://www.stackshift.com/">Stackshift</a> program, Genesis cohort</p>
</li>
<li><p>Donated to <a target="_blank" href="https://shecodeafrica.org/">SheCodeAfrica</a> to support the excellent work they do.</p>
</li>
<li><p>Showwcase AMA</p>
</li>
</ul>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/ShowwcaseHQ/status/1539592815809728513?s=20&amp;t=c8y_QvXhB_42euOLF5Bvmg">https://twitter.com/ShowwcaseHQ/status/1539592815809728513?s=20&amp;t=c8y_QvXhB_42euOLF5Bvmg</a></div>
<p> </p>
<p>Accomplishments are a natural and essential part of life, and taking the time to celebrate and recognize them is important. But it's also important to remember that accomplishments are not just about recognition or validation – they are also an opportunity for growth and development.</p>
<p>Here are a few tips for embracing your accomplishments and using them to grow:</p>
<ol>
<li><p><strong>Reflect on what you have learned:</strong> Accomplishments are not just about the result but also the journey. Take the time to reflect on what you have learned and how you have grown due to your efforts.</p>
</li>
<li><p><strong>Celebrate your successes:</strong> Taking the time to celebrate your accomplishments and acknowledge your hard work is essential. Whether with a small celebration or a simple thank you to yourself, make sure to take the time to enjoy your success.</p>
</li>
<li><p><strong>Set new goals:</strong> Accomplishments are not the journey's end – they are just the beginning. Use your accomplishments as motivation to set new goals and continue growing and developing.</p>
</li>
<li><p><strong>Share your success with others:</strong> Sharing your accomplishments with others can help inspire and motivate them to pursue their goals. Share your achievements with friends, family, and colleagues, and help them see what is possible with hard work and dedication.</p>
</li>
<li><p><strong>Use your accomplishments as a stepping stone:</strong> Accomplishments can lead to even bigger and better things. Don't be afraid to challenge yourself and push yourself to new heights.</p>
</li>
</ol>
<p>Embracing your accomplishments is an essential part of personal growth and development. So take the time to celebrate and recognize your successes, and use them as a catalyst for even greater things to come.</p>
<h2 id="heading-reflection">Reflection</h2>
<p>As the end of the year approaches, it's natural to look back and reflect on all that has happened. This year has been a rollercoaster of emotions from the highs and lows, the joys and struggles, the laughter and tears.</p>
<p>As we reflect on the year, it's essential to take stock of all that we have accomplished and all that we have learned. This might include looking back on our personal and professional goals and the challenges and successes we have encountered.</p>
<p>But it's also essential to look beyond the year's events and consider the broader emerging themes and patterns. What have we learned about ourselves and the world around us? How have our values and priorities changed over the year?</p>
<p>What do we hope to achieve in the coming year? What lessons can we carry forward from this year's experiences?</p>
<p>By reflecting on the year, we can better understand ourselves and the world around us and use this knowledge to inform our future decisions and goals.</p>
<hr />
<p>I wanted to take a moment to express my heartfelt gratitude to all of you who have supported me throughout my journey this year. Whether you offered encouragement, helped me with practical tasks, or listened to me vent, your support has meant more to me than you will ever know.</p>
<p>This year has had its ups and downs, but I am grateful to have had all of you by my side every step of the way. Your love and support have been a constant source of strength and motivation for me, and I couldn't have made it without you.</p>
<p>Thank you for being such an integral part of my life and believing in me even when I didn't believe in myself. Your love and support mean the world to me, and I am forever grateful to have you all in my life.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>It's only natural to take stock of everything that has transpired this year as we near the end of the year. But as we reflect on the year, we must remember that our difficulties have made us more resilient and robust. They have given us the ability to develop, learn, and the fortitude to handle anything life throws at us.</p>
<p>So as we move forward into the coming year, let's take the lessons and experiences of this year with us. Let's embrace the challenges and opportunities that come our way and continue to grow and develop as individuals.</p>
<p>And most importantly, let's remember to be grateful for all that we have and all that we have achieved. Gratitude allows us to find the strength and motivation to keep moving forward, no matter what the future holds.</p>
<hr />
<p>Thank you for going through this content. We will go harder in the year 2023. ✌️</p>
<p>I'd love to connect with you on <a target="_blank" href="https://twitter.com/olanetsoft">Twitter</a> | <a target="_blank" href="https://www.linkedin.com/in/olubisi-idris-ayinde-05727b17a/">LinkedIn</a> | <a target="_blank" href="https://github.com/Olanetsoft">GitHub</a> | <a target="_blank" href="https://idrisolubisi.com/">Portfolio</a></p>
<p>See you in my next blog article. Take care!!!</p>
]]></content:encoded></item><item><title><![CDATA[Understanding the Role of Developer Relations]]></title><description><![CDATA[DevRel, or Developer Relations, plays a critical role in many organizations, particularly in the tech industry. It involves building and maintaining relationships with developers and the developer community, often through various forms of outreach an...]]></description><link>https://blog.idrisolubisi.com/understanding-the-role-of-developer-relations</link><guid isPermaLink="true">https://blog.idrisolubisi.com/understanding-the-role-of-developer-relations</guid><category><![CDATA[Developer]]></category><category><![CDATA[DevRel]]></category><category><![CDATA[community]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Wed, 21 Dec 2022 13:34:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1671629654087/pLVMXO_Jj.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>DevRel, or Developer Relations, plays a critical role in many organizations, particularly in the tech industry. It involves building and maintaining relationships with developers and the developer community, often through various forms of outreach and communication.</p>
<blockquote>
<p><em>\</em>*Disclaimer<em>\</em>*: I am not an expert in any way to figure this out, but this results from research, feedback and mentorship from DevRel professionals with several years of experience in DevRel.</p>
</blockquote>
<h2 id="heading-main-focus-of-devrel">Main Focus of DevRel</h2>
<p>The main focus of DevRel is to create a positive perception of the organization and its products or services among developers. This is achieved through various activities such as local meetups, speaking engagements, writing and publishing articles, creating video content, teaching workshops, and more.</p>
<p>To build a DevRel function within your organization, you must first understand the needs and goals of your developer community. DevRel function can be achieved through research, analysis, and direct communication with developers. Once you clearly understand your audience, you can develop strategies and tactics for engaging with them.</p>
<p>One effective way to reach developers is through local meetups and in-person events. These can be an excellent opportunity to connect with developers in your area and showcase your organization and its offerings. Participating in online communities and forums is also a good idea, as these can be a great way to get feedback and build relationships with developers.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/TejasKumar_/status/1604461244744093697?s=20&amp;t=o1-47A4UCWtiQpdCAouQIQ">https://twitter.com/TejasKumar_/status/1604461244744093697?s=20&amp;t=o1-47A4UCWtiQpdCAouQIQ</a></div>
<p> </p>
<p>In addition to local meetups and online communities, DevRel professionals often engage with the developer community through speaking engagements, writing articles and blog posts, creating video content, and teaching workshops. These activities help establish your organization as a thought leader in the industry and build trust and credibility among developers.</p>
<p>It's also essential for DevRel professionals to be open-minded and willing to learn from the developer community. By listening to and addressing the needs and concerns of developers, you can create a more positive and productive relationship with them.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/olanetsoft/status/1603024911764791296?s=20&amp;t=Ac6cSCs1dVgngy-6AZljtA">https://twitter.com/olanetsoft/status/1603024911764791296?s=20&amp;t=Ac6cSCs1dVgngy-6AZljtA</a></div>
<p> </p>
<h2 id="heading-how-to-measure-devrel"><s>How to Measure DevRel</s></h2>
<p>There are several ways to measure the effectiveness of a DevRel (Developer Relations) team:</p>
<ol>
<li><p>Quantity and quality of developer engagement: This can be measured through metrics such as the number of developers reached through events, webinars, and other outreach efforts, as well as the level of engagement and feedback received from developers.</p>
</li>
<li><p>Developer satisfaction: It's essential to measure the satisfaction of developers who interact with the DevRel team. This can be done through surveys or other forms of feedback.</p>
</li>
<li><p>Product adoption and usage: One key metric for DevRel is developers' adoption and use of the company's products. This can be measured through metrics such as the number of active users or the number of integrations with other tools and platforms.</p>
</li>
<li><p>Contributions to open-source projects: If the company has an active open-source community, the DevRel team can track the number and quality of contributions made by developers.</p>
</li>
<li><p>Impact on the business: Ultimately, the goal of DevRel is to drive business results. This can be measured by revenue generated from developer-facing products, cost savings from developer support, or other business-specific metrics.</p>
</li>
</ol>
<p>Strategically, here is something to note when measuring DevRel.</p>
<blockquote>
<p>How to measure DevRel is not to measure DevRel - <a target="_blank" href="https://twitter.com/coder_blvck">Shedrack</a>, DevRel Manager, Wilco</p>
</blockquote>
<h2 id="heading-lessons">Lessons</h2>
<ul>
<li><p>Don't let the hype dictate your relationship.</p>
</li>
<li><p>Optimize with what you are naturally gifted with, not what the company would expect</p>
</li>
<li><p>How to measure DevRel is not to measure DevRel.</p>
</li>
<li><p>The more important thing for DevRel than having a personal brand is having the ability to invest in and create high-quality relationships.</p>
</li>
<li><p>As a DevRel, you meet people to create genuine relationships, not to grow your network or transactional relationships.</p>
</li>
</ul>
<h2 id="heading-key-takeaways">Key Takeaways</h2>
<p>Here are some key lessons to take note of as a DevRel professional:</p>
<ol>
<li><p>Understand the needs and goals of your developer community: It's essential to understand your audience to engage with them clearly and effectively. This can be achieved through research, analysis, and direct communication with developers.</p>
</li>
<li><p>Build relationships with developers: The main focus of DevRel is to create positive perceptions of the organization and its products or services among developers. Building relationships with developers through local meetups, speaking engagements, and participating in online communities and forums can help achieve this goal.</p>
</li>
<li><p>Establish your organization as a thought leader: Engaging with the developer community through speaking engagements, writing articles and blog posts, creating video content, and teaching workshops can help to establish your organization as a thought leader in the industry and build trust and credibility among developers.</p>
</li>
<li><p>Be open-minded and willing to learn: By listening to and addressing the needs and concerns of developers, you can create a more positive and productive relationship with them. Be open-minded and willing to learn from the developer community to support their needs effectively.</p>
</li>
<li><p>Stay up to date with industry trends: DevRel professionals need to stay updated with the latest trends and developments in the tech industry to engage with the developer community effectively. This can be achieved through continuous learning and staying connected with industry experts.</p>
</li>
</ol>
<p>Thank you, <a target="_blank" href="https://twitter.com/TejasKumar_">Tejas</a>, for sharing your experience and answering all my questions about DevRel.</p>
<p>With great appreciation, I thank <a target="_blank" href="https://twitter.com/kenny_io">Kenny</a> for his extraordinary mentorship in helping people transition into the DevRel space and for helping those already in the space better understand the Devrel space through the <a target="_blank" href="https://twitter.com/dxmentorship">DXMentorship</a> program.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://blog.idrisolubisi.com/how-i-landed-a-developer-relations-role-in-web3-after-6-months">https://blog.idrisolubisi.com/how-i-landed-a-developer-relations-role-in-web3-after-6-months</a></div>
<p> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, the role of DevRel is crucial for building and maintaining relationships with developers and the developer community. By focusing on local meetups, speaking, writing, video content, teaching, and workshops, and being open-minded and willing to learn, you can effectively engage with and support the needs of your developer community.</p>
<p>I'd love to connect with you via <a target="_blank" href="https://twitter.com/olanetsoft">Twitter</a> | <a target="_blank" href="https://www.linkedin.com/in/olubisi-idris-ayinde-05727b17a/">LinkedIn</a> | <a target="_blank" href="https://github.com/Olanetsoft">GitHub</a> | <a target="_blank" href="https://idrisolubisi.com/">Portfolio</a></p>
<p>See you in my next blog article. Take care!!!</p>
]]></content:encoded></item><item><title><![CDATA[How to Fix xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools)]]></title><description><![CDATA[Gm! I trust you all are fine; it's a bug fix.
Problem
I ran into an issue on my Mac OS when installing a blockchain project using the Cosmos SDK, which runs on top of the Tendermint Core consensus engine.
After running the following command:
make ins...]]></description><link>https://blog.idrisolubisi.com/how-to-fix-xcrun-error-invalid-active-developer-path-librarydevelopercommandlinetools</link><guid isPermaLink="true">https://blog.idrisolubisi.com/how-to-fix-xcrun-error-invalid-active-developer-path-librarydevelopercommandlinetools</guid><category><![CDATA[macOS]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Bugs and Errors]]></category><category><![CDATA[command line]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Mon, 21 Nov 2022 18:48:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/siNDDi9RpVY/upload/v1669056476511/jpgHDroK-.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Gm! I trust you all are fine; it's a bug fix.</p>
<h2 id="heading-problem">Problem</h2>
<p>I ran into an issue on my Mac OS when installing a blockchain project using the Cosmos SDK, which runs on top of the Tendermint Core consensus engine.</p>
<p>After running the following command:</p>
<pre><code class="lang-typescript">make install
</code></pre>
<p>I ran into the error as shown below:</p>
<blockquote>
<p>xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/us</p>
</blockquote>
<p>Please don't panic; you will learn how to fix it quickly.</p>
<h2 id="heading-how-to-fix-the-error">How to Fix the Error</h2>
<p>To fix this error, open the terminal, and run the following command:</p>
<pre><code class="lang-typescript">xcode-select --install
</code></pre>
<p>Why do we need to do this? The problem is that one needs to agree to the license agreement explicitly.</p>
<p>You may get an error message: "Can't install the software because it is not currently available from the Software Update server."</p>
<p>In this case, run the following command <code>xcode-select --reset</code></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>It takes a couple of minutes to resolve this issue might be an hour for you; I hope you will fix it in less than 2 minutes.</p>
<p>Kindly Like and share with others. 😊</p>
<p>I'd love to connect with you on <a target="_blank" href="https://twitter.com/olanetsoft">Twitter</a> | <a target="_blank" href="https://www.linkedin.com/in/olubisi-idris-ayinde-05727b17a/">LinkedIn</a> | <a target="_blank" href="https://github.com/Olanetsoft">GitHub</a></p>
<p>See you in my next blog article. Take care!!!</p>
]]></content:encoded></item><item><title><![CDATA[How to Build and Deploy a USDC-based Smart Contract]]></title><description><![CDATA[For thousands of projects running on the top blockchains in the world, USDC acts as a reliable, interoperable, and highly liquid digital dollar. It is a vital component of the crypto economy.
This tutorial will teach us how to build and deploy USDC-b...]]></description><link>https://blog.idrisolubisi.com/how-to-build-and-deploy-a-usdc-based-smart-contract</link><guid isPermaLink="true">https://blog.idrisolubisi.com/how-to-build-and-deploy-a-usdc-based-smart-contract</guid><category><![CDATA[usdc]]></category><category><![CDATA[Web3]]></category><category><![CDATA[Stablecoins ]]></category><category><![CDATA[Blockchain]]></category><category><![CDATA[Solidity]]></category><dc:creator><![CDATA[Idris Olubisi]]></dc:creator><pubDate>Tue, 25 Oct 2022 09:46:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1666267246642/J-nJMXej6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For thousands of projects running on the top blockchains in the world, USDC acts as a reliable, interoperable, and highly liquid digital dollar. It is a vital component of the crypto economy.</p>
<p>This tutorial will teach us how to build and deploy USDC-based smart contracts to the Goerli Ethereum network and integrate with frontend React applications using EthersJs, ReactJs, and tailwind CSS.</p>
<h2 id="heading-prerequisite">Prerequisite</h2>
<ul>
<li>Make sure to have Node/NPM installed on your computer. To install, click <a target="_blank" href="https://nodejs.org/en/">here</a> for a guide.<ul>
<li>Verify we have Node.js installed by using the following terminal command:<pre><code> node -v &amp;&amp; npm -v
</code></pre></li>
</ul>
</li>
<li>Basic understanding of JavaScript / ReactJs</li>
</ul>
<h2 id="heading-what-is-a-stablecoin">What is a Stablecoin?</h2>
<blockquote>
<p>A stablecoin is a digital currency pegged to a "stable" reserve asset like the U.S. dollar or gold. Stablecoins are designed to reduce volatility relative to unpegged cryptocurrencies like Bitcoin.
~ Coinbase</p>
</blockquote>
<p>Stablecoins aim to offer a substitute for the most widely used cryptocurrencies' significant volatility, such as Bitcoin (BTC), which has made crypto investments less suitable for everyday transactions.</p>
<h2 id="heading-types-of-stablecoins">Types of Stablecoins</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666026875744/Bkx29LMOj.png" alt="Types of Stablecoins - USDC-based Smart Contract" /></p>
<h3 id="heading-commodity-backed-stablecoins">Commodity-backed Stablecoins</h3>
<p>Commodity-backed stablecoins are stablecoins pegged to the value of a commodity like industrial metal, oil, or real estate, e.g., Tether Gold (XAUT).</p>
<h3 id="heading-crypto-backed-stablecoins">Crypto-backed Stablecoins</h3>
<p>Multiple cryptocurrencies support stablecoins to ensure effective risk allocation. Crypto-backed are stablecoins pegged to the value of another, more established cryptocurrency. e.g., DAI, BUSD. </p>
<p>Stablecoins backed by crypto have the benefit of better liquidity. But among the stablecoin variants already in use, crypto-collateralized stablecoins are among the most sophisticated.</p>
<h3 id="heading-fiat-collateralized-stablecoins">Fiat-collateralized Stablecoins</h3>
<p>Stablecoins that are "fiat-collateralized" keep a reserve of a fiat currency (or currencies), such as the dollar, as security for the stablecoin's value. </p>
<p>Commodities like crude oil or pricey metals like gold or silver can be used as collateral, such as USDC, USDT, etc.</p>
<p>However, the majority of fiat-collateralized stablecoins have U.S. dollar reserves.</p>
<h3 id="heading-algorithmic-stablecoins">Algorithmic Stablecoins</h3>
<p>Algorithmic stablecoins are stablecoins that are not backed by real-world commodities but use algorithms to modulate supply based on their market supply.</p>
<p>Their main difference is how a stablecoin maintains its value by using an algorithm to restrict its supply, a computer program that follows a predetermined formula.</p>
<h2 id="heading-building-usdc-based-smart-contract">Building USDC-based Smart Contract</h2>
<p>In this section, we will build, compile, and deploy the USDC-based smart contract to the Goerli Ethereum testnet.</p>
<h3 id="heading-write-a-usdc-based-smart-contract-logic">Write a USDC-based Smart Contract Logic</h3>
<p>Let us Navigate to the <a target="_blank" href="https://remix.ethereum.org/">Remix site</a> and create a new file called <code>UsdcDemo.sol</code> as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666099195022/5ZysVMa_o.png" alt="Create a new file on Remix site" /></p>
<p>Next, update the <code>UsdcDemo.sol</code> file with the following code snippet.</p>
<pre><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
pragma solidity ^<span class="hljs-number">0.8</span><span class="hljs-number">.4</span>;

<span class="hljs-comment">// Abstract</span>
interface USDC {
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">balanceOf</span>(<span class="hljs-params">address account</span>) <span class="hljs-title">external</span> <span class="hljs-title">view</span> <span class="hljs-title">returns</span> (<span class="hljs-params">uint256</span>);
    <span class="hljs-title">function</span> <span class="hljs-title">allowance</span>(<span class="hljs-params">address owner, address spender</span>) <span class="hljs-title">external</span> <span class="hljs-title">view</span> <span class="hljs-title">returns</span> (<span class="hljs-params">uint256</span>);
    <span class="hljs-title">function</span> <span class="hljs-title">transfer</span>(<span class="hljs-params">address recipient, uint256 amount</span>) <span class="hljs-title">external</span> <span class="hljs-title">returns</span> (<span class="hljs-params">bool</span>);
    <span class="hljs-title">function</span> <span class="hljs-title">approve</span>(<span class="hljs-params">address spender, uint256 amount</span>) <span class="hljs-title">external</span> <span class="hljs-title">returns</span> (<span class="hljs-params">bool</span>);
    <span class="hljs-title">function</span> <span class="hljs-title">transferFrom</span>(<span class="hljs-params">address sender, address recipient, uint256 amount</span>) <span class="hljs-title">external</span> <span class="hljs-title">returns</span> (<span class="hljs-params">bool</span>);
}

// <span class="hljs-title">Contract</span>
<span class="hljs-title">contract</span> <span class="hljs-title">UsdcDemo</span></span>{

    USDC public USDc;

    <span class="hljs-comment">// Contract Owner</span>
    address payable public owner; 

    <span class="hljs-keyword">constructor</span>(address usdcContractAddress) {

        USDc = USDC(usdcContractAddress);

        <span class="hljs-comment">// User who is calling this function address</span>
        owner = payable(msg.sender);
    }


    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Fund</span>(<span class="hljs-params">uint $USDC</span>) <span class="hljs-title">public</span> <span class="hljs-title">payable</span> </span>{

        <span class="hljs-comment">// Transfer USDC to this contract from the sender account</span>
        USDc.transferFrom(msg.sender, address(<span class="hljs-built_in">this</span>), $USDC * <span class="hljs-number">10</span> ** <span class="hljs-number">6</span>);  


        <span class="hljs-comment">// Transfer to the owner</span>
        USDc.transfer(owner, $USDC * <span class="hljs-number">10</span> ** <span class="hljs-number">6</span>);  
    }

    <span class="hljs-comment">// Alternatively </span>
    <span class="hljs-comment">// receive() payable external {</span>

        <span class="hljs-comment">// Send the fund to the owner of the contract.</span>
       <span class="hljs-comment">// owner.transfer(address(this).balance);</span>
    <span class="hljs-comment">// }      </span>
}
</code></pre><p>In the code snippet above, we:</p>
<ul>
<li>Created an <code>interface</code> to utilize the function created on the main USDC smart contract</li>
<li>Created a <code>UsdcDemo</code> contract</li>
<li>Initialize the <code>USDc</code> variable from the interface created and also the contract owner</li>
<li>Created the function <code>Fund</code> that accepts a parameter of the amount connected account is willing to fund. Inside this function, we utilized the <code>transferFrom</code> function from the interface to transfer the desired amount from the user to the contract, and then we sent it to the contract's owner using the <code>transfer</code> function.</li>
<li>Added a <code>receive</code> function which alternatively does the automatic transfer of tokens deposited on the smart contract to the contracts' owner to avoid funds being permanently stuck on the contract</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666100626112/js3cyVxgI.png" alt="Write a USDC-based Smart Contract Logic" /></p>
<h3 id="heading-compile-a-usdc-based-smart-contract">Compile a USDC-based Smart Contract</h3>
<p>In this section, we will compile the USDC-based smart contract we wrote in the previous step, as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666100570659/JFaavylvq.png" alt="Compile a USDC-based Smart Contract" /></p>
<h3 id="heading-deploy-a-usdc-based-smart-contract">Deploy a USDC-based Smart Contract</h3>
<p>We successfully built and compiled the USDC-based smart contract in the previous steps. We will proceed to deploy the smart contract to the Goerli Ethereum network.</p>
<blockquote>
<p>Ensure you have Metamask installed, or click <a target="_blank" href="https://metamask.io/download/">here</a> to download and install Metamask.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666101045219/QDDx3c6YM.png" alt="Deploy a USDC-based Smart Contract" /></p>
<p>Select the contract <code>UsdcDemo</code> we want to deploy, as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666101183538/kI2pEVnJB.png" alt="Select Injected Web on Remix" /></p>
<p>Next, paste the original USDC contract address <code>0x07865c6E87B9F70255377e024ace6630C1Eaa37F</code> and click the Deploy button, as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666101651201/Hko3ybZ4o.png" alt="Deploy Smart Contract" /></p>
<p>Metamask will prompt a message to confirm the request then we will see a deployment message on the console, as shown below, after the contract has successfully been deployed on the Goerli Ethereum Network.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666101803637/wubM69KWY.png" alt="USDC Smart contract successfully deployed on the Goerli Network" /></p>
<p>We have entirely built and deployed our smart contract. In the next section, we will implement a simple user interface to test and interact with the smart contract using Reactjs.</p>
<h2 id="heading-building-a-frontend-client-with-reactjs">Building a Frontend Client with ReactJs</h2>
<p>Let's clone <a target="_blank" href="https://github.com/Olanetsoft/usdcdemo-frontend">this project</a> on GitHub to start the project setup and installation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666103662097/CW2zGMVA0.png" alt="Building a Frontend Client" /></p>
<p>Next, we will launch the project locally after cloning it using the following command on our terminal.</p>
<pre><code>cd usdcdemo-frontend &amp;&amp; npm install &amp;&amp; npm run dev
</code></pre><p>After cloning and installing the project, we should have something similar to what we have below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666103578486/ZWZP5CYEJ.png" alt="Testing a USDC based smart contract with ReactJS" /></p>
<h3 id="heading-update-project-smart-contract-address-and-contract-abi">Update Project Smart Contract Address and Contract ABI</h3>
<p>In this section, we will update the cloned project smart contract address and contract ABI with our own that we just built and deployed.</p>
<p>Please navigate to the Remix Site where we wrote and deployed the USDC-based smart. Copy the contract address and ABI as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666104184726/bz8FJDd-_.png" alt="Copy contract ABI" /></p>
<p>Inside the frontend project, navigate to the <code>utils</code> folder and paste the <code>Abi</code> we copied into the <code>contract.json</code> file.</p>
<p>Next, copy the contract address on the Remix site as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666104949076/FA4wmgIqy.png" alt="Copy contract address" /></p>
<p>Inside the <code>index.js</code> file under the <code>pages</code> folder, paste the contract address we just copied to replace the existing one, as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666105264567/xfeb145Go.png" alt="Paste the contract address in the React application" /></p>
<p>In the <code>index.js</code> file, we have a few functions named <code>checkIfWalletIsConnected,</code> <code>connectWallet,</code> and <code>Fund</code>; in the following section, we will learn what each function does.</p>
<h3 id="heading-validate-if-a-user-wallet-is-connected">Validate if a User Wallet is Connected</h3>
<pre><code><span class="hljs-keyword">const</span> checkIfWalletIsConnected = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { ethereum } = <span class="hljs-built_in">window</span>;

      <span class="hljs-comment">/*
       * Check if we're authorized to access the user's wallet
       */</span>
      <span class="hljs-keyword">const</span> accounts = <span class="hljs-keyword">await</span> ethereum.request({ <span class="hljs-attr">method</span>: <span class="hljs-string">"eth_accounts"</span> });

      <span class="hljs-comment">// Validate that we have an account</span>
      <span class="hljs-keyword">if</span> (accounts.length !== <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">const</span> account = accounts[<span class="hljs-number">0</span>];

        <span class="hljs-comment">// Set the current account</span>
        setCurrentAccount(account);

        <span class="hljs-comment">// Display a success message to the user that they are connected</span>
        success(<span class="hljs-string">"🦄 Wallet is Connected!"</span>);
      } <span class="hljs-keyword">else</span> {
        warn(<span class="hljs-string">"Make sure you have MetaMask Connected!"</span>);
      }
    } <span class="hljs-keyword">catch</span> (error) {
      err(<span class="hljs-string">`<span class="hljs-subst">${error.message}</span>`</span>);
    }
  };
</code></pre><h3 id="heading-connect-wallet">Connect Wallet</h3>
<pre><code><span class="hljs-comment">/**
   * Implement your connectWallet method here
   */</span>
  <span class="hljs-keyword">const</span> connectWallet = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { ethereum } = <span class="hljs-built_in">window</span>;

      <span class="hljs-comment">// Check if MetaMask is installed</span>
      <span class="hljs-keyword">if</span> (!ethereum) {
        warn(<span class="hljs-string">"Make sure you have MetaMask Connected!"</span>);
        <span class="hljs-keyword">return</span>;
      }

      <span class="hljs-comment">//request account access if needed</span>
      <span class="hljs-keyword">const</span> accounts = <span class="hljs-keyword">await</span> ethereum.request({
        <span class="hljs-attr">method</span>: <span class="hljs-string">"eth_requestAccounts"</span>,
      });

      <span class="hljs-comment">// Get the first account we get back</span>
      setCurrentAccount(accounts[<span class="hljs-number">0</span>]);
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.log(error);
    }
  };
</code></pre><h3 id="heading-approve">Approve</h3>
<pre><code><span class="hljs-comment">// Check if the user has approved the contract to spend their USDC</span>
  <span class="hljs-keyword">const</span> Approve = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { ethereum } = <span class="hljs-built_in">window</span>;

      <span class="hljs-comment">// Check if User already connected a wallet</span>
      <span class="hljs-keyword">if</span> (ethereum) {
        <span class="hljs-keyword">const</span> provider = <span class="hljs-keyword">new</span> ethers.providers.Web3Provider(ethereum);
        <span class="hljs-keyword">const</span> signer = provider.getSigner();

        <span class="hljs-comment">// Create a contract object</span>
        <span class="hljs-keyword">const</span> usdcContract = <span class="hljs-keyword">new</span> ethers.Contract(
          usdcContractAddress,
          usdcAbi,
          signer
        );

        <span class="hljs-comment">// Use the approve function to send USDC to the contract</span>
        <span class="hljs-keyword">const</span> usdcTxn = <span class="hljs-keyword">await</span> usdcContract.approve(
          contractAddress,
          ethers.utils.parseUnits(<span class="hljs-string">"1000"</span>, <span class="hljs-number">6</span>)
        );

        <span class="hljs-comment">// Set the approving state to true</span>
        setApproving(<span class="hljs-literal">true</span>);

        <span class="hljs-comment">// Wait for the transaction to be mined</span>
        <span class="hljs-keyword">await</span> usdcTxn.wait();

        <span class="hljs-comment">// Set the approving state to false</span>
        setApproving(<span class="hljs-literal">false</span>);

        <span class="hljs-comment">// Set the isApproved state to true</span>
        setIsApproved(<span class="hljs-literal">true</span>);

        <span class="hljs-comment">// Display a success message to the user</span>
        success(<span class="hljs-string">"🦄 USDC Approved Successfully!"</span>);
      }
    } <span class="hljs-keyword">catch</span> (error) {
      err(<span class="hljs-string">`<span class="hljs-subst">${error.message}</span>`</span>);
    }
  };
</code></pre><h3 id="heading-fund">Fund</h3>
<pre><code><span class="hljs-comment">// Check if the user has approved the contract to spend their USDC</span>
  <span class="hljs-keyword">const</span> Fund = <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> { ethereum } = <span class="hljs-built_in">window</span>;

      <span class="hljs-comment">//Check is user already connected to a wallet</span>
      <span class="hljs-keyword">if</span> (ethereum) {
        <span class="hljs-keyword">const</span> provider = <span class="hljs-keyword">new</span> ethers.providers.Web3Provider(ethereum);
        <span class="hljs-keyword">const</span> signer = provider.getSigner();

        <span class="hljs-comment">// Create a contract instance</span>
        <span class="hljs-keyword">const</span> fundContract = <span class="hljs-keyword">new</span> ethers.Contract(
          contractAddress,
          contractABI,
          signer
        );

        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Connected to contract"</span>);
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"amount: "</span>, amount);

        <span class="hljs-comment">// Send the transaction</span>
        <span class="hljs-keyword">const</span> Txn = <span class="hljs-keyword">await</span> fundContract.Fund(amount, {
          <span class="hljs-attr">gasLimit</span>: <span class="hljs-number">300000</span>,
        });

        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Mining..."</span>, Txn.hash);

        <span class="hljs-comment">// Set the sending state to true</span>
        setSending(<span class="hljs-literal">true</span>);

        <span class="hljs-comment">// Wait for the transaction to be mined</span>
        <span class="hljs-keyword">await</span> Txn.wait();

        <span class="hljs-comment">// Set the sending state to false</span>
        setSending(<span class="hljs-literal">false</span>);

        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Mined -- "</span>, Txn.hash);

        <span class="hljs-comment">// Display a success message to the user</span>
        success(<span class="hljs-string">"🦄 Donation Sent Successfully!"</span>);
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Ethereum object doesn't exist!"</span>);
      }
    } <span class="hljs-keyword">catch</span> (error) {
      err(<span class="hljs-string">`<span class="hljs-subst">${error.message}</span>`</span>);
    }
  };
</code></pre><p>Let's head over to our browser to test the application; we should be able to connect our wallet, Approve USDC and donate USDC to the smart contract/owner as shown below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1666208225628/4u5ausyyn.gif" alt="USDC Smart contract demo" /></p>
<p>Kindly Check <a target="_blank" href="https://usdcdemo-frontend.vercel.app/">here</a> for the live demo.</p>
<p>To follow up, you can find the entire code for this project <a target="_blank" href="https://gist.github.com/Olanetsoft/8c3a275c388a623cc42da110af0d4a1b">here</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we learned how to build and deploy USDC-based smart contracts to the Goerli Ethereum network and integrate with frontend React applications using EthersJs, ReactJs, and tailwind CSS.</p>
<p>I'd love to connect with you via <a target="_blank" href="https://twitter.com/olanetsoft">Twitter</a> | <a target="_blank" href="https://www.linkedin.com/in/olubisi-idris-ayinde-05727b17a/">LinkedIn</a> | <a target="_blank" href="https://github.com/Olanetsoft">GitHub</a> | <a target="_blank" href="https://idrisolubisi.com/">Portfolio</a></p>
<p>See you in my next blog article. Take care!!!</p>
]]></content:encoded></item></channel></rss>