Tronwallet Adapter
概述
Tronwallet Adapter 是包含了一系列用于 Tron DApp 的钱包适配器和组件。通过开箱即用的组件和统一的方法,开发人员可以轻松地与多种钱包进行交互,包括选择/连接/断开
钱包以及签名消息或交易。
适配器
钱包适配器可以让你通过统一的 API 访问 TRON 钱包。
目前支持 TRON 网络的钱包有很多,比如TronLink、Ledger等等。 不同的钱包,甚至同一个钱包的不同版本可能有不同的接口。 Adapters 相关包的目的就是屏蔽这些差异并为 DApp 开发人员提供统一的接口。 如果 DApps 使用了 Tronwallet Adapter 代码,他们就不需要频繁的更改其代码。
例如,如果你想连接到不同的钱包,你必须使用不同的方法:
// TronLink
window.tronLink.request({ method: 'tron_requestAccounts' });
// Ledger
const transport = await TransportWebHID.create();
const app = new Trx(transport);
// WalletConnect
const wallet = new WalletConnectWallet({
network: this._config.network,
options: this._config.options,
});
使用适配器,您可以为不同的钱包使用统一的 API:
// TronLink
const tronlinkAdapter = new TronLinkAdapter();
await tronlinkAdapter.connect();
await tronlinkAdapter.signMessage(message);
// Ledger
const ledgerAdapter = new LedgerAdapter();
await ledgerAdapter.connect();
await ledgerAdapter.signMessage(message);
// WalletConnect
const walletconnectAdapter = new WalletConnectAdapter();
await walletconnectAdapter.connect();
await walletconnectAdapter.signMessage(message);
React Hooks
Adapter wallet hooks 会导出一个 useWallet()
hook 用于管理钱包的全局状态,包括当前选择的钱包、连接状态、地址等。 同时它也提供了一些与钱包交互的方法。
当你的 dapp 支持多个钱包时,借助 useWallet()
hook 你可以轻松地:
- 选择要使用的钱包
- 连接到选定的钱包
- 断开与所选钱包的连接
- 调用所选钱包的
signMessage
或者signTransaction
例子:
function Comp() {
const { wallet, address, connected, select, connect, disconnect, signMessage, signTransaction } = useWallet();
return (
<div>
<button onClick={() => select('TronLink')}>Select Wallet</button>
<button onClick={connect}>Connect</button>
<button onClick={disconnect}>Disconnect</button>
<button onClick={() => signMessage('Hello World')}>Sign Message</button>
</div>
);
}
React UI 组件
useWallet()
只管理钱包的状态。 除此之外,我们也提供了一组开箱即用的组件来帮助您与钱包进行交互:
WalletSelectButton
:选择钱包的钱包对话框WalletConnectButton
:连接到选定的钱包。WalletDisconnectButton
:断开与所选钱包的连接。WalletActionButton
:具有多种功能的按钮,包括选择/连接/断开连接
。
React 的演示参考这里
演示图片如下:
Wallet Adapters
@tronweb3/tronwallet-adapters
提供了多个钱包适配器,以帮助开发人员使用统一的 API 连接到 Tron 钱包,例如 TronLink 。
支持的钱包
@tronweb3/tronwallet-adapters
会导出每个钱包的适配器,你可以选择使用这个包或者使用你想用的个人钱包适配器。
@tronweb3/tronwallet-adapters
:包括所有钱包适配器。@tronweb3/tronwallet-adapter-tronlink
:TronLink 适配器。@tronweb3/tronwallet-adapter-tokenpocket
: TokenPocket 适配器.@tronweb3/tronwallet-adapter-bitkeep
: BitKeep 适配器.@tronweb3/tronwallet-adapter-okxwallet
: Okx Wallet 适配器.@tronweb3/tronwallet-adapter-walletconnect
:WalletConnect 适配器。@tronweb3/tronwallet-adapter-ledger
:Ledger 适配器。
安装
npm install @tronweb3/tronwallet-abstract-adapter @tronweb3/tronwallet-adapters
# or pnpm install @tronweb3/tronwallet-abstract-adapter @tronweb3/tronwallet-adapters
# or yarn install @tronweb3/tronwallet-abstract-adapter @tronweb3/tronwallet-adapters
用法
React
你可以在组件中使用 @tronweb3/tronwallet-adapters
,也可以使用 useMemo
缓存 adapter
对象来提高性能。
import { TronLinkAdapter } from '@tronweb3/tronwallet-adapters';
function App() {
const [connectState, setConnectState] = useState(AdapterState.NotFound);
const [account, setAccount] = useState('');
const [netwok, setNetwork] = useState({});
const [signedMessage, setSignedMessage] = useState('');
const adapter = useMemo(() => new TronLinkAdapter(), []);
useEffect(() => {
setConnectState(adapter.state);
setAccount(adapter.address!);
adapter.on('connect', () => {
setAccount(adapter.address!);
});
adapter.on('stateChanged', (state) => {
setConnectState(state);
});
adapter.on('accountsChanged', (data) => {
setAccount(data);
});
adapter.on('chainChanged', (data) => {
setNetwork(data);
});
adapter.on('disconnect', () => {
// when disconnect from wallet
});
return () => {
// remove all listeners when components is destroyed
adapter.removeAllListeners();
};
}, []);
async function sign() {
const res = await adapter!.signMessage('helloworld');
setSignedMessage(res);
}
return (
<div className="App">
<div>connectState: {connectState}</div>
<div>current address: {account}</div>
<div>current network: {JSON.stringify(netwok)}</div>
<button disabled={adapter.connected} onClick={() => adapter.connect()}>
Connect to TronLink
</button>
<button onClick={sign}>sign message</button>
<br />
SignedMessage: {signedMessage}
</div>
);
}
Vue
在 Vue 中,由于 created/mounted
hook 只执行一次,你可以在 mounted
或 created
hook 中初始化适配器。
// vue2.x
export default {
created() {
this.adapter = new TronLinkAdapter();
this.adapter.on('connect', () => {
// here you can do something
});
},
beforeDestroy() {
this.adapter.removeAllListeners();
}
}
// vue3
export default {
setup() {
onMounted(function() {
const adapter = new TronLinkAdapter();
adapter.on('connect', () => {
// here you can do something
});
});
onBeforeUnmount(function() {
// remove all listeners when components is destroyed
adapter.removeAllListeners();
});
return {};
}
}
API参考
适配器接口
Adapter
类为指定钱包的所有适配器定义了公共接口。
构造函数
constructor(config)
: 适配器构造函数。 详细的config,参考适配器部分。
属性
name
:适配器的名称。url
:适配器钱包的网址。icon
: 适配器钱包的图标。readyState
:适配器对应钱包的三种状态:Loading
:正在循环检测中。NotFound
:检测完毕后发现钱包未安装。Found
:检测完毕后发现钱包已安装。
address
: 适配器连接的当前账户地址。connecting
:适配器是否正在尝试连接到钱包。connected
:适配器是否连接到了钱包。
方法
connect(): Promise<void>
:连接到钱包。disconnect(): Promise<void>
:断开与钱包的连接。signMessage(message): Promise<string>
:对消息进行签名,返回签名结果。signTransaction(transaction)
:对交易进行签名,返回签名结果。multiSign(transaction, privateKey: string | null, permissionId?)
: 对多签交易进行签名.- 如果
privateKey
不是null
, 则使用该 privateKey来签名而不是使用 TronLink 签名。. - 如果
permissionId
没有提供, 默认使用0
(OwnerPerssion). - 关于多签的更多信息请查阅 文档.
- 如果
switchChain(chainId: string): Promise<void>;
: 请求 TronLink 切换当前使用的网络,需要传入chainId
.
事件
Adapter
继承了 eventemitter3
包中的 EventEmitter
类,可以通过 adapter.on('connect', function() {})
来监听事件。
事件如下:
connect(address)
: 当适配器连接到钱包时触发,参数为当前账户的地址。disconnect()
:当适配器与钱包断开连接时触发。stateChanged(state: AdapteraState)
: 当适配器的状态改变时触发。参数是适配器的状态:
enum AdapterState {
NotFound = 'NotFound',
Disconnect = 'Disconnected',
Connected = 'Connected',
}
accountsChanged(address: string)
:当用户更改钱包中当前选择的帐户时触发, 参数为新账户地址。chainChanged(chainInfo: ChainInfo)
:当用户更改钱包中当前选定的链时触发, 参数为新的网络配置:
interface ChainInfo {
node: {
chain: string;
fullNode: string;
solidityNode: string;
eventServer: string;
};
}
error(ConnectionError)
:当调用适配器的方法时出现错误时触发。 WalletError 类型定义如下。
WalletError
WalletError
是一个超类,它定义了适配器出错时的错误类型,所有的错误类型都是从这个类继承而来。
开发者可以根据错误实例查看错误类型。
try {
// do something here
} catch (error: WalletError) {
if (error instanceof WalletNotFoundError) {
console.log('Wallet is not found');
}
}
所有错误如下:
WalletNotFoundError
:未安装钱包时发生。WalletNotSelectedError
:连接但没有选择钱包时发生。WalletDisconnectedError
:钱包断开连接时发生。 当调用 signMessage() 或 signTransaction() 时不会自动连接钱包。WalletConnectionError
:尝试连接钱包时发生。WalletDisconnectionError
:尝试断开钱包连接时发生。WalletSignMessageError
:在调用signMessage()
时发生。WalletSignTransactionError
:调用signTransaction()
时发生。WalletWalletLoadError
:WalletConnectAdapter 加载钱包时发生。WalletWindowClosedError
:WalletConnectAdapter 的 walletconnect QR 窗口关闭时发生。WalletSwitchChainError
: 调用switchChain()
时发生. 目前只支持 TronLink。WalletGetNetworkError
: 调用network()
获取网络信息时发生。
TronLinkAdapter
Constructor(config: TronLinkAdapterConfig)
interface TronLinkAdapterConfig {
/**
* The icon of your dapp. Used when open TronLink app in mobile device browsers.
*/
dappIcon?: string;
/**
* The name of your dapp. Used when open TronLink app in mobile device browsers.
*/
dappName?: string;
}
-
network()
方法可用于获取当前所使用的网络节点信息。 返回的Network
类型如下所示:export enum NetworkType { Mainnet = 'Mainnet', Shasta = 'Shasta', Nile = 'Nile', /** * When use custom node */ Unknown = 'Unknown', } export type Network = { networkType: NetworkType; chainId: string; fullNode: string; solidityNode: string; eventServer: string; };
-
DApp 不支持的
disconnect
。 由于 TronLinkAdapter 不支持通过 DApp 网站断开连接,因此调用adapter.disconnect()
不会真正断开与 TronLink 的连接。 -
在移动浏览器中自动打开 TronLink 应用程序。 如果开发者在手机浏览器中调用
connect()
方法,会在TronLink app 中打开 DApp 获取 TronLink 钱包。
其它钱包适配器
其它钱包适配器的构造函数参数配置可以参考它们的 README
文档.
- TokenPocketAdapter
- BitKeepAdapter
- OkxWalletAdapter
- WalletConnectAdapter
- LedgerAdapter
Adapter React Hooks
@tronweb3/tronwallet-adapter-react-hooks
提供了 useWallet()
hook, 可以让开发者方便地连接钱包并监听钱包连接状态的变化。
安装
npm install @tronweb3/tronwallet-adapter-react-hooks @tronweb3/tronwallet-abstract-adapter @tronweb3/tronwallet-adapters
# or pnpm install @tronweb3/tronwallet-adapter-react-hooks @tronweb3/tronwallet-abstract-adapter @tronweb3/tronwallet-adapters
# or yarn install @tronweb3/tronwallet-adapter-react-hooks @tronweb3/tronwallet-abstract-adapter @tronweb3/tronwallet-adapters
用法
@tronweb3/tronwallet-adapter-react-hooks
使用 React 的 Context
来维护共享数据。 因此,开发人员需要将 App
内容包装在 WalletProvider
中。
你可以使用 onError
回调函数来处理各种错误,例如 WalletNotFoundError
、WalletConnectionError
。
import { useWallet, WalletProvider } from '@tronweb3/tronwallet-adapter-react-hooks';
import { WalletDisconnectedError, WalletError, WalletNotFoundError } from '@tronweb3/tronwallet-abstract-adapter';
import toast, { Toaster } from 'react-hot-toast';
function App() {
// use `react-hot-toast` npm package to notify user what happened here
function onError(e: WalletError) {
if (e instanceof WalletNotFoundError) {
toast.error(e.message);
} else if (e instanceof WalletDisconnectedError) {
toast.error(e.message);
} else toast.error(e.message);
}
return (
<WalletProvider onError={onError}>
<ConnectComponent></ConnectComponent>
<Profile></Profile>
</WalletProvider>
);
}
function ConnectComponent() {
const { connect, disconnect, select, connected } = useWallet();
return (<div>
<button type="button" onClick={() => select('TronLink' as any)}> Select TronLink</button>
<button type="button" disabled={connected} onClick={connect}>Connect</button><br>
<button type="button" disabled={!connected} onClick={disconnect}>Disconnect</button>
</div>);
}
function Profile() {
const { address, connected, wallet } = useWallet();
return (<div>
<p> <span>Connection Status:</span> {connected ? 'Connected' : 'Disconnected'}</p>
<p> <span>Your selected Wallet:</span> {wallet?.adapter.name} </p>
<p> <span>Your Address:</span> {address} </p>
</div>);
}
API 参考
WalletProvider
和 useWallet
像 Context.Provider
和 useContext()
一样协同工作。 底层 WalletProviderContext
通过 useWallet
获取,它的主要功能是维护一些状态。 所以开发者需要用 WalletProvider
包装应用组件。
function App() {
return (
<div>
<WalletProvider>/* here is application components */</WalletProvider>
</div>
);
}
WalletProvider
Props
WalletProvider
Propsadapters
- 是否必需:
false
- 类型:
Adapter[]
- 默认值:
[ new TronLinkAdapter() ]
用于指定支持哪些钱包适配器。 所有钱包适配器都可以从@tronweb3/tronwallet-adapters
包或它们的独立包中导入。
- 例子
import { TronLinkAdapter } from '@tronweb3/tronwallet-adapters';
function App() {
const adapters = useMemo(() => [new TronLinkAdapter()]);
return (
<div>
<WalletProvider adapters={adapters}>/* here is application components */</WalletProvider>
</div>
);
}
onError
- 是否必需:
false
- 类型:
(error:WalletError):void
- 默认值:
function(error) { console.error(error); }
用于处理使用钱包时出现的错误。 开发人员可以使用回调函数,根据error
类型告诉用户发生了什么。所有错误类型都可以在 这里 查找。
- 例子
functon onError(e) {
if (e instanceof WalletNotFoundError) {
console.error(e.message);
} else if (e instanceof WalletDisconnectedError) {
console.error(e.message);
} else console.error(e.message);
}
autoConnect
- 是否必需:
false
- 类型:
boolean
- 默认值:
true
加载页面并选择钱包时是否自动连接到指定钱包。
localStorageKey
- 是否必需:
false
- 类型:
string
- 默认值:
tronAdapterName
指定用于在 localStorage 中缓存钱包名称的键名。 当用户选择钱包时,应用程序会将所选钱包存储到 localStorage 中。
useWallet()
useWallet
是一个 React Hook,它提供了一组属性和方法用于选择和连接钱包、获取钱包状态等。
useWallet()
必须在WalletProvider
的子组件中使用!
useWallet
返回参数
useWallet
返回参数autoConnect
- 类型:
boolean
与传递给WalletProvider
的autoConnect
属性同步。
wallet
- 类型:
Wallet | null
当前选择的钱包。如果没有选择钱包,则该值为null
。
Wallet
定义如下:
interface Wallet {
adapter: Adapter; // wallet adapter
state: AdapterState;
}
enum AdapterState {
NotFound = 'NotFound',
Disconnect = 'Disconnected',
Connected = 'Connected',
}
address
- 类型:
string | null
当前选择的钱包地址。 如果没有选择钱包,则值为null
。
wallets
- 类型:
Wallet[]
初始化WalletProvider
时传入的 adapters 相对应的 wallet 数组
connecting
- 类型:
boolean
指示是否正在连接到钱包。
connected
- 类型:
boolean
表明是否与钱包连接。
disconnecting
- 类型:
boolean
指示是否正在断开与钱包的连接。
select
- 输入:
(walletAdapterName: AdapterName) => void
通过 walletAdapterName 选择一个钱包。 可以在 这里 找到有效的适配器
connect
- 类型:
() => Promise<void>
连接到当前选择的钱包。
disconnect
- 类型:
() => Promise<void>
断开与当前所选钱包的连接。
signTransaction
- 类型:
(transaction: Transaction) => Promise<SignedTransaction>
签名未签名的交易。 此方法与 TronWeb API 相同。
signMessage
- 输入:
(message: string) => Promise<string>
签名消息。
例子
import { useWallet } from '@tronweb3/tronwallet-adapter-react-hooks';
function Content() {
const { connect, disconnect, select, connected } = useWallet();
return (
<div>
<button type="button" onClick={() => select('TronLink Adapter')}>
Select TronLink
</button>
<button type="button" disabled={connected} onClick={connect}>
Connect
</button>
<button type="button" disabled={!connected} onClick={disconnect}>
Disconnect
</button>
</div>
);
}
Adapter React UI 组件
@tronweb3/tronwallet-adapter-react-ui 提供了一组开箱即用的组件,可以轻松选择、更改、连接和断开钱包。
这个包依赖于@tronweb3/tronwallet-adapter-react-hooks
来工作。 因此,开发人员必须将 App
内容包装在 WalletProvider
中。
安装
npm install @tronweb3/tronwallet-adapter-react-ui @tronweb3/tronwallet-adapter-react-hooks @tronweb3/tronwallet-abstract-adapter @tronweb3/tronwallet-adapters
# or pnpm install @tronweb3/tronwallet-adapter-react-ui @tronweb3/tronwallet-adapter-react-hooks @tronweb3/tronwallet-abstract-adapter @tronweb3/tronwallet-adapters
# or yarn install @tronweb3/tronwallet-adapter-react-ui @tronweb3/tronwallet-adapter-react-hooks @tronweb3/tronwallet-abstract-adapter @tronweb3/tronwallet-adapters
用法
@tronweb3/tronwallet-adapter-react-ui
通过 Context.Provider
提供Select Wallet Modal
。 开发人员必须将 App
内容包装在 WalletProvider
和 WalletModalProvider
中。
import { useWallet, WalletProvider } from '@tronweb3/tronwallet-adapter-react-hooks';
import { WalletModalProvider, WalletActionButton } from '@tronweb3/tronwallet-adapter-react-ui';
import '@tronweb3/tronwallet-adapter-react-ui/style.css';
import { WalletDisconnectedError, WalletError, WalletNotFoundError } from '@tronweb3/tronwallet-abstract-adapter';
import toast, { Toaster } from 'react-hot-toast';
function App() {
// here use `react-hot-toast` npm package to notify user what happened
function onError(e: WalletError) {
if (e instanceof WalletNotFoundError) {
toast.error(e.message);
} else if (e instanceof WalletDisconnectedError) {
toast.error(e.message);
} else toast.error(e.message);
}
return (
<WalletProvider onError={onError}>
<WalletModalProvider>
<ConnectComponent></ConnectComponent>
<Profile></Profile>
</WalletModalProvider>
</WalletProvider>
);
}
function ConnectComponent() {
const { connect, disconnect, select, connected } = useWallet();
return <WalletActionButton></WalletActionButton>;
}
function Profile() {
const { address, connected, wallet } = useWallet();
return (
<div>
<p>
<span>Connection Status:</span> {connected ? 'Connected' : 'Disconnected'}
</p>
<p>
<span>Your selected Wallet:</span> {wallet?.adapter.name}
</p>
<p>
<span>Your Address:</span> {address}
</p>
</div>
);
}
API参考
WalletModalProvider 和 useWalletModal
WalletModalProvider
通过 Context.Provider
提供 Select Wallet Modal
。 模式可以通过useWalletModal
控制。
function App() {
const { visible, setVisible } = useWalletModal();
function toggle() {
setVisible((visible) => !visible);
}
return (
<div>
<button onClick={toggle}>{visible ? 'Close Modal' : 'Open Modal'}</button>
</div>
);
}
WalletConnectButton
连接到所选钱包的按钮。 该按钮在以下情况下被禁用:
- 没有选择钱包
- 正在连接到钱包
- 已连接
- 被 props 禁用
Props
type ButtonProps = PropsWithChildren<{
className?: string,
disabled?: boolean,
onClick?: (e: MouseEvent<HTMLButtonElement>) => void,
style?: CSSProperties,
tabIndex?: number,
icon?: string,
}>;
WalletDisconnectButton
连接到所选钱包的按钮。 该按钮在以下情况下被禁用:
- 没有选择钱包
- 正在连接到钱包
- 被 props 禁用
Props
与 WalletConnectButton
相同。
WalletSelectButton
打开Select Wallet Modal
的按钮。
Props
与WalletConnectButton
相同。
WalletActionButton
具有多种功能的按钮,包括:
- 选择钱包
- 连接到钱包
- 断开与钱包的连接
- 显示当前选择的钱包和地址
- 复制地址
推荐使用该组件连接钱包。
演示如下:
Props
与WalletConnectButton
相同。
Updated 13 days ago