主动请求TronLink插件功能

连接网站 TIP-1102

简介

TronLink可用于管理钱包私钥,dapp在进行一些需签名的操作前,需要连接TronLink,并通过TronLink获取用户签名授权。此协议在于显式地告知用户dapp主动连接TronLink的行为,并获取用户的授权同意。 此方法遵循以太坊EIP-1102协议。

技术规范

代码示例
try {
  await tron.request({method: 'eth_requestAccounts'});
} catch (e) {}
返回值

如果成功,返回一个数组,数组只有一个元素,为同意连接的当前TronLink账户。如: ['TMVQGm1qAQYVdetCeGRRkTWYYrLXuHK2HC']

如果失败,则会返回错误码及报错信息。详见“错误码”部分。

错误码
错误码名称描述
4001用户拒绝请求用户通过点击“拒绝”按钮,或关闭弹窗,都会触发该错误码
-32002处于其他流程中当前dapp存在其他流程,无法执行当前请求
-32602参数不合规传入的参数不合规,或者传入了额外的参数
4200不支持此方法不支持此方法

交互流程

触发eth_requestAccounts之后,如果TronLink处于锁屏状态,会弹出锁屏弹窗:

image

解锁后,或者TronLink已经提前解锁,会打开连接确认的弹窗:

image

连接网站(旧版)

该连接方法已不推荐使用,之后的连接网站方法请参考连接网站 TIP-1102

简介

TronLink提供外部发起Trx转账,合约签名,授权等功能,基于安全的考虑, 需要用户在关键操作前先对发起请求的Dapp进行【连接网站】授权,在授权成功后才允许操作。 所以Dapp要先进行【连接网站】操作,等待用户允许后,方能发起需要授权的请求。

技术规范

代码示例
const res = await tronWeb.request(
  {
    method: 'tron_requestAccounts',
    params: {
      websiteIcon: '<WEBSITE ICON URI>',
      websiteName: '<WEBSITE NAME>',
    } as RequestAccountParams,
  }
);
参数
interface RequestAccountsParams {
  websiteIcon?: string;
  websiteName?: string;
}
  • method: tron_requestAccounts 固定的字符串
  • params: RequestAccountParams类型,具体参数如下
    • websiteIcon: DApp网站的Icon的URI, 具体会展示在用户已连接网站列表中
    • websiteName: dapp网站名称
返回值

类型说明

interface ReqestAccountsResponse {
  code: 200 | 4000 | 4001,
  message: string
}
返回码描述返回消息
钱包处于锁定状态空字符串
200网站此前已被用户允许连接The site is already in the whitelist
200用户同意连接User allowed the request.
4000当前请求前已经有同一个dapp发起了连接网站请求,并且弹窗仍未关闭Authorization requests are being processed, please do not resubmit
4001用户拒绝连接User rejected the request

获取TronLink的provider TIP-6963

简介

当多个钱包同时存在,会出现对window.tron对象的抢占行为。为了保证DApp可以获取到特定钱包的provider,所以实现TIP-6963规范

技术规范

代码示例
interface TIP1193Provider {
  request: (args: RequestArguments) => Promise<unknown>;
  on(event: string, listener: (...args: any[]) => void): this;
  removeListener(event: string, listener: (...args: any[]) => void): this;
  tronWeb: TronWeb;
  [key: `is${string}`]: boolean;
}

/**
 * Represents the assets needed to display a wallet
 */
interface TIP6963ProviderInfo {
  uuid: string;
  name: string;
  icon: string;
  rdns: string;
}

interface TIP6963ProviderDetail {
  info: TIP6963ProviderInfo;
  provider: TIP1193Provider;
}

// Announce Event dispatched by a Wallet
interface TIP6963AnnounceProviderEvent extends CustomEvent {
  type: "TIP6963:announceProvider";
  detail: TIP6963ProviderDetail;
}

// The DApp listens to announced providers
window.addEventListener(
  "TIP6963:announceProvider",
  (event: TIP6963AnnounceProviderEvent) => {

    // Confirm if it is a Tronlink UUID
    if (event.detail.info.rdns !== 'org.tronlink.www' || event.detail.info.name !== 'TronLink') {
      console.error('it is NOT TronLink provider');
      return;
    }

    // event.detail.provider === window.tron
    const tronProvider = event.detail.provider;

    tronProvider.on('accountsChanged', (accountArray) => {
      console.log('tip-6963 accountsChanged', accountArray);
    })
  }
);

// The DApp dispatches a request event which will be heard by 
// Wallets' code that had run earlier
window.dispatchEvent(new Event("TIP6963:requestProvider"));

DApp按照上述代码实现后,可以精准获取到TronLink提供的provider。 TronLink 的 rdns 是 org.tronlink.www, name 是 TronLink

普通转账

简介

dapp需要用户发起一笔trx转账

前提: dapp开发者完成连接网站请求,用户同意连接

波场网络上发起转账需要3个步骤,

  1. 构造转账交易
  2. 对交易进行签名
  3. 对签名后的交易进行广播

在这里,TronLink介入的是第2步签名的部分,1,3两步需要开发者使用tronWeb完成

技术规范

代码示例
if (window.tronLink.ready) {
  const tronweb = tronLink.tronWeb;
  const fromAddress = tronweb.defaultAddress.base58;
  const toAddress = "TDvSsdrNM5eeXNL3czpa6AxLDHZA9nwe9K";
  const tx = await tronweb.transactionBuilder.sendTrx(toAddress, 10, fromAddress); // 步骤1
  try {
    const signedTx = await tronweb.trx.sign(tx); // 步骤2
    await tronweb.trx.sendRawTransaction(signedTx); // 步骤3
  } catch (e) {}
}

当代码执行到await tronweb.trx.sign(tx);时,TronLink钱包会提示弹窗,需要用户进行确认,如下图

image

如果用户在弹窗中选择【拒绝】,则会抛出异常,开发者可捕获此异常进行业务处理

如果用户在弹窗中选择【签名】,dapp可以拿到签名后的交易,继续进行广播

多签转账

简介

此处可参考普通转账

技术规范

代码示例
if (window.tronLink.ready) {
  const tronweb = tronLink.tronWeb;
  const toAddress = "TDvSsdrNM5eeXNL3czpa6AxLDHZA9nwe9K";
  const activePermissionId = 2;
  const tx = await tronweb.transactionBuilder.sendTrx(
      toAddress, 10, 
      { permissionId: activePermissionId}
  ); // 步骤1
  try {
    const signedTx = await tronweb.trx.multiSign(tx, undefined, activePermissionId); // 步骤2
    await tronweb.trx.sendRawTransaction(signedTx); // 步骤3
  } catch (e) {}
}

如果用户在弹窗中选择【拒绝】,则会抛出异常,开发者可捕获此异常进行业务处理

如果用户在弹窗中选择【签名】,dapp可以拿到签名后的交易,继续进行广播

消息签名

简介

dapp需要用户对一个hex消息签名,签名后消息转发给后端进行验签,以此判断用户合法登陆

前提

dapp开发者完成【连接网站】请求,用户同意连接

技术规范

代码示例
if (window.tronLink.ready) {
  const tronweb = tronLink.tronWeb;
  try {
    const message = "0x01EF"; // any hex string
    const signedString = await tronweb.trx.signMessageV2(message);
  } catch (e) {}
}
参数

tronLink.tronWeb.trx.signMessageV2接收一个十六进制的字符串作为参数,该字符串表示当前待签名的内容

返回值

如果用户在弹窗中选择签名, dapp可以得到签名后的十六进制字符串, 比如:

0xaa302ca153b10dff25b5f00a7e2f603c5916b8f6d78cdaf2122e24cab56ad39a79f60ff3916dde9761baaadea439b567475dde183ee3f8530b4cc76082b29c341c

如果报错,则会返回如下信息

Uncaught (in promise) Invalid transaction provided

交互流程

当代码执行到await tronweb.trx.signMessageV2(message);时,TronLink钱包会提示弹窗,需要用户进行确认, 如下图, 其中消息内容会以hex的方式展示

image

如果用户在弹窗中选择【拒绝】,则会抛出异常,开发者可捕获此异常进行业务处理

添加资产

简介

dapp提供按钮给用户, 直接将指定的Token添加到用户插件的资产展示列表中

技术规范

代码示例
const res = await tronWeb.request(
  {
    method: 'wallet_watchAsset',
    params: {
      type: 'TRC20',
      options: {
          address: 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t'
      }
    } as WatchAssetParams,
  }
);
参数
interface WatchAssetParams {
  type: 'trc10' | 'trc20' | 'trc721';
  options: {
    address: string;
    symbol?: string;
    decimals?: number;
    image?: string;
  }
}
  • method: wallet_watchAsset 固定的字符串
  • params: WatchAssetParams,具体参数如下
  • type: 目前只支持’trc10′, ‘trc20’, ‘trc721’三种
  • options:
    • address: token的合约地址 或者 token id, 必传
    • symbol: 占位(目前未使用),可选
    • decimals: 占位(目前未使用),可选
    • image: 占位(目前未使用),可选
返回值

此方法没有返回值

交互流程

添加TRC10资产
if (window.tronLink.ready) {
  const tronweb = tronLink.tronWeb;
  try {
    tronweb.request({
      method: 'wallet_watchAsset',
      params: {
        type: 'trc10',
        options: {
          address: '1002000'
        },
      },
    });
  } catch (e) {}
}

代码执行时,TronLink会弹出添加窗口,用户点击确定添加TRC10资产,或者取消添加。

image

点击”添加”按钮,资产被添加到资产列表,如下图所示。

image
添加TRC20资产
if (window.tronLink.ready) {
  const tronweb = tronLink.tronWeb;
  try {
    tronweb.request({
      method: 'wallet_watchAsset',
      params: {
        type: 'trc20',
        options: {
          address: 'TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9'
        },
      },
    });
  } catch (e) {}
}

代码执行时,TronLink会弹出添加窗口,用户点击确定添加TRC20资产,或者取消添加。

image

点击”添加”按钮,资产被添加到资产列表,如下图所示。

image
添加TRC721资产
if (window.tronLink.ready) {
  const tronweb = tronLink.tronWeb;
  try {
    tronweb.request({
      method: 'wallet_watchAsset',
      params: {
        type: 'trc721',
        options: {
          address: 'TVtaUnsgKXhTfqSFRnHCsSXzPiXmm53nZt'
        },
      },
    });
  } catch (e) {}
}

代码执行时,TronLink会弹出添加窗口,用户点击确定添加TRC20资产,或者取消添加。

image

点击”添加”按钮,资产被添加到资产列表,如下图所示。

image

切换网络 TIP-3326

简介

大部分dapp都会在特定的链上提供服务。dapp可以通过调用本协议,告诉TronLink期望使用的链,TronLink会弹出弹窗告知用户即将切换的链,用户可以选择是否同意切换。 在用户同意切换后,dapp可以基于目标链,提供正常的dapp服务。 本协议遵循以太坊EIP-3326协议。

技术规范

代码示例
try {
  await tronLink.request({
    method: 'wallet_switchEthereumChain',
    params: [{chainId: '0x2b6653dc'}]
  });
} catch (e) {}
参数

params接受一个只有单一元素的数组,单一元素为SwitchTronChainParameter类型:

interface SwitchTronChainParameter {
  chainId: string;
}
  • 目前只支持如下chainId:
  • mainnet(主网): 0x2b6653dc
  • shasta(shasta测试网): 0x94a9059e
  • nile(nile测试网): 0xcd8690dc
  • chainId的值大小写敏感。
返回值

如果成功,返回null。 如果失败,则会返回错误码及报错信息。详见“错误码”部分。

错误码
错误码名称描述
4001用户拒绝请求用户通过点击“拒绝”按钮,或关闭弹窗,都会触发该错误码
4902不合法chainId目前只支持部分chainId,详见“目前支持的chainId”部分
-32002处于其他流程中当前dapp存在其他流程,无法执行当前请求
-32602参数不合规传入的参数不合规,或者传入了额外的参数
4200不支持此方法不支持此方法

交互流程

触发wallet_switchEthereumChain之后,如果TronLink处于锁屏状态,会弹出锁屏弹窗:

image

解锁后,或者TronLink已经提前解锁,会打开连接确认的弹窗:

image