Skip to main content
The TonPay Button for vanilla JavaScript is a framework-agnostic solution that works with pure HTML and JavaScript. No build tools or frameworks required - just add a script tag and start accepting payments.

Installation

1

Choose your installation method

You can use the button via npm package, CDN, or by copying the files to your project.Option A: Via npm
npm install @ton-pay/ui @tonconnect/ui
Option B: Via CDN (no installation needed)
<!-- Use unpkg CDN directly in your HTML -->
<script src="https://unpkg.com/@ton-pay/ui@latest/dist/ton-pay-embed.js"></script>
Option C: Copy to your project After npm install, copy node_modules/@ton-pay/ui/dist/ton-pay-embed.js to your public assets folder.
2

Create TonConnect manifest

Create a tonconnect-manifest.json file in your public directory:
{
  "url": "https://yourdomain.com",
  "name": "Your App Name",
  "iconUrl": "https://yourdomain.com/icon.png"
}
Learn more about the manifest format in the TonConnect documentation.

Integration Guide

There are two ways to integrate the TonPay button in vanilla JavaScript:

Option 1: Simple Embed (Quickest)

The simplest way - just add a div and script tag. Perfect for static sites and simple integrations.
1

Add container div

Place a div where you want the button to appear:
<div id="ton-pay-btn"></div>
2

Add the embed script

Add the script tag with your configuration as URL parameters:
<script src="https://unpkg.com/@ton-pay/ui@latest/dist/ton-pay-embed.js?preset=gradient&variant=long&borderRadius=8&containerId=ton-pay-btn&callback=handlePayment"></script>
3

Add TonConnect import map

For ES modules support, add the import map before your scripts:
<script type="importmap">
{
  "imports": {
    "@tonconnect/ui": "https://esm.sh/@tonconnect/ui@2.0.9"
  }
}
</script>
4

Create payment handler

Implement your payment logic:
<script type="module">
  import { createTonPay } from "https://unpkg.com/@ton-pay/ui@latest/dist/ton-pay-vanilla.mjs";
  
  // Initialize TonPay client
  const tonPay = createTonPay({
    manifestUrl: "/tonconnect-manifest.json"
  });
  
  // Define payment handler
  window.handlePayment = async () => {
    try {
      const result = await tonPay.pay(async (senderAddr) => {
        // Build your payment message
        const message = {
          address: "EQC...RECIPIENT",
          amount: "1000000", // 0.001 TON in nanotons
          payload: "dGVzdA==", // optional base64 payload
        };
        return { message };
      });
      
      console.log("Payment successful:", result.txResult);
      alert("Payment sent!");
    } catch (error) {
      console.error("Payment failed:", error);
      alert("Payment failed: " + error.message);
    }
  };
</script>
The callback parameter in the embed script should match your global function name (handlePayment in this example).

Option 2: Using TonPay Client (More Control)

For more control over the payment flow, use the createTonPay client with your own button or UI elements.
1

Set up HTML

Create your HTML structure:
<!DOCTYPE html>
<html>
<head>
  <title>My TON Payment App</title>
  <script type="importmap">
  {
    "imports": {
      "@tonconnect/ui": "https://esm.sh/@tonconnect/ui@2.0.9"
    }
  }
  </script>
</head>
<body>
  <button id="pay-btn">Pay with TON</button>
  <div id="status"></div>
</body>
</html>
2

Import and initialize

Import the TonPay client and create an instance:
<script type="module">
  import { createTonPay } from "https://unpkg.com/@ton-pay/ui@latest/dist/ton-pay-vanilla.mjs";
  
  const tonPay = createTonPay({
    manifestUrl: "/tonconnect-manifest.json",
    connectTimeoutMs: 300000 // 5 minutes (optional)
  });
</script>
3

Implement payment logic

Add your payment handler:
<script type="module">
  const payButton = document.getElementById('pay-btn');
  const statusDiv = document.getElementById('status');
  
  payButton.addEventListener('click', async () => {
    payButton.disabled = true;
    payButton.textContent = 'Processing...';
    
    try {
      const result = await tonPay.pay(async (senderAddr) => {
        statusDiv.textContent = `Sending from ${senderAddr}...`;
        
        // Build payment message
        const message = {
          address: "EQC...RECIPIENT",
          amount: "1000000",
        };
        
        return { message };
      });
      
      statusDiv.textContent = 'Payment successful!';
      console.log('Transaction:', result.txResult);
    } catch (error) {
      statusDiv.textContent = 'Payment failed: ' + error.message;
      console.error(error);
    } finally {
      payButton.disabled = false;
      payButton.textContent = 'Pay with TON';
    }
  });
</script>
The createTonPay client automatically handles wallet connection. If the user isn’t connected, it opens the TonConnect modal when pay() is called.

Integration with createTonPayTransfer

To create properly formatted payment messages with tracking, use createTonPayTransfer from the API package:
1

Add API package script

Include the API package via CDN:
<script type="module">
  import { createTonPayTransfer } from "https://unpkg.com/@ton-pay/api@latest/dist/index.mjs";
  import { createTonPay } from "https://unpkg.com/@ton-pay/ui@latest/dist/ton-pay-vanilla.mjs";
</script>
2

Use in payment handler

<script type="module">
  const tonPay = createTonPay({
    manifestUrl: "/tonconnect-manifest.json"
  });
  
  window.handlePayment = async () => {
    try {
      const result = await tonPay.pay(async (senderAddr) => {
        // Create payment with tracking
        const { message, reference, bodyBase64Hash } = 
          await createTonPayTransfer(
            {
              amount: 3.5,
              asset: "TON",
              recipientAddr: "EQC...RECIPIENT",
              senderAddr,
              commentToSender: "Order #12345",
            },
            { chain: "mainnet" }
          );
        
        // Store tracking identifiers
        console.log("Reference:", reference);
        console.log("Hash:", bodyBase64Hash);
        
        return { message, reference, bodyBase64Hash };
      });
      
      alert("Payment sent! Reference: " + result.reference);
    } catch (error) {
      alert("Payment failed: " + error.message);
    }
  };
</script>
Store reference and bodyBase64Hash to track payment status via webhooks. See the Webhooks guide for details.

Configuration

Embed Script Parameters

Configure the button appearance using URL parameters:
ParameterTypeDefaultDescription
containerIdstring"ton-pay-btn"Target element ID to render the button
preset"default" | "gradient"-Built-in theme preset
bgColorstring"#0098EA"Background color (hex) or CSS gradient (URL-encoded)
textColorstring"#FFFFFF"Text and icon color
variant"long" | "short""long"Button text variant
textstring-Custom button text (overrides variant)
loadingTextstring"Processing..."Text shown during loading
borderRadiusnumber8Border radius in pixels
fontFamilystring"inherit"CSS font-family value
widthnumber300Button width in pixels
heightnumber44Button height in pixels
showMenubooleantrueShow dropdown menu with wallet actions
callbackstring-Global function name to call on button click

Examples

<script src="https://unpkg.com/@ton-pay/ui@latest/dist/ton-pay-embed.js?preset=default&variant=long&borderRadius=8&containerId=btn-1&callback=handlePayment"></script>
URL-encode special characters in parameters. For example, # becomes %23 in color values.

JavaScript API

The embed script exposes a global TonPayEmbed object for programmatic control:

Methods

TonPayEmbed.mount(config)

Update button configuration dynamically:
TonPayEmbed.mount({
  preset: 'gradient',
  variant: 'short',
  borderRadius: 12,
  width: 350
});

TonPayEmbed.setCallback(functionName)

Change the callback function:
TonPayEmbed.setCallback('newPaymentHandler');

TonPayEmbed.setAddress(address)

Update the displayed wallet address (for menu):
TonPayEmbed.setAddress('EQC...');

TonPayEmbed.click()

Programmatically trigger button click:
TonPayEmbed.click();

Example: Dynamic Configuration

<div id="ton-pay-btn"></div>
<button onclick="changeTheme()">Change Theme</button>

<script src="https://unpkg.com/@ton-pay/ui@latest/dist/ton-pay-embed.js?containerId=ton-pay-btn&callback=handlePayment"></script>

<script>
  function changeTheme() {
    TonPayEmbed.mount({
      preset: 'gradient',
      variant: 'short',
      borderRadius: 99
    });
  }
</script>

TonPayClient API

When using createTonPay, you get access to these methods and properties:

Properties

address: string | null

Get the currently connected wallet address:
const tonPay = createTonPay({ manifestUrl: "/tonconnect-manifest.json" });
console.log(tonPay.address); // null or wallet address

Methods

waitForWalletConnection(): Promise<string>

Wait for wallet connection, opening the modal if needed:
try {
  const address = await tonPay.waitForWalletConnection();
  console.log("Connected:", address);
} catch (error) {
  console.error("Connection failed:", error);
}

pay(getMessage): Promise<PayResult>

Execute a payment transaction:
const result = await tonPay.pay(async (senderAddr) => {
  const message = {
    address: "EQC...RECIPIENT",
    amount: "1000000"
  };
  return { message };
});

console.log(result.txResult);

disconnect(): Promise<void>

Disconnect the current wallet:
await tonPay.disconnect();

Best Practices

Always wrap payment calls in try-catch blocks and display clear error messages to users.
Update your UI during payment processing to prevent multiple clicks and provide feedback.
Check amounts, addresses, and user input before calling the payment function.
TonConnect requires HTTPS for security. Use HTTPS for your manifest URL and callback URLs.
Save reference and bodyBase64Hash from createTonPayTransfer to track payments via webhooks.
Test with testnet first, try different wallets, and handle all error scenarios before going live.

Framework Integration

The vanilla JavaScript button works with any framework:

With WordPress

<!-- Add to your theme's footer or custom HTML block -->
<div id="ton-pay-btn"></div>
<script type="importmap">
{
  "imports": {
    "@tonconnect/ui": "https://esm.sh/@tonconnect/ui@2.0.9"
  }
}
</script>
<script type="module">
  import { createTonPay } from "https://unpkg.com/@ton-pay/ui@latest/dist/ton-pay-vanilla.mjs";
  const tonPay = createTonPay({ manifestUrl: "/tonconnect-manifest.json" });
  window.handlePayment = async () => { /* your logic */ };
</script>
<script src="https://unpkg.com/@ton-pay/ui@latest/dist/ton-pay-embed.js?containerId=ton-pay-btn&callback=handlePayment"></script>

With Plain HTML/CSS/JS

Simply copy the complete example above into your HTML file.

With Build Tools (Webpack, Vite, etc.)

import { createTonPay } from '@ton-pay/ui/vanilla';

const tonPay = createTonPay({
  manifestUrl: '/tonconnect-manifest.json'
});

// Use tonPay.pay() in your event handlers

Troubleshooting

  • Verify the containerId matches your div’s ID
  • Check browser console for errors
  • Ensure the script loads after the container div
  • Verify the script URL is correct and accessible
  • Ensure the callback function is defined on window object
  • Function name must match the callback parameter exactly
  • Define the callback before the embed script runs
  • Add the import map before any module scripts
  • Check that @tonconnect/ui version is compatible
  • Verify import map syntax is correct
  • Serve your manifest file from the same domain or enable CORS
  • Use HTTPS in production
  • Check that CDN resources are accessible