TON 钱包绑定接口对接文档
概述
本文档描述了如何通过 TON Connect 协议与后端的钱包授权接口对接,实现 TON 钱包的绑定和解绑功能。接口使用 JWT 认证,需在请求头中携带有效令牌。后端使用 TON 的 ton-proof 协议验证 Ed25519 签名,确保绑定请求的安全性。
基础信息
- 接口前缀:
/auth/wallet - 认证方式:JWT(在
Authorization请求头中传递Bearer <token>) - 响应格式:
- 成功:HTTP 200,无响应体
- 失败:HTTP 400,返回 JSON:
json { "code": 400, "error": "错误信息(如:参数错误)" }
接口详情
1. 获取 Nonce
用于生成绑定钱包所需的唯一 nonce。
- URL:
GET /auth/wallet/nonce - 请求头:
Authorization: Bearer <jwt-token> - 响应:
- 成功(HTTP 200):
json "uuid-string" // 例如 "550e8400-e29b-41d4-a716-446655440000" -
失败(HTTP 400,示例):
json { "code": 400, "error": "未登录" } -
说明:
- Nonce 有效期 5 分钟,需在绑定接口中使用。
- 需确保用户已登录(JWT 有效)。
2. 绑定钱包
将用户的 TON 钱包地址绑定到账户。
- URL:
PUT /auth/wallet/bind - 请求头:
Authorization: Bearer <jwt-token> Content-Type: application/json - 请求体:
json { "externalAddress": "string", "signature": "string", "timestamp": number, "domain": "string", "payload": "string", "publicKey": "string" } -
字段说明:
externalAddress:TON 钱包地址,格式为EQ...或Uf...(Base64 编码,48 字节)。signature:对消息的 Ed25519 签名(Base64 编码,64 字节)。timestamp:签名生成时间(Unix 时间戳,秒),需在 10 分钟内。domain:应用域名,必须为yourapp.com(请替换为实际域名)。payload:从/nonce接口获取的 nonce。publicKey:钱包的 Ed25519 公钥(16 进制编码,32 字节)。
-
响应:
- 成功(HTTP 200):无响应体。
-
失败(HTTP 400,示例):
json { "code": 400, "error": "参数错误" // 或 "Nonce 无效或已过期", "签名验证失败", "该钱包地址已被绑定" } -
说明:
- 需先调用
/nonce获取 nonce。 - 使用 TON Connect 生成
ton_proof,确保签名和公钥正确。
3. 解绑钱包
解除用户账户与 TON 钱包的绑定。
- URL:
PUT /auth/wallet/unbind - 请求头:
Authorization: Bearer <jwt-token> - 请求体:无
- 响应:
- 成功(HTTP 200):无响应体。
-
失败(HTTP 400,示例):
json { "code": 400, "error": "未绑定钱包" } -
说明:
- 需确保用户已绑定钱包。
TON Connect 集成
前端需使用 TON Connect SDK 生成 ton-proof,以提供签名和相关字段。以下是实现步骤:
依赖
安装 @ton/tonconnect:
npm install @ton/tonconnect
示例代码
import { TonConnect } from '@ton/tonconnect';
import axios from 'axios';
const connector = new TonConnect({
manifestUrl: 'https://yourapp.com/tonconnect-manifest.json' // 替换为实际 manifest 文件地址
});
// 获取 Nonce
async function getNonce() {
try {
const response = await axios.get('http://your-backend.com/auth/wallet/nonce', {
headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
});
return response.data;
} catch (error) {
console.error('获取 Nonce 失败:', error.response?.data?.error);
throw error;
}
}
// 绑定钱包
async function bindWallet() {
try {
const userId = "123"; // 从登录状态获取用户 ID
const nonce = await getNonce();
const message = `Sign to bind wallet for user: ${userId}`;
// 生成 ton_proof
const tonProof = await connector.requestTonProof({
payload: nonce,
message: message
});
const response = await axios.put(
'http://your-backend.com/auth/wallet/bind',
{
externalAddress: tonProof.address,
signature: tonProof.proof.signature,
timestamp: tonProof.proof.timestamp,
domain: tonProof.proof.domain.value,
payload: tonProof.proof.payload,
publicKey: tonProof.public_key
},
{ headers: { Authorization: `Bearer ${localStorage.getItem('token')}` } }
);
if (response.status === 200) {
alert('钱包绑定成功');
}
} catch (error) {
alert('绑定失败: ' + (error.response?.data?.error || '未知错误'));
}
}
// 解绑钱包
async function unbindWallet() {
try {
const response = await axios.put(
'http://your-backend.com/auth/wallet/unbind',
{},
{ headers: { Authorization: `Bearer ${localStorage.getItem('token')}` } }
);
if (response.status === 200) {
alert('钱包解绑成功');
}
} catch (error) {
alert('解绑失败: ' + (error.response?.data?.error || '未知错误'));
}
}
注意事项
- TON Connect 配置:
- 创建
tonconnect-manifest.json,包含应用信息(如域名、名称)。 - 示例:
json { "url": "https://yourapp.com", "name": "Your App Name", "iconUrl": "https://yourapp.com/icon.png" } -
部署到可公开访问的地址(如
https://yourapp.com/tonconnect-manifest.json)。 -
域名:
-
确保
tonProof.proof.domain.value为yourapp.com(与后端配置一致)。 -
公钥:
-
TON Connect 的
tonProof.public_key提供 16 进制编码的 Ed25519 公钥,直接传递。 -
错误处理:
-
处理 400 错误,显示后端返回的
error信息。 -
钱包支持:
- 测试支持的钱包(如 Tonkeeper、TON Wallet)。
- 确保用户已安装兼容的 TON 钱包扩展或应用。
测试指南
测试环境
- 后端 URL:
http://your-backend.com(替换为实际地址) - 域名:
yourapp.com(与后端配置一致) - 钱包:Tonkeeper 或其他支持 TON Connect 的钱包
测试用例
- 获取 Nonce:
- 调用
GET /auth/wallet/nonce,验证返回有效 UUID 字符串。 -
确保未登录时返回 400 错误(由全局处理器处理)。
-
绑定钱包:
- 使用 TON Connect 生成
ton_proof,调用PUT /auth/wallet/bind。 - 测试有效签名(正确地址、签名、公钥、nonce、时间戳、域名)。
-
测试无效场景:
- 无效地址(非 TON 格式)
- 无效签名(篡改或错误公钥)
- 过期 nonce(超过 5 分钟)
- 过期时间戳(超过 10 分钟)
- 错误域名
- 已绑定的地址
-
解绑钱包:
- 调用
PUT /auth/wallet/unbind,验证成功解绑。 - 测试未绑定钱包时的错误。
常见问题
- 签名验证失败:
- 检查
publicKey是否正确(16 进制,32 字节)。 - 确保
message为Sign to bind wallet for user: <userId>。 - 验证
payload与/nonce返回的 nonce 一致。