Skip to Content

TON

使用 OneKey 的 TON Connect 兼容 Provider 集成 TON 区块链。通过 window.$onekey.tonconnect 访问。

OneKey 通过 TON Connect 2.0 协议提供本文列出的操作。


快速链接


Provider 检测

// Detect OneKey TON provider const provider = window.$onekey?.tonconnect if (!provider) { throw new Error('OneKey TON provider not detected') } // Check device and wallet info console.log('Device:', provider.deviceInfo) console.log('Wallet:', provider.walletInfo) console.log('Protocol Version:', provider.protocolVersion) // 2

快速开始

连接钱包

// Basic connection const connectEvent = await provider.connect() if (connectEvent.event === 'connect') { const addressItem = connectEvent.payload.items.find( item => item.name === 'ton_addr' ) console.log('Connected:', addressItem?.address) } else { console.error('Connection failed:', connectEvent.payload.message) }

使用 Manifest 连接

对于生产应用,需要提供 manifest URL:

const connectRequest = { manifestUrl: 'https://yourapp.com/tonconnect-manifest.json', items: [ { name: 'ton_addr' }, { name: 'ton_proof', payload: 'your-challenge-string' } ] } const connectEvent = await provider.connect(2, connectRequest) if (connectEvent.event === 'connect') { const addressItem = connectEvent.payload.items.find(i => i.name === 'ton_addr') const proofItem = connectEvent.payload.items.find(i => i.name === 'ton_proof') console.log('Address:', addressItem?.address) console.log('Proof:', proofItem?.proof) }

应用 Manifest 格式

在应用根目录创建 tonconnect-manifest.json:

{ "url": "https://yourapp.com", "name": "Your App Name", "iconUrl": "https://yourapp.com/icon.png", "termsOfUseUrl": "https://yourapp.com/terms", "privacyPolicyUrl": "https://yourapp.com/privacy" }

恢复连接

恢复之前的会话:

const connectEvent = await provider.restoreConnection() if (connectEvent.event === 'connect') { console.log('Session restored') }

断开连接

await provider.disconnect()

交易

发送交易

使用 send 方法和 sendTransaction 发送 TON:

const result = await provider.send({ method: 'sendTransaction', id: Date.now().toString(), params: [ JSON.stringify({ valid_until: Math.floor(Date.now() / 1000) + 600, // 10 min validity messages: [ { address: '0:1234...', // Recipient address (raw format) amount: '1000000000', // Amount in nanotons (1 TON = 10^9 nanotons) } ] }) ] }) if ('result' in result) { console.log('Transaction BOC:', result.result) } else { console.error('Transaction failed:', result.error.message) }

发送多条消息

provider 当前声明最多支持四条消息。请读取 deviceInfo.features 中钱包声明的上限,不要将其视为整个网络的限制:

const result = await provider.send({ method: 'sendTransaction', id: Date.now().toString(), params: [ JSON.stringify({ valid_until: Math.floor(Date.now() / 1000) + 600, messages: [ { address: '0:recipient1...', amount: '500000000', // 0.5 TON }, { address: '0:recipient2...', amount: '300000000', // 0.3 TON } ] }) ] })

发送带 Payload 的交易

包含 payload 用于智能合约交互:

import { beginCell } from '@ton/core' // Create a comment cell const comment = beginCell() .storeUint(0, 32) // comment op code .storeStringTail('Hello from dApp!') .endCell() const result = await provider.send({ method: 'sendTransaction', id: Date.now().toString(), params: [ JSON.stringify({ valid_until: Math.floor(Date.now() / 1000) + 600, messages: [ { address: '0:recipient...', amount: '100000000', payload: comment.toBoc().toString('base64'), } ] }) ] })

发送带 StateInit 的交易

部署合约或初始化状态:

const result = await provider.send({ method: 'sendTransaction', id: Date.now().toString(), params: [ JSON.stringify({ valid_until: Math.floor(Date.now() / 1000) + 600, messages: [ { address: '0:contract...', amount: '50000000', stateInit: stateInitBoc.toString('base64'), // Base64 encoded StateInit } ] }) ] })

数据签名

签名任意数据

签名数据 cell 用于链下验证:

const result = await provider.send({ method: 'signData', id: Date.now().toString(), params: [ JSON.stringify({ schema_crc: 0, // Custom schema identifier cell: cellBoc.toString('base64'), // Base64 encoded cell to sign }) ] }) if ('result' in result) { console.log('Signature:', result.result.signature) // Base64 signature console.log('Timestamp:', result.result.timestamp) // UNIX timestamp }

签名证明(身份验证)

在连接时请求证明用于身份验证:

const connectEvent = await provider.connect(2, { manifestUrl: 'https://yourapp.com/tonconnect-manifest.json', items: [ { name: 'ton_addr' }, { name: 'ton_proof', payload: 'your-server-generated-challenge' // Nonce for replay protection } ] }) if (connectEvent.event === 'connect') { const proofItem = connectEvent.payload.items.find(i => i.name === 'ton_proof') if (proofItem && "proof" in proofItem) { // Send proof to your backend for verification const proof = proofItem.proof console.log({ signature: proof.signature, timestamp: proof.timestamp, domain: proof.domain, payload: proof.payload, }) } }

事件处理

监听事件

provider.listen((event) => { console.log('Wallet event:', event) }) // Or use specific event listeners provider.on('accountChanged', (address) => { if (address) { console.log('Account changed:', address) } else { console.log('Disconnected') } }) provider.on('disconnect', () => { console.log('Wallet disconnected') })

API 参考

方法

方法说明
connect(version?, request?)连接钱包
restoreConnection()恢复之前的会话
disconnect()断开钱包连接
send(message)发送 RPC 请求
listen(callback)监听钱包事件

Send 方法

方法说明
sendTransaction发送 TON 或与合约交互
signData签名任意数据 cell
disconnect通过 RPC 断开连接

类型

interface AccountInfo { address: string // Raw address (0:<hex>) network: string // Network ID (-239 mainnet, -3 testnet) publicKey: string // Hex public key (no 0x) walletStateInit: string // Base64 encoded state init } interface TransactionRequest { valid_until?: number // UNIX timestamp for validity network?: string // Network ID from?: string // Sender address messages: Message[] // Respect the wallet-advertised maximum } interface Message { address: string // Recipient (raw format) amount: string // Amount in nanotons payload?: string // Base64 BOC for contract calls stateInit?: string // Base64 StateInit for deployment } interface SignDataRequest { schema_crc: number // Schema identifier cell: string // Base64 encoded cell publicKey?: string // Optional specific key } interface SignDataResult { signature: string // Base64 signature timestamp: number // UNIX timestamp (UTC) } interface DeviceInfo { platform: string // 'iphone' | 'android' | 'windows' | 'mac' | 'linux' appName: string // 'onekey' appVersion: string // Wallet version maxProtocolVersion: number // 2 features: Array<string | { name: string; maxMessages?: number; [key: string]: unknown }> // Advertised capabilities }

错误码

错误码说明
0未知错误
1请求格式错误
100未知应用
300用户拒绝请求
400方法不支持

使用 TON Connect SDK

对于 React 应用,使用官方的 TON Connect SDK:

npm install @tonconnect/ui-react
import { TonConnectUIProvider, TonConnectButton } from '@tonconnect/ui-react' function App() { return ( <TonConnectUIProvider manifestUrl="https://yourapp.com/tonconnect-manifest.json"> <TonConnectButton /> <YourApp /> </TonConnectUIProvider> ) }

OneKey 会被 TON Connect SDK 自动检测到。

使用 SDK 发送交易

import { useTonConnectUI } from '@tonconnect/ui-react' function SendButton() { const [tonConnectUI] = useTonConnectUI() const handleSend = async () => { const result = await tonConnectUI.sendTransaction({ validUntil: Math.floor(Date.now() / 1000) + 600, messages: [ { address: 'EQA...', amount: '1000000000', } ] }) console.log('BOC:', result.boc) } return <button onClick={handleSend}>Send 1 TON</button> }

地址格式

TON 使用不同的地址格式:

import { Address } from '@ton/core' // Raw format (used in provider) const raw = '0:1234567890abcdef...' // User-friendly format (bounceable) const friendly = Address.parse(raw).toString() // e.g., 'EQASdf...' // Non-bounceable format const nonBounceable = Address.parse(raw).toString({ bounceable: false }) // e.g., 'UQASdf...' // Convert from friendly to raw const addr = Address.parse('EQASdf...') const rawAddress = `${addr.workChain}:${addr.hash.toString('hex')}`

错误处理

const result = await provider.send({ method: 'sendTransaction', id: Date.now().toString(), params: [/* ... */] }) if ('error' in result) { switch (result.error.code) { case 300: console.log('User rejected the transaction') break case 1: console.log('Bad request - check parameters') break case 400: console.log('Method not supported') break default: console.error('Error:', result.error.message) } } else { console.log('Success:', result.result) }
最后更新于