Project prerequisites
To follow along with this guide, you’ll need two things:- A Magic Publishable API Key
- Alchemy RPC URL
- A web client
make-scoped-magic-app
CLI tool to bootstrap a Next.js app with Magic authentication already baked into the client. You’re welcome to use your own client, but this tutorial and its accompanying code snippets assume the output of the make-scoped-magic-app
CLI as the starting point.
The make-scoped-magic-app
CLI tool is an easy way to bootstrap new projects with Magic. To get started, simply run the command below in the shell of your choice. Be sure to replace <PUBLISHABLE_API_KEY>
with the Publishable API Key from your Magic Dashboard.
.env
as NEXT_PUBLIC_MAGIC_API_KEY
and NEXT_PUBLIC_SEPOLIA_RPC
, respectively.
Install additional project dependencies
In addition to the packages included in the scaffold produced by themake-scoped-magic-app
CLI, you’ll need a number of packages related to Alchemy and their account abstraction tools. You’ll also need to install viem
for EVM-related types and transaction convenience methods. You may need a specific version of viem
to work properly with the Alchemy packages. At the time of writing, we’re using 1.16.0
.
Run the following command to install the required dependencies:
Initialize Alchemy smart contract accounts
Inside ofsrc/components
, create a directory named alchemy
. Inside that directory create a file named useAlchemyProvider.tsx
.
This file will contain a hook that will surface the Alchemy Provider to the rest of the app. It’ll also observe when users log in or out and connect and disconnect to the corresponding smart contract account accordingly. We’ll go through each of these three separately, then show the code for the entire file.
Initialize AlchemyProvider
To initialize the AlchemyProvider
, call the constructor with the following arguments:
chain
- The chain to point to. We’ll be using SepoliaentryPointAddress
- The entry point address is the ERC-4337 contract that enables account abstraction. In our case, we’ll be using the one provided by Alchemy, which you can hardcode as0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789
.rpcUrl
- The RPC URL from your Alchemy Sepolia project
Connect to smart contract account
When a user logs in with Magic, we need to associate their Magic account with a smart contract account through Alchemy. Just as Magic handles the creation of user wallets, Alchemy handles the creation of smart contract accounts associated with the wallet. You do this with theLightSmartContractAccount
from the @alchemy/aa-accounts
package. You’ll need to pass it the following:
rpcClient
- This should be the provider initialized previouslyowner
- The account owner; in this case you initialize aWalletClientSigner
using the RPC provider frommagic
chain
- The chain to use. It should be the same one used to initialize the Alchemy Provider.entryPointAddress
- The ERC-4337 contract that enables account abstraction. It should be the same one used to initialize the Alchemy Provider.factoryAddress
- The address that facilitates the creation of new wallet contracts. You can get this with thegetDefaultLightAccountFactoryAddress
helper function from@alchemy/aa-accounts
.
TypeScript
Disconnect from smart contract account
When a user logs out, you’ll need to disconnect from their smart contract account. This is as simple as callingprovider.disconnect()
and handling necessary state changes.
Completed useAlchemyProvider
code
When we put all of this together, we get the following:
TypeScript
Update UI Components
Now that the project successfully creates and connects to users’ smart contract accounts with Alchemy, we can update the UI to show the smart contract address, its balance, and enable sending transactions from the smart contract account. These changes take place in theUserInfoCard
and the SendTransactionCard
.
Update UserInfoCard
Update state items
First things first. Opensrc/components/magic/cards/UserInfoCard.tsx
and change the state declaration of balance
, setBalance
, and publicAddress
to magicBalance
, setMagicBalance
, and magicAddress
. While you’re at it, add a state declaration for scaBalance
, setScaBalance
, scaAddress
, and setScaAddress
to store the smart contract account balance and address.
TypeScript
#Update getBalance
Next, update the getBalance
function to set both balances:
TypeScript
Update balance display
Next, update the TSX for displaying the balance to show both balances:TypeScript
Update initial balances
The only remaining balance reference is to set the initial balance while loading to"..."
. This is in a short useEffect
that calls setBalance
. Update this useEffect
to set both balances:
TypeScript
Set scaAddress
TypeScript
Update address display
Now find theCardLabel
and div that displays the address and modify it to use the new naming for magicAddress
and also display the scaAddress
.
TypeScript
Update SendTransactionCard
To send a transaction from your smart contract account, you will need to initiate a transaction by calling the sendUserOperation
method on the Alchemy provider
object. This transaction requires the following arguments:
target
- The recipient’s wallet addressdata
- Data associated with the transaction. Since we’re just transferring tokens, there is no data and you should put"0x"
value
- the amount of tokens to send inwei
.
sendUserOperation
is not the User Operation Receipt, rather a proof of submission. We call the waitForUserOperationTransaction
function, which will return the User Operation Receipt once the transaction has been bundled, included in a block and executed on-chain.
In src/components/magic/cards/SendTransactionCard.tsx
, import the the provider
from useAlchemyProvider
hook and replace the code for sendTransaction
with the code below.
To transfer funds from your smart contract account, ensure you have enough test tokens to send. You can get some test Sepolia tokens here.
TypeScript
- Simple authentication with Email OTP
- Automatic smart contract account creation for first-time users
- Ability to have Magic users interact with their smart contract accounts
- Transfer funds from your smart contract account