用于 React 的 TON Connect
推荐用于React应用程序的SDK是UI React SDK。它是一个React组件,提供了与TON Connect交互的高级方式。
实现
1. 安装
要开始将TON Connect集成到您的DApp中,您需要安装@tonconnect/ui-react
包。您可以使用npm或yarn来实现这一目的:
- npm
- Yarn
- pnpm
npm i @tonconnect/ui-react
yarn add @tonconnect/ui-react
pnpm add @tonconnect/ui-react
2. TON Connect初始化
安装包之后,您应该为您的应用程序创建一个manifest.json
文件。有关如何创建manifest.json文件的 更多信息,请参阅此处。
创建manifest文件后,将TonConnectUIProvider导入到您的Mini App的根目录,并传入manifest URL:
import { TonConnectUIProvider } from '@tonconnect/ui-react';
export function App() {
return (
<TonConnectUIProvider manifestUrl="https://<YOUR_APP_URL>/tonconnect-manifest.json">
{ /* Your app */ }
</TonConnectUIProvider>
);
}
3. 连接到钱包
添加TonConnectButton
。TonConnect按钮是初始化连接的通用UI组件。连接钱包后,它会变成钱包菜单。建议将其放置在应用程序的右上角。
export const Header = () => {
return (
<header>
<span>My App with React UI</span>
<TonConnectButton />
</header>
);
};
您还可以为按钮添加className和style属性。请注意,您不能给TonConnectButton传递子组件:
<TonConnectButton className="my-button-class" style={{ float: "right" }}/>
此外,您始终可以使用useTonConnectUI
hook和connectWallet方法手动初始化连接。
export const Header = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<header>
<span>My App with React UI</span>
<button onClick={() => tonConnectUI.openModal()}>
Connect Wallet
</button>
</header>
);
};
连接特定钱包
要打开特定钱包的模态窗口,请使用 openSingleWalletModal()
方法。该方法将钱包的 app_name
作为参数(请参阅 wallets-list.json 文件),并打开相应的钱包模态窗口。一旦模式窗口成功打开,它将返回一个解析的 promise。
<button onClick={() => tonConnectUI.openSingleWalletModal('tonwallet')}>
Connect Wallet
</button>
重定向
5. UI自定义
要定制模态窗口的UI,您可以使用useTonConnectUI
hook和setOptions
函数。详见Hooks部分中关于useTonConnectUIhook的更多信息。
<TonConnectUIProvider
// ... other parameters
actionsConfiguration={{
twaReturnUrl: 'https://t.me/<YOUR_APP_NAME>'
}}
>
</TonConnectUIProvider>
如果您想在React应用程序中使用一些低级TON Connect UI SDK的特性,您可以使用@tonconnect/ui-react
包中的hook。
useTonAddress
使用它来获取用户当前的ton钱包地址。传递布尔参数isUserFriendly来选择地址的格式。如果钱包未连接,hook将返回空字符串。
钩子(Hooks)
如果您想在 React 应用程序中使用一些底层 TON Connect UI SDK 功能,可以使用 @tonconnect/uii-react
包中的钩子。
useTonAddress
查看所有钱包属性
import { useTonAddress } from '@tonconnect/ui-react';
export const Address = () => {
const userFriendlyAddress = useTonAddress();
const rawAddress = useTonAddress(false);
return (
userFriendlyAddress && (
<div>
<span>User-friendly address: {userFriendlyAddress}</span>
<span>Raw address: {rawAddress}</span>
</div>
)
);
};
useTonConnectModal
使用此钩子可访问打开和关闭模态窗口的功能。钩子会返回一个对象,其中包含当前模式窗口状态以及打开和关闭模式窗口的方法。
import { useTonConnectModal } from '@tonconnect/ui-react';
export const ModalControl = () => {
const { state, open, close } = useTonConnectModal();
return (
<div>
<div>Modal state: {state?.status}</div>
<button onClick={open}>Open modal</button>
<button onClick={close}>Close modal</button>
</div>
);
};
useTonWallet
此外,您还可以访问所连接钱包的更多具体细节,如名称、图像和其他属性(请参阅 WalletInfo 接口)。
import { useTonWallet } from '@tonconnect/ui-react';
export const Wallet = () => {
const wallet = useTonWallet();
return (
wallet && (
<div>
<span>Connected wallet address: {wallet.account.address}</span>
<span>Device: {wallet.device.appName}</span>
<span>Connected via: {wallet.provider}</span>
{wallet.connectItems?.tonProof?.proof && <span>Ton proof: {wallet.connectItems.tonProof.proof}</span>}
<div>Connected wallet info:</div>
<div>
{wallet.name} <img src={wallet.imageUrl} />
</div>
</div>
)
);
};
useTonConnectUI
使用它可访问 TonConnectUI
实例和用户界面选项更新功能。
让我们来看看如何在实践中使用React UI SDK。
import { Locales, useTonConnectUI } from '@tonconnect/ui-react';
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
const onLanguageChange = (language: Locales) => {
setOptions({ language });
};
return (
<div>
<label>language</label>
<select onChange={(e) => onLanguageChange(e.target.value as Locales)}>
<option value="en">en</option>
<option value="ru">ru</option>
</select>
</div>
);
};
useIsConnectionRestored
表示连接恢复进程的当前状态。 您可以用它来检测连接恢复进程是否已完成。
import { useIsConnectionRestored } from '@tonconnect/ui-react';
export const EntrypointPage = () => {
const connectionRestored = useIsConnectionRestored();
if (!connectionRestored) {
return <Loader>Please wait...</Loader>;
}
return <MainPage />;
};
通过哈希理解交易状态
位于支付处理中(使用tonweb)的原理。了解更多
后端的可选检查(tonproof)
向指定地址发送 TON 硬币(以 nanotons 为单位):
import { useTonConnectUI } from '@tonconnect/ui-react';
const transaction: SendTransactionRequest = {
validUntil: Date.now() + 5 * 60 * 1000, // 5 minutes
messages: [
{
address:
"0QD-SuoCHsCL2pIZfE8IAKsjc0aDpDUQAoo-ALHl2mje04A-", // message destination in user-friendly format
amount: "20000000", // Toncoin in nanotons
},
],
};
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(transaction)}>
Send transaction
</button>
</div>
);
};
- 在此获取更多示例:准备信息
通过哈希值了解交易状态
该原理位于支付处理部分(使用 tonweb)。查看更多
后台可选检查 (ton_proof)
了解如何签署和验证信息:签名和验证
要确保用户真正拥有声明的地址,可以使用 ton_proof
。
或
- 加载状态:在等待后台响应时显示加载状态。
- 带有 tonProof 的就绪状态:将状态设置为 'ready',并包含 tonProof 值。
- 如果出现错误,请移除加载器,然后创建不带附加参数的连接请求。
const [tonConnectUI] = useTonConnectUI();
// Set loading state
tonConnectUI.setConnectRequestParameters({ state: "loading" });
// Fetch tonProofPayload from backend
const tonProofPayload: string | null =
await fetchTonProofPayloadFromBackend();
if (tonProofPayload) {
// Set ready state with tonProof
tonConnectUI.setConnectRequestParameters({
state: "ready",
value: { tonProof: tonProofPayload },
});
} else {
// Remove loader
tonConnectUI.setConnectRequestParameters(null);
}
处理 ton_proof 结果
连接钱包后,您可以在钱包对象中找到 ton_proof
结果:
useEffect(() => {
tonConnectUI.onStatusChange((wallet) => {
if (
wallet.connectItems?.tonProof &&
"proof" in wallet.connectItems.tonProof
) {
checkProofInYourBackend(
wallet.connectItems.tonProof.proof,
wallet.account.address
);
}
});
}, [tonConnectUI]);
ton_proof 的结构
type TonProofItemReplySuccess = {
name: "ton_proof";
proof: {
timestamp: string; // Unix epoch time (seconds)
domain: {
lengthBytes: number; // Domain length
value: string; // Domain name
};
signature: string; // Base64-encoded signature
payload: string; // Payload from the request
}
}
断开钱包的调用:
钱包断线
调用以断开钱包连接:
const [tonConnectUI] = useTonConnectUI();
await tonConnectUI.disconnect();