English 简体中文 繁體中文 한국 사람 日本語 Deutsch русский بالعربية TÜRKÇE português คนไทย french

简体中文 繁體中文 English 日本語 Deutsch 한국 사람 بالعربية TÜRKÇE คนไทย Français русский

回答

收藏

6.4 编程命令驱动的机器人界面

开源社区 开源社区 7249 人阅读 | 0 人回复 | 2025-03-14

本帖最后由 riyad 于 2025-3-14 01:12 编辑   h7 g; r0 U) ]' A7 j2 f% o

! L$ N$ p% p3 ?- v2 X$ @# J* [
在本课中,我们将再创建一个项目--聊天机器人。这将是一个后台项目,因为聊天机器人就是这样工作的。你要编写一些运行在服务器上的脚本。然后使用 API 密钥连接到 Telegram 服务器。当有新消息时,你的脚本可以从 Telegram 服务器获取更新。你可以代表聊天机器人触发新消息。基本上,这就是一个独立的应用程序。
我们拿到了合约,部署了它--这就像是我们 dApp 的后台。然后,我们创建了一个网络接口,这样网络上的任何人都可以访问它并与之互动。然后,我们创建了一个 TWA(Telegram 网络应用程序),将其嵌入到 Telegram 中。我们还想做的一件事是编写一个脚本,用来控制和编程这个对话:提供一个键盘,提出一些问题,然后根据回答触发某些操作。当然,还要与 TON 进行交互,因为我们正在为区块链上的合约构建一个接口。

, A' |8 z5 m+ j' k* B  \
准备开始
我们在开始一个新项目时,先创建一个新目录并将其移动到该目录中:
  1. mkdir first_contract_tg_bot% R" |: R* ^3 W
  2. cd first_contract_tg_bot
复制代码
现在我们设置一个新软件包:

& K' ^3 n6 j# X
  1. yarn init
    - M8 I1 G: S; ?& G& U+ r7 |0 m0 t
复制代码
是时候安装几个库了。我们将继续使用 TypeScript,所以首先要安装  typescript for node、types  for node 和 swc/core,后者可将 TypeScript 编译成 JavaScript:/ A& S. V3 D( k5 v, l1 }
  1. yarn add typescript ts-node @types/node @swc/core --dev9 m- A4 ^; B( C2 z% `6 Q
复制代码
我们需要在这里创建一个新文件,名为 tsconfig.json,内容如下:

2 @. j/ o9 I2 T' P, y: w5 q. e
  1. {
    + Q$ X0 @6 Z0 h6 B; U9 c, j
  2.   "compilerOptions": {6 F; T( Z! E, Y6 @
  3.     "target": "es2020",
    ; D. W( H5 u- R$ N8 V9 }
  4.     "module": "commonjs",6 B: ~6 t6 k" o9 i; a$ N
  5.     "esModuleInterop": true,
    ) V- d. {! F* T" M! p$ L: a
  6.     "forceConsistentCasingInFileNames": true,
    ; d% _+ M0 G: r- U" l
  7.     "strict": true,! u7 X0 f8 a1 l, H8 a- `
  8.     "skipLibCheck": true,' u' U, n% U4 G. I
  9.     "resolve]sonModule": true
    ! w# Z! G. H8 R3 n4 b
  10.   },
    ) I6 d1 W5 Y5 J. g# Q$ C7 y' d- @
  11.   "ts-node": {% |( b3 F  N* @( s( H- Z
  12.     "transpileOnly": true,% ?- ^; I6 G, @& ]; R9 h
  13.     "transpiler": "ts-node/transpilers/swc"- z/ D5 E! i2 s1 s. p% Z9 a! g
  14.   }
    6 r) o/ h1 V$ I; V; I9 x! m
  15. }
复制代码
这里有 TypeScript 转译器的配置和编译器的标准配置。
这个项目是空的。我们需要安装一个新的 SDK,帮助我们与聊天机器人 API 交互。我建议使用名为 Telegraf 的 SDK:
  1. yarn add telegraf7 o$ F# Z( w% ]% M/ g! v
复制代码
在安装过程中,让我回到浏览器,给你看看它的一些文档 (https://telegrafjs.org/#/?id=example) 。它非常容易上手,当你想创建复杂的聊天机器人时,它也是一把好手。

# d# G, Z% Y: l4 a  B' U
机器人编程
我们已经安装了 Telegraf。现在,我们要在根目录下创建 src 文件夹,并在该文件夹下创建 index.tx 文件。然后,我们立即在 package.json 中创建一个脚本,并通过命令行运行我们的代码。
  1. {
    * K% q9 o: A; ~1 y+ C/ e9 f+ f
  2.   "name": "first_contract_tg_bot"# |6 q8 r/ B. t6 a. K! n3 r" k/ l, R/ r
  3.   "version": "1.0.0",  u, `8 d0 Z" R/ a: R
  4.   "main": "index. js",' u  C  Q9 K: C# n: `: G
  5.   "license": "MIT"5 Z1 G6 A" I) `
  6.   "devDependencies": {' k* M1 W1 X  F. T* E
  7.     "@swc/core"; "^1.3.42",
    ( F- P) a' ~. L" A2 t& f
  8.     "@types/node": "^18.15.9",
    $ Z2 e7 Q' |9 {4 z. f
  9.     "ts-node": "^10.9.1",  {: U6 G5 C9 m9 \: n! B
  10.     "typescript": "^5.0.2"
    ; y8 {+ [' }3 h# ?, h1 K$ K
  11.   },
    . r4 Z1 u/ `; s
  12.   "dependencies": {
    ( g; U& B. y6 v, M$ r0 K  v
  13.     "telegraf": "^4.12.2"* t( W) B% B& l- j0 C( b
  14.   },
    # E' Z: z5 Z  w# t9 ~7 j, o" S
  15.   "scripts": {
    1 \/ }/ q; ?$ M5 `, l
  16.     "start": "ts-node ./src/index.ts"8 I1 X% k  }  {$ u6 y
  17.   }& z% q' m+ }0 C, f* n+ }! G: {9 [. x
  18. }
复制代码
脚本将使用 ts-node 来实际运行我们要编程的 index.ts。让我们来看看这里的示例。当然,这不是一个 TypeScript API 示例,但我们准备了一些代码 (https://telegrafjs.org/#/?id=example) 。首先,我们要以 TypeScript 的方式导入 Telegraf:
* i4 X4 l0 X5 h2 S0 i4 C# n
  1. import { Telegraf } from "telegraf";/ t; q) }% Q8 _' t
复制代码
接下来,我们需要启动一个机器人实例。因此,我们要创建一个 Telegraf 实例:
" m3 B0 w9 j' x  h& e- |* J0 z' V
  1. const bot = new Telegraf(' ');
    ! p& X5 M2 y; _+ w1 q
复制代码
它首先接受的是令牌。我们在使用 BotFather API 时已经看到过这个令牌。因此,我们需要返回,看看我们的令牌是什么并将其复制! P# m  V4 n7 A9 `) r" G& I1 {
  1. const bot = new Telegraf("6015353320:AAF4LZh2hvZSRHQcZNDMyuePl41yd2ZAMyM");8 M4 b; }: I' l: k2 \; n% J
复制代码
开发聊天机器人时,应该保留两个实例,一个用于测试,一个用于生产。因此,我们要用 env 变量将这些令牌分开。在 src 文件夹中,我们创建一个名为 .env  的新文件,以确保该文件从未提交到仓库中。我们将其命名为 TG_BOT_TOKEN,并以此启动 .env 文件:
  1. TG_BOT_TOKEN=6015353320:AAF4LZh2hvZSRHQcZNDMyuePl41yd2ZAMyM; ?7 g! u( N' ~  M
复制代码
帮助我们与这些变量交互的库叫做 dotenv,让我们添加它:
& H) a- w- }& M6 @, f2 E& |/ k
  1. yarn add dotenv
    ) w  `; ], ~, K" r6 F% p% F4 D
复制代码
安装后,我们可以从 index.ts 中访问它:
4 ^# \" p4 \5 }) m' c, g& ^4 ^
  1. const bot = new Telegraf(process.env.TG_BOT_TOKEN!);2 F. w* M* j) N. U9 {& H  r1 E
复制代码
但首先我们需要配置并导入 dotenv。因此,让我们在文件的开头进行配置:
+ I/ {; u, V4 H9 r5 e4 Y
  1. import dotenv from "dotenv"
    ! u5 c/ R' W6 a0 X
复制代码
重要的是尽快在项目中运行 dotenv.config 函数,因此我们在导入后添加

  i* U$ n  g- y1 N: J7 T
  1. dotenv.config();
    7 y" B: |4 u% y( Q7 ^" B( X0 M
复制代码
这个变量可能是未定义的,但我们知道它实际上是在 .env 中定义的。因此,我们可以说它肯定会存在。如果它不存在,就会失败,因此不会启动 Telegraf 实例。
酷,让我们看看一步步开始机器人交互后的示例代码是怎样的:
  1. bot.start((ctx) =>% H! Z2 |* ?1 ]6 P% S6 _
  2.   ctx. reply ("Welcome to our counter app!", {
    / g: E9 T& U: J2 i, G* N  y' V4 o" ^
  3.     reply_markup: {2 `( M- [  t! U4 X
  4.       keyboard: [" ~, {% S- Y0 w' o" O$ U8 u
  5.         ["Increment by 5"],
    4 Z6 C; V% B: X# m% h1 x
  6.         ["Deposit 1 TON"],
    . g" T9 L3 ?+ Z) D4 K
  7.         ["Withdraw 0.7 TON"],! k: Z. K; L0 E/ [# Q5 f$ \
  8.       ],2 K8 S4 D2 O) o. h
  9.     },0 C3 u) n) C5 n# d6 X
  10.   })
    & z( Q$ ^- c5 R. F. e, O
  11. );
复制代码
这个 Telegraf 机器人实例为我们提供了一个启动方法。当你第一次进入聊天机器人时,它就会被触发:你应该记得,当我们刚刚打开聊天机器人时,我们点击了 start。一旦你运行了第一条信息,你就会回复一条欢迎信息,并附加一个键盘。
我们来看看这个键盘会是什么样子。Telegram 聊天机器人可以让你创建自己的键盘,取代你输入信息时看到的原始键盘。你还可以在消息下方创建内嵌键盘。我们稍后再谈;现在我们只使用一个简单的键盘。
在这里,我们将创建三行和三个按钮。在网络上,"请求 "交易(如 "请求存款")是合适的,因为您授权应用程序向您提出请求。但在这里,我们有直接的交易链接,您与聊天机器人本身没有会话,所以按钮中的动作动词更合适,比如 "存款"。当然,您也可以在后台保留会话,但这样做不妥,因为会造成安全漏洞。
  1. bot.hears("Increment by 5", (ctx) => {
    + w& U! J1 G( s, ?( V+ u
  2.   // TODO: send increment transaction
    8 Y2 G( v! l1 ]# k9 q
  3.   ctx ,reply("Incremented by 5");
      [+ P& G0 [  [6 i" L
  4. });
      W+ Q8 U. l, l& q! I
  5. bot.hears("Deposit 1 TON", (ctx) => {, Q# q3 z& B1 |6 F, I
  6.   // TODO: send deposit transaction
    , z* \: o2 T. ]% a3 U
  7.   ctx ,reply("Deposited 1 TON");
    . M4 M& z3 h' J2 R+ U" J( e" ~
  8. });
    ' F$ a: C! S" b$ |: P6 s, b

  9. " A& s( M8 ]9 r2 \: D' I, v6 e
  10. bot.hears ("Withdraw 0.7 TON", (ctx) =>
    7 [" O; G  y" x6 X# A+ F6 c+ o
  11.   // TODO: send withdraw transaction
    " a' F$ E: t1 p/ j' {: ?
  12.   ctx ,reply("Withdrawn 0.7 TON");
    3 Y+ K: m5 M7 V1 C
  13. });
复制代码
在这里,我们有几个功能。bot.hears 表示机器人会收到这样的信息。我们可以发送回复 "增加 5"。然后,我们还可以添加类似的回复。
最后,我们添加一个函数来启动机器人,并添加几行代码来确保机器人正确退出:
  1. bot.launch();
    ' d. x% T2 Q+ S
  2. . |; t6 E: P/ P4 B" |" K' d
  3. // Enable graceful stop
    0 x- @& [; D1 |
  4. process.once("SIGINT", () => bot.stop("SIGINT"));; f0 Y- w9 u' S; C
  5. process.once("SIGTERM", () => bot.stop ("SIGTERM"));
复制代码
好了,我们都准备好了,开始吧:
  M8 f! b- o/ d6 z
  1. yarn start
      L7 X- r/ k4 M8 l/ |
复制代码
我们的机器人已经开始工作,但重要的是要在应用程序中进行检查。打开机器人,再次点击 "开始":
2 n5 O8 I6 J; L6 L/ i5 b# J$ j2 u

' H0 o) `; n* [  G, y, O+ b9 u
正如您所看到的,我们有三个带有文本的按钮。点击其中任何一个按钮后,我们就会得到想要的回复。如果点击 "计数器",我们的应用程序将以网络应用程序的形式打开。那么,我们该如何让菜单操作发挥作用呢?

7 G6 M% i9 C" Y) K- p' @7 _  ]使菜单操作有效
/ K$ u' f, @- F9 J5 n% C( _" x) ]我们正在创建一个部署脚本。大家还记得吧,我们创建了一个链接,可以扫描二维码直接进入钱包,在钱包中签署交易来部署合约。现在我们也可以做同样的事情。一旦你的用户获得了选项,比如以 5 为单位递增,你就可以创建一个链接,让他直接进入 Tonhub 进行支付。6 n7 T4 y2 @! T0 h, N
首先,让我们安装使用 TON 所需的库:

' B! Z! @2 f) k% p3 }& v
  1. yarn add ton-core ton-crypto( v+ s1 b. L$ Z
复制代码
我们需要 ton-core 和 ton-crypto 来编写信息。要建立链接,我们需要这些库:

% m' E) E4 y! W9 ~  M" a
  1. yarn add qs @types/qs --dev$ t7 y- W3 f8 f1 [' v- p2 ^0 s
复制代码
现在,我们将重复使用第一课中的一些代码。确保我们的合约地址是正确的。你还记得,在 first_contract_front_end 项目中,我们创建了一个挂钩,该挂钩附加到某个合约。让我们从 useMainContract.ts 中获取地址:

1 _0 `/ e& z, C8 |* B$ \
  1. const mainContract = useAsyncInitialize(async () => {8 h/ a9 m  j! O& }% @, G7 e0 ~6 d
  2. 5 [# f( ]% J' E- Z  ?+ x, i2 L
  3.   if (!client) return;
    ; T$ ~  ~. t3 A0 _  B9 {
  4. 0 Z% l3 J/ s5 U- ~9 H) z
  5.   const contract = new MainContract(; a/ f6 d7 M' B8 Y% m
  6. 0 ~3 \5 ~. A6 Z1 o0 m
  7.     Address.parse("EQBDUxTxWo41aCY1SGZJJlDnu4uKvZtbOjuGF9mtf22M1UBq") // replace with your address from tutorial 2 step 86 V5 @; I9 e7 }& W
  8. 3 I; t& C4 D& s' v3 O5 S
  9.   );# C0 G4 g! p$ V# f* Z- C
  10. 7 z! d& N1 l0 Y9 i$ ?
  11.   return client.open(contract) as OpenedContract<MainContract>;
    9 @( @! s1 U5 @. R3 w% s' s& ~8 D. M

  12. , K5 f% w$ a3 q$ M$ v2 m3 R
  13. }, [client]);
复制代码
现在,我们需要导入地址结构。
- l, e  T1 L1 e8 X2 m/ M/ |
  1. bot. hears ("Increment by 5", (ctx) => {
    # G- B+ G4 e0 v- O% q' t
  2.   let link =
    / u- Z  _  R. `( n/ U
  3.     `https://test.tonhub.com/transfer/` +# M, u6 N. ?/ N/ W( @
  4.   Address.parse ("EQBDUxTxWo41aCY1SGZJJlDnu4uKvZtbOjuGF9mtf22M1UBq").toString- p1 t2 l/ _: G& s9 Q+ ~
  5.     RestOnly: true,
复制代码
我们不会在主网中做任何事情,这只是测试网。我们从特定地址中解析出地址类,然后将其转换为字符串。实际上,我们可以直接这样做,因为我们显然需要一个字符串。然后,让我们重新组合,使代码更简洁:
; D( I& O8 R) ^4 C
  1. bot. hears ("Increment by 5", (ctx) => {, @& _/ ?3 k; M7 M) E6 ^' K# Q3 n2 K
  2.   let link = `https://test.tonhub.com/transfer/EQBDUxTxWo41aCY1SGZJJlDnu4uKvZtbOjuGF9mtf22M1UBq?${qs.stringify(
    $ n/ {( e5 k6 T, p
  3.     {8 H3 G$ O9 v! Z3 n; v' G& s
  4.       text: "Simple test transaction",
    5 Q& f5 E' U8 B1 A& X& \
  5.       amount: toNano ("0.05") . toString (10) ,
    ! u; Z. M; Y% s5 E' f' Q
  6.       bin: msg body toBoc({ idx: false }). toString ("base64"),% F6 x! u) y: I- c6 e+ K' M
  7.     }+ W. s7 E6 p  q( \( H# v/ K1 M
  8. )}`;
复制代码
我们甚至可以这样做:

  ?& x/ b% O2 k- M
  1. ​​const SC_ADDRESS = "EQBDUxTxWo41aCY1SGZJJ1Dnu4uKvZtb0juGF9mtf22M1UBq";
    . W. i2 s* f2 x) R# O
复制代码
因此,我们把智能合约地址放到链接中:
/ K) l3 }  n7 Q. d+ I
  1. bot.hears ("Increment by 5", (ctx) => {  t5 A* A& b% c- _: @
  2.   let link = `https://test.tonhub.com/transfer/${SC_ADDRESS}?$ {qs.stringify(+ f; A9 D( X7 ~1 t# G% [3 P% f4 t
  3.     {: d) Z1 i0 J. W- R
  4.       text: "Simple test transaction",
    + z% E9 h' c8 ^  |; h: x& \
  5.       amount: toNano ("0.05") . toString (10) ,
    5 ?# U& m( \4 x3 @8 h
  6.       bin: msg ,body ,toBoc({ idx: false }). toString ("base64"),
    & i# ^5 @0 a' _, I  Z& W7 L' c" n
  7.     }0 d' a) W- l, C4 r  v* ?
  8. )}`;
复制代码
你甚至可以再做一项改进。就像我们为令牌设置环境变量一样,我们也可以在 .env 中设置智能合约地址来执行此操作,因为在生产过程中,你很可能也会在主网上设置一个合约:4 O' ~- i3 i' ^* a5 _% o' ^( R( p
  1. SC_ADDRESS=EQBDUxTxWo41aCY1SGZJJ1Dnu4uKvZtb0juGF9mtf22M1UBq
    9 S9 x" d: S2 v% J$ b! {
复制代码
现在在 index.ts 中,我们不再需要地址对象了。

' N; o; E7 d8 O9 S/ u6 s
  1. import { Address } from "ton-core";
    ' C: f* {9 W8 |  y8 I  S
复制代码
在 bot.hears 的 Amount 中,我们从上下文菜单中选择 Add import from "ton-core" ,并在链接中添加  process.env:
* L8 i$ V5 S7 J" ~
  1. bot.hears ("Increment by 5", (ctx) => {2 ^+ K- ~+ g/ W3 N& j
  2.   let link = `https://test.tonhub.com/transfer/${process.env.SC_ADDRESS}?$ {qs.stringify(
    ( @, s4 l% a0 C# p
  3.     {
    & j2 w% y# l- O4 ]6 {
  4.       text: "Simple test transaction",0 N1 G5 Z2 X! ~! S- B/ }
  5.       amount: toNano("0.05").toString(10),' }/ D) d: [' b/ ^  t  q! X& I
  6.       bin: msg_body.toBoc(( idx: false )). toString("base64"),- y" X* {9 L# ?6 {4 Z8 l; _
  7.     }
    7 N" k+ |9 x5 |5 l' q' b7 n
  8. )}`;
复制代码
在这里,我们需要形成一个信息正文。什么是信息正文?我们使用 "生成器",因为我们要把消息正文作为Cell,然后由 TON 将其转换为字符串表示法。我们要在消息正文中输入什么内容呢?
我们正在创建合约及其封装。我们将发送一个增量函数。为此,我们可以直接从 wrappers > MainContract.ts:
  1. const msg ,body = beginCell()+ U1 x- y! X, K" K7 C' s
  2.   .storeUint(1, 32) // OP code
    - C2 \7 A; d# N" i6 R  {5 z
  3.   .storeUint(increment_by, 32) // increment_by value
    , }  Z" [/ `+ H; z& @
  4.   .endCell();
复制代码
它显示了我们要递增的整数和递增多少的整数。所有这些我都会复制到我的机器人项目中:

3 C- A" }( D% R/ J
  1. bot.hears("Increment by 5", (ctx) => {
    8 a& M% g- s! E3 A9 l
  2. / @. T. k3 o8 j7 u  e. [+ ^
  3. const msg_body = beginCell() 5 `+ |: M( v# r* O7 D6 r6 X
  4.     .storeUint(1, 32)
    - x$ G7 Z6 j: `" ]6 ?
  5.     .storeUint(5, 32)) V3 d! i& c; A' _1 A! t
  6.     .endCell();% G6 a7 p7 |! y1 a9 H- [
  7. + K4 g  t8 I' O: m# z0 L
  8. let link = `https://app.tonkeeper.com/transfer/${process.env.SC_ADDRESS
    & k/ T# ~3 U% R
  9. }?${qs.stringify(
      F4 v8 y5 ?7 [7 d/ N7 x: n. M$ r
  10.     {( v$ c! q" D( X7 ?' _$ z
  11.       text: "Simple test transaction",
    9 n- h; `- G. [4 H
  12.       amount: toNano("0.05").toString(10),# l) o6 M' T! N/ O2 U1 T5 v2 l
  13.       bin: msg ,body.toBoc({ idx: false }).toString("base64"),
    / d% R# p" [$ A/ z/ S* g
  14.     }9 I) Y4 B4 {# w, g
  15. )}`;
复制代码
我们不要求增量,但我们知道它是 5,所以我们把 5 放在这里。你可以随意调整,要求增量。在我们的例子中,我们已经有了5个硬编码了。现在我们在开始时导入 qs:
: P' c& T/ a/ x
  1. import qs from "qs";& L0 m1 i  d9 y
复制代码
很好,我们导入了所有内容,现在来对对象进行字符串化。我们说要将计数器递增 5 - 这只是附加到消息中的一个文本。然后把 0.05 作为实际支付交易费用的金额。然后我们使用这个参数费。
在此,我们前往 Tonhub 开发人员文档。我们使用的链接仅适用于 Tonhub,但你也可以使用 Tonkeeper 链接。在文档中,你也可以找出 URL 的结构来提供一些值。
Bin parameter everywhere 用于传递 msg_body,一旦您想发送带有特定参数的消息。这正是我们在这里要做的事情:我们为 Tonhub 创建了一个付款链接。
但在此之前,我们需要让机器人回复用户。一位用户使用我们在开始时提供的键盘给我们发送了 "递增 5 "的消息。我们需要回复,让用户知道他能做什么。我们需要提供一个链接。我们可以简单地发送链接,但我们希望它对用户非常友好。这就是为什么我们要回复一条信息:
  1. ctx.reply("To increment counter by 5, please sign a transaction:", {. n; ]- x1 [/ T. ^
  2.     reply_markup: {  L1 r; y4 }* B) \
  3.         inline_keyboard: [2 g% [) @  c; e7 _& e3 T. R
  4.             [{
    3 }* N; R/ o" y% @
  5.                 text: "Sign transaction",
    4 Q/ L! m! L1 A! L* I
  6.                 url: link,
    ! w, B" E( g3 Y3 D
  7.             }]5 t! \4 A: V+ x
  8.         ]
    , j) |% r# }' v7 j
  9.     }  D! D3 `6 b7 j2 l- V/ J3 p
  10. })
复制代码
然后,我们创建一个额外的参数。回复标记可以是 InlineKeyboard, ReplyKeyboard, ReplyKeyboardRemove 或 ForceReply。这里有多个选项,我们希望使用 inline_keyboard。
上次我们使用的是普通键盘,位于输入行下的同一位置。现在我们创建了一个内联键盘,如上图所示。它有几个参数:文本、签名交易和 URL。因此,我们在 bot.hears 中提供了一个带有链接的 URL 参数。
有一件事我之前没有提到,但你应该记住:如果我们想把某个Cell作为链接发送,比方说,连同一些字符串或链接一起发送,我们需要把它打包成 base64,就像信息正文的Cell一样。
好吧,看来这个办法行得通:
  1. yarn start3 ]( t8 h3 J) w: g
复制代码
一切正常,于是我回到手机上。我打开开始命令提供的键盘,点击 "递增 5":

$ t- K6 [2 d: E1 m& ]% q
, g7 f6 _) [% h5 V4 D, o如您所见,我们收到了一条信息,要求我们签署一项交易,以 5 为增量。交易已发送。如何检查交易是否真的影响了我们的合约状态?如果检查网络应用程序,可以看到 "计数器值 "等于 15,而之前是 10。* a2 q" H) z% O- ?
" V2 @3 U! v4 |1 F/ X
进一步改进机器人
我们可以通过聊天机器人构建特定的用户流,用户将在后端与我们的区块链进行交互。我们在后端没有任何用户凭证,所以我们实际上是在为他提供钱包链接,让他进行支付。我希望这不会让你感到困惑,因为作为开发者,你应该始终考虑可用性。而这正是可以显著提高可用性的方法之一。
Telegram 中的网络应用程序可让您使用自动消息创建有趣、酷炫的聊天对话。这样,您就能为用户创建极具价值的精彩项目。让我们构建一个类似的链接:
  1. bot.hears("Deposit 1 TON", (ctx) => {
    . G* Y, @' [4 p4 `
  2.   const msg_body = beginCell().storeUint(2, 32).endCell();
复制代码
我们将用 2 来表示存款数额。我们不需要其他任何东西,让我们在 wrappers > MainContract.ts 中再次确认这一点:
3 N- {. {) r) a$ ~
  1. async sendDeposit(provider: ContractProvider, sender: Sender, value: bigint) {+ a* f3 \' v5 Y- w. P) `; V- ~
  2.   const msg_body = beginCell()0 P) B4 C8 n0 l9 X6 q+ U  Q& w* f
  3.     .storeUint(2, 32) // OP code
    / K' m. W4 |( j  K
  4.     .endCell()
复制代码
接下来,我们需要输入存款命令,否则我们将无法在合约上收钱。在 index.ts 中,我们只需输入一个等于 2 的整数(32 位)。在这里,我们说它将是 "Deposit 1 TON"(存款 1 Ton),实际上我们将要求提供 1 Ton的付款。它不必是一个字符串。
// Final code deposit command
  1. bot.hears("Deposit 1 TON", (ctx) => {
    , ?; c! B" x3 w# e9 O
  2.     const msg_body = beginCell().storeUint(2, 32).endCell();
    & U9 z# Z4 W9 @+ w: z/ q

  3. % t( C2 V+ s0 Q( L/ ?/ q
  4.       ( F* x0 p9 H8 t- p# N- H* E
  5.     let link = `https://app.tonkeeper.com/transfer/${
    6 G. z) l+ z" P% y
  6.         process.env.SC_ADDRESS
    : V! f5 ]: ^3 l4 {# A' D4 d: r( f
  7.     }?${qs.stringify(& r- `" Y; S* a: ]# m9 z+ ^
  8.         {6 c2 }  y( Y4 q! K
  9.             text: "Deposit 1 TON",
    ; A; G/ y2 S$ P/ z1 @6 K2 t, r2 d
  10.             amount: toNano("1").toString(10),
    ' a+ _3 J( R8 h- Q. |8 W
  11.             bin: msg_body.toBoc({ idx: false}).toString("base64"),
    9 C" a/ E3 f- A- J, n
  12.         }
    1 Z; e9 S3 U3 E8 j+ ?/ V! g9 b4 x
  13.     )}`;
复制代码
因此,我们要求用户向合约发送 1 Ton,并在信息中注明这是存款。我们在这里输入信息,然后删除回复 "已存入 1 Ton",因为我们不再需要它了:
9 c. h- o9 M( J1 Q. x1 G, B
  1. ctx.reply("To deposit 1 TON please sign a transaction:", {* |$ ?% E# @: z' B
  2.   reply_markup: {
    3 O) u- G5 B5 S$ T! ~1 p& l9 l
  3.     inline_keyboard: [
    . `8 l. V: u. _
  4.       [
    * m+ R. R/ _) [
  5.         {$ U! ~' }" k5 D/ x
  6.           text: "Sign transaction",, K0 x2 k' `# q6 X6 T- a
  7.           url: link,
    9 ]$ h& V* r% g0 l1 A2 t6 I
  8.         }
    . O2 e; r1 i. X2 }
  9.       ]$ N5 h% [% {. s; g* s9 M3 t
  10.     ]
    & |- ]; _- ~( s7 `! s# S4 j
  11.   }0 v7 F  @( e4 |7 ^( B5 A3 i
  12. });
复制代码
所以这很简单。我们形成一个消息正文、一个链接、链接文本,将 1 Ton金额设为存款,将正文放入一个字符串,然后用链接中的键盘回复。我们还需要做的一件事就是将机器人的存款逻辑复制到取款逻辑中:
// Final code withdraw command
  1. bot.hears("Withdraw 0.7 TON", (ctx) => {
    $ q9 q$ ]/ I( B3 ?; X, r8 o$ \
  2. const msg_body = beginCell().storeUint(3, 32).endCell();. z9 q/ u& y) w' P9 m* r+ z
  3.   & B5 ^$ d8 N. i9 X( U  n
  4. let link = `https://app.tonkeeper.com/transfer/${
    * z8 j- _6 f7 X, C0 ^
  5.     process.env.SC_ADDRESS
    : X; e0 O$ J3 E/ Q2 G
  6. }?${qs.stringify(
    $ j) O1 Y( R: ]) D. B. A
  7.     {, P' {5 l* {- }
  8.         text: "Deposit 1 TON",5 P& q  n' k2 q
  9.         amount: toNano("1").toString(10),
    + G% Z) j& @- U5 Q4 L
  10.         bin: msg_body.toBoc({ idx: false}).toString("base64"),5 Q0 i' M& ?- _; [) b
  11.         }
    7 u0 E. ]# i- }
  12. )}`;
    0 `* q9 M2 h6 K5 |4 j
  13.    
    / v0 @. }/ D& v
  14. ctx.reply("To deposit 1 TON please sign a transaction:", {
    " \5 W$ d1 ^- W" @/ M
  15.   reply_markup: {+ r, A% m$ `4 j! {1 ?( Q% `7 ]( i& o
  16.     inline_keyboard: [1 ]  B( j  y. k2 l: p8 m9 B. [
  17.       [- M8 x1 m; ?4 V+ s
  18.         {$ T& ?* S; Q3 F3 V7 g; x
  19.           text: "Sign transaction",- C4 \# U, i$ g" I2 e+ k, H
  20.           url: link,
    1 ]  y5 h2 Q. B2 C- w4 d: @
  21.         }
    ' I" m: |. x2 y8 {
  22.       ]
    6 R3 p+ s5 j/ k! E" `
  23.     ]$ L1 i* F+ [# N1 }; G
  24.   }! [6 Y2 E, F- P" m( q1 O
  25. });
复制代码
现在我们回到提款的包装。在 index.ts 中,我们需要提供想要提取的金额:
6 e8 A. b6 |" @: [, `; `
  1. bot.hears("Withdraw 0.7 TON", (ctx) => {
      d7 t$ U0 t/ f8 s& W- [  w4 c
  2. const msg_body = beginCell().storeUint(3, 32).storeCoins(toNano(`0.7`))endCell();
复制代码
我们添加了关于提取 0.7 TON的文字,接下来我们把足够支付GAS费Ton数放进去,因为我们要在这里拿钱:
- Z7 L' g9 T3 u* `8 A0 E
  1. let link = https://test.tonhub.com/transfer/${
    : g' t8 ?0 {6 x, f6 U; v2 }
  2.   process.env.SC_ADDRESS
    ! Q6 e+ V$ T6 H5 q! U
  3. }?${as.stringify({
    * n! f( ?0 Z0 Q, R* E
  4.   text: "Withdraw 0.7 TON",% q+ o. w: k7 ^
  5.   amount: toNano('0.05').toString (10),
    & l1 t7 u5 F3 ?6 N0 b/ l
  6.   bin: msg_body.toBoc({ idx: false }).toString("base64"), ) B) Q' G$ _) N- n; M5 j
  7. })}`;
复制代码
然后编辑机器人信息:
/ m% F+ }! h7 _* ^3 J
  1. ctx.reply("To withdraw 0.7 TON please sign a transaction:", {- C% |3 B; B$ |+ c, i
  2.     reply_markup: {. S3 `+ n; j+ P+ v5 g- m6 C
  3.         inline_keyboard: [
      J) u% A. K9 y
  4.             [{
    ' ]6 o) z$ U+ b& j, d  d2 N
  5.                 text: "Sign transaction",) N7 e0 z& ~/ K) k. b
  6.                 url: link,
    3 Q" P0 L4 H- Q, ]7 i
  7.             }]
    5 I! N) t; {7 \5 Y
  8.         ]
    3 T  P5 S9 A& Q0 a
  9.     }7 C7 X  L9 Q" ?1 G, G1 u, R/ |
  10. });
复制代码
我们用 yarn start 重启机器人,回到 Telegram 应用程序。现在,我们不仅可以存款,还可以以同样的方式取款:
现在,我们访问 Telegram 中的网络应用程序文档,阅读更多有关该 SDK 中可用内容的信息 (https://core.telegram.org/bots/webapps) 。这里有 initData 和 initDataUnsafe。当我们想在启动网络应用时发送一些原始数据时,就会用到它们。通过这个版本,我们可以检查用户 Telegram 应用程序中可用的机器人 API 版本。通过这个平台,我们可以检测平台。我们还可以调整配色方案和主题参数--这些选项由 Telegram 文档提供。我们可以检查是否已展开,并设置窗口高度。
3 P1 y/ L/ I5 C8 Z
我们现在需要的是 sendData(发送数据)--一种向机器人发送数据的方法。调用该命令后,带有数据的服务消息就会发送给支持的机器人,其中包含给定长度的数据。重要的是,运行该命令后,会有一条消息发送到你的 Telegram。基本上,一旦你运行了 sendData 函数,你发送的信息就会由我们刚刚创建的后端机器人处理。你的处理方式会是这样的:
  1. bot.on(message("web_app_data"), (ctx) => ctx.reply("ok"));
    8 D) ]* x! m' T; j" q& V
复制代码
您还需要从 telegraf/filters:
& X1 B0 Q5 M- S6 S( _7 U
  1. import { message } from "telegraf/filters";
    1 M: K8 c- n' Q( t% x' C
复制代码
您可以在这里发送贴纸或消息,但要过滤网络应用程序的数据。在这里,您将收到从网络应用程序发送的数据。需要注意的是,这是用于关闭的,因此一旦运行 sendData 方法,网络应用程序就会关闭。# ?  S3 M* i' S$ E! S& P" H, f
1 o2 ~+ j+ @" P0 f( v7 i
结论
差不多就是这样。我们今天学到了很多东西。实际上,我们已经知道了如何使用一种最好的方式将应用程序推向大众。TON 涉及大规模应用,因此你必须掌握如何构建应用程序,以便将其整合到载体中。如果 Telegram 是这么多人的载体,TON 是我们非常喜爱的区块链,而且这个平台已经为这么多人做好了准备,那么你们为什么不构建自己的应用程序,并将可扩展技术带入已经有这么多用户在等待你们产品的地方呢?
7 C4 t5 M5 e/ a" h! y' i, _" @. z
我很高兴你们现在已经具备了这样的条件。我希望你已经明白了一切,希望你所学到的一切都能帮助你打造自己的产品。下一章再见。谢谢!
- F8 }7 u& [2 K
0 i" B3 ?, D3 e& g7 x

2 ^7 O7 W) O# B: I- M+ K9 ?
0 H& _! |% u- }6 m) U# U( ^: M) p+ s
1 y/ v# r* I2 k) {
* a5 U0 ?8 O4 |& z- h2 O# R

: i3 ]9 I' W0 X9 s! C: l2 G" E" ~3 Z8 R

0 p5 d, l$ k+ ?0 m- f+ Y
. Z& N2 [8 T7 T) w$ r& ~, R& o6 P1 r( S8 C* [6 ~* S

" t2 L; O* b; L  w) [' `$ N4 y  D- A6 Y& B8 q, B: B3 S, |
" Q3 c6 J- F9 M, O3 ~

2 [" V0 i* }! b" W, P# d4 u: K$ q6 ]

6 e1 A( ]% A. S! L2 S! W/ [
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则