Overview

Wallet Pregeneration allows you to create wallets for users before they set up a wallet with Para. This feature gives you control over when users claim and take ownership of their wallet. This guide will walk you through the process of creating, managing, and claiming pregenerated wallets using Para’s SDK.

Pregenerated wallets can be associated with an email address, a phone number, a Twitter or Discord username, or a custom ID of your choosing (for example, an external database ID). A Para user can attempt to claim any current pregenerated wallets in their app storage.

  • For email or phone, the user will need to have the same email address or phone number linked to their account.
  • For Discord or Twitter, the user will need to have authenticated via those services on your application with the same username.
  • For a custom ID, the ID in question cannot have been claimed by another user. After a successful claim, only the first user to claim a custom ID will thereafter be allowed to claim pregenerated wallets with that ID on your application.

Creating a Pregenerated Wallet

Before creating a wallet for a user, it’s a good practice to check if one already exists.

1

Check if a pregenerated wallet exists

const hasWallet = await para.hasPregenWallet({
  pregenIdentifier: "user@example.com",
  pregenIdentifierType: "EMAIL",
});
2

Create a pregenerated wallet if needed

if (!hasWallet) {
  const pregenWallet = await para.createPregenWallet({
    type: WalletType.EVM,
    pregenIdentifier: "user@example.com",
    pregenIdentifierType: "EMAIL",
  });
  console.log("Pregenerated Wallet ID:", pregenWallet.id);
}

The identifier doesn’t have to be an email. It can be any string specific to your application, such as a user ID. See the Method parameters above for more details.

Storing and Managing User Share

After creating a pregenerated wallet, it’s crucial to securely store the user share. This share is part of Para’s 2/2 MPC protocol and remains the application’s responsibility until the wallet is claimed.

To retrieve the user share for a pregenerated wallet, use the getUserShare method:

const userShare: string = await para.getUserShare();

You must securely store this user share in your backend, associated with the user’s identifier. If this share is lost, the wallet becomes permanently inaccessible.

Best Practices for Storing the UserShare

While temporarily managing the UserShare, it’s important that you take extra care with how you store this information. If you ever face a situation where data becomes compromised across your systems, reach out to the Para team so we can work on possible key rotation. However, keep in mind that Para does not store backups of this share in case of data loss.

To mitigate this category of risks, we’ve compiled a few best practices:

  • Encrypt UserShares in-transit and at-rest.
  • Ensure your database has backups and periodic replicas to mitigate against data deletion risks.
  • Complete a fire drill prior to going live, testing scenarios such as:
    • You are unable to access your DB
    • Your DB is deleted
    • An internal team member’s credentials are compromised

Para is happy to offer pre-launch security reviews for teams in the Growth tier or above. Let us know if you need help!

This share management is temporary - once the user claims their wallet, Para will handle the share security through the user’s authentication methods.

Using a Pregenerated Wallet

Before using a pregenerated wallet for signing operations, you must first load the user share into your Para client instance. Retrieve the UserShare from your secure storage and load it into Para using the setUserShare method:

// Load the user share you previously stored securely
await para.setUserShare(userShare);

Once the share is loaded, the wallet becomes available for signing operations, just like any other Para wallet:

// Sign a message directly
const messageBase64 = btoa("Hello, World!");
const signature = await para.signMessage({
  walletId,
  messageBase64,
});

You can perform this operation using either @getpara/server-sdk or @getpara/react-sdk/@getpara/web-sdk depending on your application architecture. The Para client that has the user share loaded is the one that can perform signing operations.

Using with Ecosystem Libraries

Once the userShare is set, your Para client functions like any standard wallet. You can now easily integrate with popular blockchain libraries to perform transactions and other operations.

For detailed integration guides with blockchain ecosystems, see:

Claiming a Pregenerated Wallet

Claiming pregenerated wallets must be done client-side with the Para Client SDK. The Server SDK does not support the key rotation operations required for wallet claiming.

Claiming transfers ownership of a pregenerated wallet to a user’s Para account. This process requires:

  1. The user must be fully authenticated with Para
  2. The wallet’s user share must be loaded into the Para client
  3. The wallet’s identifier must match the authenticated user’s identifier

Prerequisites for Claiming

1

Authenticate the user

Ensure the user has completed Para’s authentication flow and has an active session.

// User must be authenticated through Para's systems
if (!(await para.isFullyLoggedIn())) {
  // Redirect to authentication flow or show login modal
}
2

Load the wallet's user share

Since this is a client side only operation, you need to securely send the UserShare from your server to the client. Once received, load it into the Para client:

// Load the previously stored user share into the Para client
await para.setUserShare(userShare);
3

Update wallet identifier if needed

Ensure the pregenerated wallet’s identifier matches the authenticated user’s identifier:

// If you originally created the wallet with a custom identifier (like a UUID),
// update it to match the user's actual email or phone before claiming
await para.updatePregenWalletIdentifier({
  walletId,
  newPregenIdentifier: user.email,
  newPregenIdentifierType: "EMAIL",
});

Claiming the Wallet

Once prerequisites are met, you can claim the wallet:

// Claim all pregenerated wallets associated with this user
const recoverySecret = await para.claimPregenWallets();

// Or claim specific wallets by identifier
const recoverySecret = await para.claimPregenWallets({
  pregenIdentifier: user.email,
  pregenIdentifierType: "EMAIL",
});

If the userShare is already loaded into the Para client before authentication occurs, and if the pregenerated wallet’s identifier matches the authenticating user, the wallet will be automatically claimed during authentication.

Controlling When Wallets are Claimed

You have control over when users claim their pregenerated wallets:

  • Delayed Claiming: Only load the userShare and update the identifier when you’re ready for the user to claim the wallet. This allows your application to continue using the wallet on behalf of the user.

  • Immediate Claiming: If you want immediate claiming upon user authentication, load the userShare before authentication and ensure the identifiers match.

  • No Claiming: Keep using different identifiers for the wallet than the user’s actual identifier to prevent automatic claiming.

This flexibility lets you design the optimal user experience for your application.

Core Pregeneration Methods

Best Practices and Considerations

Reference Example

For complete examples demonstrating the usage of pregeneration methods, refer to our examples repository: