本帖最后由 riyad 于 2025-3-14 01:12 编辑
) Q9 t0 T* w4 b1 Q/ _# m
; u" f/ @( p4 W! I2 b2 y' s& V在本课中,我们将再创建一个项目--聊天机器人。这将是一个后台项目,因为聊天机器人就是这样工作的。你要编写一些运行在服务器上的脚本。然后使用 API 密钥连接到 Telegram 服务器。当有新消息时,你的脚本可以从 Telegram 服务器获取更新。你可以代表聊天机器人触发新消息。基本上,这就是一个独立的应用程序。 我们拿到了合约,部署了它--这就像是我们 dApp 的后台。然后,我们创建了一个网络接口,这样网络上的任何人都可以访问它并与之互动。然后,我们创建了一个 TWA(Telegram 网络应用程序),将其嵌入到 Telegram 中。我们还想做的一件事是编写一个脚本,用来控制和编程这个对话:提供一个键盘,提出一些问题,然后根据回答触发某些操作。当然,还要与 TON 进行交互,因为我们正在为区块链上的合约构建一个接口。
# V9 P5 H) v6 B. Y" ? 准备开始我们在开始一个新项目时,先创建一个新目录并将其移动到该目录中: - mkdir first_contract_tg_bot
! y5 m% a0 u- P! o# r - cd first_contract_tg_bot
复制代码现在我们设置一个新软件包:
% v: Y; z% V& l, ~8 G- yarn init
5 S4 P/ n6 M5 l/ w: C% C
复制代码 是时候安装几个库了。我们将继续使用 TypeScript,所以首先要安装 typescript for node、types for node 和 swc/core,后者可将 TypeScript 编译成 JavaScript:5 U$ t4 W% }" G: K5 S$ P3 I8 G
- yarn add typescript ts-node @types/node @swc/core --dev
6 l/ G! C7 h; H* U, [
复制代码我们需要在这里创建一个新文件,名为 tsconfig.json,内容如下:
) M; P) B, s" Z4 h& S- {" R6 U- ^& c) j5 N$ e
- "compilerOptions": {. g0 m. [4 B& r- K3 ?: d3 v
- "target": "es2020",
n. q9 V1 v4 q2 ~, q - "module": "commonjs",
1 V0 Q9 s+ V7 A E! Y& D+ T' P, y# }0 l - "esModuleInterop": true,: p( |! [4 f1 H' S
- "forceConsistentCasingInFileNames": true,$ I: w0 u e# r5 P+ `
- "strict": true,
( `; L$ ~2 ^! W: J7 G' ~# b - "skipLibCheck": true,( V5 l6 N9 I. w* Q7 {
- "resolve]sonModule": true: }( ~1 ^ I% k' \/ M: }( \
- },5 n2 H/ s* x; [ e% A
- "ts-node": {5 Z6 u% i0 D8 i; L# _7 a
- "transpileOnly": true,. m% c2 g; d7 c* e* s4 J0 I7 u# u1 |
- "transpiler": "ts-node/transpilers/swc" F& y6 D2 r! J7 O5 w K
- }
' {0 K. y0 B J( i( W - }
复制代码这里有 TypeScript 转译器的配置和编译器的标准配置。 这个项目是空的。我们需要安装一个新的 SDK,帮助我们与聊天机器人 API 交互。我建议使用名为 Telegraf 的 SDK: - yarn add telegraf
! I) y8 T% K" `
复制代码
) K# u% Y* u+ R) v% o- y 机器人编程我们已经安装了 Telegraf。现在,我们要在根目录下创建 src 文件夹,并在该文件夹下创建 index.tx 文件。然后,我们立即在 package.json 中创建一个脚本,并通过命令行运行我们的代码。 - {6 P9 h# D% M" \$ K* N
- "name": "first_contract_tg_bot"2 X* E0 O: P+ h5 G4 U; n6 |
- "version": "1.0.0",, ~6 q4 U6 u- G. U7 ~4 m7 o( i
- "main": "index. js",% h" h: ?8 b8 m+ W) L0 A
- "license": "MIT"
- X2 [4 H7 Q d3 r' J% U) } - "devDependencies": {
& H) c8 h/ W! N* H$ Y( @ - "@swc/core"; "^1.3.42",
; ]0 z( ?% C! I0 S& `3 w0 P - "@types/node": "^18.15.9",8 q+ W1 Y$ M7 j" i
- "ts-node": "^10.9.1",4 H1 o3 d' {( T! |" w' a
- "typescript": "^5.0.2"" g" ]+ c+ n0 b# Y4 g- h: v- U8 o- g
- },& l4 P. a4 y9 K9 D7 x" \
- "dependencies": {/ G0 @( l1 P0 {$ a4 c
- "telegraf": "^4.12.2"
% S: t% U) \9 w4 y - },
, c+ F# X* }1 {( A H1 }' k - "scripts": {( o& W1 Q* a" v) ?
- "start": "ts-node ./src/index.ts"& Q/ _& X m7 n) X8 a1 w# H
- }: d. ?% j) S# ^% r4 N# B! S: R
- }
复制代码 脚本将使用 ts-node 来实际运行我们要编程的 index.ts。让我们来看看这里的示例。当然,这不是一个 TypeScript API 示例,但我们准备了一些代码 (https://telegrafjs.org/#/?id=example) 。首先,我们要以 TypeScript 的方式导入 Telegraf:) p9 ~& M8 s8 O$ x% y& }. O! H
- import { Telegraf } from "telegraf";4 s; q6 H" M* S1 \
复制代码接下来,我们需要启动一个机器人实例。因此,我们要创建一个 Telegraf 实例: ) F. }1 s; e/ C1 @1 U0 H
- const bot = new Telegraf(' ');1 h. ]+ z E* \1 e- {/ o4 n
复制代码 它首先接受的是令牌。我们在使用 BotFather API 时已经看到过这个令牌。因此,我们需要返回,看看我们的令牌是什么并将其复制( A+ w2 C, S7 T6 @! g
- const bot = new Telegraf("6015353320:AAF4LZh2hvZSRHQcZNDMyuePl41yd2ZAMyM");
4 V2 w& ~ z( w' }% Q. m$ x9 l" J
复制代码 开发聊天机器人时,应该保留两个实例,一个用于测试,一个用于生产。因此,我们要用 env 变量将这些令牌分开。在 src 文件夹中,我们创建一个名为 .env 的新文件,以确保该文件从未提交到仓库中。我们将其命名为 TG_BOT_TOKEN,并以此启动 .env 文件:- TG_BOT_TOKEN=6015353320:AAF4LZh2hvZSRHQcZNDMyuePl41yd2ZAMyM/ d) |5 V: L0 t4 n4 ^
复制代码帮助我们与这些变量交互的库叫做 dotenv,让我们添加它: J2 \+ `- z! ^1 ^) {5 J" B
- yarn add dotenv
8 i: d/ i- H. A7 T; E+ }- A# k: K4 q
复制代码安装后,我们可以从 index.ts 中访问它: " e1 ?' g6 z& J! U+ j4 u
- const bot = new Telegraf(process.env.TG_BOT_TOKEN!);
* d) p) V' g2 S. e* \# _6 q9 Q
复制代码但首先我们需要配置并导入 dotenv。因此,让我们在文件的开头进行配置:
! p& W9 C% \% o0 f2 t8 c- import dotenv from "dotenv"
# x, ], V: g: w- J6 V( g ~
复制代码重要的是尽快在项目中运行 dotenv.config 函数,因此我们在导入后添加
" {. G q% L7 `. Z9 ^- dotenv.config();# R* @& H, B5 I; |
复制代码这个变量可能是未定义的,但我们知道它实际上是在 .env 中定义的。因此,我们可以说它肯定会存在。如果它不存在,就会失败,因此不会启动 Telegraf 实例。 酷,让我们看看一步步开始机器人交互后的示例代码是怎样的: - bot.start((ctx) =>9 ]; u& ?% ^5 a$ V5 V2 i# Q
- ctx. reply ("Welcome to our counter app!", {3 `* F+ E1 [" _! B
- reply_markup: {
% q- C4 j% _5 j2 u - keyboard: [
1 G/ w% l4 _' [5 C5 x, T. L) t3 l - ["Increment by 5"],: P! r$ P7 `# U9 Y% @7 L
- ["Deposit 1 TON"],
& ^1 p; Y7 q0 F3 V - ["Withdraw 0.7 TON"],5 t! q! |! l( g) a# b
- ]," L7 l5 o$ e4 v# \- W, j4 v) a* u
- },
$ h& Z% w' ?0 W9 ^5 L - })
1 U8 [) Z) i9 V5 w7 u2 N8 h" C: D - );
复制代码这个 Telegraf 机器人实例为我们提供了一个启动方法。当你第一次进入聊天机器人时,它就会被触发:你应该记得,当我们刚刚打开聊天机器人时,我们点击了 start。一旦你运行了第一条信息,你就会回复一条欢迎信息,并附加一个键盘。 我们来看看这个键盘会是什么样子。Telegram 聊天机器人可以让你创建自己的键盘,取代你输入信息时看到的原始键盘。你还可以在消息下方创建内嵌键盘。我们稍后再谈;现在我们只使用一个简单的键盘。 在这里,我们将创建三行和三个按钮。在网络上,"请求 "交易(如 "请求存款")是合适的,因为您授权应用程序向您提出请求。但在这里,我们有直接的交易链接,您与聊天机器人本身没有会话,所以按钮中的动作动词更合适,比如 "存款"。当然,您也可以在后台保留会话,但这样做不妥,因为会造成安全漏洞。 - bot.hears("Increment by 5", (ctx) => {7 m5 j# \7 u1 {5 z5 q$ i' p V
- // TODO: send increment transaction( ?5 C0 b8 h6 }8 \4 [: V6 N
- ctx ,reply("Incremented by 5");5 @2 q" I0 t! D9 y2 g* b$ t
- });
/ I( N3 p- A( x - bot.hears("Deposit 1 TON", (ctx) => {5 F. J8 l4 y2 K0 f
- // TODO: send deposit transaction9 C: o8 T7 O1 Q9 {% N8 k
- ctx ,reply("Deposited 1 TON");7 q" A$ ^4 t& ]; Y D1 L4 h
- });- ?8 |- X5 R( ?
, Y6 r `6 C6 u$ g( V `- bot.hears ("Withdraw 0.7 TON", (ctx) => 4 [& s, d& }* @8 x
- // TODO: send withdraw transaction
7 k8 p8 z. i" l M - ctx ,reply("Withdrawn 0.7 TON");
, ~$ D! F& h( v3 _: m+ Z- U - });
复制代码在这里,我们有几个功能。bot.hears 表示机器人会收到这样的信息。我们可以发送回复 "增加 5"。然后,我们还可以添加类似的回复。 最后,我们添加一个函数来启动机器人,并添加几行代码来确保机器人正确退出: - bot.launch();
6 k. h' _* k/ H! \7 K5 Y - - v- Y0 W8 B, s4 ~% y5 ]& \ C
- // Enable graceful stop" v4 {! t; q4 G3 [/ N7 j" k3 ^2 z) k
- process.once("SIGINT", () => bot.stop("SIGINT"));
; h* c1 u% I4 y - process.once("SIGTERM", () => bot.stop ("SIGTERM"));
复制代码好了,我们都准备好了,开始吧:
) k, ^6 u& P, G% T% Z- yarn start
5 x0 T0 M1 v- r
复制代码我们的机器人已经开始工作,但重要的是要在应用程序中进行检查。打开机器人,再次点击 "开始":
: u8 \1 R! R$ D& [1 B8 w
# F1 ~+ @1 a0 |1 p, J% ^7 c4 f# n, t正如您所看到的,我们有三个带有文本的按钮。点击其中任何一个按钮后,我们就会得到想要的回复。如果点击 "计数器",我们的应用程序将以网络应用程序的形式打开。那么,我们该如何让菜单操作发挥作用呢? & M/ }, }4 J& L2 k( |% _
使菜单操作有效 w& z [1 Q. q8 Z
我们正在创建一个部署脚本。大家还记得吧,我们创建了一个链接,可以扫描二维码直接进入钱包,在钱包中签署交易来部署合约。现在我们也可以做同样的事情。一旦你的用户获得了选项,比如以 5 为单位递增,你就可以创建一个链接,让他直接进入 Tonhub 进行支付。
" y; l9 ]* M* D* v5 r首先,让我们安装使用 TON 所需的库: # H4 J0 i$ _& g1 H( B
- yarn add ton-core ton-crypto' H$ G$ O/ `! [: y
复制代码我们需要 ton-core 和 ton-crypto 来编写信息。要建立链接,我们需要这些库: 0 b' O+ y4 d5 ?% H" F
- yarn add qs @types/qs --dev: w& J& i4 j2 ?4 h; m2 Q
复制代码现在,我们将重复使用第一课中的一些代码。确保我们的合约地址是正确的。你还记得,在 first_contract_front_end 项目中,我们创建了一个挂钩,该挂钩附加到某个合约。让我们从 useMainContract.ts 中获取地址:
6 I$ J, e8 V T; u; B- const mainContract = useAsyncInitialize(async () => {* R. k) ~% [& A U2 `
+ P8 @6 D4 Q Q( Z' ^5 ]8 l( Z" @- if (!client) return;
8 U/ q6 t; {3 C. M' F - - B) D5 _% c2 s1 I$ i# T0 f
- const contract = new MainContract(
, c$ c% l% }; O$ z8 W5 v/ k$ r9 i
8 X8 L' n- q" y, F N% o- Address.parse("EQBDUxTxWo41aCY1SGZJJlDnu4uKvZtbOjuGF9mtf22M1UBq") // replace with your address from tutorial 2 step 8
& |7 B0 J8 ^" O& q - 4 \, v. h/ n/ k0 M( ^9 f$ w
- );9 ~0 w. U" Q# d& N
- ! x8 I' l) C( X6 [% O. B2 Q
- return client.open(contract) as OpenedContract<MainContract>;8 k/ M9 b( h5 ]$ p4 @
2 v. P* F# a6 x2 f+ {4 i B/ q- }, [client]);
复制代码现在,我们需要导入地址结构。 + t F1 S' H ^4 N$ a5 W
- bot. hears ("Increment by 5", (ctx) => {0 q) w9 Q8 ?# K: ^0 Z
- let link =
9 E7 p& ^. W/ _& f# |/ o - `https://test.tonhub.com/transfer/` +# u) P l9 _+ f0 c0 a) B
- Address.parse ("EQBDUxTxWo41aCY1SGZJJlDnu4uKvZtbOjuGF9mtf22M1UBq").toString
( e* A1 l2 F6 h) D4 \% X - RestOnly: true,
复制代码我们不会在主网中做任何事情,这只是测试网。我们从特定地址中解析出地址类,然后将其转换为字符串。实际上,我们可以直接这样做,因为我们显然需要一个字符串。然后,让我们重新组合,使代码更简洁: & ~- z9 ~* ?0 u1 K, j6 H8 A2 |. U4 k
- bot. hears ("Increment by 5", (ctx) => {
* Q& C, }$ S0 d8 A; d1 H j5 i - let link = `https://test.tonhub.com/transfer/EQBDUxTxWo41aCY1SGZJJlDnu4uKvZtbOjuGF9mtf22M1UBq?${qs.stringify(7 P B% [& G V2 \7 G# w4 K
- {" s& o5 c% F' ~# z2 f
- text: "Simple test transaction",
/ B8 o5 z$ U) B; N - amount: toNano ("0.05") . toString (10) ,7 [9 i+ C! [: B8 L
- bin: msg body toBoc({ idx: false }). toString ("base64"),
: R* I$ A9 `6 r - }
' y9 s1 K* T2 h - )}`;
复制代码我们甚至可以这样做: , r Q$ n( h# K# X# f! ^( N$ B
- const SC_ADDRESS = "EQBDUxTxWo41aCY1SGZJJ1Dnu4uKvZtb0juGF9mtf22M1UBq"; S& g/ [$ L8 |5 M9 \7 F
复制代码因此,我们把智能合约地址放到链接中: * c9 x$ O% C1 {: B0 Y9 b( M* @
- bot.hears ("Increment by 5", (ctx) => {
4 ^4 a& V( h9 J8 L# e4 a - let link = `https://test.tonhub.com/transfer/${SC_ADDRESS}?$ {qs.stringify(
- l, |1 M4 l+ C0 L: M$ T: D' g - {
3 }4 |2 P/ a5 Q$ _* ` - text: "Simple test transaction",
6 U. I( {, E8 b7 J. ]$ i: y, s0 Z7 a - amount: toNano ("0.05") . toString (10) ,, s+ w7 l: m. F; |# v
- bin: msg ,body ,toBoc({ idx: false }). toString ("base64")," N* X4 y F; y5 E3 n8 b; M" G
- }
! T- U" e" a. B; G- E& U - )}`;
复制代码 你甚至可以再做一项改进。就像我们为令牌设置环境变量一样,我们也可以在 .env 中设置智能合约地址来执行此操作,因为在生产过程中,你很可能也会在主网上设置一个合约:
3 _* u% U0 N& U% D: a# _( g- SC_ADDRESS=EQBDUxTxWo41aCY1SGZJJ1Dnu4uKvZtb0juGF9mtf22M1UBq
: E& u. K8 T% k( v
复制代码现在在 index.ts 中,我们不再需要地址对象了。
! t! y* i z" |) L% `- import { Address } from "ton-core";
1 L+ Q, W! ]! }, v
复制代码在 bot.hears 的 Amount 中,我们从上下文菜单中选择 Add import from "ton-core" ,并在链接中添加 process.env:
* t# X4 y: t4 x/ R3 M- bot.hears ("Increment by 5", (ctx) => {
7 s: i+ R3 B8 e% d! i+ q% B - let link = `https://test.tonhub.com/transfer/${process.env.SC_ADDRESS}?$ {qs.stringify(3 ^8 B$ S1 n' d0 i& N- m
- {
/ Y9 ~% P7 K6 X - text: "Simple test transaction",
[( y" G7 S; \1 Q, L - amount: toNano("0.05").toString(10),
/ D) x. ]1 l) V1 U$ i: H - bin: msg_body.toBoc(( idx: false )). toString("base64"),, V. g' v- Q" J l1 g1 c
- }2 _% c% y- T0 R' w y; B8 b+ n
- )}`;
复制代码在这里,我们需要形成一个信息正文。什么是信息正文?我们使用 "生成器",因为我们要把消息正文作为Cell,然后由 TON 将其转换为字符串表示法。我们要在消息正文中输入什么内容呢? 我们正在创建合约及其封装。我们将发送一个增量函数。为此,我们可以直接从 wrappers > MainContract.ts: - const msg ,body = beginCell()4 h/ U4 \: s! W& j0 {/ h
- .storeUint(1, 32) // OP code
/ q" x# ~9 P2 P8 C - .storeUint(increment_by, 32) // increment_by value& M7 E; G; }& }/ A
- .endCell();
复制代码它显示了我们要递增的整数和递增多少的整数。所有这些我都会复制到我的机器人项目中: $ U% y" C6 y& l& s2 P# l3 b6 q
- bot.hears("Increment by 5", (ctx) => {
3 I0 A7 C/ @+ e: Z
/ v# ^3 O3 m1 h- const msg_body = beginCell()
0 d$ V9 L" E" p7 Y- v- K - .storeUint(1, 32)
& K4 ]8 d( H7 x T - .storeUint(5, 32)* I! M1 {1 l$ S. t) o0 C* C( k
- .endCell();
! _4 @9 p2 W) X9 o
' b$ p: J5 J7 z; x- let link = `https://app.tonkeeper.com/transfer/${process.env.SC_ADDRESS
' T' m. j' U5 x3 \- O2 ], Z$ `, ^- ^ - }?${qs.stringify(
+ f( Y) w" Y n! k/ }4 G6 E - {
5 y: T2 |2 n0 y3 _. P i, E3 _ - text: "Simple test transaction",/ h: j; p" ^# t V# l' A+ Z& [
- amount: toNano("0.05").toString(10),5 p3 }4 a% Z0 V& `+ q5 V+ y9 h9 l
- bin: msg ,body.toBoc({ idx: false }).toString("base64"),
% N7 Z7 T1 X( {* ]+ \; S - }2 D* b. h$ y; j. \
- )}`;
复制代码 我们不要求增量,但我们知道它是 5,所以我们把 5 放在这里。你可以随意调整,要求增量。在我们的例子中,我们已经有了5个硬编码了。现在我们在开始时导入 qs:
u5 V2 ~2 N. q& h- import qs from "qs";
- P' q# V7 k+ J& H8 N
复制代码很好,我们导入了所有内容,现在来对对象进行字符串化。我们说要将计数器递增 5 - 这只是附加到消息中的一个文本。然后把 0.05 作为实际支付交易费用的金额。然后我们使用这个参数费。 在此,我们前往 Tonhub 开发人员文档。我们使用的链接仅适用于 Tonhub,但你也可以使用 Tonkeeper 链接。在文档中,你也可以找出 URL 的结构来提供一些值。 Bin parameter everywhere 用于传递 msg_body,一旦您想发送带有特定参数的消息。这正是我们在这里要做的事情:我们为 Tonhub 创建了一个付款链接。 但在此之前,我们需要让机器人回复用户。一位用户使用我们在开始时提供的键盘给我们发送了 "递增 5 "的消息。我们需要回复,让用户知道他能做什么。我们需要提供一个链接。我们可以简单地发送链接,但我们希望它对用户非常友好。这就是为什么我们要回复一条信息: - ctx.reply("To increment counter by 5, please sign a transaction:", {
4 y1 l7 A; n8 N; L7 o" V" w/ Q - reply_markup: { Y3 V4 Z- R% f/ e/ r2 r
- inline_keyboard: [) \" @* c0 [) U' W
- [{
/ M. S7 a1 M' Q! y - text: "Sign transaction",, j0 K& o n* i- V" o8 e
- url: link,
% n" l9 w# F1 R& M5 E - }]3 Q& ~3 p( K" }9 V$ X: l* O
- ]. ^8 l1 Y2 _0 e$ b- \$ G( X
- }; e6 [/ H# a2 F
- })
复制代码然后,我们创建一个额外的参数。回复标记可以是 InlineKeyboard, ReplyKeyboard, ReplyKeyboardRemove 或 ForceReply。这里有多个选项,我们希望使用 inline_keyboard。 上次我们使用的是普通键盘,位于输入行下的同一位置。现在我们创建了一个内联键盘,如上图所示。它有几个参数:文本、签名交易和 URL。因此,我们在 bot.hears 中提供了一个带有链接的 URL 参数。 有一件事我之前没有提到,但你应该记住:如果我们想把某个Cell作为链接发送,比方说,连同一些字符串或链接一起发送,我们需要把它打包成 base64,就像信息正文的Cell一样。 好吧,看来这个办法行得通: - yarn start3 A L( l, s7 U3 J& U
复制代码一切正常,于是我回到手机上。我打开开始命令提供的键盘,点击 "递增 5": $ |( U" K$ B5 ]- x" v
. T6 l9 N _, Z2 a; x# D1 _8 i
如您所见,我们收到了一条信息,要求我们签署一项交易,以 5 为增量。交易已发送。如何检查交易是否真的影响了我们的合约状态?如果检查网络应用程序,可以看到 "计数器值 "等于 15,而之前是 10。
( O/ I) v5 D& Q3 ]6 F' l0 J4 c/ n0 q3 j- }1 [5 \4 e
进一步改进机器人我们可以通过聊天机器人构建特定的用户流,用户将在后端与我们的区块链进行交互。我们在后端没有任何用户凭证,所以我们实际上是在为他提供钱包链接,让他进行支付。我希望这不会让你感到困惑,因为作为开发者,你应该始终考虑可用性。而这正是可以显著提高可用性的方法之一。 Telegram 中的网络应用程序可让您使用自动消息创建有趣、酷炫的聊天对话。这样,您就能为用户创建极具价值的精彩项目。让我们构建一个类似的链接: - bot.hears("Deposit 1 TON", (ctx) => {4 o) x+ g" p/ h( c/ Z, V
- const msg_body = beginCell().storeUint(2, 32).endCell();
复制代码我们将用 2 来表示存款数额。我们不需要其他任何东西,让我们在 wrappers > MainContract.ts 中再次确认这一点: % R/ k8 S7 [; V7 h& p; V$ b% x. l
- async sendDeposit(provider: ContractProvider, sender: Sender, value: bigint) {: \4 I# j' N2 s5 [
- const msg_body = beginCell()8 j; F# S6 P9 S/ Z9 N
- .storeUint(2, 32) // OP code5 {4 S$ t+ I. D9 i2 l% k }6 A
- .endCell()
复制代码接下来,我们需要输入存款命令,否则我们将无法在合约上收钱。在 index.ts 中,我们只需输入一个等于 2 的整数(32 位)。在这里,我们说它将是 "Deposit 1 TON"(存款 1 Ton),实际上我们将要求提供 1 Ton的付款。它不必是一个字符串。 // Final code deposit command - bot.hears("Deposit 1 TON", (ctx) => {1 F# n% k( L' T
- const msg_body = beginCell().storeUint(2, 32).endCell();+ }/ ]) n4 X3 R
" |. H! K8 y3 _# x& k4 y-
6 ?, Y$ H7 D$ _, B - let link = `https://app.tonkeeper.com/transfer/${
: p# X0 R. h6 {8 i8 R# _" l - process.env.SC_ADDRESS
# ~% P' s+ C* a - }?${qs.stringify(
7 n6 R+ O" Y4 j1 A( A - {, V. z& I* \$ e+ L7 l! L( p) U
- text: "Deposit 1 TON",
: C1 v9 x* U2 ~4 E1 H( v+ V' I - amount: toNano("1").toString(10),) B& ^) F3 j0 c3 }& e8 ^/ [" D* ?5 {
- bin: msg_body.toBoc({ idx: false}).toString("base64"),
) D8 R% ^! D, A0 p - }
, D1 r4 q1 G# [8 V K - )}`;
复制代码 因此,我们要求用户向合约发送 1 Ton,并在信息中注明这是存款。我们在这里输入信息,然后删除回复 "已存入 1 Ton",因为我们不再需要它了:+ X/ q( h; d) l0 O
- ctx.reply("To deposit 1 TON please sign a transaction:", {
5 ?: r; {# l6 Z* o - reply_markup: {$ O/ B2 J# `$ \( i- I
- inline_keyboard: [8 ~3 m& ~% x z3 b+ b) |5 K
- [' T0 l' y; k3 Q( l7 O9 z* L7 g
- {
4 C' }! {/ e3 d' `8 e1 R3 ~ - text: "Sign transaction",
+ @$ V* J1 I2 D5 M1 |* g4 H; W - url: link,
( h$ V: n& M! M: g d( z' m - }
% j) Y$ a9 `/ v. S$ z - ]$ c0 p3 ]7 x- q7 U" h) l. E# N% b
- ]
2 i& B. L8 g+ r/ v' F8 T - }
3 M# F |% c+ f) L5 o: G6 N - });
复制代码所以这很简单。我们形成一个消息正文、一个链接、链接文本,将 1 Ton金额设为存款,将正文放入一个字符串,然后用链接中的键盘回复。我们还需要做的一件事就是将机器人的存款逻辑复制到取款逻辑中: // Final code withdraw command - bot.hears("Withdraw 0.7 TON", (ctx) => {
9 E, ]; e; t( l/ v, U5 n( n Y2 T - const msg_body = beginCell().storeUint(3, 32).endCell();
4 O0 h& _+ P5 y9 a# i* Y$ ^ -
& |' u1 S3 g" |. E4 M - let link = `https://app.tonkeeper.com/transfer/${* h5 t* d: E& Q/ s0 G
- process.env.SC_ADDRESS3 T! n- J4 z/ Z1 A S
- }?${qs.stringify(: S5 [* m, R3 \
- {( K( n) L4 ^/ Y1 ~5 X' U4 g
- text: "Deposit 1 TON",# H& e* D3 |, U3 n5 l
- amount: toNano("1").toString(10),. @' x" k) R$ s* x
- bin: msg_body.toBoc({ idx: false}).toString("base64"),
5 r5 y0 h) U& O+ K7 I' f - }: Y( C$ |5 x& v1 w8 w
- )}`;' h/ w c J! D% _# p; L1 F! Z) Z: `
- 8 r% `8 A* ~; i6 Y6 g ?! Y
- ctx.reply("To deposit 1 TON please sign a transaction:", {1 m; K' D7 z% G" f Z( W
- reply_markup: {6 T5 B) F: y: P( _
- inline_keyboard: [4 m |4 T* d" \- C
- [( b8 R C0 F8 w/ s: ?+ z; K5 Q, t
- {
/ t3 y- e- ^: A: ] - text: "Sign transaction",3 b/ b( C! T: h4 N) x: W
- url: link,
- Z' `' {$ Z) H$ h: F - }5 O. x6 s3 x* G
- ]4 O' w( ~! U/ v: \
- ]
" K6 m- t+ f: C - }
& e& q/ }2 H1 ^1 ]7 C - });
复制代码现在我们回到提款的包装。在 index.ts 中,我们需要提供想要提取的金额: : I' ^5 u) u; D: D
- bot.hears("Withdraw 0.7 TON", (ctx) => {
, M7 S& t- ?" T) a - const msg_body = beginCell().storeUint(3, 32).storeCoins(toNano(`0.7`))endCell();
复制代码我们添加了关于提取 0.7 TON的文字,接下来我们把足够支付GAS费Ton数放进去,因为我们要在这里拿钱:
) s0 d( M/ D; k/ Q3 I% }0 o- let link = https://test.tonhub.com/transfer/${: i8 Q+ |9 H! `! B" r
- process.env.SC_ADDRESS
* U, s* G. Y9 w5 y# [ - }?${as.stringify({
) j4 ?6 D- U) C& ] - text: "Withdraw 0.7 TON",
, @. T$ f2 a7 r1 d# { - amount: toNano('0.05').toString (10),
) d- K! F4 C$ K+ G4 S* M2 _ - bin: msg_body.toBoc({ idx: false }).toString("base64"),
) d7 l4 r3 O) s, b2 N - })}`;
复制代码然后编辑机器人信息: 9 L- X2 k7 L9 q x0 d
- ctx.reply("To withdraw 0.7 TON please sign a transaction:", {
; D0 v* f v9 Q2 m T - reply_markup: {; N& G# U- h e. u
- inline_keyboard: [, [# {$ o8 S- [
- [{% V6 G. K" N$ T ^9 z' x& `4 i
- text: "Sign transaction",
. e P) H# r% t7 U1 F - url: link,
. T# R0 R1 k2 P - }]$ C$ E& Y" o- z2 p2 ]5 C
- ]
( [/ ~$ t) j9 o0 i4 B - }
' B3 c9 W6 C$ u - });
复制代码我们用 yarn start 重启机器人,回到 Telegram 应用程序。现在,我们不仅可以存款,还可以以同样的方式取款: 现在,我们访问 Telegram 中的网络应用程序文档,阅读更多有关该 SDK 中可用内容的信息 (https://core.telegram.org/bots/webapps) 。这里有 initData 和 initDataUnsafe。当我们想在启动网络应用时发送一些原始数据时,就会用到它们。通过这个版本,我们可以检查用户 Telegram 应用程序中可用的机器人 API 版本。通过这个平台,我们可以检测平台。我们还可以调整配色方案和主题参数--这些选项由 Telegram 文档提供。我们可以检查是否已展开,并设置窗口高度。
1 i! S3 f+ T F" t8 z* H
我们现在需要的是 sendData(发送数据)--一种向机器人发送数据的方法。调用该命令后,带有数据的服务消息就会发送给支持的机器人,其中包含给定长度的数据。重要的是,运行该命令后,会有一条消息发送到你的 Telegram。基本上,一旦你运行了 sendData 函数,你发送的信息就会由我们刚刚创建的后端机器人处理。你的处理方式会是这样的: - bot.on(message("web_app_data"), (ctx) => ctx.reply("ok"));
# u& ?& V/ ]; j+ n/ h8 [
复制代码您还需要从 telegraf/filters: ( \0 V0 a/ v A1 v/ O" V4 e
- import { message } from "telegraf/filters";( {; Q4 {" Z, p/ M. {& C- ^+ J
复制代码 您可以在这里发送贴纸或消息,但要过滤网络应用程序的数据。在这里,您将收到从网络应用程序发送的数据。需要注意的是,这是用于关闭的,因此一旦运行 sendData 方法,网络应用程序就会关闭。
& T# A9 t* y/ R8 r. i' |0 f; @7 ?, p7 e# `6 u, [7 C3 ^7 N
结论差不多就是这样。我们今天学到了很多东西。实际上,我们已经知道了如何使用一种最好的方式将应用程序推向大众。TON 涉及大规模应用,因此你必须掌握如何构建应用程序,以便将其整合到载体中。如果 Telegram 是这么多人的载体,TON 是我们非常喜爱的区块链,而且这个平台已经为这么多人做好了准备,那么你们为什么不构建自己的应用程序,并将可扩展技术带入已经有这么多用户在等待你们产品的地方呢? : s- M9 v2 u. F! ^) l9 b) B. r \9 O
我很高兴你们现在已经具备了这样的条件。我希望你已经明白了一切,希望你所学到的一切都能帮助你打造自己的产品。下一章再见。谢谢!
: `9 R/ C1 \; G% `3 g$ L+ |5 ?) a) B5 i J# L
# j; r! ~) w* C
/ Y3 H1 ~: R2 n8 h! o! C
- `# |! I* t" Y
3 o) P6 \2 X$ q4 R
. Y1 t3 b$ h R; E
, H; v1 w' K$ f( |2 s) j1 G/ H' M& b; `' `8 P2 @! ?9 G
|5 i) l- v! o6 N
. D x. G; h, R8 G! b3 @8 T3 u, Y! ~
6 H: X$ {8 x( f% L* O! A$ T1 S# d- }4 f7 ~8 L0 Q
$ J' H; k2 ~6 t# G, I
/ H, J0 u; P4 `3 x* e, j1 k% ]8 M$ i$ j# W3 _2 L8 o# a5 y
: D. \8 Y& O% B$ o! k7 W- I5 H# L2 n4 ?, _
|