
{"id":13619,"date":"2024-10-14T08:44:53","date_gmt":"2024-10-14T08:44:53","guid":{"rendered":"https:\/\/mycryptomania.com\/?p=13619"},"modified":"2024-10-14T08:44:53","modified_gmt":"2024-10-14T08:44:53","slug":"streamline-dapp-access-implementing-account-abstraction-erc-4337-with-privy","status":"publish","type":"post","link":"https:\/\/mycryptomania.com\/?p=13619","title":{"rendered":"Streamline Dapp Access: Implementing Account Abstraction ERC-4337 with Privy"},"content":{"rendered":"<p>One of the biggest challenges in Web3 today is improving user experience. Traditionally, users are required to have a crypto wallet, manage gas fees, and sign their own transactions to interact with decentralized applications (dapps). This complex process often creates friction for users unfamiliar with blockchain. However, ERC-4337 account abstraction changes the game by making Web3 feel more like Web2. With it, users no longer need to create wallets, handle gas fees, or sign transactions\u200a\u2014\u200athese steps can be abstracted away. In this article, we\u2019ll explore how to implement account abstraction in your dapp using Privy, simplifying the Web3 experience.<\/p>\n<p><a href=\"https:\/\/medium.com\/media\/90e6277b224370f45b09056b4ec4261b\/href\">https:\/\/medium.com\/media\/90e6277b224370f45b09056b4ec4261b\/href<\/a><\/p>\n<h3>Table of\u00a0Contents<\/h3>\n<p>\u00b7 <a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#db92\">Table of Contents<\/a><br \/>\u00b7 <a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#829e\">Intro to Account Abstraction<\/a><br \/>\u00b7 <a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#8374\">Introduction to Privy<\/a><br \/>\u00b7 <a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#e042\">Hands On Demonstration<\/a><br \/> \u2218 <a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#38ac\">1- Creating the Privy App<\/a><br \/> \u2218 <a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#6ef5\">2- Creating the Dapp<\/a><br \/> \u2218 <a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#5f3e\">3 Test the smart account<\/a><br \/>\u00b7 <a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#3e1d\">Conclusions<\/a><br \/>\u00b7 <a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#8a1e\">Code Repository<\/a><br \/>\u00b7 <a href=\"https:\/\/medium.com\/coinmonks?source=rss----721b17443fd5---4#76d6\">References<\/a><\/p>\n<h3>Intro to Account Abstraction<\/h3>\n<p>The user experience for newcomers to crypto can be challenging due to several\u00a0factors:<\/p>\n<p><strong>Private keys are difficult to manage<\/strong>: Users must securely handle long, complex private keys, which are easy to lose or mishandle.<strong>Every action incurs gas fees<\/strong>: Simple transactions require users to spend cryptocurrency on gas, which can be confusing and\u00a0costly.<strong>Maintaining wallet privacy is hard<\/strong>: Ensuring anonymity and privacy while using a wallet can be complex, especially for beginners.<strong>Signing every transaction<\/strong>: Every on-chain action must be signed by the user\u2019s wallet, adding another layer of complexity, as it requires users to interact with cryptographic tools that aren\u2019t always user-friendly.<\/p>\n<p>Account abstraction aims to solve many of the issues related to current private key and wallet management. Simply put, it offers a new approach to transaction signing.<\/p>\n<p>In traditional crypto transactions, you need to use your private key to sign the data and send the transaction, which is how tools like MetaMask\u00a0work:<\/p>\n<p>With <strong>account abstraction<\/strong>, however, you can sign transactions using alternative methods such as Google, GitHub, X (formerly Twitter), LinkedIn, Instagram, Telegram, and others, making the process more flexible and user-friendly.<\/p>\n<p>Additionally, <strong>account abstraction<\/strong> introduces the ability to create custom transaction rules, such\u00a0as:<\/p>\n<p>Requiring multiple users to sign a transaction (multi-signature transactions).Setting time-based restrictions (e.g., only allowing transactions during the\u00a0day).Implementing spending limits that prevent transactions exceeding a certain\u00a0amount.<\/p>\n<p>These features provide more control and flexibility over how wallets and transactions operate, creating a smoother and more secure user experience.<\/p>\n<p>With <strong>account abstraction<\/strong>, a new level of customization is introduced that allows others to pay for your transaction fees. Before this innovation, performing any on-chain operation required having enough gas fees in your own wallet. This typically meant buying the gas (ETH, MATIC, etc.) from an exchange and transferring it to your wallet to cover transaction costs.<\/p>\n<p>However, with <strong>account abstraction<\/strong>, users are no longer required to hold gas in their wallets. Instead, they can create the transaction, and a third party (like a sponsor or dApp) can cover the gas fees on their behalf. This allows for a much smoother onboarding process where the user doesn\u2019t need to worry about acquiring gas tokens, reducing friction significantly.<\/p>\n<p>The user doesn\u2019t even need a traditional wallet. They simply generate the transaction, and someone else\u200a\u2014\u200asuch as a service provider\u200a\u2014\u200acan pay the gas fees for them. This feature helps to simplify the user experience while making decentralized applications more accessible to a broader audience.<\/p>\n<p>Let\u2019s understand how account abstraction works.<\/p>\n<p>In a traditional user experience, the user has a wallet that allows them to manage an externally owned account (EOA). The user holds a private key, which they use to sign transactions before submitting them to a blockchain node.<\/p>\n<p>In the context of account abstraction defined by ERC-4337, there are five key\u00a0actors:<\/p>\n<p><strong>User<\/strong>: Initiates a user operation, which functions as a meta transaction.<strong>Bundler<\/strong>: Collects, verifies, and signs user operations from various users. It bundles these operations into a single transaction, acting similarly to an Externally Owned Account (EOA) in traditional transactions. The bundled transaction is then sent to the Entry\u00a0Point.<strong>Entry Point<\/strong>: Receives the bundled transaction from the Bundler. It verifies the validity of each user operation and communicates with the Paymaster to ensure that there are sufficient funds in the Entry Point\u2019s account to cover the gas fees for the operations. Once validated, it calls the Smart Contract Account to execute the transaction.<strong>Paymaster<\/strong>: Responsible for sponsoring the gas fees associated with the user operations.<strong>Smart Contract Account<\/strong>: Executes all user operations contained in the transaction that the Entry Point has forwarded.<a href=\"https:\/\/blog.thirdweb.com\/account-abstraction-erc4337\/\">https:\/\/blog.thirdweb.com\/account-abstraction-erc4337\/<\/a><\/p>\n<h3>Introduction to\u00a0Privy<\/h3>\n<p>Implementing account abstraction in a dApp can be quite challenging due to its inherent complexity. I recently discovered <strong>Privy<\/strong>, which greatly simplifies the process of generating a smart account for our users by abstracting much of the complexity.<\/p>\n<p>The <strong>Privy React SDK<\/strong> is an authentication library that provides one of the easiest ways to onboard users to web3 in a React app providing:<\/p>\n<p><strong>Multiple login options<\/strong>: Users can sign in via email, phone, external wallets, or popular social platforms, offering flexible login experiences.<strong>Customizable onboarding UIs<\/strong>: You can tailor the user journey, progressively introducing web3 concepts to your users at their own\u00a0pace.<strong>Self-custodial embedded wallets<\/strong>: Privy offers powerful embedded wallet solutions while maintaining self-custody, and it also includes robust connectors for external\u00a0wallets.<\/p>\n<p>This is an example of how a login looks with\u00a0<strong>Privy<\/strong>:<\/p>\n<p><strong>Privy <\/strong>offers multiple login methods to simplify the user onboarding experience. Users can choose from various options, including:<\/p>\n<p><strong>Email<\/strong>: A straightforward method for users who prefer traditional email authentication.<strong>Google<\/strong>: Quick login with an existing Google\u00a0account.<strong>X (formerly Twitter)<\/strong>: Users can sign in using their X (Twitter) account.<strong>Other Socials<\/strong>: Privy also supports a wide range of other social platforms, including <strong>Discord<\/strong>, <strong>GitHub<\/strong>, <strong>TikTok<\/strong>, <strong>LinkedIn<\/strong>, <strong>Farcaster<\/strong>, <strong>Telegram<\/strong>, and more, offering flexibility for different user preferences.<\/p>\n<p>This flexibility in login methods ensures users can easily connect to your dApp using the platform or method they\u2019re most comfortable with, creating a seamless web3 experience.<\/p>\n<h3>Hands On Demonstration<\/h3>\n<p>This is the Dapp that we are going to build with\u00a0Privy:<\/p>\n<p>The code repository is available <a href=\"https:\/\/github.com\/RosarioB\/privy_tutorial\">here<\/a>.<\/p>\n<h4>1- Creating the Privy\u00a0App<\/h4>\n<p>To begin with let\u2019s connect to <a href=\"https:\/\/www.privy.io\/\">privy.io<\/a> and create our Privy\u00a0app.<\/p>\n<p>In the \u201cLogin Methods\u201d section, we can configure user authentication. We can allow users to log in via email, SMS, or external\u00a0wallets.<\/p>\n<p>We can also allow our user to log in with socials, by configuring the social of interest in the socials\u00a0panel:<\/p>\n<p>In the section \u201cEmbedded wallets\u201d &#8211; \u201cSmart wallets\u201d we can configure the settings related to the smart\u00a0account.<\/p>\n<p>In the section \u201cEnable smart wallets for your app\u201d I have chosen LightAccount but you can choose any of the options presented:<\/p>\n<p>In the section \u201cConfigure chain\u201d we can configure the chain, the bundler and paymaster URLs:<\/p>\n<p>I have chosen Base Sepolia as the blockchain, and for the bundler and paymaster URLs, I used the API key generated with Pimlico. Pimlico will sponsor the gas fees for our transactions since we\u2019re using its paymaster.<\/p>\n<h4>2- Creating the\u00a0Dapp<\/h4>\n<p>Let\u2019s start by creating a new NextJS application with:<\/p>\n<p>npx create-next-app@latest<\/p>\n<p>Let\u2019s also add the library <a href=\"https:\/\/nextui.org\/docs\/guide\/installation#:~:text=in%20your%20project%3A-,Global%20Installation,-The%20easiest%20way\">NextUI\u00a0<\/a>:<\/p>\n<p>npm install @nextui-org\/react framer-motion<\/p>\n<p>And modify the file tailwind.config.ts:<\/p>\n<p>import { nextui } from &#8220;@nextui-org\/react&#8221;;<br \/>import type { Config } from &#8220;tailwindcss&#8221;;<\/p>\n<p>const config: Config = {<br \/>  content: [<br \/>    &#8220;.\/pages\/**\/*.{js,ts,jsx,tsx,mdx}&#8221;,<br \/>    &#8220;.\/components\/**\/*.{js,ts,jsx,tsx,mdx}&#8221;,<br \/>    &#8220;.\/app\/**\/*.{js,ts,jsx,tsx,mdx}&#8221;,<br \/>    &#8220;.\/node_modules\/@nextui-org\/theme\/dist\/**\/*.{js,ts,jsx,tsx}&#8221;,<br \/>  ],<br \/>  theme: {<br \/>    extend: {},<br \/>  },<br \/>  plugins: [nextui()],<br \/>};<br \/>export default config;<\/p>\n<p>Then we install the Privy\u00a0library:<\/p>\n<p>npm install @privy-io\/react-auth@latest<\/p>\n<p>In the root directory, create a new file called\u00a0.env.local. Inside this file, add your Privy app ID, which you can retrieve from the Privy dashboard:<\/p>\n<p>NEXT_PUBLIC_PRIVY_APP_ID=&lt;your_privy_app_id&gt;<\/p>\n<p>Create a new file called providers.tsx, where we will configure Privy:<\/p>\n<p>export default function Providers({ children }: { children: React.ReactNode }) {<br \/>  return (<br \/>    &lt;NextUIProvider&gt;<br \/>      &lt;PrivyProvider<br \/>        appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID as string}<br \/>        config={{<br \/>          appearance: {<br \/>            theme: &#8220;light&#8221;,<br \/>            accentColor: &#8220;#676FFF&#8221;,<br \/>          },<br \/>          embeddedWallets: {<br \/>            createOnLogin: &#8220;all-users&#8221;,<br \/>          },<br \/>          defaultChain: baseSepolia,<br \/>          supportedChains: [baseSepolia],<br \/>        }}<br \/>      &gt;<br \/>        &lt;SmartWalletsProvider&gt;<br \/>          &lt;main className=&#8221;h-full&#8221;&gt;{children}&lt;\/main&gt;<br \/>        &lt;\/SmartWalletsProvider&gt;<br \/>      &lt;\/PrivyProvider&gt;<br \/>    &lt;\/NextUIProvider&gt;<br \/>  );<br \/>}<\/p>\n<p>The embeddedWallet setting refers to the wallet that Privy automatically generates for the user. This is not a smart account. For instance, when a user logs in via Google, Facebook, email, or other methods, Privy creates an embedded wallet for\u00a0them.<\/p>\n<p>Wrap your application inside the template.tsx file with the Providers component:<\/p>\n<p>export default function RootLayout({<br \/>  children,<br \/>}: Readonly&lt;{<br \/>  children: React.ReactNode;<br \/>}&gt;) {<br \/>  return (<br \/>    &lt;html lang=&#8221;en&#8221;&gt;<br \/>      &lt;body className={`${raleway.className} antialiased`}&gt;<br \/>        &lt;Providers&gt;{children}&lt;\/Providers&gt;<br \/>      &lt;\/body&gt;<br \/>    &lt;\/html&gt;<br \/>  );<br \/>}<\/p>\n<p>Let\u2019s create a very simple\u00a0page:<\/p>\n<p>export default function Home() {<br \/>  const { ready, authenticated, logout, user } = usePrivy();<br \/>  const { login } = useLogin();<br \/>  const { client } = useSmartWallets();<br \/>  const [isLoadingNft, setIsLoadingNft] = useState(false);<br \/>  const [recipientNftAddress, setRecipientNftAddress] = useState(&#8220;&#8221;);<br \/>  const [errorMessageNft, setErrorMessageNft] = useState(&#8220;&#8221;);<br \/>  const [nftTx, setNftTx] = useState(&#8220;&#8221;);<\/p>\n<p>  const mintNftTransaction = async () =&gt; {<br \/>    setIsLoadingNft(true);<br \/>    setNftTx(&#8220;&#8221;);<br \/>    if (!client) {<br \/>      console.error(&#8220;No smart account client found&#8221;);<br \/>      return;<br \/>    }<\/p>\n<p>    setErrorMessageNft(&#8220;&#8221;);<\/p>\n<p>    try {<br \/>      const tx = await client.sendTransaction({<br \/>        chain: baseSepolia,<br \/>        to: ERC721_ADDRESS,<br \/>        value: BigInt(0),<br \/>        data: encodeFunctionData({<br \/>          abi: erc721Abi,<br \/>          functionName: &#8220;safeMint&#8221;,<br \/>          args: [recipientNftAddress as `0x${string}`],<br \/>        }),<br \/>      });<br \/>      console.log(&#8220;tx&#8221;, tx);<br \/>      setNftTx(tx);<br \/>    } catch (error) {<br \/>      console.error(&#8220;Transaction failed:&#8221;, error);<br \/>      setErrorMessageNft(&#8220;Transaction failed. Please try again.&#8221;);<br \/>    }<br \/>    setIsLoadingNft(false);<br \/>  };<\/p>\n<p>  const handleLogout = () =&gt; {<br \/>    \/\/ Reset all input fields<br \/>    setIsLoadingNft(false);<br \/>    setRecipientNftAddress(&#8220;&#8221;);<br \/>    setErrorMessageNft(&#8220;&#8221;);<br \/>    setNftTx(&#8220;&#8221;);<\/p>\n<p>    logout();<br \/>  };<\/p>\n<p>  return (<br \/>    &lt;div className=&#8221;min-h-screen min-w-screen&#8221;&gt;<br \/>      &lt;div className=&#8221;grid grid-cols-1 lg:grid-cols-4 h-screen text-black&#8221;&gt;<br \/>        &lt;div className=&#8221; col-span-2 bg-gray-50 p-12 h-full flex flex-col lg:flex-row items-center justify-center space-y-2&#8243;&gt;<br \/>          &lt;div className=&#8221;flex flex-col justify-evenly h-full&#8221;&gt;<br \/>            &lt;div className=&#8221;flex flex-col gap-4&#8243;&gt;<br \/>              &lt;div className=&#8221;flex flex-col gap-2&#8243;&gt;&lt;\/div&gt;<br \/>              &lt;div className=&#8221;text-3xl lg:text-6xl font-black&#8221;&gt;<br \/>                Privy Tutorial<br \/>              &lt;\/div&gt;<br \/>              &lt;div className=&#8221;text-md lg:text-lg&#8221;&gt;Your Privy Tutorial App&lt;\/div&gt;<br \/>              {ready &amp;&amp; !authenticated &amp;&amp; (<br \/>                &lt;Button<br \/>                  radius=&#8221;sm&#8221;<br \/>                  color=&#8221;secondary&#8221;<br \/>                  className=&#8221;w-4 text-white&#8221;<br \/>                  onClick={() =&gt; login()}<br \/>                &gt;<br \/>                  Login<br \/>                &lt;\/Button&gt;<br \/>              )}<br \/>              {ready &amp;&amp; authenticated &amp;&amp; (<br \/>                &lt;Button<br \/>                  radius=&#8221;sm&#8221;<br \/>                  color=&#8221;danger&#8221;<br \/>                  className=&#8221;w-4&#8243;<br \/>                  onClick={handleLogout}<br \/>                &gt;<br \/>                  Logout<br \/>                &lt;\/Button&gt;<br \/>              )}<br \/>            &lt;\/div&gt;<br \/>          &lt;\/div&gt;<br \/>        &lt;\/div&gt;<br \/>        &lt;div className=&#8221;col-span-2 bg-white h-full p-12 lg:p-48 flex flex-col lg:flex-row items-center justify-center w-full space-y-4&#8243;&gt;<br \/>          {!user &amp;&amp; &lt;div className=&#8221;lg:w-1\/2&#8243;&gt;&lt;\/div&gt;}<br \/>          {user &amp;&amp; (<br \/>            &lt;div className=&#8221;lg:flex lg:flex-row justify-center w-full&#8221;&gt;<br \/>              &lt;div className=&#8221;flex flex-col gap-4 w-full&#8221;&gt;<br \/>                &lt;div className=&#8221;flex flex-col gap-2 w-full&#8221;&gt;<br \/>                  &lt;div className=&#8221;flex flex-col gap-2&#8243;&gt;<br \/>                    &lt;div className=&#8221;text-base font-semibold&#8221;&gt;Wallets&lt;\/div&gt;<br \/>                    &lt;div className=&#8221;flex items-center&#8221;&gt;<br \/>                      &lt;Input<br \/>                        size=&#8221;sm&#8221;<br \/>                        value={user.wallet?.address}<br \/>                        label=&#8221;Embedded Wallet&#8221;<br \/>                        isReadOnly<br \/>                        className=&#8221;flex-grow&#8221;<br \/>                      \/&gt;<br \/>                    &lt;\/div&gt;<br \/>                    &lt;div className=&#8221;flex items-center&#8221;&gt;<br \/>                      &lt;Input<br \/>                        size=&#8221;sm&#8221;<br \/>                        value={client?.account.address}<br \/>                        label=&#8221;Smart Wallet&#8221;<br \/>                        isReadOnly<br \/>                        className=&#8221;flex-grow&#8221;<br \/>                      \/&gt;<br \/>                    &lt;\/div&gt;<br \/>                    &lt;Divider \/&gt;<br \/>                    &lt;div className=&#8221;flex flex-col gap-2&#8243;&gt;<br \/>                      &lt;div className=&#8221;text-base font-semibold&#8221;&gt;Mint NFT&lt;\/div&gt;<br \/>                      &lt;div className=&#8221;flex items-center&#8221;&gt;<br \/>                        &lt;Input<br \/>                          size=&#8221;sm&#8221;<br \/>                          value={recipientNftAddress}<br \/>                          onChange={(e) =&gt;<br \/>                            setRecipientNftAddress(e.target.value)<br \/>                          }<br \/>                          placeholder=&#8221;Enter recipient address&#8221;<br \/>                          label=&#8221;Recipient Address&#8221;<br \/>                        \/&gt;<br \/>                      &lt;\/div&gt;<br \/>                      &lt;Button<br \/>                        radius=&#8221;sm&#8221;<br \/>                        color=&#8221;secondary&#8221;<br \/>                        className=&#8221;w-1\/5&#8243;<br \/>                        onClick={() =&gt; mintNftTransaction()}<br \/>                        isLoading={isLoadingNft}<br \/>                        isDisabled={!recipientNftAddress}<br \/>                      &gt;<br \/>                        Mint NFT<br \/>                      &lt;\/Button&gt;<br \/>                      {errorMessageNft &amp;&amp; (<br \/>                        &lt;div className=&#8221;text-red-500 text-xs text-center mt-1&#8243;&gt;<br \/>                          {errorMessageNft}<br \/>                        &lt;\/div&gt;<br \/>                      )}<br \/>                      {nftTx &amp;&amp; (<br \/>                        &lt;div className=&#8221;flex flex-col&#8221;&gt;<br \/>                          &lt;div className=&#8221;flex items-center&#8221;&gt;<br \/>                            &lt;Input<br \/>                              size=&#8221;sm&#8221;<br \/>                              value={nftTx}<br \/>                              label=&#8221;NFT Minting Transaction&#8221;<br \/>                              isReadOnly<br \/>                              className=&#8221;flex-grow&#8221;<br \/>                            \/&gt;<br \/>                          &lt;\/div&gt;<br \/>                        &lt;\/div&gt;<br \/>                      )}<br \/>                    &lt;\/div&gt;<br \/>                  &lt;\/div&gt;<br \/>                &lt;\/div&gt;<br \/>              &lt;\/div&gt;<br \/>            &lt;\/div&gt;<br \/>          )}<br \/>        &lt;\/div&gt;<br \/>      &lt;\/div&gt;<br \/>    &lt;\/div&gt;<br \/>  );<br \/>}<\/p>\n<p>At the start the applications is very simple with just a Login Button to log in the user by means of\u00a0Privy:<\/p>\n<p>As the user has logged in the applican looks like\u00a0this:<\/p>\n<p>In particular in the right hand side we\u00a0have:<\/p>\n<p>We have different input\u00a0fields:<\/p>\n<p><strong>Embedded Wallet<\/strong>: This is the wallet generated by Privy during\u00a0login.<strong>Smart Wallet<\/strong>: This refers to the smart account created using account abstraction, with gas fees sponsored by the Pimlico paymaster.<\/p>\n<p>Next, we have a \u201cMint NFT\u201d section, which we\u2019ll use to test the smart\u00a0account.<\/p>\n<h4>3 Test the smart\u00a0account<\/h4>\n<p>In the previous panel we have a button \u201cMint NFT\u201d that sends a transaction from the smart account to an ERC 721 deployed on Base Sepolia at the address 0x515F9a95c2d21fDe738CE65f7025C3BC79c7239A:<\/p>\n<p>\/\/ SPDX-License-Identifier: MIT<br \/>\/\/ Compatible with OpenZeppelin Contracts ^5.0.0<br \/>pragma solidity ^0.8.26;<\/p>\n<p>import &#8220;@openzeppelin\/contracts\/token\/ERC721\/ERC721.sol&#8221;;<br \/>import &#8220;@openzeppelin\/contracts\/token\/ERC721\/extensions\/ERC721Enumerable.sol&#8221;;<\/p>\n<p>contract MyNFT is ERC721, ERC721Enumerable {<br \/>    uint256 private _nextTokenId;<\/p>\n<p>    constructor()<br \/>        ERC721(&#8220;MyNFT&#8221;, &#8220;NFT&#8221;)<br \/>    {}<\/p>\n<p>    function safeMint(address to) public {<br \/>        uint256 tokenId = _nextTokenId++;<br \/>        _safeMint(to, tokenId);<br \/>    }<\/p>\n<p>    \/\/ The following functions are overrides required by Solidity.<\/p>\n<p>    function _update(address to, uint256 tokenId, address auth)<br \/>        internal<br \/>        override(ERC721, ERC721Enumerable)<br \/>        returns (address)<br \/>    {<br \/>        return super._update(to, tokenId, auth);<br \/>    }<\/p>\n<p>    function _increaseBalance(address account, uint128 value)<br \/>        internal<br \/>        override(ERC721, ERC721Enumerable)<br \/>    {<br \/>        super._increaseBalance(account, value);<br \/>    }<\/p>\n<p>    function supportsInterface(bytes4 interfaceId)<br \/>        public<br \/>        view<br \/>        override(ERC721, ERC721Enumerable)<br \/>        returns (bool)<br \/>    {<br \/>        return super.supportsInterface(interfaceId);<br \/>    }<br \/>}<\/p>\n<p>If we add the recipient address and press the \u201cMint NFT\u201d button, it will be created an user operation from the smart account that will allow us to mint a new NFT from the ERC721 contract and the Pimlico paymaster will sponsor the gas\u00a0fees.<\/p>\n<p>As we press the button \u201cMint NFT\u201d a new transaction will be created and the transaction hash will be showed on the\u00a0screen:<\/p>\n<p>We can also check the transaction on Sepolia Basescan\u00a0<a href=\"https:\/\/sepolia.basescan.org\/tx\/0x3207b8c6d739112a993e115a25312618d2bd65ab89d3206b061141bf1d5bb1a7\">here<\/a>.<\/p>\n<h3>Conclusions<\/h3>\n<p>In this article, we explored how Privy enables our dapp to implement account abstraction, simplifying the complexities behind it. Privy proves to be a valuable tool for easing user onboarding and bridging the gap between Web3 and Web2 applications. Adding this library to your dapp can significantly enhance the user experience.<\/p>\n<h3>Code Repository<\/h3>\n<p><a href=\"https:\/\/github.com\/RosarioB\/privy_tutorial\">https:\/\/github.com\/RosarioB\/privy_tutorial<\/a><\/p>\n<h3>References<\/h3>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=PZ8svp68NXM\">What is Account Abstraction? ERC-4337<\/a><a href=\"https:\/\/www.youtube.com\/watch?v=ZMaHhOFvYXk&amp;list=PLMj8NvODurfE9yPZ2beXSjuEgVtVcY1a6&amp;index=4\">A Deep Dive into ERC\u00a04337<\/a><a href=\"https:\/\/docs.privy.io\/\">Privy Doc<\/a><\/p>\n<p><a href=\"https:\/\/medium.com\/coinmonks\/streamline-dapp-access-implementing-account-abstraction-erc-4337-with-privy-5680fd547934\">Streamline Dapp Access: Implementing Account Abstraction ERC-4337 with Privy<\/a> was originally published in <a href=\"https:\/\/medium.com\/coinmonks\">Coinmonks<\/a> on Medium, where people are continuing the conversation by highlighting and responding to this story.<\/p>","protected":false},"excerpt":{"rendered":"<p>One of the biggest challenges in Web3 today is improving user experience. Traditionally, users are required to have a crypto wallet, manage gas fees, and sign their own transactions to interact with decentralized applications (dapps). This complex process often creates friction for users unfamiliar with blockchain. However, ERC-4337 account abstraction changes the game by making [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-13619","post","type-post","status-publish","format-standard","hentry","category-interesting"],"_links":{"self":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts\/13619"}],"collection":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=13619"}],"version-history":[{"count":0,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts\/13619\/revisions"}],"wp:attachment":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=13619"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=13619"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=13619"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}