How to create browser wallet authentication

Authorize transactions with a browser wallet.

Overview

FunWallet is the core class of the FunKit SDK. It enables you to execute any transaction on an EVM chain and provides a straightforward method for implementing robust authentication schemes. In this guide, I will show you how to create a FunWallet that uses Metamask as an authenticator.

Import required objects

We have to import three objects in order to create a FunWallet.

  1. FunWallet to create the object.

  2. configureEnvironment to set up the environment for a FunWallet.

  3. Auth for authenticating into a FunWallet.

import { FunWallet, configureEnvironment, Auth } from "@funkit/core";

Configuring the FunWallet environment

To begin, we need to set up the environment for your FunWallet. This is usually boilerplate code, but I will show you the process so that you can make adjustments in the future.

Let me explain the environment variables that we will need to input.

  1. chain - Each FunWallet exists on an EVM-compatible blockchain, and for this guide, we will be using the Goerli testnet.

  2. gasSponsor - All wallets have to pay gas to execute transactions on a blockchain and FunWallets are no exception to that. But FunWallets also have the option of a gas sponsor that can cover the gas cost. For this guide, we will use a gasless sponsor that is specified by sponsorAddress.

  3. apiKey - We have provided a rate limited apiKey used strictly for demoing purposes. Please visit our dashboard to receive your own production apiKey.

It is important to note that the use of a gasSponsor is tied to your apiKey.

await configureEnvironment({
chain: "goerli",
gasSponsor: {
sponsorAddress: "0xCB5D0b4569A39C217c243a436AC3feEe5dFeb9Ad",
},
apiKey: "ZrhepzWGxm74D0sqstuhT6dGrJxhoy8SZIToX6I3",
});

Creating Auth

Now that we’ve set up the environment, we need a way to sign transactions. All authentication in FunKit is handled with the Auth object. We’ll use MetaMask as a signer and this is how we pull the interface.

const auth = new Auth({ windowEth: window.ethereum });

The browser wallet auth type encompasses all browser wallets accessible via window.ethereum, including MetaMask, Brave Wallet, etc.

Initializing FunWallet with Auth

With the Auth instance that we created in the step before, we are now able to initialize your FunWallet. Here are the FunWallet constructor parameters

  1. users - This is an User[] that holds all users that can access your FunWallet. Since we’re only using 1 private key, our User[] only has 1 instance.

  2. uniqueId - This is a random seed that is generated from our Auth instance. The purpose of this seed is the generate the address of our FunWallet.

const auth = new Auth({ windowEth: window.ethereum });
const funWallet = new FunWallet({
users: [{ userId: auth.getAddress() }],
uniqueId: auth.getWalletUniqueId(),
});

Creating FunWallet

The final step is call .create(). This will execute a transaction on the Goerli testnet (chain)to deploy your FunWallet .

const operation = await funWallet.create(auth, await auth.getAddress());
await funWallet.executeOperation(auth, operation);

Summary

Putting together all the pieces we have createWallet() that you can use to create your FunWallet. Also, I’ve put it into a React app that makes it easily reusable.

,
transfer.js
import "./App.css";
import { FunWallet, Auth, configureEnvironment } from "@funkit/core";
function App() {
const createWallet = async () => {
await configureEnvironment({
chain: "goerli",
gasSponsor: {
sponsorAddress: "0xCB5D0b4569A39C217c243a436AC3feEe5dFeb9Ad"
},
apiKey: "ZrhepzWGxm74D0sqstuhT6dGrJxhoy8SZIToX6I3"
})
const auth = new Auth({ windowEth: window.ethereum })
const funWallet = new FunWallet({
users: [{ userId: await auth.getAddress() }],
uniqueId: await auth.getWalletUniqueId()
})
const operation = await funWallet.create(auth, await auth.getAddress())
await funWallet.executeOperation(auth, operation)
}
return (
<div className="App">
<header className="App-header">
<button onClick={createWallet}>Connect Metamask</button>
</header>
</div>
);
}
export default App;

Live example