TON Connect SDK

repository·main·Indexed 19 days ago

https://github.com/ton-connect/sdk

An implementation of the TonConnect protocol that enables Dapps to connect to TON wallets for blockchain interactions. The SDK provides tools ranging from low-level protocol models (@tonconnect/protocol) to high-level React UI components, along with isomorphic utilities for fetch and EventSource to ensure cross-environment compatibility between browsers and NodeJS.

Tokens
32K
Snippets
102
Records
145
Agent score
67%

What's inside ton-connect-sdk

  1. Choose the right TON Connect package for your project

    main

    Depending on your application type, choose one of the following packages to integrate TON wallet connectivity:

    • For Dapps (General): Use @tonconnect/sdk to connect your app to TON wallets via the TonConnect protocol.
    • For Dapps (UI-based): Use @tonconnect/ui or @tonconnect/ui-react to quickly add pre-built UI elements like 'connect wallet' buttons and selection dialogs.
    • For Wallet Apps: Use @tonconnect/protocol to access protocol requests, responses, event models, and encoding/decoding functions required to implement the protocol within a wallet.
  2. How @tonconnect/isomorphic-fetch works

    main

    The package works by polyfilling the global environment in NodeJS:

    1. In NodeJS: When imported, it assigns fetch (from the node-fetch package) to the global variable.
    2. In Browser: If the bundler produces a browser-compatible build, the package exports an empty script, relying on the browser's native fetch implementation.

    Important Limitation: This package does not provide a fetch polyfill for browsers that do not support fetch natively.

  3. Understand TMA Debug testing scenarios

    main

    The tool allows testing of different library loading orders to ensure compatibility. Use these scenarios to verify your integration:

    ScenarioDescription
    TC OnlyNo TMA libraries, only TON Connect
    TWA → TCtelegram-web-app.js loads before TON Connect
    TC → TWATON Connect loads before telegram-web-app.js
    SDK → TC@telegram-apps/sdk inits before TON Connect
    TC → SDKTON Connect loads before @telegram-apps/sdk
  4. Understand Network Identifiers and the CHAIN enum

    main

    The protocol uses network identifiers to ensure operations target the correct network.

    • CHAIN enum: Provides predefined TON network IDs:
      • MAINNET = '-239'
      • TESTNET = '-3'
    • ChainId type: This is defined as CHAIN | string, allowing you to use the predefined enum values or any custom network identifier string. This enables support for custom networks without protocol changes.

    ChainId is used in several contexts:

    1. Establishing connections: Via the TonAddressItem.network field.
    2. Transaction/Data operations: Via the SignDataPayload.network field to indicate the network context for signing or sending.
  5. Sign and relay a message (gasless) with `signMessage`

    main

    Use signMessage to ask a wallet to sign an internal message without broadcasting it. This is used for gasless or sponsored transactions where a dApp or relayer submits the signed BoC to the network (e.g., paying gas in Jettons instead of TON).

    Key Differences from sendTransaction:

    • Broadcasting: signMessage does NOT broadcast; sendTransaction DOES.
    • Gas: signMessage does NOT deduct gas from the user's wallet; sendTransaction DOES.
    • Result: signMessage returns an internalBoc (the signed message) which you must then wrap in an external message and submit via a relayer.

    Implementation Note: To ensure users only see wallets that support this feature, initialize TonConnectUI with walletsRequiredFeatures: { signMessage: { minMessages: 1 } }.

    const result = await tonConnectUI.signMessage({
        validUntil: Math.floor(Date.now() / 1000) + 300,
        network: '-239',
        messages: [
            {
                address: 'Ef8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAU',
                amount: '5000000',
                payload: bodyBoc, // base64
                stateInit: initBoc // base64
            }
        ]
    });
    
    const signedBoc = result.internalBoc; // base64 signed internal message
    // Now submit signedBoc to a relayer (e.g., TonAPI gasless API)
  6. Handle the Public Manifest Requirement for TON Connect

    main

    TON Connect requires the app manifest to be publicly accessible via HTTPS. You cannot use localhost, 127.0.0.1, or private IPs directly in manifest links or the manifestUrl provided to the SDK. All URLs within the manifest (such as url and icons) must also be publicly accessible over the internet.

    ❌ Not allowed:

    • Using http://localhost:3000 for url or icons.
    • Using local paths or proxies like ngrok for the manifest itself in standard app-to-wallet communication.

    ✅ Allowed:

    • Hosting the manifest and all its assets on a public domain or static host like GitHub Pages, Vercel, or Netlify.
  7. Connect to a wallet

    main

    Connecting a user involves different strategies depending on the wallet type:

    1. Remote Wallets (Universal Link): Pass a source containing universalLink and bridgeUrl. The SDK returns a link that you must present to the user (e.g., via QR code or deep link).
    2. Injected Wallets: Pass a source containing the jsBridgeKey.
    3. Unified Link: Pass an array of sources to connector.connect(sources) to allow the SDK to handle multiple potential connection methods.
    4. Embedded Wallets: If the app is running inside a wallet's browser, detect it using isWalletInfoCurrentlyEmbedded and connect immediately using the jsBridgeKey to improve UX.
    // 1. Remote connection
    const source = {
        universalLink: 'https://app.tonkeeper.com/ton-connect',
        bridgeUrl: 'https://bridge.tonapi.io/bridge'
    };
    const link = connector.connect(source);
    
    // 2. Injected connection
    connector.connect({ jsBridgeKey: 'tonkeeper' });
    
    // 3. Unified connection
    connector.connect([
        { bridgeUrl: 'https://bridge.tonapi.io/bridge' },
        { bridgeUrl: 'https://<OTHER_WALLET_BRIDGE>' }
    ]);
  8. Configure UI preferences (Border Radius, Theme, and Colors)

    main

    Use uiPreferences within uiOptions to adjust the visual style of the interface.

    Border Radius

    Supported modes are 'm' (default), 's', and 'none'. You can set this in the TonConnectUI constructor or dynamically via uiOptions.

    Theme

    Set the theme to THEME.LIGHT, THEME.DARK, or 'SYSTEM' (default). Import THEME from @tonconnect/ui.

    Color Schemes

    You can redefine colors for specific themes using colorsSet. This allows you to target [THEME.DARK] and [THEME.LIGHT] independently.

    import { THEME } from '@tonconnect/ui';
    
    // Set theme and border radius
    tonConnectUI.uiOptions = {
        uiPreferences: {
            theme: THEME.DARK,
            borderRadius: 's',
            colorsSet: {
                [THEME.DARK]: {
                    connectButton: {
                        background: '#29CC6A'
                    }
                },
                [THEME.LIGHT]: {
                    text: {
                        primary: '#FF0000'
                    }
                }
            }
        }
    };
  9. Publish a version using changesets

    main

    The project uses changesets to manage package versions and changelogs.

    For a standard release:

    1. Run pnpm changeset add and select the modified packages. Choose the version type (MAJOR, MINOR, or PATCH) and write the changelog.
    2. Run pnpm changeset version to update package.json and CHANGELOG.md across all affected packages.
    3. Build the packages: pnpm build.
    4. Publish the packages: pnpm publish -r --access=public.
    5. Push changes and tags: git push origin HEAD && git push origin --tags.

    For a beta release:

    1. Enter beta mode: pnpm changeset pre enter beta.
    2. Follow the standard release steps (add changeset, version, build).
    3. Publish with the beta tag: cd packages/[package-name] && pnpm publish --access=public --tag=beta.
    4. Exit beta mode: pnpm changeset pre exit.
    5. Push changes and tags.
    # Example: Adding a changeset
    pnpm changeset add
    
    # Example: Applying version updates
    pnpm changeset version
    
    # Example: Publishing all updated packages
    pnpm publish -r --access=public
  10. Integrate TON Connect UI into a standard Dapp

    main
    For non-React applications or projects requiring custom UI implementation, use @tonconnect/ui. It provides a UI kit including 'connect wallet' buttons, 'select wallet' dialogs, and confirmation modals to simplify the integration process.
  11. Configure `skipRedirectToWallet` for iOS compatibility

    main

    On iOS, universal links opened via window.open may fail to redirect to the wallet app if there is an asynchronous delay between the user's click and the redirect. To manage this, use the skipRedirectToWallet option.

    Options

    • 'ios' (default): Optimized for iOS behavior.
    • 'never': Use this if your click handler performs no asynchronous calls before calling sendTransaction. This provides the best UX by allowing a synchronous redirect.
    • 'always': Always skip the automatic redirect.

    Usage

    You can set this per-call or globally via uiOptions.

    // Per-call configuration
    const result = await tonConnectUI.sendTransaction(defaultTx, {
        modals: ['before', 'success', 'error'],
        notifications: ['before', 'success', 'error'],
        skipRedirectToWallet: 'ios' // 'ios', 'never', or 'always'
    });
    
    // Global configuration via uiOptions
    tonConnectUI.uiOptions = {
        actionsConfiguration: {
            skipRedirectToWallet: 'ios'
        }
    };
    
    // Best practice: use 'never' if the handler is synchronous
    const onClick = async () => {
        const txBody = packTxBodySynchrone();
        tonConnectUI.sendTransaction(txBody, { skipRedirectToWallet: 'never' });
        // ...
    };