A demo application showcasing Dynamic Wallet-as-a-Service (WaaS) integration with TON blockchain. This example demonstrates how to create embedded TON wallets, send transactions, transfer Jettons, and generate TON Connect proofs.
- Node.js 18+
- A Dynamic account with:
- Embedded Wallets enabled with TON chain selected
- Wallet connectors configured for TON
- (Recommended) A TON Center API key to avoid rate limiting (HTTP 429 errors)
npm installCreate a .env.local file in the root directory:
# Required: Your Dynamic environment ID
NEXT_PUBLIC_DYNAMIC_ENVIRONMENT_ID=your-environment-id
# Optional: Custom Dynamic API base URL
# NEXT_PUBLIC_DYNAMIC_API_BASE_URL=https://app.dynamic.xyz/api/v0
# Recommended: TON Center RPC with API key
# NEXT_PUBLIC_TON_RPC_URL=https://toncenter.com/api/v2/jsonRPC?api_key=YOUR_API_KEYNote: Without a TON Center API key, you may encounter HTTP 429 rate limit errors. Get a free API key via the @tonapibot Telegram bot. Once obtained, configure it in:
- Dynamic Dashboard — Add it to your TON chain configuration in the Chains & Networks settings
- Environment variable — Set
NEXT_PUBLIC_TON_RPC_URLabove for balance fetching in this app
npm run devOpen http://localhost:3000 in your browser.
The Dynamic SDK is configured with TON wallet connectors in providers.tsx:
import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core';
import { TonWalletConnectors } from '@dynamic-labs/ton';
<DynamicContextProvider
settings={{
environmentId: process.env.NEXT_PUBLIC_DYNAMIC_ENVIRONMENT_ID!,
walletConnectors: [TonWalletConnectors],
}}
>
{children}
</DynamicContextProvider>import { useDynamicWaas } from '@dynamic-labs/sdk-react-core';
import { ChainEnum } from '@dynamic-labs/sdk-api-core';
const { createWalletAccount } = useDynamicWaas();
await createWalletAccount([ChainEnum.Ton]);import { isTonWallet } from '@dynamic-labs/ton';
if (isTonWallet(primaryWallet)) {
const txHash = await primaryWallet.sendBalance({
amount: '0.1',
toAddress: 'UQ...',
});
}if (isTonWallet(primaryWallet)) {
const txHash = await primaryWallet.sendJetton({
jettonMasterAddress: 'EQ...', // Jetton contract address
recipientAddress: 'UQ...',
jettonAmount: BigInt(1000000), // Amount in smallest units
forwardTonAmount: BigInt(50000000), // 0.05 TON for gas
forwardPayload: 'optional memo',
});
}if (isTonWallet(primaryWallet)) {
const proof = await primaryWallet.generateTonConnectProof('your-challenge-payload');
// Send proof to your backend for verification
}MIT