发送消息
TON Connect 2.0 不仅仅提供了在 dApp 中认证用户的强大选项:它还可以通过已连接的钱包发送外部消息!
您将了解到:
- 如何从 DApp 发送消息到区块链
- 如何在一次交易中发送多条消息
- 如何使用 TON Connect 部署合约
演示页面
我们将使用 JavaScript 的低级 TON Connect SDK 。我们将在钱包已连接的页面上的浏览器控制台上做实验。以下是示例页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/@tonconnect/sdk@latest/dist/tonconnect-sdk.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/tonweb.js"></script>
</head>
<body>
<script>
window.onload = async () => {
window.connector = new TonConnectSDK.TonConnect({
manifestUrl: 'https://ratingers.pythonanywhere.com/ratelance/tonconnect-manifest.json'
});
connector.restoreConnection();
}
</script>
</body>
</html>
随意将其复制粘贴到您的浏览器控制台并运行。
发送多条消息
1) 了解任务
我们将在一次交易中发送两条独立的消息:一条发送到您自己的地址,携带 0.2 TON,另一条发送到其他钱包地址,携带 0.1 TON。
顺便说一下,一次交易中发送的消息有限制:
2) 发送消息
运行以下代码:
console.log(await connector.sendTransaction({
validUntil: Math.floor(new Date() / 1000) + 360,
messages: [
{
address: connector.wallet.account.address,
amount: "200000000"
},
{
address: "0:b2a1ecf5545e076cd36ae516ea7ebdf32aea008caa2b84af9866becb208895ad",
amount: "100000000"
}
]
}));
您会注意到这个命令没有在控制台打印任何东西,像返回无内容的函数一样,null
或 undefined
。这意味着 connector.sendTransaction
不会立即退出。
打开您的钱包应用,您会看到原因。有一个请求,显示您要发送的内容以及coin将会去向哪里。请接受它。
3) 获取结果
函数将退出,并且区块链的输出将被打印:
{
boc: "te6cckEBAwEA4QAC44gBZUPZ6qi8Dtmm1cot1P175lXUARlUVwlfMM19lkERK1oCUB3RqDxAFnPpeo191X/jiimn9Bwnq3zwcU/MMjHRNN5sC5tyymBV3SJ1rjyyscAjrDDFAIV/iE+WBySEPP9wCU1NGLsfcvVgAAACSAAYHAECAGhCAFlQ9nqqLwO2abVyi3U/XvmVdQBGVRXCV8wzX2WQRErWoAmJaAAAAAAAAAAAAAAAAAAAAGZCAFlQ9nqqLwO2abVyi3U/XvmVdQBGVRXCV8wzX2WQRErWnMS0AAAAAAAAAAAAAAAAAAADkk4U"
}
BOC 是 Bag of Cells,这是 TON 中存储数据的方式。现在我们可以解码它。
在您选择的工具中解码这个 BOC,您将得到以下cell树:
x{88016543D9EAA8BC0ED9A6D5CA2DD4FD7BE655D401195457095F30CD7D964111...
$10 ext_in_msg_info
$00 src:MsgAddressExt (null address)
"EQ..."a dest:MsgAddressInt (your wallet)
0 import_fee:Grams
$0 (no state_init)
$0 (body starts in this cell)
...
返回发送交易的 BOC 的目的是跟踪它。
发送复杂的交易
cell的序列化
在我们继续之前,让我们谈谈我们打算发送的消息格式。
- payload (string base64, 可选): 以 Base64 编码的单cell BoC。
- 我们将使用它来存储转账上的文本评论
- stateInit (string base64, 可选): 以 Base64 编码的单cell BoC。
- 我们将使用它来部署智能合约
构建消息后,您可以将其序列化为 BOC。
TonWeb.utils.bytesToBase64(await payloadCell.toBoc())
带评论的转账
您可以使用 toncenter/tonweb JS SDK 或您喜欢的工具将cell序列化为 BOC。
转账上的文本评论被编码为操作码 0 (32 个零位) + 评论的 UTF-8 字节。以下是将其转换为cell包的示例。
let a = new TonWeb.boc.Cell();
a.bits.writeUint(0, 32);
a.bits.writeString("TON Connect 2 教程!");
let payload = TonWeb.utils.bytesToBase64(await a.toBoc());
console.log(payload);
// te6ccsEBAQEAHQAAADYAAAAAVE9OIENvbm5lY3QgMiB0dXRvcmlhbCFdy+mw
智能合约部署
我们将部署一个非常简单的 聊天机器人 Doge,在智能合约示例中提到。首先,我们加载它的代码并在数据中存储一些独特的内容,以便我们接收到一个尚未被其他人部署的全新实例。然后我们将代码和数据合并到 stateInit 中。
let code = TonWeb.boc.Cell.oneFromBoc(TonWeb.utils.base64ToBytes('te6cckEBAgEARAABFP8A9KQT9LzyyAsBAGrTMAGCCGlJILmRMODQ0wMx+kAwi0ZG9nZYcCCAGMjLBVAEzxaARfoCE8tqEssfAc8WyXP7AN4uuM8='));
let data = new TonWeb.boc.Cell();
data.bits.writeUint(Math.floor(new Date()), 64);
let state_init = new TonWeb.boc.Cell();
state_init.bits.writeUint(6, 5);
state_init.refs.push(code);
state_init.refs.push(data);
let state_init_boc = TonWeb.utils.bytesToBase64(await state_init.toBoc());
console.log(state_init_boc);
// te6ccsEBBAEAUwAABRJJAgE0AQMBFP8A9KQT9LzyyAsCAGrTMAGCCGlJILmRMODQ0wMx+kAwi0ZG9nZYcCCAGMjLBVAEzxaARfoCE8tqEssfAc8WyXP7AAAQAAABhltsPJ+MirEd
let doge_address = '0:' + TonWeb.utils.bytesToHex(await state_init.hash());
console.log(doge_address);
// 0:1c7c35ed634e8fa796e02bbbe8a2605df0e2ab59d7ccb24ca42b1d5205c735ca
现在,是时候发送我们的交易了!
console.log(await connector.sendTransaction({
validUntil: Math.floor(new Date() / 1000) + 360,
messages: [
{
address: "0:1c7c35ed634e8fa796e02bbbe8a2605df0e2ab59d7ccb24ca42b1d5205c735ca",
amount: "69000000",
payload: "te6ccsEBAQEAHQAAADYAAAAAVE9OIENvbm5lY3QgMiB0dXRvcmlhbCFdy+mw",
stateInit: "te6ccsEBBAEAUwAABRJJAgE0AQMBFP8A9KQT9LzyyAsCAGrTMAGCCGlJILmRMODQ0wMx+kAwi0ZG9nZYcCCAGMjLBVAEzxaARfoCE8tqEssfAc8WyXP7AAAQAAABhltsPJ+MirEd"
}
]
}));
在 准备消息 页面获取更多关于传输 NFT 和 Jettons 的示例。
确认后,我们可以在 tonscan.org 看到我们的交易已完成。
如果用户拒绝了交易请求会发生什么?
处理请求拒绝相当简单,但当您正在开发某个项目时,最好提前知道会发生什么。
当用户在钱包应用中的弹出窗口中点击“取消”时,会抛出异常:Error: [TON_CONNECT_SDK_ERROR] Wallet declined the request
。这个错误可以被视为最终的(不像连接取消那样) - 如果它被抛出,那么直到发送下一个请求,请求的交易绝对不会发生。