Wallet Pregeneration
Wallet Pregeneration offers a streamlined and efficient way to create non-custodial wallets programmatically without requiring end users to initiate or complete an authentication flow. This feature simplifies the onboarding process, making digital ownership more accessible and straightforward for your users. This feature is currently in beta, so please reach out to Magic for early access!
Using Magic's Wallet Pregeneration, you can generate wallets that users can later claim by authenticating through your application. This approach is particularly useful for a variety of use cases, such as preloading wallets with NFTs or tokens. For instance, you might want to provide new users with initial token balances or exclusive NFTs as part of a promotion or reward system. By preloading these assets into pregenerated wallets, you can enhance user engagement and provide a smooth and rewarding onboarding experience.
This guide demonstrates how to use the Wallet Pregeneration feature. We'll cover the steps to programmatically create these wallets, preload them with Sepolia tokens and allow users to claim them with minimal friction. The examples provided are based on a Next.js web app generated using the Magic CLI tool but can be easily adapted for any JavaScript framework.
#Project prerequisites
To follow along with this guide, you’ll need the following:
- A Magic Publishable API Key
- A Magic Secret API Key (for wallet pregeneration requests)
- Early access to the feature (Reach out to Magic for this)
- A web client
You can get your Publishable and Secret API Key from your Magic Dashboard.
We’ll use the 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 generate your application, simply run the command below in the shell of your choice. Be sure to replace <YOUR_PUBLISHABLE_API_KEY>
with the Publishable API Key from your Magic Dashboard.
01npx make-scoped-magic-app \\
02 --template nextjs-dedicated-wallet \\
03 --network ethereum-sepolia \\
04 --login-methods EmailOTP \\
05 --publishable-api-key <YOUR_PUBLISHABLE_API_KEY>
This will bootstrap the starting point of the tutorial for you. In the scaffolded project, be sure to add your Magic Publishable API Key to the .env
as NEXT_PUBLIC_MAGIC_API_KEY
.
01# Publishable API Key found in the Magic Dashboard
02NEXT_PUBLIC_MAGIC_API_KEY=pk_live_1234567890
03
04# The RPC URL for the blockchain network
05NEXT_PUBLIC_BLOCKCHAIN_NETWORK=ethereum-sepolia
#Wallet pregeneration
There are 3 available endpoints related to the wallet pregeneration process. This section will guide you through using these endpoints to create, monitor, and query pregenerated wallets. By utilizing these endpoints, you can programmatically generate wallets for your users, track the status of wallet creation, and query detailed information about the generated wallets.
This approach ensures that you have full control and visibility over the wallet pregeneration process. You can use any HTTP client to send the POST requests. For this guide we will be using cURL requests. Let's take a further look into the details of each endpoint and how to use them effectively.
Each application needs to be manually enabled to use the Wallet Pregeneration feature, so reach out to Magic for early access!
#Create wallets
To create wallets tied to specific emails, we send a payload with identifiers
along with the Magic secret key to the create_wallets
endpoint.
The identifiers array contains identifier_payload
objects, which consist of 1 or multiple of the users email addresses and identifier type, which in this case is email_address
. You can pregenerate multiple wallets in a single POST request, but for the sake of this guide we will just be creating one wallet.
The first thing we need to do is send a POST request to generate the wallets and link them to the email addresses attached. The request requires the Magic secret API key as a header and the identifiers
payload as the data.
01curl --request POST \\
02 --url '<https://api.magic.link/v1/api/wallet_pregen/create_wallets>' \\
03 --header 'X-Magic-Secret-Key: <your_magic_secret_api_key>' \\
04 --header 'Content-Type: application/json' \\
05 --data '{
06 "identifiers": [
07 {
08 "identifier": "[email protected]",
09 "identifier_type": "email_address"
10 },
11 // You can add more identifier_payload objects as needed
12 ]
13 }'
Once you send the request you will receive an object back from the request containing the data, which will include a job_id
if the request was successful, error_code
, message
and status
of the request. The status will return “ok” if the request is successful.
Now that we’ve successfully generated the wallets, we can take the job_id
and check if users have claimed their wallets.
#Query job status
The get_job_status
endpoint allows you to monitor the progress and status of wallet pregeneration jobs. This is essential for ensuring that the wallets are created successfully and are ready for users to claim. By querying the job status, you can retrieve detailed information about the job, such as the number of wallets processed, any errors encountered, and the overall status of the job.
Similar to the previous POST request, we will need to add the Magic secret API key as headers and add the job_id
from the previous request as the body.
The body should look similar to this:
01{
02 "job_id": "91a5be54-61bf-4761-e89k-b7f35ace81d3"
03}
To query the job status, you can use the following cURL command. This command sends a POST request to the get_job_status
endpoint with the necessary headers and body parameters:
01curl --request POST \\
02 --url '<https://api.magic.link/v1/api/wallet_pregen/get_job_status>' \\
03 --header 'X-Magic-Secret-Key: <your_magic_secret_api_key>' \\
04 --header 'Content-Type: application/json' \\
05 --data '{
06 "job_id": "91a5be54-61bf-4761-e89k-b7f35ace81d3"
07 }'
The response from the get_job_status
endpoint provides detailed information about the wallet pregeneration job.
01{
02 "data": {
03 "client_id": "A5cJpjmJk3eQq4PXC9uJuoWESlcD3_CIwZgvDVdY0wg=",
04 "created_at": 1716331284,
05 "expires_at": 1718923161,
06 "job_id": "91a5be54-61bf-4761-e89k-b7f35ace81d3",
07 "key_generation_stats": {
08 "errors": 0,
09 "processed": 1,
10 "total": 1
11 },
12 "status": "SUCCESS",
13 "updated_at": 1716331161
14 },
15 "error_code": "",
16 "message": "",
17 "status": "ok"
18}
Here is a brief overview of the key fields in the return object:
data
: Contains the main details of the job.client_id
: A unique identifier for the client.created_at
: Timestamp of when the job was created.expires_at
: Timestamp of when the job expires.job_id
: The unique identifier for the job.key_generation_stats
: Statistics about the key generation process.errors
: Number of errors encountered.processed
: Number of wallets processed.total
: Total number of wallets to be generated.
status
: The current status of the job (e.g., SUCCESS, PENDING).updated_at
: Timestamp of the last update to the job status.
error_code
: Error code if any issues occurred (empty if no errors).message
: Additional message information (empty if no issues).status
: Overall status of the API request (e.g., "ok").
Once we confirm that the wallet(s) have been generated, we can move on to the next step and query the identifiers tied to the pregenerated wallet public addresses.
#Query wallet identifiers
The get_identifiers
endpoint allows you to retrieve detailed information about the identifiers associated with pregenerated wallets. This query is useful for checking which specific identifiers, such as email addresses, are linked to the pregenerated wallet public addresses. Additionally, you can filter the results to see which wallets have been claimed by users and set limits on the number of results returned.
We will be using this endpoint to retrieve the users wallet address so we can send it some tokens. This way, when a user logs in to the Magic application using Email OTP, they will see a balance in their wallet from the transfer.
The body for this request should contain the job_id
, along with optional parameters of claimed
and limit
.
01{
02 "job_id": "91a5be54-61bf-4761-e89k-b7f35ace81d3",
03 "claimed": false, // optional
04 "limit": 1 // optional
05}
Just like the previous requests, we should set the Magic private API key as the X-Magic-Secret-Key
header. Send the POST request with the required payload to retrieve the identifiers tied to the pregenerated wallet public addresses. This will allow you to see which identifiers are associated with each wallet and whether they have been claimed.
Here's an example of the POST request to the get_identifiers
endpoint:
01curl --request POST \\
02 --url '<https://api.magic.link/v1/api/wallet_pregen/get_identifiers>' \\
03 --header 'X-Magic-Secret-Key: <your_magic_secret_api_key>' \\
04 --header 'Content-Type: application/json' \\
05 --data '{
06 "job_id": "91a5be54-61bf-4761-e89k-b7f35ace81d3",
07 "claimed": false, // optional
08 "limit": 10 // optional
09 }'
If successful, the response will include detailed information about the identifiers associated with the pregenerated wallets. This information will indicate whether the wallets have been claimed and provide the corresponding public addresses. Here’s an example of the response you can expect:
01{
02 "data": {
03 "identifiers": [
04 {
05 "claimed": false,
06 "expires_at": 1718925889,
07 "identifier": "[email protected]",
08 "identifier_type": "email_address",
09 "job_id": "91a5be54-61bf-4761-e89k-b7f35ace81d3",
10 "public_address": "0xBAcFD5E443eFDFECb9850a9d8a23C33701E66742",
11 "status": "success",
12 "status_detail": "Successfully generated wallet"
13 }
14 ]
15 },
16 "error_code": "",
17 "message": "",
18 "status": "ok"
19}
This information allows you to effectively manage and track the pregenerated wallets, ensuring that each identifier is correctly associated with a wallet and verifying the claim status of your digital assets.
Now that we’ve got the user information, we want to copy the public_address
of the user so we can transfer it some Sepolia ETH testnet tokens.
#Fund wallet
For this guide, we will just be transferring some testnet tokens to the pregenerated wallet. However, you can also do things like airdrop NFTs, distribute loyalty points or issue event tickets to enhance user engagement and provide additional value.
You can either transfer funds from an existing wallet or use a Sepolia faucet and paste in the unclaimed wallet address from the previous step. Keep that wallet address handy, as we will want to cross reference it with the wallet address displayed in our application after logging in.
Once that transaction is successful we can move on to the next step.
#Claim wallet
The application we generated earlier has Email One-Time Passcode (OTP) enabled, which streamlines the authentication process for users. With this feature, along with our pregenerated wallets, all we need to do is log in using one of the email address that we added as the identifier payload during the wallet pregeneration process.
Run your local server and navigate to your localhost
. You will see a component for logging in with an email. Add the email that you pregenerated the wallet for and retrieve the OTP code from that email’s inbox. Back in the app, paste the code into the prompt and continue.
Congratulations! You should now see some cards displayed on the screen including one with your pregenerated wallet address and balance.
#Next steps
We have a suite of resources to help developers and companies with a wide variety of use cases. Below are some ideas to get you started, but feel free to browse our documentation or reach out with specific questions.
- Wallet Pregeneration docs
- Add support for OAuth social providers like Google, Github, and Discord
- Add support for one or more of the 25+ blockchains accessible through Magic
- Use Magic across a variety of platforms, including Web, iOS, Android, Unity, and more
- Learn more about Magic's security framework and how it can make your applications more secure
- Read Magic's Whitepaper