<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Abdul Azeez V</title>
    <description>The latest articles on DEV Community by Abdul Azeez V (@azeezv).</description>
    <link>https://dev.to/azeezv</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1392107%2F1db1bd51-43df-45f3-b2bb-6e3129ace9d8.jpeg</url>
      <title>DEV Community: Abdul Azeez V</title>
      <link>https://dev.to/azeezv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/azeezv"/>
    <language>en</language>
    <item>
      <title>How to setup domains and subdomains in localhost</title>
      <dc:creator>Abdul Azeez V</dc:creator>
      <pubDate>Tue, 15 Oct 2024 09:56:58 +0000</pubDate>
      <link>https://dev.to/azeezv/how-to-setup-domains-and-subdomains-in-localhost-27an</link>
      <guid>https://dev.to/azeezv/how-to-setup-domains-and-subdomains-in-localhost-27an</guid>
      <description>&lt;p&gt;I was developing a web app having multiple independent apps that meant to be run at different subdomains. So i wanted to mock this domain system in localhost. &lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;For demo let assume, we have two apps running on ports &lt;code&gt;3000&lt;/code&gt; (a NextJs Frontend) and &lt;code&gt;5000&lt;/code&gt; (a ChatApp). &lt;/p&gt;

&lt;p&gt;We need to add the all dns mapping to &lt;code&gt;/etc/hosts&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/hosts &lt;span class="c"&gt;# linux, macos&lt;/span&gt;
notepad C:&lt;span class="se"&gt;\\&lt;/span&gt;Windows&lt;span class="se"&gt;\\&lt;/span&gt;System32&lt;span class="se"&gt;\\&lt;/span&gt;drivers&lt;span class="se"&gt;\\&lt;/span&gt;etc&lt;span class="se"&gt;\\&lt;/span&gt;hosts &lt;span class="c"&gt;# windows (Run cmd as Administrator)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the domains we need to the end of file. for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;127.0.0.1 example.local
127.0.0.1 chat.example.local 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install and import required packages&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn init
yarn add express vhost http-proxy-middleware
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;vhost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createProxyMiddleware&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http-proxy-middleware&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create proxies for apps running on a NextApp running on port &lt;code&gt;3000&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextAppProxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createProxyMiddleware&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;changeOrigin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// Add ws support&lt;/span&gt;
  &lt;span class="na"&gt;logLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;debug&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Add logging for debugging&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create proxy for app running on port &lt;code&gt;5000&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatAppProxy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createProxyMiddleware&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:5000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;changeOrigin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c1"&gt;// Add ws support&lt;/span&gt;
  &lt;span class="na"&gt;logLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;debug&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// Add logging for debugging&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Set up virtual hosts&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;vhost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;example.local&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextAppProxy&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;vhost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chat.example.local&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chatAppProxy&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Vhost proxy server running on port 80&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the NextJs frontend will be accessible on address &lt;code&gt;example.local&lt;/code&gt; and chat app will be at &lt;code&gt;chat.example.local&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Huraay 😍😍&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/abdxzi/28962cd6b570dbea7ab221af14076437" rel="noopener noreferrer"&gt;Complete Code&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>development</category>
    </item>
    <item>
      <title>Demystifying Account Abstraction</title>
      <dc:creator>Abdul Azeez V</dc:creator>
      <pubDate>Sun, 14 Jul 2024 15:10:37 +0000</pubDate>
      <link>https://dev.to/azeezv/demystifying-account-abstraction-oa9</link>
      <guid>https://dev.to/azeezv/demystifying-account-abstraction-oa9</guid>
      <description>&lt;p&gt;What if your crypto wallet got hacked or you forgot the seed phrase? You lost complete access to your funds, right?&lt;/p&gt;

&lt;p&gt;Not anymore. &lt;/p&gt;

&lt;p&gt;Nowadays account abstraction is a word we always hear in the web3 circles. It is considered a significant step towards the mass adoption of web3 technology.&lt;/p&gt;

&lt;p&gt;So by definition, account abstraction is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A concept in blockchain technology that separates the control logic of an account from the account itself, allowing for more flexible and programmable account behaviors&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What does that mean? What benefits does it bring? Let's go deep by understanding how accounts and transactions work in Ethereum.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accounts in Ethereum
&lt;/h2&gt;

&lt;p&gt;There are two types of accounts in Ethereum:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekib3hfne3wrl47mgg7v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fekib3hfne3wrl47mgg7v.png" alt="Two Types of Ethereum Accounts" width="800" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both EOA and smart contracts can store assets like NFTs and tokens. But, only EOA can initiate a transaction. Smart contracts can store code run on EVMs, while EOA can't. There are no private key associated with smart contracts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv13qduirtk6w669mjwbq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv13qduirtk6w669mjwbq.png" alt="Typical EOA transaction flow" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Ethereum Externally owned accounts (EOAs) initiate a transaction, sign it with private key and send it to mempool which is validated by validators. The private key kept by the user is the only barrier to accessing the crypto assets. Account abstraction intends to abstract away this dependancy. &lt;/p&gt;

&lt;p&gt;Block theory has a good explanation on this &lt;a href="https://blocktheory.com/decoded/account-abstraction-use-cases/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Demerits of EOA accounts:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Loss of Private key results in total loss of funds&lt;/li&gt;
&lt;li&gt;Recovery of wallets not possible&lt;/li&gt;
&lt;li&gt;The transaction requires paying gas directly from the EOA&lt;/li&gt;
&lt;li&gt;Bad User Experience&lt;/li&gt;
&lt;li&gt;Limited Functionality&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Smart Contract Wallets (SWC)
&lt;/h2&gt;

&lt;p&gt;We can overcome the private key issue by using smart contracts as our wallets, or Smart contract wallets (SCW). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7bzdjooagh618uwc98pk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7bzdjooagh618uwc98pk.png" alt="Smart contract wallet (SCW)" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Using SCWs we can abstract the signature from asset ownership. Multi-signature wallets can be implemented using smart contracts which increases security. But still, an EOA is needed to initiate the transaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Account Abstracted Wallets
&lt;/h2&gt;

&lt;p&gt;Account abstraction aims to detach the validity conditions of a transaction like signature verification, gas payment, nonce increase, and chain compatibility to an EVM smart contract level.&lt;br&gt;
How to do it?&lt;/p&gt;

&lt;h3&gt;
  
  
  History of Account Abstraction
&lt;/h3&gt;

&lt;p&gt;Achieving account abstraction has been a long-time dream of many Ethereum developers. It was initially proposed as &lt;strong&gt;EIP-86&lt;/strong&gt; by Vitalik Buterin 2016. However, it needed significant changes to the protocol. &lt;strong&gt;EIP 1014&lt;/strong&gt;, &lt;strong&gt;EIP 2938&lt;/strong&gt; and &lt;strong&gt;EIP 3074&lt;/strong&gt; are some of the proposals that helped in the development of account abstraction architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  EIP 4337
&lt;/h3&gt;

&lt;p&gt;EIP 4337 was the last proposal for Account Abstraction in Ethereum. It introduced a concept of pseudo transactions called &lt;strong&gt;UserOperations (UserOps)&lt;/strong&gt;. UserOps decouples the transaction validation from the consensus layer through an &lt;strong&gt;alternative mempool (altmempool)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5w1scp0u7inaoxc419n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5w1scp0u7inaoxc419n.png" alt="ERC4337 Transaction flow" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In EIP 4337, UserOps are sent to an altmempool by the user which is picked by a &lt;strong&gt;bundler&lt;/strong&gt;. Bundler act as proxy EOAs, bundling the UserOperations and sending them to a global singleton &lt;a href="https://etherscan.io/address/0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789#code" rel="noopener noreferrer"&gt;EntryPoint contract&lt;/a&gt;. The entry point calls the smart contract accounts deployed, which have the code to validate transactions. After successful validation, the transaction is executed.&lt;/p&gt;

&lt;p&gt;Paymaster is a smart contract that sponsors the gas fees for UserOps, enabling gasless transactions for end users. It abstracts the gas payment from the user and allows user-friendly transaction models like ERC20 tokens, etc. Users don't need ETH anymore to pay for gas.&lt;/p&gt;

&lt;p&gt;The Transaction validation through smart contracts allows the possibility of signing transactions using social logins, biometrics, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of AA:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Security&lt;/strong&gt;: Multi-sig, social recovery, and other security mechanisms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recovery Options&lt;/strong&gt;: Built-in recovery mechanisms to regain access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sponsored Transactions&lt;/strong&gt;: Can pay gas using alternative methods or tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved UX&lt;/strong&gt;: Abstracts away private key management for users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch Transactions&lt;/strong&gt;: Multiple operations can be bundled and executed atomically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Authentication&lt;/strong&gt;: Authentication methods like biometrics, social recovery, or hardware wallets.&lt;/li&gt;
&lt;li&gt;Account Segmentation&lt;/li&gt;
&lt;li&gt;No need for EOA to initiate a transaction&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  READ MORE
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cyber.fund/content/AA" rel="noopener noreferrer"&gt;Deconstructing Account Abstraction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://notes.ethereum.org/@vbuterin/account_abstraction_roadmap" rel="noopener noreferrer"&gt;The road to account abstraction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/nethermind-eth/the-history-and-future-of-account-abstraction-10cb097ebdc8" rel="noopener noreferrer"&gt;The History and Future of Account Abstraction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://usa.visa.com/solutions/crypto/rethink-digital-transactions-with-account-abstraction.html" rel="noopener noreferrer"&gt;What is account abstraction&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/abdul-azeez-v/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;  |  &lt;a href="https://github.com/abdxzi" rel="noopener noreferrer"&gt;Github&lt;/a&gt; &lt;/p&gt;

</description>
      <category>web3</category>
      <category>ethereum</category>
      <category>solidity</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>How to disable cache in Xampp and NodeJs Server</title>
      <dc:creator>Abdul Azeez V</dc:creator>
      <pubDate>Fri, 07 Jun 2024 17:13:17 +0000</pubDate>
      <link>https://dev.to/azeezv/how-to-stop-cache-in-xampp-and-nodejs-server-2p21</link>
      <guid>https://dev.to/azeezv/how-to-stop-cache-in-xampp-and-nodejs-server-2p21</guid>
      <description>&lt;p&gt;When developing frontend sometimes i use NodeJs and Xampp as servers. Sometimes Caching of static files becomes a problem such as styles dont update even though the css files are modified. So i needed to disable the caching.&lt;/p&gt;

&lt;h2&gt;
  
  
  XAMPP Server
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fadt6dpxq5lvmsnrkrf54.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fadt6dpxq5lvmsnrkrf54.png" alt="xampp" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Edit &lt;code&gt;httpd.conf&lt;/code&gt; ([xampp folder]/apache/conf/http.conf) file and add following at the end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="c"&gt;# Don't cache html, htm, js, css
&lt;/span&gt;
&amp;lt;&lt;span class="n"&gt;filesMatch&lt;/span&gt; &lt;span class="s2"&gt;"\.(html|htm|js|css)$"&lt;/span&gt;&amp;gt;
  &lt;span class="n"&gt;FileETag&lt;/span&gt; &lt;span class="n"&gt;None&lt;/span&gt;
  &amp;lt;&lt;span class="n"&gt;ifModule&lt;/span&gt; &lt;span class="n"&gt;mod_headers&lt;/span&gt;.&lt;span class="n"&gt;c&lt;/span&gt;&amp;gt;
     &lt;span class="n"&gt;Header&lt;/span&gt; &lt;span class="n"&gt;unset&lt;/span&gt; &lt;span class="n"&gt;ETag&lt;/span&gt;
     &lt;span class="n"&gt;Header&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="n"&gt;Cache&lt;/span&gt;-&lt;span class="n"&gt;Control&lt;/span&gt; &lt;span class="s2"&gt;"max-age=0, no-cache, no-store, must-revalidate"&lt;/span&gt;
     &lt;span class="n"&gt;Header&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="n"&gt;Pragma&lt;/span&gt; &lt;span class="s2"&gt;"no-cache"&lt;/span&gt;
     &lt;span class="n"&gt;Header&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt; &lt;span class="n"&gt;Expires&lt;/span&gt; &lt;span class="s2"&gt;"Wed, 11 Jan 1984 05:00:00 GMT"&lt;/span&gt;
  &amp;lt;/&lt;span class="n"&gt;ifModule&lt;/span&gt;&amp;gt;
&amp;lt;/&lt;span class="n"&gt;filesMatch&lt;/span&gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  NodeJS Server
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;nocache&lt;/code&gt; module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm i nocache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nocache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nocache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;nocache&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OR&lt;/p&gt;

&lt;p&gt;Use set &lt;code&gt;etag&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;etag&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>cache</category>
    </item>
    <item>
      <title>Make NFT using ERC721</title>
      <dc:creator>Abdul Azeez V</dc:creator>
      <pubDate>Wed, 22 May 2024 03:55:56 +0000</pubDate>
      <link>https://dev.to/azeezv/make-nft-using-erc721-243i</link>
      <guid>https://dev.to/azeezv/make-nft-using-erc721-243i</guid>
      <description>&lt;h2&gt;
  
  
  What is ERC721 ?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://eips.ethereum.org/EIPS/eip-721" rel="noopener noreferrer"&gt;ERC721&lt;/a&gt; is a standard that describes how to build NFTs on EVM compatible blockchains. We use the &lt;a href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol" rel="noopener noreferrer"&gt;OppenZeppelin&lt;/a&gt; implementaion of ERC721&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's make the NFT
&lt;/h2&gt;

&lt;p&gt;First we need to setup the images and the metadata describing each image. We are creating 6 NFTs. So we have 6 images and metadata files in a directory. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrul5n9hu3cuqedig7ob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrul5n9hu3cuqedig7ob.png" alt="Images and Metadata" width="693" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Metadata JSON Schema is given &lt;a href="https://eips.ethereum.org/EIPS/eip-721" rel="noopener noreferrer"&gt;Metadata Schema&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MyNFT Collection #1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My First NFT."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ipfs://imageBaseURI/1.png"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Metadata needs the image path. So upload images folder to IPFS first. I used &lt;a href="https://www.pinata.cloud/" rel="noopener noreferrer"&gt;pinata&lt;/a&gt; here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsj7jm0dk9p968yykk1nf.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsj7jm0dk9p968yykk1nf.PNG" alt="IPFS Upload" width="471" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now use the image directory CID to correct metadata files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MyNFT Collection #1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My First NFT."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://gateway.pinata.cloud/ipfs/&amp;lt;PASTE_CID_HERE&amp;gt;/1.png"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upload the metadata files to the IPFS. Now we have both NFT images and metadata in IPFS. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmiwwycfcu6do6cyy293t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmiwwycfcu6do6cyy293t.png" alt="Pinata File Upload" width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can deploy the contract and mint the NFT.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smart Contract
&lt;/h3&gt;

&lt;p&gt;Lets import packages needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// SPDX-License-Identifier: MIT&lt;/span&gt;

&lt;span class="nx"&gt;pragma&lt;/span&gt; &lt;span class="nx"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@openzeppelin/contracts/token/ERC721/ERC721.sol&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@openzeppelin/contracts/access/Ownable.sol&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the contract extends ERC721:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;contract&lt;/span&gt; &lt;span class="nx"&gt;MyNFT&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;ERC721&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ERC721URIStorage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Ownable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;_nextTokenId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="nx"&gt;initialOwner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;ERC721&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MyNFT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MNT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nc"&gt;Ownable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialOwner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="c1"&gt;// functions goes here ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additional functions needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;safeMint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt; &lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;onlyOwner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="nx"&gt;tokenId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_nextTokenId&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;_safeMint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;_setTokenURI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;tokenURI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="nx"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kr"&gt;public&lt;/span&gt;
        &lt;span class="nx"&gt;view&lt;/span&gt;
        &lt;span class="nf"&gt;override&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ERC721&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ERC721URIStorage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;returns &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tokenURI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;supportsInterface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes4&lt;/span&gt; &lt;span class="nx"&gt;interfaceId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kr"&gt;public&lt;/span&gt;
        &lt;span class="nx"&gt;view&lt;/span&gt;
        &lt;span class="nf"&gt;override&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ERC721&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ERC721URIStorage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;returns &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;supportsInterface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interfaceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/abdxzi/dev.to/blob/main/code/MyNFT.sol"&gt;&lt;em&gt;Complete code&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy contract using hardhat
&lt;/h3&gt;

&lt;p&gt;Install hardhat&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npx&lt;/span&gt; &lt;span class="nx"&gt;hardhat&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get a JSON RPC url from Infura/Alchemy. Setup the &lt;code&gt;hardhat.config.json&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Use the script to deploy and mint the NFT:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hardhat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// Deploy contract with initial owner address&lt;/span&gt;
     &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deployContract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MyNFT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xcF469d3BEB3Fc24cEe979eFf83BE33ed50988502&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForDeployment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Contract deployed to:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uris&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://gateway.pinata.cloud/ipfs/&amp;lt;PASTE_CID_HERE&amp;gt;/1.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://gateway.pinata.cloud/ipfs/&amp;lt;PASTE_CID_HERE&amp;gt;/2.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://gateway.pinata.cloud/ipfs/&amp;lt;PASTE_CID_HERE&amp;gt;/3.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// Add more URIs as needed&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;uris&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recipientAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xYourRecipientAddressHere&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Replace with the actual recipient address&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;myNFT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safeMint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;recipientAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;uris&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Minted NFT with URI &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;uris&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt; to address &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;recipientAddress&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exitCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we created and deployed an NFT using ERC721&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/abdxzi" rel="noopener noreferrer"&gt;Github&lt;/a&gt; | &lt;a href="https://www.linkedin.com/in/abdul-azeez-v/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>solidity</category>
      <category>nft</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>How to Implement a Whitelist in NFT contracts using Merkle Tree</title>
      <dc:creator>Abdul Azeez V</dc:creator>
      <pubDate>Sun, 19 May 2024 10:31:23 +0000</pubDate>
      <link>https://dev.to/azeezv/how-to-implement-a-whitelist-in-nft-contracts-using-merkle-tree-4apk</link>
      <guid>https://dev.to/azeezv/how-to-implement-a-whitelist-in-nft-contracts-using-merkle-tree-4apk</guid>
      <description>&lt;h2&gt;
  
  
  Story
&lt;/h2&gt;

&lt;p&gt;I was recently trying to make a fan club nft for a web3 community.  The project required that only members could mint a limited NFT collection, so I needed to implement a whitelist for the minting function. Here are some solutions I found online:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store the &lt;code&gt;whitelist&lt;/code&gt; onchain in nft contract&lt;/li&gt;
&lt;li&gt;Store &lt;code&gt;whitelist&lt;/code&gt; in serverside and call nft minting from there only by a preselected wallet.&lt;/li&gt;
&lt;li&gt;Using merkle tree implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I chose the third one cause it has more advantages over others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Undrestanding merkle tree
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg4co68r5juaptdblvcrt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg4co68r5juaptdblvcrt.png" alt="Merkle tree" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Merkle tree is a tree data structure where each non-leaf node is a hash of it's child nodes&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How it is solving our problem ?&lt;/p&gt;

&lt;p&gt;If we generate a merkle tree using our &lt;code&gt;whitelist&lt;/code&gt; we only need to store the single &lt;code&gt;merkle root hash&lt;/code&gt; onchain, &lt;em&gt;not the entire list&lt;/em&gt;. By just using the merkle root hash and the merkle proof created on server side, we can verify wether the address is in whitelist or not.&lt;/p&gt;

&lt;p&gt;This method reduces the amount of data stored onchain and gas fee needed for the operation.&lt;/p&gt;

&lt;p&gt;Read to undrestand more: &lt;a href="https://medium.com/coinmonks/merkle-tree-a-simple-explanation-and-implementation-48903442bc08" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Merkle tree white list implemetation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqr24pjxvm21wmo75t3md.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqr24pjxvm21wmo75t3md.png" alt="Logic" width="800" height="1836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, create the whitelist database in the server and compute merkle root hash of the whitelist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ethers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MerkleTree&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;merkletreejs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Your whitelist from database&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;whitelist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x90F79bf6EB2c4f870365E785982E1f101E93b906&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x976EA74026E726554dB657fA54763abd0C3a0aa9&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;keccak256&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;leaves&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;whitelist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;merkleTree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MerkleTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;leaves&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;sortPairs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// We need to store this hash in NFT contract&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;merkleRootHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merkleTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getHexRoot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// 0x09485889b804a49c9e383c7966a2c480ab28a13a8345c4ebe0886a7478c0b73d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a NFT contract using any of the NFT standards (&lt;code&gt;ERC721&lt;/code&gt;, &lt;code&gt;ERC1155&lt;/code&gt; etc). Add functions that can verify the merkle proof.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// SPDX-License-Identifier: MIT&lt;/span&gt;
&lt;span class="nx"&gt;pragma&lt;/span&gt; &lt;span class="nx"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@openzeppelin/contracts/access/Ownable.sol&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@openzeppelin/contracts/utils/cryptography/MerkleProof.sol&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;contract&lt;/span&gt; &lt;span class="nx"&gt;MerkleTreeWhitelistContract&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;Ownable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// merkle root hash computed before&lt;/span&gt;
    &lt;span class="nx"&gt;bytes32&lt;/span&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;merkleRoot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x09485889b804a49c9e383c7966a2c480ab28a13a8345c4ebe0886a7478c0b73d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// function to change metkle root after deployment&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setMerkleRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes32&lt;/span&gt; &lt;span class="nx"&gt;merkleRootHash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;external&lt;/span&gt; &lt;span class="nx"&gt;onlyOwner&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;merkleRoot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merkleRootHash&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// function to verify merkle proof&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;verifyAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes32&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="nx"&gt;calldata&lt;/span&gt; &lt;span class="nx"&gt;_merkleProof&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kr"&gt;private&lt;/span&gt; 
    &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="nf"&gt;returns &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;bytes32&lt;/span&gt; &lt;span class="nx"&gt;leaf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encodePacked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;MerkleProof&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_merkleProof&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;merkleRoot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;leaf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// White list checker function&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;whitelistFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes32&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="nx"&gt;calldata&lt;/span&gt; &lt;span class="nx"&gt;_merkleProof&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;external&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;verifyAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_merkleProof&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INVALID_PROOF&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Do some useful stuff&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the user clicks a button on your website, you send the request to your server with the user's address. If the user is in the whitelist, create the Merkle proof on your server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ethers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MerkleTree&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;merkletreejs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="c1"&gt;// whitelist stored in database&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;whitelist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x90F79bf6EB2c4f870365E785982E1f101E93b906&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x976EA74026E726554dB657fA54763abd0C3a0aa9&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="c1"&gt;// Variable to store merkle proof&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;proof&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userWalletAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PASTE_USER_WALLET_ADDRESS_HERE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;whitelist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userWalletAddress&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;keccak256&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;leaves&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;whitelist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;merkleTree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MerkleTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;leaves&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;sortPairs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hashedAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userWalletAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;proof&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;merkleTree&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getHexProof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hashedAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Send this proof to NFT contract along with other data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using this merkle proof and merkle root already stored onchain, the contract can verify whether the address allowed to mint the nft operation or not.&lt;/p&gt;

&lt;p&gt;Problem solved 😻&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/abdxzi" rel="noopener noreferrer"&gt;Github&lt;/a&gt;  |  &lt;a href="https://www.linkedin.com/in/abdul-azeez-v/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>nft</category>
      <category>ethereum</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Snip tool</title>
      <dc:creator>Abdul Azeez V</dc:creator>
      <pubDate>Fri, 10 May 2024 17:50:18 +0000</pubDate>
      <link>https://dev.to/azeezv/snip-tool-1fhh</link>
      <guid>https://dev.to/azeezv/snip-tool-1fhh</guid>
      <description>&lt;p&gt;Hello there, this is my first post here. &lt;/p&gt;

&lt;p&gt;I developed a python version of snip tool, similar to the one found in Windows. I was building a OCR related application. I needed to control the screen capture programatically. But the one in windows (&lt;code&gt;WIN + Shift + S&lt;/code&gt;) couldn't do it. So i created one using tkinter and PIL package.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/f3f20300dc1fed282b2706d7e791dd3eec45ab34d9b50cb5f91dec08f4ea11cb/68747470733a2f2f692e696d6775722e636f6d2f565a5943684c312e706e67" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/f3f20300dc1fed282b2706d7e791dd3eec45ab34d9b50cb5f91dec08f4ea11cb/68747470733a2f2f692e696d6775722e636f6d2f565a5943684c312e706e67" alt="sniptool" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Usage:
&lt;/h3&gt;

&lt;p&gt;To snip screen directly,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/abdxzi/sniptool.git
&lt;span class="nb"&gt;cd &lt;/span&gt;sniptool
python snipping_tool.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add in programs,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;snipper&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ScreenSnipper&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ScreenSnipper&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;snips&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;snip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;snips&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# [&amp;lt;PIL.Image.Image image mode=RGB size=310x250 at 0x228AEDB4D50&amp;gt;, &amp;lt;PIL.Image.Image image mode=RGB size=454x307 at 0x228AEDB4E10&amp;gt;]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns PIL Imgae format, which can be further used in programs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/abdxzi/sniptool" rel="noopener noreferrer"&gt;Source Code&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>showdev</category>
      <category>coding</category>
      <category>firstpost</category>
    </item>
  </channel>
</rss>
