Skip to main content

Overview

This guide walks you through creating TON wallets using Dynamic’s Node SDK. You’ll learn how to set up different threshold signature schemes and understand the security implications for TON blockchain operations.

Prerequisites

Before you begin, make sure you have:

Step 1: Choose Your Security Model

Dynamic supports three threshold signature schemes for TON wallets:
  • Security: Highest - requires both your server and Dynamic’s infrastructure
  • Availability: Lower - both parties must be online
  • Use case: High-value transactions, maximum security

TWO_OF_THREE

  • Security: High - requires 2 out of 3 shares
  • Availability: Medium - can tolerate one party being offline
  • Use case: Balanced security and availability

THREE_OF_FIVE

  • Security: High - requires 3 out of 5 shares
  • Availability: Highest - can tolerate two parties being offline
  • Use case: Maximum fault tolerance and availability

Step 2: Create Your First TON Wallet

Here’s a complete example of creating a TON wallet:
import { DynamicTonWalletClient } from '@dynamic-labs-wallet/node-ton';
import { ThresholdSignatureScheme } from '@dynamic-labs-wallet/node';

// Create authenticated client
export const authenticatedTonClient = async () => {
  const client = new DynamicTonWalletClient({
    environmentId: process.env.DYNAMIC_ENVIRONMENT_ID!,
  });

  await client.authenticateApiToken(process.env.DYNAMIC_AUTH_TOKEN!);
  return client;
};

export const createTonWallet = async ({
  thresholdSignatureScheme = ThresholdSignatureScheme.TWO_OF_TWO,
  password,
  onError
}: {
  thresholdSignatureScheme?: ThresholdSignatureScheme;
  password?: string;
  onError?: (error: Error) => void;
}) => {
  const tonClient = await authenticatedTonClient();

  const wallet = await tonClient.createWalletAccount({
    thresholdSignatureScheme,
    password,
    onError,
    backUpToClientShareService: true,
  });

  return {
    accountAddress: wallet.accountAddress,
    rawPublicKey: wallet.rawPublicKey,
    walletId: wallet.walletId,
    externalServerKeyShares: wallet.externalServerKeyShares,
  };
};

// Usage example
const wallet = await createTonWallet({
  thresholdSignatureScheme: ThresholdSignatureScheme.TWO_OF_TWO,
  password: 'your-secure-password',
  onError: (error: Error) => {
    console.error('TON wallet creation error:', error);
  },
});

console.log('TON wallet created:', wallet.accountAddress);
console.log('External server key shares:', wallet.externalServerKeyShares);

Step 3: Handle Errors Gracefully

Always implement proper error handling for TON wallet creation:
try {
  const wallet = await createTonWallet({
    thresholdSignatureScheme: ThresholdSignatureScheme.TWO_OF_TWO,
    onError: (error: Error) => {
      console.error('Wallet creation error:', error);
    },
  });
  console.log('TON wallet created successfully:', wallet.accountAddress);
} catch (error) {
  if (error.message.includes('invalid session')) {
    console.error('Invalid session ID - please re-authenticate');
  } else {
    console.error('TON wallet creation failed:', error.message);
  }
}

Step 4: Store Wallet Information Securely

After creating a TON wallet, you’ll receive important information that should be stored securely:
const wallet = await tonClient.createWalletAccount({
  thresholdSignatureScheme: ThresholdSignatureScheme.TWO_OF_TWO,
  backUpToClientShareService: true,
});

// Store these securely in your database
const walletData = {
  accountAddress: wallet.accountAddress,
  walletId: wallet.walletId,
  thresholdScheme: ThresholdSignatureScheme.TWO_OF_TWO,
  chainName: 'TON',
  createdAt: new Date().toISOString(),
  externalServerKeyShares: wallet.externalServerKeyShares,
};

// Never store externalServerKeyShares in plain text
// They should be encrypted and stored securely

Step 5: Derive the TON Address

You can also derive the TON address from a public key using deriveTonAddress(). This is a synchronous method:
const address = tonClient.deriveTonAddress({
  publicKeyHex: wallet.rawPublicKey,
  workchain: 0, // 0 = basechain (default)
});

console.log('Derived TON address:', address); // e.g. EQD...

Best Practices

  1. Password Security: Use strong, unique passwords for each TON wallet
  2. Error Handling: Always handle potential errors during wallet creation with the onError callback
  3. Monitoring: Log wallet creation events for audit purposes
  4. Backup Strategy: Implement secure backup strategies for key shares with backUpToClientShareService: true

TON-Specific Considerations

Workchain

TON organizes accounts into workchains. Most user wallets live on workchain 0 (basechain). The masterchain (-1) is used for system contracts.

Address Format

TON wallet addresses are user-friendly base64url strings (e.g., EQD... for non-bounceable). The SDK derives these using WalletContractV5R1.

Nanotons

TON uses nanotons as the smallest unit: 1 TON = 1,000,000,000 nanotons.

Next Steps

Now that you’ve created a TON wallet, you can: