跳转至

tronlink-signer

GitHub: https://github.com/TronLink/mcp-tronlink-signer/tree/main/packages/tronlink-signer

通过 TronLink 浏览器钱包签署 TRON 交易的独立 SDK。私钥始终留在 TronLink 中,所有签名操作均通过本地授权页面在浏览器内完成。

安装

npm install tronlink-signer

快速开始

import { TronSigner } from "tronlink-signer";

const signer = new TronSigner();
await signer.start();

const { address, network } = await signer.connectWallet();
const { txId, status } = await signer.sendTrx("TXxx...", 1); // status: "success" | "pending" | "failed"
const { txId: txId2, status: s2 } = await signer.signTransaction(tx, "nile", true); // 广播 + 自动确认
const { balance } = await signer.getBalance("TXxx...");

await signer.stop();

API

new TronSigner(config?: Partial<AppConfig>)

创建一个新的签名实例。若未传入配置,则通过 loadConfig() 从环境变量中读取。

signer.start(): Promise<void>

启动用于浏览器授权的本地 HTTP 服务。

signer.stop(): Promise<void>

停止服务并清除所有待处理请求。

signer.getConfig(): AppConfig

返回当前配置信息。

signer.connectWallet(network?, options?): Promise<{ address: string; network: string }>

打开浏览器连接 TronLink 并获取钱包地址与当前网络。如果钱包已连接(同一浏览器标签页仍打开),则会无需用户交互自动完成。

signer.sendTrx(to, amount, network?, options?): Promise<BroadcastResult>

向指定地址发送 TRX,会打开浏览器授权页面供用户确认。返回 { txId, status, error? },其中 status"success""pending""failed"(参见广播结果)。

参数 类型 说明
to string 接收方 TRON 地址(base58 格式)
amount string \| number 发送的 TRX 数量
network TronNetwork 可选,网络覆盖参数
options SignerOptions 可选,传入 { signal } 可启用取消功能

signer.sendTrc20(contractAddress, to, amount, decimals?, network?, options?): Promise<BroadcastResult>

发送 TRC20 代币,会打开浏览器授权页面。返回 { txId, status, error? } — 参见广播结果

参数 类型 说明
contractAddress string TRC20 代币合约地址
to string 接收方 TRON 地址(base58 格式)
amount string 人类可读单位的金额(如 "1.5" 表示 1.5 USDT),精度转换会自动处理
decimals number 可选,代币精度。省略时通过合约的 decimals() 自动检测(推荐 — 可避免 USDD/SUN/JST 等非 6dp 代币出现 10^N 量级错误)
network TronNetwork 可选,网络覆盖参数
options SignerOptions 可选,传入 { signal } 可启用取消功能

signer.signMessage(message, network?, options?): Promise<{ signature: string }>

对纯文本消息进行签名。

signer.signTypedData(typedData, network?, options?): Promise<{ signature: string }>

对 EIP-712 结构化数据进行签名。

const { signature } = await signer.signTypedData({
  domain: { name: "MyDApp", version: "1", chainId: 728126428 },
  types: {
    Greeting: [{ name: "contents", type: "string" }],
  },
  primaryType: "Greeting",
  message: { contents: "Hello Tron!" },
});

signer.signTransaction(transaction, network?, broadcast?, options?): Promise<{ signedTransaction; txId?; status?; error? }>

对原始交易进行签名。当 broadcasttrue 时,签名后的交易会通过 TronLink 广播到链上,且 SDK 会自动轮询链上确认状态 — 可能的 status 取值参见广播结果

参数 类型 说明
transaction Record<string, unknown> 待签名的原始交易对象
network TronNetwork 可选,网络覆盖参数
broadcast boolean 签名后是否广播(默认:false
options SignerOptions 可选 — 取消、确认控制、广播回调
// 仅签名
const { signedTransaction } = await signer.signTransaction(tx);

// 签名、广播并等待确认(默认行为)
const { signedTransaction, txId, status, error } = await signer.signTransaction(tx, "nile", true);
// status === "success" — 已在链上确认
// status === "pending" — 广播成功但在超时时间内未被确认
// status === "failed"  — 链上执行失败;`error` 包含失败原因

// 广播但不等待确认
const result = await signer.signTransaction(tx, "nile", true, { confirm: false });

// 在交易进入内存池时立即收到通知
const result = await signer.signTransaction(tx, "nile", true, {
  onBroadcasted: ({ txId }) => console.log("Broadcast:", txId),
});

广播结果

广播类方法(sendTrxsendTrc20、以及 broadcast: true 时的 signTransaction)均返回 BroadcastResult

interface BroadcastResult {
  txId: string;
  status: "success" | "pending" | "failed";
  error?: string; // 当 status === "failed" 时携带
}

"failed" 表示交易已上链但执行失败(如 OUT_OF_ENERGY、Solidity revert)。它不会抛出异常 — 请检查 status。SDK 仅在广播本身没有发生时才会抛出(签名异常、用户拒绝、网络不可达等)。

signer.waitForTransaction(txId, network?, options?): Promise<{ status; error? }>

轮询网络以确认交易状态。当交易在链上确认时返回 { status: "success" };达到超时时间则返回 { status: "pending" };如果交易 revert / 能量耗尽则返回 { status: "failed", error }

参数 类型 说明
txId string 要监控的交易 ID
network TronNetwork 可选,网络覆盖参数
options WaitForTransactionOptions 可选 — timeoutMs(默认:30000)、signal
const { status, error } = await signer.waitForTransaction(txId, "nile");
if (status === "success") console.log("已在链上确认");
else if (status === "failed") console.warn("执行失败:", error);

提示: 在使用 signTransactionbroadcast: true 时,确认轮询会自动执行 — 除非设置了 confirm: false,否则无需另行调用 waitForTransaction

signer.getBalance(address, network?): Promise<{ balance: string; balanceSun: number }>

查询指定地址的 TRX 余额,无需浏览器授权。

signer.onBrowserDisconnect

用于设置授权页面被关闭或失去连接(心跳超时)时触发的回调。可用于资源清理或重新提示用户。

signer.onBrowserDisconnect = () => {
  console.log("浏览器授权页面已关闭");
};

取消与选项

所有签名方法均支持可选的 SignerOptions

选项 类型 说明
signal AbortSignal 用于取消待处理请求。若已被中止,则不会打开浏览器页面。
confirm boolean 广播后是否等待链上确认(默认:true),仅在 broadcast: true 时生效。
confirmTimeoutMs number 等待确认的最长时间(毫秒,默认:30000)。
onBroadcasted (info) => void 在交易进入内存池后(确认前)触发,回调中的错误会被吞掉。
const controller = new AbortController();

// 30 秒后取消
setTimeout(() => controller.abort(), 30_000);

try {
  const { txId } = await signer.sendTrx("TXxx...", 1, undefined, {
    signal: controller.signal,
  });
} catch (e) {
  // e.message === "CANCELLED_BY_CALLER"
}

工作原理

  1. 你的代码调用签名方法(如 signMessage
  2. 本地 HTTP 服务在端口 3386 启动,并打开单个浏览器标签页显示授权页面
  3. 授权页面通过 TIP-6963 协议发现钱包(回退到 window.tron
  4. 自动解锁钱包,并在需要时切换网络
  5. 对于 connectWallet,如果钱包已连接,会无需用户交互自动完成
  6. 对于签名/发送操作,用户查看交易详情后点击 批准拒绝
  7. 授权页面会将交易类型(TRX 转账、TRC20、TRC721 NFT、质押、委托、投票等)解析为人类可读的展示
  8. TronLink 在浏览器中完成签名
  9. 结果返回给你的代码 — 页面保持打开状态并轮询下一个请求

后续所有操作都会复用同一个浏览器标签页。每个服务会话有唯一 ID — 来自旧会话的浏览器标签页会自动失效。页面会通过心跳检测服务断开并显示会话过期提示。本地服务仅绑定到 127.0.0.1。若端口 3386 已被占用,会自动递增。请求超时时间为 5 分钟。进程退出时(SIGINT/SIGTERM)服务会优雅关闭。

网络

所有签名方法均支持可选的 network 参数:

网络 完整节点地址 区块链浏览器
mainnet(默认) https://api.trongrid.io https://tronscan.org
nile https://nile.trongrid.io https://nile.tronscan.org
shasta https://api.shasta.trongrid.io https://shasta.tronscan.org

环境变量

变量名 说明 默认值
TRON_NETWORK 默认网络 mainnet
TRON_HTTP_PORT 本地 HTTP 服务端口 3386
TRON_API_KEY TronGrid API Key(可选) -

类型定义

type TronNetwork = "mainnet" | "nile" | "shasta";

interface AppConfig {
  network: TronNetwork;
  httpPort: number;
  apiKey?: string;
}

interface NetworkConfig {
  name: string;
  fullHost: string;
  explorerUrl: string;
}

interface SignerOptions {
  signal?: AbortSignal;
  confirm?: boolean;
  confirmTimeoutMs?: number;
  onBroadcasted?: (info: { txId: string; signedTransaction: Record<string, unknown> }) => void;
}

interface WaitForTransactionOptions {
  timeoutMs?: number;
  signal?: AbortSignal;
}

type BroadcastStatus = "success" | "pending" | "failed";

interface BroadcastResult {
  txId: string;
  status: BroadcastStatus;
  error?: string;
}

导出

// 类
export { TronSigner } from "./tron-signer.js";

// 配置
export { NETWORKS, DEFAULT_HTTP_PORT, REQUEST_TIMEOUT_MS, loadConfig } from "./config.js";

// 类型
export type {
  TronNetwork, NetworkConfig, AppConfig,
  PendingRequestType, PendingRequest,
  SendTrxData, SendTrc20Data,
  SignMessageData, SignTypedDataData, SignTransactionData,
  SignerOptions, WaitForTransactionOptions,
  BroadcastStatus, BroadcastResult,
} from "./types.js";