本指南聚焦JavaScript对接TP钱包的全流程,先拆解核心原理:涵盖TP钱包的去中心化身份机制、链上交互逻辑及与前端JS的通信链路,夯实技术基础,随后推进实战环节,详解环境配置、SDK引入、账户授权、链上数据查询、交易签名与发送等关键步骤,搭配实用代码示例与常见问题规避技巧,助力开发者高效完成对接,实现DApp与TP钱包的无缝联动。
Web3 生态中,前端 DApp 与加密钱包的交互是核心入口能力之一,TP 钱包作为国内市场占有率领先的多链钱包,同时支持浏览器插件与移动端内置浏览器,是众多开发者对接钱包的首选对象,本文将从核心原理出发,详解两种主流场景下的对接方案,覆盖实战代码、异常处理与优化建议,帮助开发者快速集成 TP 钱包功能。
核心原理:TP 钱包的交互标准
TP 钱包的交互逻辑完全遵循行业通用协议,无需开发者自行实现底层加密逻辑,核心依赖两大标准:
- EIP-1193 协议:以太坊基金会制定的钱包 Provider 标准,要求兼容钱包在同环境下(插件/内置浏览器)挂载全局
window.ethereum对象,提供统一的账户、链操作接口; - WalletConnect 协议:跨环境适配标准,解决外部浏览器(未安装插件)的钱包对接问题,通过扫码配对实现 DApp 与移动端钱包的安全交互。
TP 钱包在同环境下会添加专属标识(如 isTrustWallet/isTP),方便开发者区分 TP 钱包与 MetaMask 等其他钱包,避免误识别。
TP 钱包插件/内置浏览器(同环境对接)
当用户在 Chrome 安装 TP 插件,或在 TP 内置浏览器打开 DApp 时,页面会自动挂载 TP 的 EIP-1193 Provider,直接通过 window.ethereum 调用接口,无需额外依赖,体验最优。
步骤1:检测 TP 钱包环境
先判断当前环境是否为 TP 钱包,避免误识别其他钱包,同时提供友好引导:
async function isTPWalletAvailable() {
// 优先检测 TP 钱包专属标识(插件/内置浏览器)
if (window.ethereum?.isTrustWallet || window.ethereum?.isTP) {
return true;
}
// 兼容 TP 内置浏览器的 UA 特征(适配不同版本)
if (navigator.userAgent.includes('Trust') || navigator.userAgent.includes('TPWallet')) {
return true;
}
// 可选:检测是否为其他钱包(如 MetaMask),提示用户切换
if (window.ethereum?.isMetaMask) {
alert('请切换到 TP 钱包插件或使用 TP 内置浏览器打开本页面');
return false;
}
return false;
}
步骤2:发起钱包授权连接
调用 eth_requestAccounts 触发授权弹窗,用户确认后返回钱包地址,同时处理重复连接、拒绝授权等异常:
async function connectTPWallet() {
try {
// 先检测 TP 环境
if (!await isTPWalletAvailable()) return;
// 检查是否已连接账户,避免重复请求
const accounts = await window.ethereum.request({ method: 'eth_accounts' });
if (accounts.length > 0) {
console.log('已连接 TP 钱包,地址:', accounts[0]);
return accounts[0];
}
// 发起授权请求
const newAccounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
const currentAddress = newAccounts[0];
console.log('TP 钱包连接成功,地址:', currentAddress);
return currentAddress;
} catch (error) {
console.error('连接失败:', error.message);
// 处理用户拒绝授权的标准错误码(EIP-1193 定义)
if (error.code === 4001) alert('您已拒绝钱包授权,请点击钱包确认连接');
// 其他异常提示
else alert(`连接异常:${error.message}`);
}
}
步骤3:链信息获取与切换
TP 钱包支持多链,开发者可根据业务需求获取当前链 ID、切换目标链,或引导用户添加未配置的链:
// 获取当前链 ID(十六进制格式,对应链 ID 十进制值)
async function getCurrentChainId() {
const chainId = await window.ethereum.request({ method: 'eth_chainId' });
console.log('当前链 ID:', chainId); // 示例:以太坊主网 0x1,Polygon 主网 0x89,BSC 主网 0x38
return chainId;
}
// 切换到指定链,若链未添加则自动引导添加
async function switchToChain(chainId, chainName, rpcUrl, nativeCurrency) {
try {
await window.ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId }]
});
console.log(`已切换到 ${chainName}`);
} catch (error) {
// 链未添加的标准错误码(EIP-3085)
if (error.code === 4902) {
try {
await window.ethereum.request({
method: 'wallet_addEthereumChain',
params: [{
chainId,
chainName,
rpcUrls: [rpcUrl],
nativeCurrency: nativeCurrency || { name: 'ETH', symbol: 'ETH', decimals: 18 }
}]
});
} catch (addError) {
console.error('添加链失败:', addError.message);
alert('请手动在 TP 钱包中添加该链');
}
} else {
console.error('切换链失败:', error.message);
}
}
}
// 示例:切换到 Polygon 主网
switchToChain('0x89', 'Polygon Mainnet', 'https://polygon-rpc.com', { name: 'MATIC', symbol: 'MATIC', decimals: 18 });
步骤4:监听钱包状态变化
同步钱包的账户切换、链切换、断开连接事件,实时更新 DApp 状态:
function listenWalletEvents() {
// 账户切换/断开事件
window.ethereum.on('accountsChanged', (accounts) => {
if (accounts.length === 0) {
console.log('钱包已断开连接');
// 清空 DApp 本地账户状态
localStorage.removeItem('tp_wallet_address');
} else {
const newAddress = accounts[0];
console.log('账户已切换:', newAddress);
// 更新 DApp 账户状态(如绑定到全局变量)
window.currentWalletAddress = newAddress;
localStorage.setItem('tp_wallet_address', newAddress);
}
});
// 链切换事件
window.ethereum.on('chainChanged', (newChainId) => {
console.log('链已切换:', newChainId);
// 简单处理:刷新页面(生产环境可优化为手动更新链相关数据)
window.location.reload();
});
}
// 初始化监听(连接成功后调用)
listenWalletEvents();
外部浏览器(跨环境对接,WalletConnect)
如果用户在 Chrome、Safari 等外部浏览器打开 DApp,未安装 TP 插件,可通过 WalletConnect 协议实现扫码配对,无需依赖本地 Provider,适配所有主流浏览器。
核心代码实现
需先安装依赖:npm install @walletconnect/sign-client qrcode,同时需在 WalletConnect Cloud 申请项目 ID(唯一标识 DApp,用于生成配对链接):
import { SignClient } from '@walletconnect/sign-client';
import QRCode from 'qrcode';
// 初始化 WalletConnect(需替换为你的项目 ID)
const WALLET_CONNECT_PROJECT_ID = '你的 WalletConnect 项目 ID';
async function connectTPWalletExternal() {
try {
// 1. 初始化 WalletConnect 客户端
const client = await SignClient.init({
projectId: WALLET_CONNECT_PROJECT_ID,
metadata: {
name: '你的 DApp 名称',
description: '你的 DApp 描述',
url: '你的 DApp 官网',
icons: ['你的 DApp 图标 URL']
}
});
// 2. 创建配对请求(指定支持的链和方法)
const { uri, approval } = await client.connect({
requiredNamespaces: {
eip155: {
methods: ['eth_requestAccounts', 'eth_sendTransaction'], // 支持的链上方法
chains: ['eip155:1', 'eip155:137'], // 支持的链:以太坊主网、Polygon 主网
events: ['accountsChanged', 'chainChanged'] // 监听的事件
}
}
});
// 3. 生成配对二维码(适配移动端/桌面端)
if (uri) {
const qrContainer = document.getElementById('wallet-qrcode');
if (qrContainer) {
// 生成二维码
await QRCode.toCanvas(qrContainer, uri, { width: 200 });
// 移动端优化:自动打开 TP 钱包(若检测到移动端)
if (/Mobile|Android|iPhone/i.test(navigator.userAgent)) {
window.location.href = `tp://wc?uri=${encodeURIComponent(uri)}`;
}
console.log('请用 TP 钱包扫码连接 DApp');
} else {
alert('二维码容器未找到,请检查页面元素');
}
}
// 4. 等待用户确认连接,返回钱包地址
const session = await approval();
const address = session.namespaces.eip155.accounts[0].split(':')[2];
console.log('外部浏览器连接 TP 钱包成功,地址:', address);
return address;
} catch (error) {
console.error('WalletConnect 连接失败:', error.message);
alert(`连接失败:${error.message}`);
}
}
常见问题与优化建议
- 环境适配:优先同环境对接(插件/内置浏览器),体验更好;外部浏览器用 WalletConnect,注意移动端跳转逻辑优化;
- 错误码处理:EIP-1193 标准错误码(4001 用户拒绝、4902 链未添加)需做友好提示,避免技术术语;
- WalletConnect 版本:使用最新版
@walletconnect/sign-client,旧版本可能存在兼容性问题; - 项目 ID 安全:WalletConnect 项目 ID 需妥善保管,避免前端暴露敏感信息(可结合后端接口生成配对链接);
- 测试环境:对接前需在 Sepolia 测试网、Polygon 测试网等环境测试,避免主网操作风险;
- UA 检测适配:TP 钱包内置浏览器的 UA 可能随版本变化,定期更新检测规则,避免环境识别失败。
本文覆盖了 TP 钱包对接的两种核心场景,代码均经过实战验证,开发者可根据 DApp 的用户场景选择对应方案,同环境对接体验最优,跨环境对接用 WalletConnect 适配所有浏览器,配合完善的错误处理与状态监听,可快速实现稳定的钱包交互功能,提升 Web3 用户的使用体验。
相关阅读: