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

# Sign TON Transactions

> Learn how to sign TON transactions using Dynamic's Node SDK

## Overview

This guide shows you how to sign TON transactions using Dynamic's Node SDK. You build your transaction cell using `@ton/ton`, serialize it to a base64 string, and pass it to `signTransaction()`. The method returns a **base64-encoded Ed25519 signature** that you then attach to the cell before broadcasting.

## Prerequisites

* [Created a TON wallet](/node/ton/create-wallet)
* [Installed TON dependencies](https://github.com/ton-org/ton)

## Step 1: Install Dependencies

```bash theme={"system"}
bun add @ton/ton @ton/crypto
```

## Step 2: Build, Sign, and Send a Transaction

The approach for signing transactions depends on how you created your wallet:

### With Automatic Backup (Recommended)

If you created your wallet with `backUpToDynamic: true`, you can sign directly without retrieving key shares:

```typescript theme={"system"}
import { DynamicTonWalletClient } from '@dynamic-labs-wallet/node-ton';
import { WalletContractV5R1, internal, beginCell, toNano } from '@ton/ton';

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

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

const tonClient = await authenticatedTonClient();

// Build the transfer message body
const transferBody = beginCell()
  .storeUint(0, 32)   // op (0 = text comment)
  .storeStringTail('Hello, TON!')
  .endCell();

// Serialize to base64 string for signing
const transactionString = transferBody.toBoc().toString('base64');

// ✅ Simple signing - no externalServerKeyShares needed
// Returns a base64-encoded Ed25519 signature
const signature = await tonClient.signTransaction({
  walletMetadata,
  transaction: transactionString,
});

console.log('Signature (base64):', signature);
```

### With Manual Backup

If you created your wallet with `backUpToDynamic: false`, you must retrieve and provide external key shares:

```typescript theme={"system"}
// ⚠️ First, get external server key shares (required for manual backup)
const keyShares = await tonClient.getExternalServerKeyShares({
  walletMetadata,
});

const signature = await tonClient.signTransaction({
  walletMetadata,
  externalServerKeyShares: keyShares, // Required for manual backup!
  transaction: transactionString,
  password: 'your-password', // Only if wallet was created with password
});
```

**Password Handling Notes:**

* If your wallet was created **without a password**, omit the `password` parameter
* If your wallet was created **with a password**, you must provide it for all operations
* The password parameter is always optional in the API, but required if the wallet is password-protected

## Step 3: Broadcast the Transaction

After signing, attach the signature to the cell and broadcast via the TON HTTP API:

```typescript theme={"system"}
import { WalletContractV5R1, Cell } from '@ton/ton';

// Reconstruct the signed external message
const signatureBuffer = Buffer.from(signature, 'base64');

// Build the signed message cell
const signedCell = beginCell()
  .storeBuffer(signatureBuffer)
  .storeSlice(transferBody.beginParse())
  .endCell();

const boc = signedCell.toBoc().toString('base64');

const response = await fetch('https://toncenter.com/api/v2/sendBoc', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ boc }),
});

const result = await response.json();
console.log('Broadcast result:', result);
```

## Common Transaction Bodies

### Simple TON Transfer (no comment)

```typescript theme={"system"}
const transferBody = beginCell().endCell();
const transactionString = transferBody.toBoc().toString('base64');
```

### TON Transfer with Comment

```typescript theme={"system"}
const transferBody = beginCell()
  .storeUint(0, 32)
  .storeStringTail('Payment for services')
  .endCell();
const transactionString = transferBody.toBoc().toString('base64');
```

## Next Steps

* [Sign TON messages](/node/ton/sign-messages)
* [Import existing TON private keys](/node/ton/import-private-keys)
