Web3 Dev Tutorial: thirdweb lets users connect without a Wallet!
my web3 app header, with a typical "Connect" button

Web3 Dev Tutorial: thirdweb lets users connect without a Wallet!

In this article I will walk through my simple example using thirdweb 's tools for Account Abstraction. There are 5 sections of information:

  1. User flow to connect to the blockchain app without a wallet
  2. High level overview of Account Abstraction
  3. Setup required to use thirdweb's toolkit
  4. A look at my example code
  5. Final thoughts/conclusions


Simple User Flow - A Big Idea

The big idea with Account Abstraction is to allow anyone to use blockchain applications without needing to understand blockchain.

Consider the header in the picture at the top of this article. There is a simple "Connect" button, with a prompt to "connect with an email address or Google account." Very few users would be intimidated by a "Connect" button. The label could be changed to say "Login" if preferred.

The point is that any web user can proceed without any blockchain knowledge.

Three Connecting Options for No-Wallet Users

Clicking on "Connect" will bring up the following modal, with 3 connection options:

Article content

If the user presses the "Sign in with Google" button, the app will connect using the email associated with the Google account. If the user is already logged into Google from their browser, there will not be a "verification step" and the user will be connected to the blockchain straight away. BOOM!

If the user enters an email address instead, the following verification modal will pop:

Article content

Within a few seconds, the user will receive an email with a 6-digit code to enter into this modal. When entered, the connection is made to the blockchain. This flow is still very straight-forward.

If the user clicks "Continue as Guest" the following popup displays:

Article content

The user now enters a password to create a completely anonymous guest wallet, which will be tied to the browser on their device. Future connects as Guest will use the same guest wallet by entering the same password. A user can choose to create a new guest wallet on the device, but only after exporting the existing guest wallet (as a json file). An exported wallet can be imported again later with the same password.

Wait! Did he say "export a wallet?" Run away!!!

I did not try the export/import feature. I don't like this option as well. It uses the word "wallet" and indicates that you may need to export and import a wallet for this app. Not what blockchain-illiterate users want to see!! This could send them running for the hills! (I am pretty sure I saw that this guest access can be deactivated. I hope so.)

On the other hand, this method does provide a convenient way for a single user to access the application without needing to provide any other personal account information. A big plus for the privacy conscious among us.

After Connecting

After successful connection, my example app shows the following modified Header:

Article content

Notice that the "Connect" button changed to "Disconnect". The information on the page also changed, to inform the user that they are connected to the blockchain. Once connected with Google or email, if you close the browser and later navigate back to this page, it will automatically reconnect with the same account.

For my example, I coded the Disconnect button as an option to fully disconnect, meaning the next time the user navigates to the site, it will not auto-reconnect. As soon as the Disconnect button is pressed, the header and info section revert back to the original state as shown at the top of this article.

Note that without the separate Disconnect button, the thirdweb button changes to show the first and last characters of the user's created wallet address, and clicking the button while connected will bring up a typical crypto wallet interface. This is not what I wanted, since this App is targeting blockchain-illiterate Web2 users. Another option would be to simply hide the button while connected, but that would remove any option to disconnect.

User Flow Summary

As you can see above, the user does not need a Web3 wallet or any blockchain knowledge to use this app. The application connects to the Mumbai testnet blockchain, and allows blockchain transactions to be performed by the app in the background. There is no need for the user to pay crypto transaction fees with this setup. (The gas fees would be covered by the application owner's funds provided to thirdweb.)

In this way, a developer can create a decentralized Web3 application for any user with a web browser. Open the Web3 onboarding floodgates!!!


High Level Process

How do these "no wallet" connections work anyways? After all, a blockchain requires a blockchain account to own and pay for any transactions, and the wallet is the user's interface to their blockchain account. Understanding a little about the process components will help us understand the setup required to use thirdweb's tools.

Two Types of Accounts

The solution to abstracting the blockchain away from the user is defined in the Ethereum ERC-4337 proposal. The details are beyond the scope of this article, but at a high level we can understand that there are 2 types of blockchain accounts: externally-owned accounts (EOA's) and smart contract accounts.

Smart contract accounts are associated with the "programs" that run on blockchains. EOA accounts are the ones owned by individuals who use the apps and smart contracts. All transactions on the blockchain must be paid for by an EOA.

In order to make it so our users do not have to directly manage an EOA, we can use thirdweb's toolkit to create an EOA for them inside our app (this is called an embedded wallet). Then a smart contract is created to act like a wallet (known as a smart wallet) for the EOA account. This is all done in a way that only allows the wallet to be accessed from the user's device, with the user's credentials.

Four Required Services

In order to execute transactions (called UserOperations) that come from this combination of an EOA and smart contract (and which are paid for by a different "sponsor" EOA account), we need some new services in place.

  • The bundler: a process that prepares and adds UserOperations into a block for the blockchain.
  • The aggregator: a helper smart contract which can correctly and securely sign the transactions.
  • The paymaster: a service that manages the transaction payments that are made on behalf of the users' accounts.
  • An account factory: a smart contract which creates smart wallets as-needed for the users of our app.

The first 3 are services provided by thirdweb which can support many applications. The account factory contract is created by a developer on their thirdweb account, which allows each developer to manage their own users' wallet creation process.


Setup on thirdweb

Setting up a development environment with thirdweb is easy and free, and this application requires creating only 2 items there.

To begin, simply connect to their website with a wallet (you can use MetaMask, Coinbase Wallet, and others). I would advise to use a new wallet account that you will only use for thirdweb development purposes.

Create an API Key

To use thirdweb's services you will need an API Key. You can create one from the "Settings" tab.

Article content

Make sure it is enabled for the following: Smart Wallets, Embedded Wallets, RPC, and Storage. Record your private key in a safe place. You will use the Client ID in your application code to authenticate to thirdweb's services.

Deploy an Account Factory

Next, you will need to deploy an Account Factory contract for your application. It is strongly suggested to deploy on a test network first! (Deploying on a public network requires adding a method of payment to your thirdweb account.)

Deploy your account factory from the "Contracts" tab. This example uses the Mumbai testnet.

Article content

Simply click on "Deploy contract" and choose the Account Factory option.

Once you have an Account Factory, you will need to include the contract address in your application code. (More on that below.)

After users have connected to your application, you can see their smart wallets by clicking on your AccountFactory link in the Contracts tab, and then selecting "Accounts" on the left side menu:

Article content

To see the EOA accounts that thirdweb creates for your users, you can click on the "Wallets" tab, and then select the "Embedded Wallets" option on the left:

Article content

The address of all the EOA accounts are displayed with the date they were created and last used. If the accounts were created using an email address or Google account, the associated email is also shown. (This is a point to be covered by your application's Privacy Policy, assuming you are required to have one.)


Example Code

Hint: there is a link to this example's GitHub repo at the end of the article!

Time to walk through the code for my Connect-Disconnect application.

Here is the application structure.

Article content

This is a pretty standard folder structure for React apps. The main project folder is called connect-disconnect and the application code is all within the src/ sub-folder. To allow everything to work, you should define 3 values in your .env file.

REACT_APP_CLIENT_ID="paste your Client ID here"
REACT_APP_ACCOUNT_FACTORY="paste your address here"

GENERATE_SOURCEMAP=false        

The first 2 are your thirdweb Client ID and Account Factory address, which we discussed in the previous section. The third setting prevents a bunch of console warnings when launching the app, and was recommended online somewhere.

You need to include the thirdweb and supporting packages as shown below.

  "dependencies": {
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "@thirdweb-dev/react": "^4.0.7",
    "@thirdweb-dev/sdk": "^4.0.6",
    "bootstrap": "^5.3.2",
    "ethers": "^5.7.2",
    "react": "^18.2.0",
    "react-bootstrap": "^2.9.0",
    "react-dom": "^18.2.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4",
    "url": "latest",
    "http": "npm:http-browserify",
    "https": "npm:https-browserify",
    "zlib": "npm:browserify-zlib",
    "http-browserify": "latest",
    "https-browserify": "latest",
    "browserify-zlib": "latest",
    "assert": "^2.0.0",
    "stream": "^0.0.2"
  },        

It's always best to install packages via your package manager as documented on the thirdweb site, as opposed to copy-pasting mine above.

index.js

The key to allowing your application to use the thirdweb Connection modals is to wrap your React app inside the ThirdwebProvider element. This is done in your top-level index.js file, shown below:

Article content
index.js code

Notice how the <ThirdwebProvider> tag encloses the <App /> tag. This is required, and makes all the thirdweb items available to your app. Note how your Account Factory and Client ID are used in the definition of the ThirdwebProvider and specifically the smartWallet options. The 2 wallet options (localWallet and embeddedWallet) are the Smart Wallet and Embedded Wallet that I described in the High Level Process section. (NOTE: it is possible to define additional connection options here, like MetaMask or other popular wallets. These could be used by blockchain-savvy users.)

App.js

Let's look at our React app's top-level component next, App.js.

Article content
App.js component code

Note at lines 3-7 we import 3 React hooks from the thirdweb react library:

  • useConnectionStatus() returns a status of the connection of any user wallet to our application. Possible values are "undefined", "connecting", "connected" and "disconnected". This hook is called at line 24.
  • useAddress() returns the address of the smart wallet that is currently connected to our application. It is used on line 27.
  • useContract() is not used in this example. It is a hook that can get any smart contract from the blockchain for our application to interact with. (Hint: my next example uses this!)

Lines 29 - 41 above are important! This logic ensures that the connected wallet address is stored correctly at all times in the React State (in the walletAddress state variable). Whenever a user presses the Disconnect button, this state variable gets set back to null.

The rest of our App.js code is the display render portion:

Article content
More App.js component code

Our main application component renders 2 other components, the Navigation component which contains the connect/disconnect button, and the purple Header component which displays the instruction text to the user.

Note that both of these components take the walletAddress state variable as input. They will use it to determine what to display.

Navigation.js

Below is all the code it takes to display the navigation bar with a logo, title, and the fully functioning connect/disconnect button.

Article content
Navigation.js component code

The first thing to note is that we import 2 thirdweb items at line 4.

  • ConnectWallet is the thirdweb Connect button which provides the pop-up for a user to connect. The exact button functionality is already defined by our ThirdwebProvider code in the index.js file. Note that here on the display side (lines 8 and 40), I was able to add my own logo to the pop-up modal!
  • useDisconnect is another React hook, which provides the routine that disconnects from a smart wallet (if one is connected). This disconnect routine is acquired at line 11, and used at line 30 as the function to call when our Disconnect button is clicked.

Line 26 checks to see if a wallet address exists. If so, it will render our Disconnect button, which is a react-bootstrap library button (imported at line 2). If the wallet address does not exist (is null) the component will instead display the thirdweb ConnectWallet modal to allow the user to connect.

Header.js

The last code to look at is our Header component, shown below.

Article content
Header.js component code

This code simply renders a title for the header, and then displays some information that is different based on whether we have a connected wallet address or not. If a wallet is connected, it displays a message that you are connected, and instructions on how to disconnect. If not, it displays a message that you need to connect.

This is a simple example, but in a real application, you could use the same type of logic to determine that the user has not connected a wallet, and hide any of your application functionality that writes data to the blockchain. (Transactions that are read-only do not cost gas, and thus can be executed without a connected wallet, if so desired.)


Final Thoughts

Account Abstraction opens the door to the full Web2 user base for blockchain apps, and thirdweb has a really good set of tools for Web3 developers to enable this new reach.

As a developer who has been learning blockchain programming for over a year now, using the thirdweb Account Abstraction tools was not quite "brain-dead simple" but it really was pretty easy.

The amount of functionality you get out-of-the-box with their smart wallet connector is pretty impressive. The modal has a light or dark theme, and there is a larger version than the "compact" size I chose. You can also create a fully custom wallet for your application with their SDK, should you need that.

The price plans for using thirdweb's services seem reasonable, and developers should be able to support a lot of transactions before growing out of the free tier. Enough to do a lot of learning at the least!

There is a LOT of online documentation available on thirdweb's site, but it can be difficult to wade through and find the explanation you need. The tools are developing quickly, and some of the documents I found were old or not applicable to what I was trying to use. I think this was the most challenging part for me.

TIP: join the thirdweb Discord and post your questions in the Support channel!! They respond reasonably fast, and are very helpful!

Next Steps

I am already making good progress on the next version of this ... an application that connects to a custom smart contract and allows any user to interact in a way that changes the state of data on the blockchain. So stay tuned for more!

If you want to look at this whole project, or clone it to run locally yourself, you can find it here on my GitHub.

Cheers!

Great article! It's nice how you explained the concept along with a working example.

To view or add a comment, sign in

More articles by Scott Weberg

  • Hey! Who's Tools Are These??

    When you advance from chatting and vibe-coding to building autonomous agent workflows, your problems go from…

  • My AI Agent Told Me Not to Use AI!

    Me: "Vic, I just set your model to arguably the best model in the world." Vic: "Appreciated, Scott.

  • Down the Agentic AI Rabbit Hole

    AI for the public began as a really smart chatbot ..

  • Team-Level Innovation

    I have had the privilege to lead several technology engineering teams in my career, and I think it is really important…

  • Fun Web3 Example Application!

    In this article I will provide an overview (both use and code) of my completed Web3 application, Best Pet Poll. The…

  • Web3 Developers: Easy to Add a Privacy Policy with thirdweb Connect

    (NOTE: in my last article, I described how to code the thirdweb smart wallet connection referenced here.) I am…

  • 5 Ways React Wrecks Novices

    (A tongue-in-cheek rant from a C/C++ backend guy learning React for Web3.) I believe those who invented React (and…

    2 Comments
  • "DYOR" Prevents Embarrassment

    I was reminded again today of the importance of that common phrase in crypto-space, do your own research or DYOR for…

  • Ertha - a Massive Game & Metaverse

    UPDATE, April 2025 The Ertha team has shelved the release of the PC game, and is focused on a mobile / web app version…

  • Despite the Hype the Metaverse Will Be a While Yet

    The Metaverse hype is real, but waning. I have a unique perspective on the cycle of innovation in technology, having…

    1 Comment

Others also viewed

Explore content categories