Skip to main content
You are viewing docs for the previous version of the Wallets SDK. We recommend upgrading to V1. See the updated version of this page or the V1 migration guide.
Authorize transactions directly from a server environment using a Crossmint API key, and a secret provided by you. Signing happens entirely in-process with no external network call, making this the lowest-latency option available. Because this key lives as a secret in your infrastructure, enforcing regular rotations is recommended — for example, quarterly — to limit exposure in the event of a compromised environment, a departed employee, or an infrastructure incident. For a conceptual overview, see Server signer in the Wallet Signers guide. To learn how to register additional operational signers on an existing wallet, see Registering a signer.

Configuration

1

Generate a Signer Secret

You must generate a signer secret to ensure that no one — including Crossmint — can access or control your wallet. This secret:
  1. Must be either 64 hex characters (case-insensitive) or use the prefixed format xmsk1_<64-hex-chars>.
  2. Remains on your server and is never transmitted to Crossmint. The SDK derives a private/public keypair from it locally and uses public-key infrastructure (PKI) for authorization — only the public key is ever shared.
Generate and store this secret securely. This secret can grant full signing authority over the wallet.
Generate a secret using the tool below or programmatically, and store it as the CROSSMINT_SIGNER_SECRET environment variable on your server:
CROSSMINT_SIGNER_SECRET="xmsk1_<your-64-hex-character-secret>"
# OR
CROSSMINT_SIGNER_SECRET="<your-64-hex-character-secret>"

# EXAMPLE
CROSSMINT_SIGNER_SECRET="b62b473b3ba7d3d72bf7c3a397f1eb61c305a4193ce670dd056686c13d95bbaa"
The Crossmint SDK automatically derives chain-specific signing keys from this secret, scoped to your project ID, environment, and target chain. A single secret can be safely reused across chains within a project.
2

Create a Wallet with a Server Signer

Pass type: "server" as the signer type when creating a wallet. The SDK handles key derivation and address resolution automatically.
import { CrossmintWallets, createCrossmint } from "@crossmint/wallets-sdk";

const crossmint = createCrossmint({
    apiKey: "<your-server-api-key>",
});
const crossmintWallets = CrossmintWallets.from(crossmint);

const wallet = await crossmintWallets.createWallet({
    chain: "base-sepolia",
    signer: {
        type: "server",
        secret: process.env.CROSSMINT_SIGNER_SECRET,
    },
    alias: "my-server-wallet"
});
The alias parameter lets you retrieve the wallet later without storing the wallet address:
const wallet = await crossmintWallets.getWallet(
    "evm:alias:my-server-wallet",
    { signer: { type: "server", secret: process.env.CROSSMINT_SIGNER_SECRET } }
);

HKDF-SHA256 Key Derivation Tool

Use this tool to generate a master signer secret for your server-side or agent wallet environment. The secret is generated entirely in your browser — nothing is transmitted to any server.

Generate Your Own Key Programmatically

You can also generate a signer secret programmatically:
import { randomBytes } from "crypto";

function generateSignerSecret(): string {
  const bytes = randomBytes(32);
  const hex = bytes.toString("hex");
  return `xmsk1_${hex}`;
}

const secret = generateSignerSecret();
console.log(`CROSSMINT_SIGNER_SECRET="${secret}"`);

Under the Hood

A server signer is, at its core, a secret that gets deterministically mapped into a private key compatible with the underlying blockchain network. You provide a master secret, and the Crossmint SDK derives chain-specific signing keys from it — so a single secret works across all supported chains within a project.

How Key Derivation Works

A 32-byte (256-bit) random value serves as your master secret. The SDK derives chain-specific private keys from this master secret using HKDF-SHA256, scoped to your project ID, environment, and target chain:
key = HKDF-SHA256(
  ikm:  <master secret>,
  salt: "crossmint",
  info: "<projectId>:<environment>:<chain>-<algorithm>"
)
The projectId and environment are extracted automatically from your server API key by the SDK — the same master secret produces entirely different signing keys per project, environment, and chain. This means a single secret can be safely reused across chains within a single project. You can derive the public address using Crossmint’s wallets SDK — see the derive-server-signer helper for reference.

How Are Server Signer Locators Derived

When referencing a server signer in API calls (for example, when submitting approvals or registering it as an operational signer), use the locator format server:<address>:
server:0x1234567890123456789012345678901234567890
The <address> is the public address derived from your signer secret for the target chain. The SDK computes this automatically when you use type: "server" — you only need the locator format when working with the REST API directly.