TON
使用 OneKey 的 TON Connect 兼容 Provider 集成 TON 区块链。通过 window.$onekey.tonconnect 访问。
OneKey 实现了 TON Connect 2.0 协议,确保与所有 TON dApp 兼容。
快速链接
Provider 检测
// 检测 OneKey TON provider
const provider = window.$onekey?.tonconnect
if (!provider) {
throw new Error('未检测到 OneKey TON provider')
}
// 检查设备和钱包信息
console.log('设备:', provider.deviceInfo)
console.log('钱包:', provider.walletInfo)
console.log('协议版本:', provider.protocolVersion) // 2快速开始
连接钱包
// 基本连接
const connectEvent = await provider.connect()
if (connectEvent.event === 'connect') {
const addressItem = connectEvent.payload.items.find(
item => item.name === 'ton_addr'
)
console.log('已连接:', addressItem.address)
} else {
console.error('连接失败:', 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('地址:', addressItem.address)
console.log('证明:', 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('会话已恢复')
}断开连接
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 分钟有效期
messages: [
{
address: '0:1234...', // 接收方地址(原始格式)
amount: '1000000000', // 金额,单位 nanotons (1 TON = 10^9 nanotons)
}
]
})
]
})
if ('result' in result) {
console.log('交易 BOC:', result.result)
} else {
console.error('交易失败:', result.error.message)
}发送多条消息
TON 支持每笔交易最多 4 条消息:
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'
// 创建评论 cell
const comment = beginCell()
.storeUint(0, 32) // 评论操作码
.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 编码的 StateInit
}
]
})
]
})数据签名
签名任意数据
签名数据 cell 用于链下验证:
const result = await provider.send({
method: 'signData',
id: Date.now().toString(),
params: [
JSON.stringify({
schema_crc: 0, // 自定义 schema 标识符
cell: cellBoc.toString('base64'), // Base64 编码的待签名 cell
})
]
})
if ('result' in result) {
console.log('签名:', result.result.signature) // Base64 签名
console.log('时间戳:', result.result.timestamp) // UNIX 时间戳
}签名证明(身份验证)
在连接时请求证明用于身份验证:
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
}
]
})
if (connectEvent.event === 'connect') {
const proofItem = connectEvent.payload.items.find(i => i.name === 'ton_proof')
if (proofItem) {
// 将证明发送到后端进行验证
const proof = proofItem.proof
console.log({
signature: proof.signature,
timestamp: proof.timestamp,
domain: proof.domain,
payload: proof.payload,
})
}
}事件处理
监听事件
provider.listen((event) => {
console.log('钱包事件:', event)
})
// 或使用特定的事件监听器
provider.on('accountChanged', (address) => {
if (address) {
console.log('账户已变更:', address)
} else {
console.log('已断开连接')
}
})
provider.on('disconnect', () => {
console.log('钱包已断开连接')
})API 参考
方法
| 方法 | 说明 |
|---|---|
connect(version?, request?) | 连接钱包 |
restoreConnection() | 恢复之前的会话 |
disconnect() | 断开钱包连接 |
send(message) | 发送 RPC 请求 |
listen(callback) | 监听钱包事件 |
Send 方法
| 方法 | 说明 |
|---|---|
sendTransaction | 发送 TON 或与合约交互 |
signData | 签名任意数据 cell |
disconnect | 通过 RPC 断开连接 |
类型
interface AccountInfo {
address: string // 原始地址 (0:<hex>)
network: string // 网络 ID (-239 主网, -3 测试网)
publicKey: string // 十六进制公钥(无 0x)
walletStateInit: string // Base64 编码的 state init
}
interface TransactionRequest {
valid_until?: number // 有效期 UNIX 时间戳
network?: string // 网络 ID
from?: string // 发送方地址
messages: Message[] // 最多 4 条消息
}
interface Message {
address: string // 接收方(原始格式)
amount: string // 金额,单位 nanotons
payload?: string // Base64 BOC 用于合约调用
stateInit?: string // Base64 StateInit 用于部署
}
interface SignDataRequest {
schema_crc: number // Schema 标识符
cell: string // Base64 编码的 cell
publicKey?: string // 可选的特定密钥
}
interface SignDataResult {
signature: string // Base64 签名
timestamp: number // UNIX 时间戳 (UTC)
}
interface DeviceInfo {
platform: string // 'iphone' | 'android' | 'windows' | 'mac' | 'linux'
appName: string // 'onekey'
appVersion: string // 钱包版本
maxProtocolVersion: number // 2
features: string[] // 支持的功能
}错误码
| 错误码 | 说明 |
|---|---|
| 0 | 未知错误 |
| 1 | 请求格式错误 |
| 100 | 未知应用 |
| 300 | 用户拒绝请求 |
| 400 | 方法不支持 |
使用 TON Connect SDK
对于 React 应用,使用官方的 TON Connect SDK:
npm install @tonconnect/ui-reactimport { 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}>发送 1 TON</button>
}地址格式
TON 使用不同的地址格式:
import { Address } from '@ton/core'
// 原始格式(provider 中使用)
const raw = '0:1234567890abcdef...'
// 用户友好格式(可弹回)
const friendly = Address.parse(raw).toString()
// 例如 'EQASdf...'
// 不可弹回格式
const nonBounceable = Address.parse(raw).toString({ bounceable: false })
// 例如 'UQASdf...'
// 从友好格式转换为原始格式
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('用户拒绝了交易')
break
case 1:
console.log('请求格式错误 - 请检查参数')
break
case 400:
console.log('方法不支持')
break
default:
console.error('错误:', result.error.message)
}
} else {
console.log('成功:', result.result)
}Last updated on