> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getpara.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Wallet Pregeneration

> Create and manage server-side pregenerated wallets using Para's Server SDK

export const Link = ({href, label, newTab = false}) => {
  const [isHovered, setIsHovered] = useState(false);
  return <a href={href} target={newTab ? '_blank' : '_self'} rel={newTab ? 'noopener noreferrer' : undefined} className="not-prose inline-block relative text-black font-semibold cursor-pointer border-b-0 no-underline" onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)}>
      {label}
      <span className={`absolute left-0 bottom-0 w-full rounded-sm bg-gradient-to-r from-orange-600 to-purple-600 transition-all duration-300 ${isHovered ? 'h-0.5' : 'h-px'}`} />
    </a>;
};

export const Card = ({imgUrl, title, description, href, horizontal = false, newTab = false}) => {
  const [isHovered, setIsHovered] = useState(false);
  const handleClick = e => {
    e.preventDefault();
    if (newTab) {
      window.open(href, '_blank', 'noopener,noreferrer');
    } else {
      window.location.href = href;
    }
  };
  return <div className={`not-prose relative my-2 p-[1px] rounded-xl transition-all duration-300 ${isHovered ? 'bg-gradient-to-r from-[#FF4E00] to-[#874AE3]' : 'bg-gray-200'}`} onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)}>
      <a href={href} onClick={handleClick} className={`not-prose flex ${horizontal ? 'flex-row' : 'flex-col'} font-normal h-full bg-white overflow-hidden w-full cursor-pointer rounded-[11px] no-underline`}>
        {imgUrl && <div className={`relative overflow-hidden flex-shrink-0 ${horizontal ? 'w-[30%] rounded-l-[11px]' : 'w-full'}`} onClick={e => e.stopPropagation()}>
            <img src={imgUrl} alt={title} className="w-full h-full object-cover pointer-events-none select-none" draggable="false" />
            <div className="absolute inset-0 pointer-events-none" />
          </div>}
        <div className={`flex-grow px-6 py-5 ${horizontal ? 'w-[70%]' : 'w-full'} flex flex-col ${horizontal && imgUrl ? 'justify-center' : 'justify-start'}`}>
          {title && <h2 className="font-semibold text-base text-gray-800 m-0">{title}</h2>}
          {description && <div className={`font-normal text-gray-500 re leading-6 ${horizontal || !imgUrl ? 'mt-0' : 'mt-1'}`}>
              <p className="m-0 text-xs">{description}</p>
            </div>}
        </div>
      </a>
    </div>;
};

Pregenerated wallets are a powerful feature of Para that enable server-side wallet creation without requiring user authentication. This approach allows your application to perform blockchain operations autonomously, making it ideal for agent-based systems, automated workflows, and backend services.

The pregeneration flow works by creating a wallet associated with an identifier of your choice (email, phone, username, or custom ID). Para then provides you with the user share of the 2/2 MPC key, which you must securely store on your server until it's either claimed by a user or used for signing operations.

## Key Benefits

* **Authentication-free operations**: Create and use wallets without requiring user authentication
* **Autonomous agents**: Provide blockchain capabilities to AI agents or automated systems
* **User pre-provisioning**: Create wallets for existing user bases before they interact with your application
* **Server-side signing**: Perform blockchain operations entirely from your backend

## Creating a Pregenerated Wallet

<CodeGroup>
  ```typescript Node.js theme={null}
  import { Para as ParaServer } from "@getpara/server-sdk";

  const paraServer = new ParaServer("YOUR_API_KEY");
  const pregenId = { email: "user@example.com" };

  const hasWallet = await paraServer.hasPregenWallet({
    pregenId,
  });

  if (!hasWallet) {
    await paraServer.createPregenWallet({
      type: "EVM",
      pregenId,
    });
  }
  ```

  ```typescript Bun theme={null}
  import { Para as ParaServer } from "@getpara/server-sdk";

  const paraServer = new ParaServer("YOUR_API_KEY", { 
    disableWebSockets: true 
  });
  const pregenId = { email: "user@example.com" };

  const hasWallet = await paraServer.hasPregenWallet({
    pregenId,
  });

  if (!hasWallet) {
    await paraServer.createPregenWallet({
      type: "EVM",
      pregenId,
    });
  }
  ```

  ```typescript Deno theme={null}
  import { Para as ParaServer, WalletType } from "@getpara/server-sdk";

  const paraServer = new ParaServer("YOUR_API_KEY", { 
    disableWebSockets: true 
  });
  const pregenId = { email: "user@example.com" };

  const hasWallet = await paraServer.hasPregenWallet({
    pregenId,
  });

  if (!hasWallet) {
    await paraServer.createPregenWallet({
      type: WalletType.EVM,
      pregenId,
    });
  }
  ```
</CodeGroup>

### Method Parameters

<ResponseField name="createPregenWallet Args" type="object">
  <Expandable title="properties">
    <ResponseField name="type" type="TWalletType" required>
      The type of wallet to create (`'EVM'`, `'SOLANA'`, `'COSMOS'`, or `'STELLAR'`).
    </ResponseField>

    <ResponseField name="pregenId" type="PregenAuth" required>
      The identifier for the new wallet. The `pregenId` must be an object of the form:

      ```typescript theme={null}
      | { email: string; }
      | { phone: `+${number}`; }
      | { farcasterUsername: string; }
      | { telegramUserId: string; }
      | { discordUsername: string; }
      | { xUsername: string; }
      | { customId: string; }
      ```
    </ResponseField>
  </Expandable>
</ResponseField>

<Note>
  The identifier can be an email or phone number, a third-party user ID (for Farcaster, Telegram, Discord, or X), or a custom ID relevant to your application. Choose an identifier that works best for your application architecture.
</Note>

## Securing the User Share

After creating a pregenerated wallet, you must securely store the user share. This component is critical for the wallet's operation and security.

```typescript theme={null}
const userShare = await paraServer.getUserShare();
const encryptedUserShare = await encryptUserShare(userShare);
await database.pregenWallets.save({
  walletId,
  encryptedUserShare,
});
```

<Warning>
  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.
</Warning>

### Secure Storage Best Practices

We strongly recommend implementing robust encryption for user shares both in transit and at rest. Consider using a high-entropy encryption key with AES-GCM encryption. Do not store encryption keys in the same database as the encrypted data.

<Check>
  Para offers pre-launch security reviews for teams in the Growth tier or above. Reach out to the Para team for assistance with your implementation!
</Check>

### Storage Security Recommendations

* **Encrypt** user shares in-transit and at-rest
* Implement **access controls** for your share database
* Maintain regular **database backups** to prevent data loss
* Create **disaster recovery** processes for compromise scenarios
* Have a **key rotation** plan in case of security incidents
* Complete **security fire drills** before launching

## Using a Pregenerated Wallet

To use a pregenerated wallet for blockchain operations, you need to:

1. Retrieve the encrypted user share from your database
2. Decrypt the user share
3. Load it into your Para client instance

```typescript theme={null}
const encryptedUserShare = await database.getUserShare(walletId);
const userShare = decryptUserShare(encryptedUserShare);

await paraServer.setUserShare(userShare);
```

<Warning>
  When implementing `setUserShare` in API routes or serverless functions, it's critical to create a new Para client instance for each request. This prevents different users' shares from conflicting with each other. Creating a new Para client has minimal overhead and won't impact request performance.
</Warning>

### Signing Operations

Once the user share is loaded, you can test the wallet functionality by signing a message. However, for production use, we recommend using the blockchain library integrations described in the next section.

```typescript theme={null}
const messageBase64 = Buffer.from("Hello, World!").toString('base64');
const signature = await paraServer.signMessage({
  walletId,
  messageBase64,
});
```

### Using with Blockchain Libraries

Pregenerated wallets work seamlessly with all blockchain integration libraries. Here are some examples:

<CardGroup cols={3}>
  <Card title="EVM Integration" imgUrl="/images/v2/network-evm.png" href="/v2/server/guides/evm" description="Use pregenerated wallets with Ethers.js and other EVM libraries" />

  <Card title="Solana Integration" imgUrl="/images/v2/network-solana.png" href="/v2/server/guides/solana" description="Sign Solana transactions with pregenerated wallets" />

  <Card title="Cosmos Integration" imgUrl="/images/v2/network-cosmos.png" href="/v2/server/guides/cosmos" description="Interact with Cosmos chains using pregenerated wallets" />

  <Card title="Stellar Integration" imgUrl="/images/v2/network-stellar.png" href="/v2/server/guides/stellar" description="Sign Stellar transactions with pregenerated wallets" />
</CardGroup>

## Wallet Claiming Flow

<Warning>
  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.
</Warning>

For applications that need to transfer ownership of pregenerated wallets to users, implement a client-side claiming flow.
Your backend still prepares the stored user share for the authenticating identifier before the client receives it.

1. Look up the stored pregenerated wallet from the authenticating identifier
2. Decrypt and load the stored user share into a fresh server-side Para client
3. Update the pregenerated wallet identifier if it was created with a custom ID
4. Return the updated user share to the client
5. Let the client SDK load the share and claim the wallet

```typescript theme={null}
import { Para as ParaServer } from "@getpara/server-sdk";

export async function preparePregenClaim(email: string) {
  const wallet = await getPregenWalletByEmail(email);
  const para = new ParaServer(process.env.PARA_API_KEY!);
  const userShare = await decryptUserShare(wallet.encryptedUserShare);

  await para.setUserShare(userShare);
  await para.updatePregenWalletIdentifier({
    walletId: wallet.walletId,
    newPregenId: { email },
  });

  return {
    userShare: await para.getUserShare(),
  };
}
```

<Info>
  Calling `setUserShare` before `updatePregenWalletIdentifier` lets the server SDK update the wallet metadata in the
  loaded share. Return that updated share to the client so the loaded wallet identifier matches the user's auth
  identifier during claim.
</Info>

For a comprehensive guide on implementing the claiming flow, refer to our web documentation:

<Card title="Client-Side Wallet Claiming" imgUrl="/images/v2/feature-pregeneration.png" href="/v2/react/guides/pregen" description="Complete guide to implementing the client-side claiming flow for pregenerated wallets" horizontal />

## Core Pregeneration Methods

<Expandable title="Server SDK Pregeneration Methods">
  <ResponseField name="createPregenWallet" type="function">
    Create a new pregenerated wallet for an identifier
  </ResponseField>

  <ResponseField name="hasPregenWallet" type="function">
    Check if a pregenerated wallet exists for an identifier
  </ResponseField>

  <ResponseField name="getPregenWallets" type="function">
    Retrieve pregenerated wallets for a given identifier
  </ResponseField>

  <ResponseField name="getUserShare" type="function">
    Get the user share that must be securely stored
  </ResponseField>

  <ResponseField name="setUserShare" type="function">
    Load a previously stored user share
  </ResponseField>

  <ResponseField name="updatePregenWalletIdentifier" type="function">
    Update the identifier of a pregenerated wallet
  </ResponseField>
</Expandable>

## Use Cases

<AccordionGroup>
  <Accordion title="AI Agents">
    Pregenerated wallets enable autonomous AI agents to perform blockchain operations. For example, an AI trading agent could analyze market conditions and execute trades using its own wallet, without requiring human intervention or authentication.
  </Accordion>

  <Accordion title="Automated Workflows">
    Create automation systems that perform recurring blockchain operations on predetermined schedules. For instance, a DeFi yield harvesting service could automatically collect and reinvest yields at optimal times using pregenerated wallets.
  </Accordion>

  <Accordion title="User Pre-provisioning">
    Create wallets for your existing user base before they engage with blockchain features. When users are ready to interact with these features, they can claim ownership of their pregenerated wallet through a seamless onboarding process.
  </Accordion>

  <Accordion title="Background Services">
    Build backend services that perform blockchain operations on behalf of users or systems. For example, a gas fee management service could optimize transaction timing based on network conditions without requiring user input.
  </Accordion>

  <Accordion title="Cross-platform Systems">
    Maintain consistent wallet identities across different platforms by using the same pregenerated wallets. This allows users to have a unified experience regardless of which platform they're using to access your service.
  </Accordion>
</AccordionGroup>

## Best Practices

* **Choose appropriate identifiers** that align with your application architecture
* **Implement robust encryption** for user share storage
* **Create backup systems** to prevent data loss
* **Use a separate database** for user share storage with enhanced security
* **Monitor for suspicious activity** in your pregenerated wallet systems
* **Implement rate-limiting** to prevent abuse of wallet creation
* **Document your recovery procedures** for security incidents
* **Consider multi-region replication** for high-availability systems

## Example Implementation

Here's a reference example demonstrating the creation and secure storage of pregenerated wallets:

<Card title="Server-Side Pregeneration Example" imgUrl="/images/v2/feature-pregeneration.png" href="https://github.com/getpara/examples-hub/blob/2.0.0/server/with-node/src/routes/createWallet.ts" description="Complete example of creating and securely storing pregenerated wallets on a server" horizontal />

## Community Showcase

Check out some novel use cases of pregenerated wallets created by our community:

<Card horizontal title="Awesome Para" imgUrl="/images/v2/awesome-para.png" href="https://github.com/getpara/awesome-para" description="Explore community-contributed examples, libraries, and integrations" />
