Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/tkhq/sdk/llms.txt

Use this file to discover all available pages before exploring further.

Turnkey wallets are HD (hierarchical deterministic) wallets whose private key material is generated and stored inside Turnkey’s secure enclaves. You never hold the raw key — you request signatures through the API.
Never store private key material directly in your application or database. Turnkey’s export flow exists for cases where users need to take custody of their keys, but it should not be part of normal application operation.

Creating a wallet

Wallets are created as part of sub-organization creation, or explicitly via the API after login. The createSuborg server action creates a sub-organization with a default wallet that includes one Ethereum and one Solana account:
server/wallets.ts
import { server } from "@turnkey/sdk-server";

const result = await server.createSuborg({
  email: "user@example.com",
});
// result.subOrganizationId is the user's org ID
You can also create additional wallets for an existing user via the Turnkey server client:
server/wallets.ts
import { Turnkey, DEFAULT_ETHEREUM_ACCOUNTS, DEFAULT_SOLANA_ACCOUNTS } from "@turnkey/sdk-server";

const turnkey = new Turnkey({
  apiBaseUrl: "https://api.turnkey.com",
  apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY!,
  apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY!,
  defaultOrganizationId: process.env.TURNKEY_ORGANIZATION_ID!,
});

const result = await turnkey.apiClient().createWallet({
  organizationId: userSuborgId,
  walletName: "Savings wallet",
  accounts: [
    ...DEFAULT_ETHEREUM_ACCOUNTS,
    ...DEFAULT_SOLANA_ACCOUNTS,
  ],
});

Address derivation per blockchain

Turnkey uses BIP-32 HD derivation paths. The @turnkey/sdk-server package exports pre-built account configurations for every supported chain.

Ethereum

import { DEFAULT_ETHEREUM_ACCOUNTS, defaultEthereumAccountAtIndex } from "@turnkey/sdk-server";

// Default: m/44'/60'/0'/0/0
console.log(DEFAULT_ETHEREUM_ACCOUNTS);
// [
//   {
//     curve: "CURVE_SECP256K1",
//     pathFormat: "PATH_FORMAT_BIP32",
//     path: "m/44'/60'/0'/0/0",
//     addressFormat: "ADDRESS_FORMAT_ETHEREUM",
//   }
// ]

// Derive additional accounts
const account2 = defaultEthereumAccountAtIndex(1); // m/44'/60'/1'/0/0

Solana

import { DEFAULT_SOLANA_ACCOUNTS, defaultSolanaAccountAtIndex } from "@turnkey/sdk-server";

// Default: m/44'/501'/0'/0'
console.log(DEFAULT_SOLANA_ACCOUNTS);
// [
//   {
//     curve: "CURVE_ED25519",
//     pathFormat: "PATH_FORMAT_BIP32",
//     path: "m/44'/501'/0'/0'",
//     addressFormat: "ADDRESS_FORMAT_SOLANA",
//   }
// ]

const account2 = defaultSolanaAccountAtIndex(1); // m/44'/501'/1'/0'

Other chains

@turnkey/sdk-server exports default accounts for every supported chain:
ImportChain
DEFAULT_ETHEREUM_ACCOUNTSEthereum (EVM)
DEFAULT_SOLANA_ACCOUNTSSolana
DEFAULT_COSMOS_ACCOUNTSCosmos
DEFAULT_SUI_ACCOUNTSSui
DEFAULT_APTOS_ACCOUNTSAptos
DEFAULT_XLM_ACCOUNTSStellar
DEFAULT_BITCOIN_MAINNET_P2WPKH_ACCOUNTSBitcoin mainnet (native SegWit)
DEFAULT_BITCOIN_MAINNET_P2TR_ACCOUNTSBitcoin mainnet (Taproot)
DEFAULT_TON_V4R2_ACCOUNTSTON

Getting wallet accounts and addresses

After login, the useTurnkey hook provides the wallets array which contains all wallets and their accounts:
components/WalletDisplay.tsx
"use client";

import { useTurnkey } from "@turnkey/react-wallet-kit";

export function WalletDisplay() {
  const { wallets } = useTurnkey();

  return (
    <ul>
      {wallets.map((wallet) => (
        <li key={wallet.walletId}>
          <strong>{wallet.walletName}</strong>
          <ul>
            {wallet.accounts?.map((account) => (
              <li key={account.address}>
                {account.addressFormat}: {account.address}
              </li>
            ))}
          </ul>
        </li>
      ))}
    </ul>
  );
}
To refresh the wallet list after creating a new wallet, call refreshWallets:
const { refreshWallets } = useTurnkey();
await refreshWallets();

Signing transactions

Turnkey provides ecosystem-specific signer packages that integrate with popular libraries.
Install @turnkey/ethers and connect it to a TurnkeyServerClient:
terminal
npm install @turnkey/ethers ethers
sign/ethers.ts
import { TurnkeySigner } from "@turnkey/ethers";
import { ethers } from "ethers";
import { TurnkeyServerClient } from "@turnkey/sdk-server";

const client = new TurnkeyServerClient({
  stamper: myStamper,
  apiBaseUrl: "https://api.turnkey.com",
  organizationId: userSuborgId,
});

const signer = new TurnkeySigner({
  client,
  organizationId: userSuborgId,
  signWith: walletAddress,
});

// Connect to a provider
const connectedSigner = signer.connect(
  new ethers.JsonRpcProvider("https://mainnet.infura.io/v3/YOUR_KEY")
);

// Sign and send a transaction
const tx = await connectedSigner.sendTransaction({
  to: "0xRecipientAddress",
  value: ethers.parseEther("0.01"),
});

Importing and exporting wallets

Turnkey provides secure import and export flows backed by encrypted iframe-based communication. Private key material is never visible to your application code.

Export a wallet

components/ExportWallet.tsx
"use client";

import { useTurnkey } from "@turnkey/react-wallet-kit";

export function ExportWalletButton({ walletId }: { walletId: string }) {
  const { handleExportWallet } = useTurnkey();

  return (
    <button onClick={() => handleExportWallet({ walletId })}>
      Export wallet
    </button>
  );
}

Import a wallet

components/ImportWallet.tsx
"use client";

import { useTurnkey } from "@turnkey/react-wallet-kit";

export function ImportWalletButton() {
  const { handleImportWallet } = useTurnkey();

  async function onImport() {
    const newWalletId = await handleImportWallet({
      walletName: "Imported wallet",
      successPageDuration: 2000,
    });
    console.log("Imported wallet ID:", newWalletId);
  }

  return <button onClick={onImport}>Import wallet</button>;
}

Multi-wallet setup

A single user (sub-organization) can hold multiple wallets. Create additional wallets by calling createWallet on the API client:
server/wallets.ts
import { Turnkey, DEFAULT_ETHEREUM_ACCOUNTS } from "@turnkey/sdk-server";

const turnkey = new Turnkey({
  apiBaseUrl: "https://api.turnkey.com",
  apiPublicKey: process.env.TURNKEY_API_PUBLIC_KEY!,
  apiPrivateKey: process.env.TURNKEY_API_PRIVATE_KEY!,
  defaultOrganizationId: process.env.TURNKEY_ORGANIZATION_ID!,
});

// Create a second wallet for the same user
const result = await turnkey.apiClient().createWallet({
  organizationId: userSuborgId,
  walletName: "DeFi wallet",
  accounts: DEFAULT_ETHEREUM_ACCOUNTS,
});

console.log("New wallet ID:", result.walletId);
After creating a new wallet, call refreshWallets() in the client to update the provider state.