本帖最后由 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 \ 准备开始我们在开始一个新项目时,先创建一个新目录并将其移动到该目录中: - mkdir first_contract_tg_bot% R" |: R* ^3 W
- cd first_contract_tg_bot
复制代码现在我们设置一个新软件包:
& K' ^3 n6 j# X- 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 }
- 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- {
+ Q$ X0 @6 Z0 h6 B; U9 c, j - "compilerOptions": {6 F; T( Z! E, Y6 @
- "target": "es2020",
; D. W( H5 u- R$ N8 V9 } - "module": "commonjs",6 B: ~6 t6 k" o9 i; a$ N
- "esModuleInterop": true,
) V- d. {! F* T" M! p$ L: a - "forceConsistentCasingInFileNames": true,
; d% _+ M0 G: r- U" l - "strict": true,! u7 X0 f8 a1 l, H8 a- `
- "skipLibCheck": true,' u' U, n% U4 G. I
- "resolve]sonModule": true
! w# Z! G. H8 R3 n4 b - },
) I6 d1 W5 Y5 J. g# Q$ C7 y' d- @ - "ts-node": {% |( b3 F N* @( s( H- Z
- "transpileOnly": true,% ?- ^; I6 G, @& ]; R9 h
- "transpiler": "ts-node/transpilers/swc"- z/ D5 E! i2 s1 s. p% Z9 a! g
- }
6 r) o/ h1 V$ I; V; I9 x! m - }
复制代码这里有 TypeScript 转译器的配置和编译器的标准配置。 这个项目是空的。我们需要安装一个新的 SDK,帮助我们与聊天机器人 API 交互。我建议使用名为 Telegraf 的 SDK: - yarn add telegraf7 o$ F# Z( w% ]% M/ g! v
复制代码
# d# G, Z% Y: l4 a B' U 机器人编程我们已经安装了 Telegraf。现在,我们要在根目录下创建 src 文件夹,并在该文件夹下创建 index.tx 文件。然后,我们立即在 package.json 中创建一个脚本,并通过命令行运行我们的代码。 - {
* K% q9 o: A; ~1 y+ C/ e9 f+ f - "name": "first_contract_tg_bot"# |6 q8 r/ B. t6 a. K! n3 r" k/ l, R/ r
- "version": "1.0.0", u, `8 d0 Z" R/ a: R
- "main": "index. js",' u C Q9 K: C# n: `: G
- "license": "MIT"5 Z1 G6 A" I) `
- "devDependencies": {' k* M1 W1 X F. T* E
- "@swc/core"; "^1.3.42",
( F- P) a' ~. L" A2 t& f - "@types/node": "^18.15.9",
$ Z2 e7 Q' |9 {4 z. f - "ts-node": "^10.9.1", {: U6 G5 C9 m9 \: n! B
- "typescript": "^5.0.2"
; y8 {+ [' }3 h# ?, h1 K$ K - },
. r4 Z1 u/ `; s - "dependencies": {
( g; U& B. y6 v, M$ r0 K v - "telegraf": "^4.12.2"* t( W) B% B& l- j0 C( b
- },
# E' Z: z5 Z w# t9 ~7 j, o" S - "scripts": {
1 \/ }/ q; ?$ M5 `, l - "start": "ts-node ./src/index.ts"8 I1 X% k } {$ u6 y
- }& z% q' m+ }0 C, f* n+ }! G: {9 [. x
- }
复制代码 脚本将使用 ts-node 来实际运行我们要编程的 index.ts。让我们来看看这里的示例。当然,这不是一个 TypeScript API 示例,但我们准备了一些代码 (https://telegrafjs.org/#/?id=example) 。首先,我们要以 TypeScript 的方式导入 Telegraf:
* i4 X4 l0 X5 h2 S0 i4 C# n- import { Telegraf } from "telegraf";/ t; q) }% Q8 _' t
复制代码接下来,我们需要启动一个机器人实例。因此,我们要创建一个 Telegraf 实例: " m3 B0 w9 j' x h& e- |* J0 z' V
- const bot = new Telegraf(' ');
! p& X5 M2 y; _+ w1 q
复制代码 它首先接受的是令牌。我们在使用 BotFather API 时已经看到过这个令牌。因此,我们需要返回,看看我们的令牌是什么并将其复制! P# m V4 n7 A9 `) r" G& I1 {
- const bot = new Telegraf("6015353320:AAF4LZh2hvZSRHQcZNDMyuePl41yd2ZAMyM");8 M4 b; }: I' l: k2 \; n% J
复制代码 开发聊天机器人时,应该保留两个实例,一个用于测试,一个用于生产。因此,我们要用 env 变量将这些令牌分开。在 src 文件夹中,我们创建一个名为 .env 的新文件,以确保该文件从未提交到仓库中。我们将其命名为 TG_BOT_TOKEN,并以此启动 .env 文件:- TG_BOT_TOKEN=6015353320:AAF4LZh2hvZSRHQcZNDMyuePl41yd2ZAMyM; ?7 g! u( N' ~ M
复制代码帮助我们与这些变量交互的库叫做 dotenv,让我们添加它: & H) a- w- }& M6 @, f2 E& |/ k
- yarn add dotenv
) w `; ], ~, K" r6 F% p% F4 D
复制代码安装后,我们可以从 index.ts 中访问它: 4 ^# \" p4 \5 }) m' c, g& ^4 ^
- 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
- import dotenv from "dotenv"
! u5 c/ R' W6 a0 X
复制代码重要的是尽快在项目中运行 dotenv.config 函数,因此我们在导入后添加
i* U$ n g- y1 N: J7 T- dotenv.config();
7 y" B: |4 u% y( Q7 ^" B( X0 M
复制代码这个变量可能是未定义的,但我们知道它实际上是在 .env 中定义的。因此,我们可以说它肯定会存在。如果它不存在,就会失败,因此不会启动 Telegraf 实例。 酷,让我们看看一步步开始机器人交互后的示例代码是怎样的: - bot.start((ctx) =>% H! Z2 |* ?1 ]6 P% S6 _
- ctx. reply ("Welcome to our counter app!", {
/ g: E9 T& U: J2 i, G* N y' V4 o" ^ - reply_markup: {2 `( M- [ t! U4 X
- keyboard: [" ~, {% S- Y0 w' o" O$ U8 u
- ["Increment by 5"],
4 Z6 C; V% B: X# m% h1 x - ["Deposit 1 TON"],
. g" T9 L3 ?+ Z) D4 K - ["Withdraw 0.7 TON"],! k: Z. K; L0 E/ [# Q5 f$ \
- ],2 K8 S4 D2 O) o. h
- },0 C3 u) n) C5 n# d6 X
- })
& z( Q$ ^- c5 R. F. e, O - );
复制代码这个 Telegraf 机器人实例为我们提供了一个启动方法。当你第一次进入聊天机器人时,它就会被触发:你应该记得,当我们刚刚打开聊天机器人时,我们点击了 start。一旦你运行了第一条信息,你就会回复一条欢迎信息,并附加一个键盘。 我们来看看这个键盘会是什么样子。Telegram 聊天机器人可以让你创建自己的键盘,取代你输入信息时看到的原始键盘。你还可以在消息下方创建内嵌键盘。我们稍后再谈;现在我们只使用一个简单的键盘。 在这里,我们将创建三行和三个按钮。在网络上,"请求 "交易(如 "请求存款")是合适的,因为您授权应用程序向您提出请求。但在这里,我们有直接的交易链接,您与聊天机器人本身没有会话,所以按钮中的动作动词更合适,比如 "存款"。当然,您也可以在后台保留会话,但这样做不妥,因为会造成安全漏洞。 - bot.hears("Increment by 5", (ctx) => {
+ w& U! J1 G( s, ?( V+ u - // TODO: send increment transaction
8 Y2 G( v! l1 ]# k9 q - ctx ,reply("Incremented by 5");
[+ P& G0 [ [6 i" L - });
W+ Q8 U. l, l& q! I - bot.hears("Deposit 1 TON", (ctx) => {, Q# q3 z& B1 |6 F, I
- // TODO: send deposit transaction
, z* \: o2 T. ]% a3 U - ctx ,reply("Deposited 1 TON");
. M4 M& z3 h' J2 R+ U" J( e" ~ - });
' F$ a: C! S" b$ |: P6 s, b
" A& s( M8 ]9 r2 \: D' I, v6 e- bot.hears ("Withdraw 0.7 TON", (ctx) =>
7 [" O; G y" x6 X# A+ F6 c+ o - // TODO: send withdraw transaction
" a' F$ E: t1 p/ j' {: ? - ctx ,reply("Withdrawn 0.7 TON");
3 Y+ K: m5 M7 V1 C - });
复制代码在这里,我们有几个功能。bot.hears 表示机器人会收到这样的信息。我们可以发送回复 "增加 5"。然后,我们还可以添加类似的回复。 最后,我们添加一个函数来启动机器人,并添加几行代码来确保机器人正确退出: - bot.launch();
' d. x% T2 Q+ S - . |; t6 E: P/ P4 B" |" K' d
- // Enable graceful stop
0 x- @& [; D1 | - process.once("SIGINT", () => bot.stop("SIGINT"));; f0 Y- w9 u' S; C
- process.once("SIGTERM", () => bot.stop ("SIGTERM"));
复制代码好了,我们都准备好了,开始吧: M8 f! b- o/ d6 z
- 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- yarn add ton-core ton-crypto( v+ s1 b. L$ Z
复制代码我们需要 ton-core 和 ton-crypto 来编写信息。要建立链接,我们需要这些库:
% m' E) E4 y! W9 ~ M" a- 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$ \- const mainContract = useAsyncInitialize(async () => {8 h/ a9 m j! O& }% @, G7 e0 ~6 d
- 5 [# f( ]% J' E- Z ?+ x, i2 L
- if (!client) return;
; T$ ~ ~. t3 A0 _ B9 { - 0 Z% l3 J/ s5 U- ~9 H) z
- const contract = new MainContract(; a/ f6 d7 M' B8 Y% m
- 0 ~3 \5 ~. A6 Z1 o0 m
- Address.parse("EQBDUxTxWo41aCY1SGZJJlDnu4uKvZtbOjuGF9mtf22M1UBq") // replace with your address from tutorial 2 step 86 V5 @; I9 e7 }& W
- 3 I; t& C4 D& s' v3 O5 S
- );# C0 G4 g! p$ V# f* Z- C
- 7 z! d& N1 l0 Y9 i$ ?
- return client.open(contract) as OpenedContract<MainContract>;
9 @( @! s1 U5 @. R3 w% s' s& ~8 D. M
, K5 f% w$ a3 q$ M$ v2 m3 R- }, [client]);
复制代码现在,我们需要导入地址结构。 - l, e T1 L1 e8 X2 m/ M/ |
- bot. hears ("Increment by 5", (ctx) => {
# G- B+ G4 e0 v- O% q' t - let link =
/ u- Z _ R. `( n/ U - `https://test.tonhub.com/transfer/` +# M, u6 N. ?/ N/ W( @
- Address.parse ("EQBDUxTxWo41aCY1SGZJJlDnu4uKvZtbOjuGF9mtf22M1UBq").toString- p1 t2 l/ _: G& s9 Q+ ~
- RestOnly: true,
复制代码我们不会在主网中做任何事情,这只是测试网。我们从特定地址中解析出地址类,然后将其转换为字符串。实际上,我们可以直接这样做,因为我们显然需要一个字符串。然后,让我们重新组合,使代码更简洁: ; D( I& O8 R) ^4 C
- bot. hears ("Increment by 5", (ctx) => {, @& _/ ?3 k; M7 M) E6 ^' K# Q3 n2 K
- let link = `https://test.tonhub.com/transfer/EQBDUxTxWo41aCY1SGZJJlDnu4uKvZtbOjuGF9mtf22M1UBq?${qs.stringify(
$ n/ {( e5 k6 T, p - {8 H3 G$ O9 v! Z3 n; v' G& s
- text: "Simple test transaction",
5 Q& f5 E' U8 B1 A& X& \ - amount: toNano ("0.05") . toString (10) ,
! u; Z. M; Y% s5 E' f' Q - bin: msg body toBoc({ idx: false }). toString ("base64"),% F6 x! u) y: I- c6 e+ K' M
- }+ W. s7 E6 p q( \( H# v/ K1 M
- )}`;
复制代码我们甚至可以这样做:
?& x/ b% O2 k- M- const SC_ADDRESS = "EQBDUxTxWo41aCY1SGZJJ1Dnu4uKvZtb0juGF9mtf22M1UBq";
. W. i2 s* f2 x) R# O
复制代码因此,我们把智能合约地址放到链接中: / K) l3 } n7 Q. d+ I
- bot.hears ("Increment by 5", (ctx) => { t5 A* A& b% c- _: @
- let link = `https://test.tonhub.com/transfer/${SC_ADDRESS}?$ {qs.stringify(+ f; A9 D( X7 ~1 t# G% [3 P% f4 t
- {: d) Z1 i0 J. W- R
- text: "Simple test transaction",
+ z% E9 h' c8 ^ |; h: x& \ - amount: toNano ("0.05") . toString (10) ,
5 ?# U& m( \4 x3 @8 h - bin: msg ,body ,toBoc({ idx: false }). toString ("base64"),
& i# ^5 @0 a' _, I Z& W7 L' c" n - }0 d' a) W- l, C4 r v* ?
- )}`;
复制代码 你甚至可以再做一项改进。就像我们为令牌设置环境变量一样,我们也可以在 .env 中设置智能合约地址来执行此操作,因为在生产过程中,你很可能也会在主网上设置一个合约:4 O' ~- i3 i' ^* a5 _% o' ^( R( p
- SC_ADDRESS=EQBDUxTxWo41aCY1SGZJJ1Dnu4uKvZtb0juGF9mtf22M1UBq
9 S9 x" d: S2 v% J$ b! {
复制代码现在在 index.ts 中,我们不再需要地址对象了。
' N; o; E7 d8 O9 S/ u6 s- 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" ~
- bot.hears ("Increment by 5", (ctx) => {2 ^+ K- ~+ g/ W3 N& j
- let link = `https://test.tonhub.com/transfer/${process.env.SC_ADDRESS}?$ {qs.stringify(
( @, s4 l% a0 C# p - {
& j2 w% y# l- O4 ]6 { - text: "Simple test transaction",0 N1 G5 Z2 X! ~! S- B/ }
- amount: toNano("0.05").toString(10),' }/ D) d: [' b/ ^ t q! X& I
- bin: msg_body.toBoc(( idx: false )). toString("base64"),- y" X* {9 L# ?6 {4 Z8 l; _
- }
7 N" k+ |9 x5 |5 l' q' b7 n - )}`;
复制代码在这里,我们需要形成一个信息正文。什么是信息正文?我们使用 "生成器",因为我们要把消息正文作为Cell,然后由 TON 将其转换为字符串表示法。我们要在消息正文中输入什么内容呢? 我们正在创建合约及其封装。我们将发送一个增量函数。为此,我们可以直接从 wrappers > MainContract.ts: - const msg ,body = beginCell()+ U1 x- y! X, K" K7 C' s
- .storeUint(1, 32) // OP code
- C2 \7 A; d# N" i6 R {5 z - .storeUint(increment_by, 32) // increment_by value
, } Z" [/ `+ H; z& @ - .endCell();
复制代码它显示了我们要递增的整数和递增多少的整数。所有这些我都会复制到我的机器人项目中:
3 C- A" }( D% R/ J- bot.hears("Increment by 5", (ctx) => {
8 a& M% g- s! E3 A9 l - / @. T. k3 o8 j7 u e. [+ ^
- const msg_body = beginCell() 5 `+ |: M( v# r* O7 D6 r6 X
- .storeUint(1, 32)
- x$ G7 Z6 j: `" ]6 ? - .storeUint(5, 32)) V3 d! i& c; A' _1 A! t
- .endCell();% G6 a7 p7 |! y1 a9 H- [
- + K4 g t8 I' O: m# z0 L
- let link = `https://app.tonkeeper.com/transfer/${process.env.SC_ADDRESS
& k/ T# ~3 U% R - }?${qs.stringify(
F4 v8 y5 ?7 [7 d/ N7 x: n. M$ r - {( v$ c! q" D( X7 ?' _$ z
- text: "Simple test transaction",
9 n- h; `- G. [4 H - amount: toNano("0.05").toString(10),# l) o6 M' T! N/ O2 U1 T5 v2 l
- bin: msg ,body.toBoc({ idx: false }).toString("base64"),
/ d% R# p" [$ A/ z/ S* g - }9 I) Y4 B4 {# w, g
- )}`;
复制代码 我们不要求增量,但我们知道它是 5,所以我们把 5 放在这里。你可以随意调整,要求增量。在我们的例子中,我们已经有了5个硬编码了。现在我们在开始时导入 qs:
: P' c& T/ a/ x- import qs from "qs";& L0 m1 i d9 y
复制代码很好,我们导入了所有内容,现在来对对象进行字符串化。我们说要将计数器递增 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:", {. n; ]- x1 [/ T. ^
- reply_markup: { L1 r; y4 }* B) \
- inline_keyboard: [2 g% [) @ c; e7 _& e3 T. R
- [{
3 }* N; R/ o" y% @ - text: "Sign transaction",
4 Q/ L! m! L1 A! L* I - url: link,
! w, B" E( g3 Y3 D - }]5 t! \4 A: V+ x
- ]
, j) |% r# }' v7 j - } D! D3 `6 b7 j2 l- V/ J3 p
- })
复制代码然后,我们创建一个额外的参数。回复标记可以是 InlineKeyboard, ReplyKeyboard, ReplyKeyboardRemove 或 ForceReply。这里有多个选项,我们希望使用 inline_keyboard。 上次我们使用的是普通键盘,位于输入行下的同一位置。现在我们创建了一个内联键盘,如上图所示。它有几个参数:文本、签名交易和 URL。因此,我们在 bot.hears 中提供了一个带有链接的 URL 参数。 有一件事我之前没有提到,但你应该记住:如果我们想把某个Cell作为链接发送,比方说,连同一些字符串或链接一起发送,我们需要把它打包成 base64,就像信息正文的Cell一样。 好吧,看来这个办法行得通: - 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 中的网络应用程序可让您使用自动消息创建有趣、酷炫的聊天对话。这样,您就能为用户创建极具价值的精彩项目。让我们构建一个类似的链接: - bot.hears("Deposit 1 TON", (ctx) => {
. G* Y, @' [4 p4 ` - const msg_body = beginCell().storeUint(2, 32).endCell();
复制代码我们将用 2 来表示存款数额。我们不需要其他任何东西,让我们在 wrappers > MainContract.ts 中再次确认这一点: 3 N- {. {) r) a$ ~
- async sendDeposit(provider: ContractProvider, sender: Sender, value: bigint) {+ a* f3 \' v5 Y- w. P) `; V- ~
- const msg_body = beginCell()0 P) B4 C8 n0 l9 X6 q+ U Q& w* f
- .storeUint(2, 32) // OP code
/ K' m. W4 |( j K - .endCell()
复制代码接下来,我们需要输入存款命令,否则我们将无法在合约上收钱。在 index.ts 中,我们只需输入一个等于 2 的整数(32 位)。在这里,我们说它将是 "Deposit 1 TON"(存款 1 Ton),实际上我们将要求提供 1 Ton的付款。它不必是一个字符串。 // Final code deposit command - bot.hears("Deposit 1 TON", (ctx) => {
, ?; c! B" x3 w# e9 O - const msg_body = beginCell().storeUint(2, 32).endCell();
& U9 z# Z4 W9 @+ w: z/ q
% t( C2 V+ s0 Q( L/ ?/ q- ( F* x0 p9 H8 t- p# N- H* E
- let link = `https://app.tonkeeper.com/transfer/${
6 G. z) l+ z" P% y - process.env.SC_ADDRESS
: V! f5 ]: ^3 l4 {# A' D4 d: r( f - }?${qs.stringify(& r- `" Y; S* a: ]# m9 z+ ^
- {6 c2 } y( Y4 q! K
- text: "Deposit 1 TON",
; A; G/ y2 S$ P/ z1 @6 K2 t, r2 d - amount: toNano("1").toString(10),
' a+ _3 J( R8 h- Q. |8 W - bin: msg_body.toBoc({ idx: false}).toString("base64"),
9 C" a/ E3 f- A- J, n - }
1 Z; e9 S3 U3 E8 j+ ?/ V! g9 b4 x - )}`;
复制代码 因此,我们要求用户向合约发送 1 Ton,并在信息中注明这是存款。我们在这里输入信息,然后删除回复 "已存入 1 Ton",因为我们不再需要它了:
9 c. h- o9 M( J1 Q. x1 G, B- ctx.reply("To deposit 1 TON please sign a transaction:", {* |$ ?% E# @: z' B
- reply_markup: {
3 O) u- G5 B5 S$ T! ~1 p& l9 l - inline_keyboard: [
. `8 l. V: u. _ - [
* m+ R. R/ _) [ - {$ U! ~' }" k5 D/ x
- text: "Sign transaction",, K0 x2 k' `# q6 X6 T- a
- url: link,
9 ]$ h& V* r% g0 l1 A2 t6 I - }
. O2 e; r1 i. X2 } - ]$ N5 h% [% {. s; g* s9 M3 t
- ]
& |- ]; _- ~( s7 `! s# S4 j - }0 v7 F @( e4 |7 ^( B5 A3 i
- });
复制代码所以这很简单。我们形成一个消息正文、一个链接、链接文本,将 1 Ton金额设为存款,将正文放入一个字符串,然后用链接中的键盘回复。我们还需要做的一件事就是将机器人的存款逻辑复制到取款逻辑中: // Final code withdraw command - bot.hears("Withdraw 0.7 TON", (ctx) => {
$ q9 q$ ]/ I( B3 ?; X, r8 o$ \ - const msg_body = beginCell().storeUint(3, 32).endCell();. z9 q/ u& y) w' P9 m* r+ z
- & B5 ^$ d8 N. i9 X( U n
- let link = `https://app.tonkeeper.com/transfer/${
* z8 j- _6 f7 X, C0 ^ - process.env.SC_ADDRESS
: X; e0 O$ J3 E/ Q2 G - }?${qs.stringify(
$ j) O1 Y( R: ]) D. B. A - {, P' {5 l* {- }
- text: "Deposit 1 TON",5 P& q n' k2 q
- amount: toNano("1").toString(10),
+ G% Z) j& @- U5 Q4 L - bin: msg_body.toBoc({ idx: false}).toString("base64"),5 Q0 i' M& ?- _; [) b
- }
7 u0 E. ]# i- } - )}`;
0 `* q9 M2 h6 K5 |4 j -
/ v0 @. }/ D& v - ctx.reply("To deposit 1 TON please sign a transaction:", {
" \5 W$ d1 ^- W" @/ M - reply_markup: {+ r, A% m$ `4 j! {1 ?( Q% `7 ]( i& o
- inline_keyboard: [1 ] B( j y. k2 l: p8 m9 B. [
- [- M8 x1 m; ?4 V+ s
- {$ T& ?* S; Q3 F3 V7 g; x
- text: "Sign transaction",- C4 \# U, i$ g" I2 e+ k, H
- url: link,
1 ] y5 h2 Q. B2 C- w4 d: @ - }
' I" m: |. x2 y8 { - ]
6 R3 p+ s5 j/ k! E" ` - ]$ L1 i* F+ [# N1 }; G
- }! [6 Y2 E, F- P" m( q1 O
- });
复制代码现在我们回到提款的包装。在 index.ts 中,我们需要提供想要提取的金额: 6 e8 A. b6 |" @: [, `; `
- bot.hears("Withdraw 0.7 TON", (ctx) => {
d7 t$ U0 t/ f8 s& W- [ w4 c - 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
- let link = https://test.tonhub.com/transfer/${
: g' t8 ?0 {6 x, f6 U; v2 } - process.env.SC_ADDRESS
! Q6 e+ V$ T6 H5 q! U - }?${as.stringify({
* n! f( ?0 Z0 Q, R* E - text: "Withdraw 0.7 TON",% q+ o. w: k7 ^
- amount: toNano('0.05').toString (10),
& l1 t7 u5 F3 ?6 N0 b/ l - bin: msg_body.toBoc({ idx: false }).toString("base64"), ) B) Q' G$ _) N- n; M5 j
- })}`;
复制代码然后编辑机器人信息: / m% F+ }! h7 _* ^3 J
- ctx.reply("To withdraw 0.7 TON please sign a transaction:", {- C% |3 B; B$ |+ c, i
- reply_markup: {. S3 `+ n; j+ P+ v5 g- m6 C
- inline_keyboard: [
J) u% A. K9 y - [{
' ]6 o) z$ U+ b& j, d d2 N - text: "Sign transaction",) N7 e0 z& ~/ K) k. b
- url: link,
3 Q" P0 L4 H- Q, ]7 i - }]
5 I! N) t; {7 \5 Y - ]
3 T P5 S9 A& Q0 a - }7 C7 X L9 Q" ?1 G, G1 u, R/ |
- });
复制代码我们用 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 函数,你发送的信息就会由我们刚刚创建的后端机器人处理。你的处理方式会是这样的: - 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
- 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/ [ |