Skip to main content

Overview

This comprehensive example demonstrates all available functions in the Dynamic TON SDK, showing the actual API usage patterns and how to handle common operations.

Complete Example Code

// Import statements
import { DynamicTonWalletClient } from "@dynamic-labs-wallet/node-ton";
import { beginCell, toNano } from "@ton/ton";
import { ThresholdSignatureScheme } from "@dynamic-labs-wallet/node";
import fs from "fs";

// Initialize TON 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;
};

// Example usage demonstrating all available functions
async function main() {
  try {
    console.log("🚀 Starting TON Client Demo...\n");

    // Initialize the TON client
    const tonClient = await authenticatedTonClient();
    console.log("✅ TON client authenticated successfully\n");

    // 1. Create a new TON wallet
    console.log("📝 Creating new TON wallet...");
    const tonWallet = await tonClient.createWalletAccount({
      thresholdSignatureScheme: ThresholdSignatureScheme.TWO_OF_TWO,
      onError: (error: Error) => {
        console.error("❌ TON wallet creation error:", error);
      },
      backUpToClientShareService: true,
    });

    console.log("✅ TON wallet created:", tonWallet.accountAddress);
    console.log("externalServerKeyShares:", tonWallet.externalServerKeyShares);
    console.log("rawPublicKey:", tonWallet.rawPublicKey);

    // Save wallet info to file
    fs.writeFileSync("tonWallet.json", JSON.stringify(tonWallet, null, 2));
    console.log("💾 Wallet saved to tonWallet.json\n");

    // 2. Derive TON address from public key (synchronous)
    console.log("🔍 Deriving TON address...");
    try {
      const address = tonClient.deriveTonAddress({
        publicKeyHex: tonWallet.rawPublicKey,
        workchain: 0,
      });
      console.log("✅ Derived address:", address);
    } catch (error) {
      console.log("⚠️ Could not derive address:", error);
    }

    // 3. Get wallet information
    console.log("\n🔍 Getting wallet details...");
    try {
      const walletDetails = await tonClient.getWallet({
        accountAddress: tonWallet.accountAddress,
      });
      console.log("✅ Wallet details retrieved:", walletDetails);
    } catch (error) {
      console.log("⚠️ Could not retrieve wallet details:", error);
    }

    // 4. Get all TON wallets
    console.log("\n📋 Getting all TON wallets...");
    try {
      const allWallets = await tonClient.getTonWallets();
      console.log("✅ Found", allWallets.length, "TON wallets");
    } catch (error) {
      console.log("⚠️ Could not retrieve all wallets:", error);
    }

    // 5. Sign a message
    console.log("\n✍️ Signing a message...");
    try {
      const message = "Hello, TON! This is a test message from Dynamic TON wallet.";
      const signedMessage = await tonClient.signMessage({
        accountAddress: tonWallet.accountAddress,
        message,
      });
      console.log("✅ Message signed successfully (base64)");
      console.log("Signature:", signedMessage);
    } catch (error) {
      console.log("⚠️ Message signing failed:", error instanceof Error ? error.message : String(error));
    }

    // 6. Sign a transaction (TON transfer example)
    console.log("\n💸 Preparing TON transaction...");
    try {
      // Build transfer body and serialize to base64 string
      const transferBody = beginCell()
        .storeUint(0, 32)
        .storeStringTail("Hello from Dynamic!")
        .endCell();
      const transactionString = transferBody.toBoc().toString("base64");

      console.log("📝 Transaction prepared, signing with TON wallet...");

      // Sign — returns base64-encoded Ed25519 signature
      const signature = await tonClient.signTransaction({
        senderAddress: tonWallet.accountAddress,
        transaction: transactionString,
      });

      console.log("✅ Transaction signed successfully");
      console.log("Signature (base64):", signature);
    } catch (error) {
      console.log("⚠️ Transaction signing failed:", error instanceof Error ? error.message : String(error));
    }

    // 7. Import private key (if you have one)
    console.log("\n🔑 Testing private key import...");
    try {
      const importedWallet = await tonClient.importPrivateKey({
        privateKey: "your-private-key-here", // Replace with actual private key
        chainName: "TON",
        thresholdSignatureScheme: ThresholdSignatureScheme.TWO_OF_TWO,
        backUpToClientShareService: true,
        password: "test-password",
      });
      console.log("✅ Private key imported:", importedWallet.accountAddress);
    } catch (error) {
      console.log("ℹ️ Private key import skipped (no valid key provided)");
    }

    // 8. Export key information
    console.log("\n📤 Exporting key information...");
    try {
      const exportedKey = await tonClient.exportKey({
        accountAddress: tonWallet.accountAddress,
        chainName: "TON",
      });
      console.log("✅ Key exported:", exportedKey);
    } catch (error) {
      console.log("ℹ️ Key export not available or requires additional setup");
    }

    // 9. Offline export private key from key shares
    console.log("\n🔓 Offline exporting private key...");
    try {
      if (tonWallet.externalServerKeyShares) {
        const { derivedPrivateKey } = await tonClient.offlineExportPrivateKey({
          keyShares: tonWallet.externalServerKeyShares,
        });
        console.log("✅ Private key exported offline (hex):", derivedPrivateKey);
      }
    } catch (error) {
      console.log("ℹ️ Offline export not available or requires additional setup");
    }

    // 10. Test connection to TON network
    console.log("\n🌐 Testing TON network connection...");
    try {
      const response = await fetch(
        `https://toncenter.com/api/v2/getAddressBalance?address=${tonWallet.accountAddress}`
      );
      const data = await response.json();
      const balanceNanotons = BigInt(data.result ?? "0");
      console.log("✅ TON network connection successful");
      console.log("Wallet balance:", balanceNanotons.toString(), "nanotons");
      console.log("Balance in TON:", Number(balanceNanotons) / 1_000_000_000);
    } catch (error) {
      console.log("ℹ️ TON network connection test skipped");
    }

    console.log("\n🎉 TON Client Demo completed successfully!");
    console.log("📁 Check tonWallet.json for wallet details");

    // Summary
    console.log("\n📊 Demo Summary:");
    console.log("✅ Successfully completed:");
    console.log(`   • Created TON wallet: ${tonWallet.accountAddress}`);
    console.log(`   • Raw public key: ${tonWallet.rawPublicKey}`);
    console.log(`   • External server key shares: ${tonWallet.externalServerKeyShares?.length || 0}`);
    console.log(`   • TON network connection: Working`);

  } catch (error) {
    console.error("❌ Error in TON demo:", error);
  }
}

// Run the example
main();

Key API Patterns

1. Wallet Creation

const wallet = await tonClient.createWalletAccount({
  thresholdSignatureScheme: ThresholdSignatureScheme.TWO_OF_TWO,
  onError: (error: Error) => {
    console.error("Wallet creation error:", error);
  },
  backUpToClientShareService: true,
});

2. Message Signing

const signature = await tonClient.signMessage({
  message: "Hello, TON!",
  accountAddress: wallet.accountAddress,
});
// Returns base64-encoded Ed25519 signature

3. Transaction Signing

import { beginCell, toNano } from "@ton/ton";

// Serialize your cell to base64 before signing
const transferBody = beginCell()
  .storeUint(0, 32)
  .storeStringTail("Hello!")
  .endCell();

const signature = await tonClient.signTransaction({
  senderAddress: wallet.accountAddress,
  transaction: transferBody.toBoc().toString("base64"),
});
// Returns base64-encoded Ed25519 signature

4. Derive TON Address

// Synchronous — no await needed
const address = tonClient.deriveTonAddress({
  publicKeyHex: wallet.rawPublicKey,
  workchain: 0,
});

5. Wallet Retrieval

const walletDetails = await tonClient.getWallet({
  accountAddress: wallet.accountAddress,
});

6. Getting All Wallets

const allWallets = await tonClient.getTonWallets();

Available Functions

The TON SDK provides the following main functions:
  • createWalletAccount() - Create new TON wallet
  • importPrivateKey() - Import existing private key
  • getWallet() - Get specific wallet details
  • getTonWallets() - Get all TON wallets
  • deriveTonAddress() - Derive TON address from a public key hex
  • signMessage() - Sign messages (Ed25519, base64 output)
  • signTransaction() - Sign TON transactions (returns signed BOC)
  • exportKey() - Export wallet key data
  • offlineExportPrivateKey() - Export private key from key shares offline

Error Handling

Always implement proper error handling:
try {
  const result = await tonClient.someFunction(params);
  console.log("Operation successful:", result);
} catch (error) {
  console.error("Operation failed:", error instanceof Error ? error.message : String(error));
}

Environment Setup

Make sure you have these environment variables:
DYNAMIC_AUTH_TOKEN=your_auth_token_here
DYNAMIC_ENVIRONMENT_ID=your_environment_id_here

Dependencies

Install required packages:
bun add @dynamic-labs-wallet/node-ton @ton/ton @ton/crypto @dynamic-labs-wallet/node

Next Steps