Sick Gaming
[Tut] How I Built My Own ERC-20 Token (2/2) - Printable Version

+- Sick Gaming (https://www.sickgaming.net)
+-- Forum: Programming (https://www.sickgaming.net/forum-76.html)
+--- Forum: Python (https://www.sickgaming.net/forum-83.html)
+--- Thread: [Tut] How I Built My Own ERC-20 Token (2/2) (/thread-100787.html)



[Tut] How I Built My Own ERC-20 Token (2/2) - xSicKxBot - 02-22-2023

How I Built My Own ERC-20 Token (2/2)

<div>
<div class="kk-star-ratings kksr-auto kksr-align-left kksr-valign-top" data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;1151626&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;top&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;2&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;5&quot;,&quot;greet&quot;:&quot;Rate this post&quot;,&quot;legend&quot;:&quot;5\/5 - (2 votes)&quot;,&quot;size&quot;:&quot;24&quot;,&quot;width&quot;:&quot;142.5&quot;,&quot;_legend&quot;:&quot;{score}\/{best} - ({count} {votes})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>
<div class="kksr-stars">
<div class="kksr-stars-inactive">
<div class="kksr-star" data-star="1" style="padding-right: 5px">
<div class="kksr-icon" style="width: 24px; height: 24px;"></div>
</p></div>
<div class="kksr-star" data-star="2" style="padding-right: 5px">
<div class="kksr-icon" style="width: 24px; height: 24px;"></div>
</p></div>
<div class="kksr-star" data-star="3" style="padding-right: 5px">
<div class="kksr-icon" style="width: 24px; height: 24px;"></div>
</p></div>
<div class="kksr-star" data-star="4" style="padding-right: 5px">
<div class="kksr-icon" style="width: 24px; height: 24px;"></div>
</p></div>
<div class="kksr-star" data-star="5" style="padding-right: 5px">
<div class="kksr-icon" style="width: 24px; height: 24px;"></div>
</p></div>
</p></div>
<div class="kksr-stars-active" style="width: 142.5px;">
<div class="kksr-star" style="padding-right: 5px">
<div class="kksr-icon" style="width: 24px; height: 24px;"></div>
</p></div>
<div class="kksr-star" style="padding-right: 5px">
<div class="kksr-icon" style="width: 24px; height: 24px;"></div>
</p></div>
<div class="kksr-star" style="padding-right: 5px">
<div class="kksr-icon" style="width: 24px; height: 24px;"></div>
</p></div>
<div class="kksr-star" style="padding-right: 5px">
<div class="kksr-icon" style="width: 24px; height: 24px;"></div>
</p></div>
<div class="kksr-star" style="padding-right: 5px">
<div class="kksr-icon" style="width: 24px; height: 24px;"></div>
</p></div>
</p></div>
</div>
<div class="kksr-legend" style="font-size: 19.2px;"> 5/5 – (2 votes) </div>
</p></div>
<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube"><a href="https://blog.finxter.com/how-i-built-my-own-erc-20-token-2-2/"><img src="https://blog.finxter.com/wp-content/plugins/wp-youtube-lyte/lyteCache.php?origThumbUrl=https%3A%2F%2Fi.ytimg.com%2Fvi%2FGNV3pPgdKKE%2Fhqdefault.jpg" alt="YouTube Video"></a><figcaption></figcaption></figure>
<p>In the <a href="https://blog.finxter.com/how-i-built-my-own-erc-20-token-1-2/" data-type="post" data-id="1148734" target="_blank" rel="noreferrer noopener">first part</a>, we connected the front end with <a href="https://blog.finxter.com/metamask-simple-tutorial/" data-type="post" data-id="38157" target="_blank" rel="noreferrer noopener">Metamask</a> but couldn’t fetch the balance. Let’s try to fetch the balance from the wallet this time. But first, install the <code>ether.js</code> library to communicate with the smart contract.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">npm install --save ethers</pre>
<p>Import <code>ether.js</code> library to <code>App.js</code>.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import {ethers} from "ethers";</pre>
<p>Now we need to import the contract ABI. </p>
<p class="has-base-background-color has-background"><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f4a1.png" alt="?" class="wp-smiley" style="height: 1em; max-height: 1em;" /> The <strong>contract ABI</strong> is the JSON format of the contract that saves the bytecode of the deployed contract. </p>
<p>Create a <code>contracts</code> folder inside the source folder. Inside this <code>contracts</code> folder, create a JSON file called <code>SilverToken.json</code>. </p>
<p>Copy the ABI of the contract from the <a rel="noreferrer noopener" href="https://blog.finxter.com/solidity-remix-ide-quickstart/" data-type="post" data-id="946353" target="_blank">Remix IDE</a> and paste it inside the JSON file. Now import the ABI from the JSON file to the <code>app.js</code>.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import contractABI from "./contracts/SilverToken.json";</pre>
<p>Create a variable for the contract address.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const contractAddress = "0xC16322799f2645D5b7a1287392072aA668F8144B";</pre>
<p>We need to create a contract instance to get access to the methods of our deployed smart contract. We need three things to create an instance of the contract. Those are the provider, signer, and contract ABI. </p>
<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="957" height="632" src="https://blog.finxter.com/wp-content/uploads/2023/02/image-300.png" alt="" class="wp-image-1149109" srcset="https://blog.finxter.com/wp-content/uploads/2023/02/image-300.png 957w, https://blog.finxter.com/wp-content/uploads/2023/02/image-300-300x198.png 300w, https://blog.finxter.com/wp-content/uploads/2023/02/image-300-768x507.png 768w" sizes="(max-width: 957px) 100vw, 957px" /></figure>
</div>
<p>We already imported the ABI. So, let’s create <a rel="noreferrer noopener" href="https://blog.finxter.com/state-variables-in-solidity/" data-type="post" data-id="765838" target="_blank">state variables</a> for the provider, signer, and contract and initially keep all the values null.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const [provider, setProvider] = useState(null);
const [signer, setSigner] = useState(null);
const [contract, setContract] = useState(null);</pre>
<p>Inside the <code>connectMetamask</code> button define <code>provider</code>, <code>signer</code>, and <code>contract</code>.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const provider = new Web3Provider(window.ethereum);
const signer = provider.getSigner();
const contract = new ethers.Contract( contractAddress, contractABI, signer);
setProvider(provider);
setContract(contract);
setSigner(signer);</pre>
<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="624" height="410" src="https://blog.finxter.com/wp-content/uploads/2023/02/image-302.png" alt="" class="wp-image-1151646" srcset="https://blog.finxter.com/wp-content/uploads/2023/02/image-302.png 624w, https://blog.finxter.com/wp-content/uploads/2023/02/image-302-300x197.png 300w" sizes="(max-width: 624px) 100vw, 624px" /></figure>
</div>
<p>We defined the provider with the help of the <code>Web3Provider</code> method of the <code>ethers</code> library. In our case, the provider would be Metamask.</p>
<p>I was unable to access the <code>providers</code> library of ethers for some unknown reason. That’s why I imported the <code>providers</code> library from the <code>npm</code> Ethereum providers. You can use <a href="https://www.npmjs.com/package/@ethersproject/providers" data-type="URL" data-id="https://www.npmjs.com/package/@ethersproject/providers" target="_blank" rel="noreferrer noopener">this link</a> if you need it. </p>
<p>First, install and then import the <code>providers</code> library.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">npm i @ethersproject/providers</pre>
<p>since we will use the <code>Web3Provider</code> from the <code>providers</code> library, we will import this only.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import { Web3Provider } from "@ethersproject/providers";</pre>
<p>We are committing a transaction, so we must need a signer. We called the signer by using the <code>getSigner()</code> method of the provider.</p>
<div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="682" height="1024" src="https://blog.finxter.com/wp-content/uploads/2023/01/image-245-682x1024.png" alt="" class="wp-image-1073516" srcset="https://blog.finxter.com/wp-content/uploads/2023/01/image-245-682x1024.png 682w, https://blog.finxter.com/wp-content/uploads/2023/01/image-245-200x300.png 200w, https://blog.finxter.com/wp-content/uploads/2023/01/image-245.png 714w" sizes="(max-width: 682px) 100vw, 682px" /></figure>
</div>
<p>Then we created an instance of our smart contract with the <code>contract()</code> method of the <code>ethers</code> library. </p>
<p>This <code>contract()</code> method takes the <a href="https://blog.finxter.com/solidity-members-of-address-types-and-type-information/" data-type="post" data-id="896974" target="_blank" rel="noreferrer noopener">contract address</a>, ABI, and the signer as the parameters.</p>
<p>Now the provider, signer, and contract are defined. So, we need to change the state of these three that we have defined as null earlier.</p>
<p>Now let’s <code><a rel="noreferrer noopener" href="https://blog.finxter.com/javascript-intro-how-to-see-your-code-output/" data-type="post" data-id="175068" target="_blank">console.log</a></code> the contract to check if all changes occurred.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">console.log(contract);</pre>
<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="559" height="358" src="https://blog.finxter.com/wp-content/uploads/2023/02/image-303.png" alt="" class="wp-image-1151653" srcset="https://blog.finxter.com/wp-content/uploads/2023/02/image-303.png 559w, https://blog.finxter.com/wp-content/uploads/2023/02/image-303-300x192.png 300w" sizes="(max-width: 559px) 100vw, 559px" /></figure>
</div>
<p>As you can see in my console, the contract’s state was initially null. But now it returns the contract address that we are connected to.</p>
<h2>Get Wallet Balance</h2>
<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="707" height="462" src="https://blog.finxter.com/wp-content/uploads/2023/02/image-306.png" alt="" class="wp-image-1151677" srcset="https://blog.finxter.com/wp-content/uploads/2023/02/image-306.png 707w, https://blog.finxter.com/wp-content/uploads/2023/02/image-306-300x196.png 300w" sizes="(max-width: 707px) 100vw, 707px" /></figure>
</div>
<p>Create a <code>getBalance()</code> method to get the balance from the address.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""> const getBalance = async () => { const balanceInBig = await contract.balanceOf(activeAccount); const balanceInNum = Number(balanceInBig) / 100; setTokenBalance(balanceInNum); };
</pre>
<p>We are using the <code>balanceOf</code> method of the contract to get the balance of our address. The balance will be returned as a <code>bigInteger</code> number. Read more about <code>BigInt</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt" data-type="URL" data-id="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt" target="_blank" rel="noreferrer noopener">here</a>.</p>
<p>In the 2nd line, we converted the big integer number to a readable format.</p>
<p>To initiate the <code>getBalance()</code> function, we can use <a rel="noreferrer noopener" href="https://blog.finxter.com/project-react-dapp-for-selling-ebooks-in-a-decentralized-manner-1-4/" data-type="post" data-id="1055370" target="_blank">React</a>‘s <code>useEffect()</code> hook.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">useEffect(() => { if (contract != null) { getBalance(); } }, [contract]);
</pre>
<p>The <code>useEffect()</code> hook will trigger the <code>getBalance</code> method if a contract is available. The <code>useEffect()</code> hook will render the page again whenever the contract is changed.</p>
<h2>Transfer the Balance</h2>
<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="709" height="636" src="https://blog.finxter.com/wp-content/uploads/2023/02/image-307.png" alt="" class="wp-image-1151678" srcset="https://blog.finxter.com/wp-content/uploads/2023/02/image-307.png 709w, https://blog.finxter.com/wp-content/uploads/2023/02/image-307-300x269.png 300w" sizes="(max-width: 709px) 100vw, 709px" /></figure>
</div>
<p>Now to transfer the balance, we need a form where we will input the address of the account to which we will be transferring the amount. Let’s do this part in a separate functional component.</p>
<p>Let’s create a components folder inside the source folder and create a new file called <code>Transaction.js</code>. </p>
<p>Inside this file, create a component structure by pressing “<code>rsc</code>” on the keyboard. If the autocompletion doesn’t work, no need to worry. Write the code manually.</p>
<p>I will create a simple form using custom codes from flowbite. You can check it out or make your own custom one. Inside the return function, paste the following.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""> return ( &lt;div className="w-1/2 mx-auto bg-slate-600 mt-10 p-5 border rounded-lg"> &lt;form onSubmit={transactionHandler}> &lt;div className="mb-6"> &lt;label for="address" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white" > Receiver Address &lt;/label> &lt;input type="text" id="address" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Enter Receiver Address" required /> &lt;/div> &lt;div className="mb-6"> &lt;label for="amount" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white" > Transfer Amount &lt;/label> &lt;input type="number" id="amount" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required /> &lt;/div> &lt;button type="submit" className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" > Send Token &lt;/button> &lt;div className="mt-5"> &lt;h3 className="text-slate-100">{transactionHash}&lt;/h3> &lt;/div> &lt;/form> &lt;/div> );
</pre>
<p>We created two input fields inside the form. One is text type for the receiver address, and another is a number type for the amount that would be sent to the receiver.</p>
<p>The id of each input filed is changed to “<code>address</code>” and “<code>amount</code>” respectively.</p>
<p>A <code>transactionHandler()</code> function will be triggered whenever you click on the <code>send</code> button. This function will collect the info from the input fields and do something further.</p>
<p>Let’s define the <code>transactionHandler()</code> function.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">const transactionHandler = async (event) => { event.preventDefault(); let receiverAddress = event.target.address.value; let sendAmount = event.target.amount.value; let transferAmount = sendAmount * 100; let trans = await contract.transfer(receiverAddress, transferAmount); console.log(trans); setTransactionHash("Transaction confirmed with hash:" + trans.hash); };
</pre>
<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="624" height="219" src="https://blog.finxter.com/wp-content/uploads/2023/02/image-304.png" alt="" class="wp-image-1151666" srcset="https://blog.finxter.com/wp-content/uploads/2023/02/image-304.png 624w, https://blog.finxter.com/wp-content/uploads/2023/02/image-304-300x105.png 300w" sizes="(max-width: 624px) 100vw, 624px" /></figure>
</div>
<p>The <code>transactionHandler()</code> is an <code>async await</code> function that will trigger an event. The <code>preventDefault()</code> method will prevent the function from reloading automatically for changes.</p>
<p>The <code>transferAmount</code> and <code>receiverAddress</code> variables will collect the info from the input fields. “<code>event.target</code>” will access the input fields by using the id of the input field “<code>amount</code>” and “<code>address</code>.”</p>
<p>We need to use the <code>transfer</code> method of the contract to commit the transaction. To access the contract state, we need to pass it as a prop from the <code>app.js</code> file.</p>
<p>Call the <code>transaction.js</code> component from the <code>app.js</code> file and pass the contract as props.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;Transaction contract={contract}>&lt;/Transaction></pre>
<p>We are using the “<code>contract.transfer</code>” method to commit the transaction. This method will take the receiver address and the send amount as parameters.</p>
<p>We will get a transaction hash as a transfer confirmation when the transaction is done. We can store this transaction hash as a state variable to display it on the user interface.</p>
<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="707" height="478" src="https://blog.finxter.com/wp-content/uploads/2023/02/image-308.png" alt="" class="wp-image-1151679" srcset="https://blog.finxter.com/wp-content/uploads/2023/02/image-308.png 707w, https://blog.finxter.com/wp-content/uploads/2023/02/image-308-300x203.png 300w" sizes="(max-width: 707px) 100vw, 707px" /></figure>
</div>
<p>Let’s create a new account on the Goerli testnet. This will be our receiver account. </p>
<p>Now use this address and send an amount of 50 tokens from the main wallet. We need to multiply the amount by 100 to get the exact value, as we used a two-digit return in the decimals function of the smart contract.</p>
<p>Now if you check this transaction hash on the Etherscan website, you will get the complete transaction details. You will also receive the token balance on the Metamask receiver wallet.</p>
<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="624" height="424" src="https://blog.finxter.com/wp-content/uploads/2023/02/image-305.png" alt="" class="wp-image-1151670" srcset="https://blog.finxter.com/wp-content/uploads/2023/02/image-305.png 624w, https://blog.finxter.com/wp-content/uploads/2023/02/image-305-300x204.png 300w" sizes="(max-width: 624px) 100vw, 624px" /></figure>
</div>
<p>This is the screenshot of my recent transaction. To get your transaction details, just use the transaction hash in the search bar. Make sure you choose the Goerli testnet as the network.</p>
<p>That’s all for today. Thanks for the reading! <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/2665.png" alt="♥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> </p>
<p class="has-base-background-color has-background"><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f449.png" alt="?" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Github</strong>: <a rel="noreferrer noopener" href="https://github.com/finxter/silver_wallet" target="_blank">https://github.com/finxter/silver_wallet</a></p>
</div>


https://www.sickgaming.net/blog/2023/02/21/how-i-built-my-own-erc-20-token-2-2/