🌐 mpp-ton

March 23, 2026 Β· View on GitHub

TON blockchain payment method for the Machine Payments Protocol (MPP)

Enable AI agents to pay for services using TON native coins or Jettons. Built for the TON AI Hackathon (March 2026) β€” Agent Infrastructure Track.

MPP TON License: MIT

What is this?

MPP (Machine Payments Protocol) is an open standard by Stripe + Tempo for machine-to-machine payments. When an agent requests a paid resource, the server returns HTTP 402 Payment Required with a challenge. The agent pays and retries β€” getting access automatically.

mpp-ton adds TON blockchain as a payment rail, so agents can pay with:

  • TON coins (native transfers)
  • Jettons (USDT, etc.) β€” coming soon

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        MPP Flow                              β”‚
β”‚                                                              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”     GET /api/data      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”‚
β”‚  β”‚  Agent   β”‚ ──────────────────────▢│   Server    β”‚         β”‚
β”‚  β”‚ (Client) β”‚ ◀───── 402 + Challenge β”‚ (mppx +     β”‚         β”‚
β”‚  β”‚          β”‚                        β”‚  mpp-ton)   β”‚         β”‚
β”‚  β”‚          β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚             β”‚         β”‚
β”‚  β”‚          β”‚  β”‚ TON Blockchainβ”‚     β”‚             β”‚         β”‚
β”‚  β”‚          │──▢ Send Payment  β”‚     β”‚             β”‚         β”‚
β”‚  β”‚          β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚             β”‚         β”‚
β”‚  β”‚          β”‚                        β”‚             β”‚         β”‚
β”‚  β”‚          β”‚  GET /api/data         β”‚             β”‚         β”‚
β”‚  β”‚          β”‚  + Payment Credential  β”‚             β”‚         β”‚
β”‚  β”‚          β”‚ ──────────────────────▢│ Verify tx   β”‚         β”‚
β”‚  β”‚          β”‚ ◀───── 200 + Receipt   β”‚ on-chain    β”‚         β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    + Data               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Quick Start

Install

npm install @tesserae/mpp-ton

Server β€” Accept TON Payments

import crypto from 'node:crypto'
import { Mppx } from 'mppx/server'
import { tonCharge } from '@tesserae/mpp-ton/server'
import { tonToNano } from '@tesserae/mpp-ton'

const mppx = Mppx.create({
  methods: [
    tonCharge({
      recipient: 'EQD...your-wallet-address...',
      network: 'testnet',
    }),
  ],
  secretKey: crypto.randomBytes(32).toString('base64'),
})

// In your request handler:
export async function handler(request: Request) {
  const result = await mppx.charge({
    amount: tonToNano('0.1'), // 0.1 TON
    recipient: 'EQD...your-wallet-address...',
  })(request)

  if (result.status === 402) return result.challenge

  return result.withReceipt(Response.json({ data: 'premium content' }))
}

Client β€” Pay with TON

import { Mppx } from 'mppx/client'
import { tonCharge } from '@tesserae/mpp-ton/client'

const mppx = Mppx.create({
  methods: [
    tonCharge({
      mnemonic: ['word1', 'word2', '...', 'word24'],
      network: 'testnet',
    }),
  ],
  polyfill: false,
})

// Automatically handles 402 β†’ pay β†’ get data
const res = await mppx.fetch('https://api.example.com/weather-data')
const data = await res.json()

Project Structure

mpp-ton/
β”œβ”€β”€ packages/
β”‚   └── mpp-ton/                  # Core payment method (npm: @tesserae/mpp-ton)
β”‚       └── src/
β”‚           β”œβ”€β”€ index.ts          # Method definition + exports
β”‚           β”œβ”€β”€ client.ts         # Client-side credential creation
β”‚           β”œβ”€β”€ server.ts         # Server-side verification
β”‚           β”œβ”€β”€ ton-api.ts        # TON Center API helpers
β”‚           └── types.ts          # Shared types
β”œβ”€β”€ apps/
β”‚   β”œβ”€β”€ demo-server/              # Weather data API (charges TON)
β”‚   └── demo-client/              # Agent that pays for weather data
β”œβ”€β”€ package.json                  # Workspace root
└── README.md

API Reference

Method Definition

import { ton } from '@tesserae/mpp-ton'

// ton.name === 'ton'
// ton.intent === 'charge'

Request Parameters (what the server specifies):

FieldTypeDescription
amountstringAmount in nanoTON (1 TON = 1e9)
recipientstringTON wallet address
jettonstring?Jetton master address (optional)
networkstring?'mainnet' or 'testnet'
memostring?Payment memo/comment

Credential Payload (what the client sends as proof):

FieldTypeDescription
txHashstringTransaction hash on TON
bocstring?Signed BOC for pull mode
ltstring?Logical time
senderAddressstringSender wallet address

Client Config

tonCharge({
  mnemonic: string[]        // 24-word mnemonic
  // OR
  secretKey: string         // 64-byte hex secret key

  network: 'testnet'        // 'mainnet' | 'testnet'
  apiKey: string            // TON Center API key (optional)
  endpoint: string          // Custom API endpoint (optional)
})

Server Config

tonCharge({
  recipient: string         // Your TON wallet address (required)
  network: 'testnet'        // 'mainnet' | 'testnet'
  apiKey: string            // TON Center API key (optional)
  endpoint: string          // Custom API endpoint (optional)
  maxTxAge: 300             // Max transaction age in seconds
})

Utilities

import { tonToNano, nanoToTon, TON_DECIMALS, NANOTON_PER_TON } from '@tesserae/mpp-ton'

tonToNano('1.5')    // '1500000000'
nanoToTon('100000000000') // '100'

Running the Demo

1. Install dependencies

git clone https://github.com/tesserae-labs/mpp-ton
cd mpp-ton
npm install
npm run build

2. Start the server

# Uses a demo wallet address on testnet
npm run demo:server

The server starts at http://localhost:3000 and charges 0.1 TON per weather data request.

3. Run the client

# Generate a new wallet (you'll need to fund it on testnet)
npm run demo:client

Or with an existing wallet:

TON_MNEMONIC="word1 word2 ... word24" npm run demo:client

Getting testnet TON

  1. Run the client once to generate a wallet address
  2. Open @testgiver_ton_bot on Telegram
  3. Send your wallet address to get testnet TON
  4. Run the client again

How Verification Works

  1. Client sends payment to the recipient address on TON
  2. Client creates credential with txHash, senderAddress, and optional lt
  3. Server receives credential and queries TON Center API
  4. Server verifies:
    • Transaction exists and is recent (< 5 min by default)
    • Recipient matches the expected address
    • Amount is >= the required amount
    • (For Jettons: correct Jetton master address)
  5. Server returns Receipt with the verified tx hash

Hackathon Context

Tesserae GPU Hackathon β€” March 2026

This project demonstrates how the Machine Payments Protocol can be extended beyond its built-in payment methods (Tempo, Stripe) to support any blockchain. TON is a natural fit because:

  • Fast finality (~5 seconds) β€” agents don't wait long
  • Low fees (~$0.01) β€” viable for micropayments
  • 900M+ Telegram users β€” massive potential user base for agents
  • Jetton ecosystem β€” USDT on TON for stablecoin payments

The architecture follows MPP's custom payment method pattern (Method.from β†’ Method.toClient β†’ Method.toServer), making it a drop-in addition to any MPP-enabled service.

License

MIT


Built with 🧭 by Tesserae for the Machine Payments Protocol ecosystem.