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

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

回答

收藏

4.4 存款/提款逻辑测试

开源社区 开源社区 8736 人阅读 | 0 人回复 | 2025-03-08

在本课中,我们将编写一些有趣的测试。
首先,我们要更新之前编写的合约的初始化过程,因为我们引入了一个新变量,它应该存储在 c4 存储器中。
如果您现在尝试运行我们的测试 - yarn test 您可以看到测试将失败。您还将看到发生在我们合约上的交易跟踪,其中一个交易的错误代码为 9. Have a look at the exit codes documentation.
9 - Cell下溢。从片断基元读取数据时,试图读取的位或引用数超过总数。
更新我们的合约包装器
首先,让我们更新我们的合约包装器,以便它能意识到 c4 存储中的第三个参数。也就是说,我们将更新 MainContractConfig 和 mainContractConfigToCell 函数
  1. // ...library imports
    9 R5 t8 M" _/ K( Z; W
  2. - `+ Q9 D0 n! U) @7 {" ~
  3. export type MainContractConfig = {4 [" F# n: h$ \$ I+ s0 Y* L
  4.   number: number;1 x/ V, K: S' t! K/ h
  5.   address: Address;
    2 D- ]( [' ^# ^/ W: l
  6.   owner_address: Address;: Q8 g' a4 ^1 D, i8 u* V9 b6 t
  7. };- D, x1 h" E% f3 O1 H
  8. ' B; E* C* V( M9 v% r$ t$ q4 _1 d
  9. export function mainContractConfigToCell(config: MainContractConfig): Cell {. s) n& f7 r* f0 t9 [! s/ L) [
  10.   return beginCell()
    8 k  h8 s" a! i3 _, K
  11.     .storeUint(config.number, 32)% [% q* g# |' U8 z& n
  12.     .storeAddress(config.address)! K% \' x! L# S% m% f
  13.     .storeAddress(config.owner_address)9 v4 }6 Z6 t. _$ E
  14.     .endCell();; |9 e0 X1 G4 q" R2 p
  15. }
    * E: t2 h- G7 l3 B' u

  16. 5 c! P0 l5 q$ o8 B' I
  17. // ...contact wrapper class
复制代码
封装文件中还有一点需要更新-getData 方法,这样它也会返回 owner_address 我们还将创建新方法 getBalance,以测试存款后余额是否增加:
1 Y+ r% x$ v$ _: N, h1 j
  1. async getData(provider: ContractProvider) {0 j; l5 |; s  q5 t
  2.     const { stack } = await provider.get("get_contract_storage_data", []);& u- N8 Z* G1 d7 s2 ]# r* ^
  3.     return {/ q2 t3 S7 g( y) P; P& I
  4.       number: stack.readNumber(),. }) m6 _7 K, Y& U6 w4 Z( \0 y1 N
  5.       recent_sender: stack.readAddress(),  I8 C3 l1 t& }( [5 W( Y
  6.       owner_address: stack.readAddress()," o" M+ r- j  i6 |% m6 v
  7.     };" W& G6 o: b  w5 X, b0 h
  8.   }
    1 f' _6 X% _/ `# n6 e2 ~
  9.   
    / r; h- F# @3 Q$ D, E4 p: z2 A' w
  10. async getBalance(provider: ContractProvider) {
    ! a# i2 J0 h4 _
  11.     const { stack } = await provider.get("balance", []);# J0 q4 f) j# b" ~7 y& a3 l
  12.     return {: Z+ i/ P; {8 X& r
  13.       number: stack.readNumber(),$ L) K- H) C7 m* ]# f8 r8 Z
  14.     };
    $ E; A8 e& }3 c! m9 X! j
  15. }
复制代码
  1. // ...library imports# ^, k1 P5 D, G7 u1 Y- x

  2. 5 e) c) {. B" h" [1 h: ?& q. C
  3. describe("main.fc contract tests", () => {7 O/ G) ]- h* c' H" N0 Y
  4.   it("should get the proper most recent sender address", async () => {) q8 E9 J: L; w! N7 A# a
  5.     const blockchain = await Blockchain.create();4 w  `% y2 M; v" Z; r: K; S! V3 J
  6.     const codeCell = Cell.fromBoc(Buffer.from(hex, "hex"))[0];
    9 V6 V+ z) @& q* h7 h" ^4 y

  7. 5 `. }9 `- [, c% b
  8.     const initAddress = await blockchain.treasury("initAddress");5 `/ b5 c$ m/ D, @, d* o
  9.     const ownerAddress = await blockchain.treasury("ownerAddress");3 z: i  {; |- |! {' t+ B# A4 c
  10.    
    0 F, M+ w  r+ v
  11.     const myContract = blockchain.openContract(* W( G. C# u' t2 {# p
  12.       await MainContract.createFromConfig(+ j3 w8 n0 d% w* U  T
  13.         {
    & h) D( F" y3 E2 ]' ^
  14.           number: 0,
    % z# p; o2 l# p# k" A# r" Y
  15.           address: initAddress.address,
      v( A; A: g) U2 U  E  V7 A% }
  16.           owner_address: ownerAddress.address, // now we create myContract from 3 parameters
    - K; t$ a5 ^( i; E% ], b/ f
  17.         },
    ! c8 k  g( @. r% v  k+ W
  18.         codeCell
    , I. _, o8 z( b# Q% y- a
  19.       )0 r8 A5 E. D# o0 {. k! U
  20.     );1 B% ]& H1 x( h. }: q4 W0 T5 g

  21. 8 e" H; t) z% d: x
  22. // ...rest of testing code
复制代码

: R3 l8 U, d  {; G% J
我们引入一个新的金库,它实际上将是合约的所有者,只有这个所有者以后才能提取资金。这些更新在 tests/main.spec.ts 中进行:
  1. // ...library imports, t6 z% S8 N9 @
  2. 8 f6 B% B7 F0 K7 d% @: F9 K
  3. describe("main.fc contract tests", () => {
    3 Z2 N0 k, f8 {6 T4 F0 k/ t
  4.   it("should get the proper most recent sender address", async () => {) c8 g! a$ F. x8 O  J8 e2 `) h1 d
  5.     const blockchain = await Blockchain.create();
    9 n& o0 a7 |* O7 X5 F: m
  6.     const codeCell = Cell.fromBoc(Buffer.from(hex, "hex"))[0];
    3 S8 X3 q. ^5 r# A- l
  7. 9 G9 ]& a* e7 ?+ f4 i7 [" z- s
  8.     const initAddress = await blockchain.treasury("initAddress");
    2 P; s- ~5 I" \1 A
  9.     const ownerAddress = await blockchain.treasury("ownerAddress");
    ) ]( Y/ j3 k2 M1 S+ u4 O
  10.    
    * N7 f+ J+ }) L* G0 I1 ]
  11.     const myContract = blockchain.openContract(7 b1 N! m) z' A5 ?3 O; ?/ t% J
  12.       await MainContract.createFromConfig(
    7 R+ g  k( e/ }1 Y! g
  13.         {: ?: `4 X) Z. g$ C& N
  14.           number: 0,8 d5 |; l* X( ]& R9 @
  15.           address: initAddress.address,  y* i. J8 T8 [! {
  16.           owner_address: ownerAddress.address, // now we create myContract from 3 parameters, Z) f) D0 Y2 C) U
  17.         },
    # W8 V" i/ _2 v& o* u
  18.         codeCell
    5 s$ s' r0 O2 O( U; }1 E2 G7 U* _
  19.       )
    - j; @+ l$ L1 }; Q" `7 I
  20.     );  B0 e( c( d  t/ s; Z

  21.   I) _% k5 u# ], u5 v
  22. // ...rest of testing code
复制代码
现在我们好了。 yarn test 成功通过我们之前编写的测试。

' e) d8 n9 s' m存款测试
让我们在 main.spec.ts 文件中再添加几个测试。
由于我们必须在每次新测试前重新启动合约,因此我们还将把合约启动引入 Jest 的 beforeEach 函数:
  1. // We need to additionally import SandboxContract and TreasuryContract0 Q% o+ Z& J6 W
  2. import { Blockchain, SandboxContract, TreasuryContract } from "@ton/sandbox";0 q# t# Q  }& K+ K3 X0 ]/ B0 b
  3. // ... other library imports
    % t2 {4 Q5 p$ |6 L' G: z& {
  4. describe("main.fc contract tests", () => {
    & Z3 Q% z; G( t- K; ?
  5.   let blockchain: Blockchain;7 O9 B8 A' K5 F# ~7 ?; l7 |2 W2 j* o
  6.   let myContract: SandboxContract<MainContract>;& t3 r- n% d! ~) l
  7.   let initWallet: SandboxContract<TreasuryContract>;2 A, _/ P9 T5 l& P5 J
  8.   let ownerWallet: SandboxContract<TreasuryContract>;
    8 E2 j* {! x' y- D. B0 R
  9. # i8 H; j- m% X- o
  10.   beforeEach(async () => {
    0 }7 l' B  E6 n5 L
  11.     blockchain = await Blockchain.create();4 {9 u* S: {0 f- C/ e7 K+ g# X5 F, L0 G
  12.     initWallet = await blockchain.treasury("initWallet");
    # b& e( T5 e' f* N
  13.     ownerWallet = await blockchain.treasury("ownerWallet");) E3 a( c7 \3 H7 {
  14. 3 @9 h: h" x, a) _* m, u
  15.     const codeCell = Cell.fromBoc(Buffer.from(hex, "hex"))[0];
    6 e/ r1 z( f$ y4 M9 X/ e% g

  16. 6 V6 A" p# g) K7 @: @8 z8 g
  17.     myContract = blockchain.openContract(/ h/ V% Z: N8 e9 {3 Y
  18.       await MainContract.createFromConfig(1 H  e  D0 A7 |
  19.         {
    " A3 U" `/ \8 k/ d7 e) Q. @
  20.           number: 0,  q/ o4 b: V* N( d7 @
  21.           address: initWallet.address,) |1 ]) J2 b% E* x" z- V
  22.           owner_address: ownerWallet.address,
    + |1 r/ r. g" l/ d4 Q/ v
  23.         },
    ! b3 p/ v& a  U% h
  24.         codeCell
    ' z* T! E+ s/ \6 Q# R5 a; C
  25.       )2 }0 f6 @$ E2 P" ?/ q* t
  26.     );
    8 V5 ^: k4 J1 c8 d$ E  @2 V
  27.   });7 }1 G" `& K% j7 ~9 a
  28. + i$ |1 R  @/ Y7 O) |  R
  29.   it("should get the proper most recent sender address", async () => {" W  ~) Y- V1 D. e# _9 k5 K
  30.     const senderWallet = await blockchain.treasury("sender");6 R6 F; V& }5 s2 S' Y, }6 Z

  31. 6 a& M6 m& d" {' k
  32.     const sentMessageResult = await myContract.sendIncrement(
    7 }) b% N3 w) _# ]) Z
  33.       senderWallet.getSender(),
    . ~/ o/ v$ o' P0 L+ c9 _3 V" D
  34.       toNano("0.05"),
    - o/ C0 a  k$ N
  35.       13 X2 d% v" ^; W& Z* @0 M
  36.     );; Z. Q7 Q6 T1 c5 H* E
  37. + O, k2 Y# H" q0 f7 o' c
  38.     expect(sentMessageResult.transactions).toHaveTransaction({
    % b3 z* {' l" X7 F  z) e& e
  39.       from: senderWallet.address,
    8 r& u8 Y6 }7 `" `
  40.       to: myContract.address,# k) K. j* q2 O% L3 b
  41.       success: true,0 U6 \* o( M; ]: T0 g5 p
  42.     });
    + w* P) r9 R1 N" E, x) [) f; R

  43. " G& [3 U- p; c" v0 o" T. _2 i
  44.     const data = await myContract.getData();* c( `, w0 k2 }* }- b( u( r6 @

  45. " D" \) {' h# N
  46.     expect(data.recent_sender.toString()).toBe(senderWallet.address.toString());8 x% |( ]9 s5 O/ p; M& w8 b
  47.     expect(data.number).toEqual(1);
    : v3 m& `; N- c) f$ a: A2 O" A. T
  48.   });( Y8 e  o! _' U8 q! z3 o
  49.   it("successfully deposits funds", () => {
    : ^6 _/ y$ `+ |5 H
  50.     // test logic is coming' q  h8 g" Q8 ~
  51.   });
    1 H! O" d/ w1 N4 `
  52.   it("should return deposit funds as no command is sent", () => {+ c% V4 q; ]# V9 j1 B8 y1 v+ }
  53.     // test logic is coming6 O: ~, Y" O% [0 Y
  54.   });
    % R* H- A& R- g/ i
  55.   it("successfully withdraws funds on behalf of owner", () => {
    , s7 H  g; M* W
  56.     // test logic is coming
    $ f7 e4 @: x  k5 ~# G! {' {
  57.   });
    ) L, i1 c+ o" A2 a1 d; f  P( L
  58.   it("fails to withdraw funds on behalf of non-owner", () => {2 p/ N( x$ w2 e/ X* B
  59.     // test logic is coming; C/ R$ _7 V# U# |1 _( u3 o
  60.   });
    ' M/ K7 T$ `. Y- K2 z3 K$ p* }  Q
  61.   it("fails to withdraw funds because lack of balance", () => {
      J6 I9 V% E7 w$ J
  62.     // test logic is coming9 p( I; c9 K% F) W
  63.   });
    6 B9 l% `! T# q2 M5 ?- S) A( D
  64. });
复制代码
我们只是将第一个测试的部分行移动到了 beforeEach 中,其余的行应留在第一个测试中 it
让我们为存款写一个测试。我们将发送一条 op == 2 的信息,然后检查余额。像往常一样,首先创建一个封装方法,我们将其称为 sendDeposit:
  1. async sendDeposit(provider: ContractProvider, sender: Sender, value: bigint) {
    : Y  [! D7 q7 F+ p' J9 r
  2.     const msg_body = beginCell()
    ) e; F& \8 B+ R0 d. X6 I9 _3 _$ z9 j
  3.       .storeUint(2, 32) // OP code6 _$ p. C  X2 {9 ?% s% Y: y) y
  4.       .endCell();) P. M' j0 F4 \6 |  o

  5. ; G# g. y. w* ]2 x7 x+ A5 ~
  6.     await provider.internal(sender, {
    " r7 r) N: V3 L2 L# s( ~6 f
  7.       value,
    8 i: n# R, f% t5 R3 W' J# m8 ?
  8.       sendMode: SendMode.PAY_GAS_SEPARATELY,3 e. `1 R' j% D- v1 q7 T' E
  9.       body: msg_body,
    8 n0 Z. m4 O2 _! b7 E& H" T
  10.     });# u8 O; ?1 d- u: k1 g7 k0 ?
  11.   }
复制代码
我们将不详细介绍这种方法,因为它非常简单--我们只需在信息正文中传递一个操作码。
下面是我们如何使用该方法运行存款测试。
  1. it("successfully deposits funds", async () => {. V% H9 w  I" D) J2 y" T
  2.     const senderWallet = await blockchain.treasury("sender");3 U/ X+ q( H( d9 j& @7 ~
  3. 7 B0 \- F  d: x% t8 I
  4.     const depositMessageResult = await myContract.sendDeposit(  t9 d8 p8 @2 ~* ~4 R2 j! s
  5.       senderWallet.getSender(),
    1 ?' L5 }. D+ [+ G
  6.       toNano("5"). T  `& u. {) T8 P+ Q
  7.     );
    ' @+ U1 W; b. `# h$ D5 x% p
  8. * x. N9 e; b* H+ p1 n
  9.     expect(depositMessageResult.transactions).toHaveTransaction({
    7 L; @% N( f- t& o0 c' K( t
  10.       from: senderWallet.address,; G% ^7 L7 w9 H! B% [
  11.       to: myContract.address,8 m. |# p, D  V7 T8 I1 }0 A
  12.       success: true,8 X; B- p& E/ H' t& a  d
  13.     });5 M- {9 L7 @" y! R, y, g

  14. ' ^# K/ U' G" f# F7 t- R6 c% O
  15.     const balanceRequest = await myContract.getBalance();
    ' j/ D  s- M/ r! g5 l

  16. ) i1 }5 {3 I  R8 C& `9 {, u
  17.     expect(balanceRequest.number).toBeGreaterThan(toNano("4.99"));$ u7 J: G4 p) f( d$ Z! }- s" c% S
  18.   });
复制代码
请注意我们是如何检查合约余额是否大于 4.99 TON的,因为我们知道手续费会损失一些资金。
我们再写一个存款测试,但这次会出现误报。我们将在没有存款操作码的情况下发送资金,并期待返回交易,因为该操作码未知。
和以往一样,我们还有一个包装器:
  1. async sendNoCodeDeposit(: e# l+ O& e( z* A% K+ j
  2.     provider: ContractProvider,
    " n) S* H, F! Y% c  ~0 m
  3.     sender: Sender,
    6 r, \; Y  g4 E( U
  4.     value: bigint/ Z- I8 d% _$ o" f& g0 @/ U
  5.   ) {
    4 v/ `- L% ~+ R& c' k
  6.     const msg_body = beginCell().endCell();  N& C7 p6 `  m: g3 D  X8 Q8 x5 L
  7. 4 r0 L" l9 p7 k( C- m+ e$ F
  8.     await provider.internal(sender, {- f0 Q+ s$ [! L* |$ O+ G
  9.       value,
    3 f4 l/ P6 i8 E/ M0 z. Q
  10.       sendMode: SendMode.PAY_GAS_SEPARATELY,# Q9 y0 x) K( e) p* b! z, `
  11.       body: msg_body,/ Q3 W  n& p! K/ P  ]9 B5 J
  12.     });
    - ^, [( U! x' e0 F
  13.   }
复制代码
下面是测试代码:

" \1 e; o/ G$ u$ i& V4 N/ h6 ^, N
  1. it("should return funds as no command is sent", async () => {
    3 \$ s, ^: H3 ^( x. e
  2.     const senderWallet = await blockchain.treasury("sender");
    ) p  r- E: P7 S. ]

  3. ! Y7 w; E  I1 ]/ S
  4.     const depositMessageResult = await myContract.sendNoCodeDeposit(8 i5 ^5 F5 L) `7 K
  5.       senderWallet.getSender(),  _( A- G  e$ h. E+ K4 q3 \& i% [
  6.       toNano("5")
    % h/ Q. c1 }4 l6 c$ A
  7.     );& }* J- t8 O! M* c/ ~
  8. 9 l* C- v. ?& V3 T' H
  9.     expect(depositMessageResult.transactions).toHaveTransaction({
    ; m5 t: Z  {  e1 G) B/ E( W
  10.       from: myContract.address,0 Z  g  r9 V$ O! P9 Y6 S& @+ _
  11.       to: senderWallet.address,
    2 h+ }* y# |6 s) ?. f
  12.       success: true,
    3 p: N8 F5 s/ r% o2 |  `
  13.     });/ e: J3 v) R& ]: [7 k, j5 y

  14. 0 A: O% G) r$ d: |/ |: o
  15.     const balanceRequest = await myContract.getBalance();
    " _" R& U& o$ L

  16. ( g& I! ^2 C6 O& q# u0 t: C
  17.     expect(balanceRequest.number).toBe(0);5 @/ @4 t  s0 K8 ?  B
  18. });
复制代码
提款测试
让我们先创建一个用于提款的新包装器:
  1. async sendWithdrawalRequest(
    - p/ J4 K6 _/ J2 U9 r) v( t( [3 d
  2.     provider: ContractProvider,
    5 p9 t6 m( J  _& H% [# u! m, ?$ p
  3.     sender: Sender,2 @- D" Q" {4 }6 V- @: Y5 A8 W  Y. S
  4.     value: bigint,
    5 P9 L0 s* d$ p
  5.     amount: bigint  x; L2 C5 H- h. g, i
  6.   ) {5 s9 Y+ e7 s7 B4 _8 E! D
  7.     const msg_body = beginCell()! I" a3 v4 d$ E8 {
  8.       .storeUint(3, 32) // OP code
    ; o1 I8 x4 g. B: a
  9.       .storeCoins(amount)  U" B8 F1 C; h' T4 {  H7 r3 G8 {
  10.       .endCell();
    - G$ m/ }/ {, _8 }# Y) N: \
  11. # i9 ^5 L( b3 c" s, O% @
  12.     await provider.internal(sender, {
    7 j6 l8 f6 L. P" A0 k
  13.       value,
    $ m, n( P% V( I# h0 _
  14.       sendMode: SendMode.PAY_GAS_SEPARATELY,
    1 N4 v8 U6 @$ p
  15.       body: msg_body,
    5 f$ C3 g% I1 D' h  v
  16.     });
    7 ^4 i8 S5 f! w( @# p  P
  17.   }
复制代码
我们输入适当的 msg_body 和所需的提款 amount 。
我们将进行 3 项不同的测试。让我们一起来看看:
  1. it("successfully withdraws funds on behalf of owner", async () => {  B0 H  I: v3 e" z
  2.     const senderWallet = await blockchain.treasury("sender");
    * x( @8 \) J( h  b
  3. ) R3 J  z8 V7 U7 S( h% \
  4.     await myContract.sendDeposit(senderWallet.getSender(), toNano("5"));1 _, D/ r) ?* ~
  5. 8 X" }9 q' q% T8 w
  6.     const withdrawalRequestResult = await myContract.sendWithdrawalRequest(
    ' L: a& ]) U5 \  v
  7.       ownerWallet.getSender(),
    ( P% [+ H6 L, {9 t- A3 k4 _/ J4 s' u
  8.       toNano("0.05"),/ Q5 a# D, u# D6 C4 I% [( ?
  9.       toNano("1")5 H4 h1 j8 t( E% Z+ ?* U3 J, f( k: v
  10.     );1 k" o: s8 Q+ c* K& O/ r

  11. 5 l% N' |+ u1 T
  12.     expect(withdrawalRequestResult.transactions).toHaveTransaction({
    + B6 t1 e3 @% h3 Y
  13.       from: myContract.address,
    4 R; }9 e5 J6 N/ T
  14.       to: ownerWallet.address,
    & A* d. {" T4 {4 J* |5 K8 L
  15.       success: true,
    . {% r1 ?1 m" [: w9 @
  16.       value: toNano(1),
      H: T* Z4 Q/ W* _
  17.     });
    3 [/ A. S" P; c) \; X1 J& a
  18.   });
复制代码
要成功提款,我们首先要正确存款。然后我们调用 sendWithdrawalRequest 指定我们要提取 1 Ton。请注意,0.05 Ton只是为了支付费用而指定的信息值。% |4 C$ A4 g% |, H
  1. it("fails to withdraw funds on behalf of not-owner", async () => {
    $ C4 T9 b% z, I+ }8 H0 _+ l; ?, k
  2.     const senderWallet = await blockchain.treasury("sender");' M+ Q( g% ?$ ~+ J

  3. - D# X; ?2 B/ e/ a' m7 q# R
  4.     await myContract.sendDeposit(senderWallet.getSender(), toNano("5"));
    9 S1 i' l% ]8 ~+ v

  5. ) V( O% {1 P1 ?4 K. ?  ?; m0 C
  6.     const withdrawalRequestResult = await myContract.sendWithdrawalRequest(
    7 C' ~# m) @5 s% T( b5 U' L
  7.       senderWallet.getSender(),# h8 O* X; G1 v5 i
  8.       toNano("0.5"),
    & E6 |# a& K% O9 Q, I+ `$ b
  9.       toNano("1")+ `7 j2 e$ t/ H. U1 a
  10.     );1 M2 }: {. _, M( B

  11. / T) ^5 m) C. _! G+ J! C
  12.     expect(withdrawalRequestResult.transactions).toHaveTransaction({& {+ Q4 R# G# f# M) K  K* t
  13.       from: senderWallet.address,! `7 z# K- B  f: U$ r
  14.       to: myContract.address,
    $ n' S) M8 D7 S% `+ R" D
  15.       success: false,
    ) y* _! ^4 }: V# m! ?8 t9 D
  16.       exitCode: 103,
    - |' b! X. A0 ?
  17.     });
    6 b- n* w, S8 R
  18.   });
复制代码
在本次测试中,我们代表发送方钱包而不是所有者钱包发送提款请求(两者的区别在于初始化时我们提供的助记词).
还请注意,我们是如何通过 success: false 和具体的失败原因 exitCode: 103. 为了确保我们做得正确,请看一下我们的合约代码,我们有这样一行代码:
  1. throw_unless(103, equal_slice_bits(sender_address, owner_address));. ?# N# E+ Z7 N5 l7 r
复制代码
我们进行最后一项测试--由于没有余额,提款失败:
  1. it("fails to withdraw funds because lack of balance", async () => {
    " U  ?% `7 z1 h0 Z4 _  z- O
  2.     const withdrawalRequestResult = await myContract.sendWithdrawalRequest(& H. B) O7 B' [. L! g% t) s: v3 B
  3.       ownerWallet.getSender(),
      d" \6 R* X9 V. q
  4.       toNano("0.5"),
      ?4 v* p* k# }6 x
  5.       toNano("1")& |; X9 z% G( X) `. T7 H
  6.     );9 Z4 n# M9 o" d5 l! y

  7. * u  u& S1 |8 m# r6 _/ m
  8.     expect(withdrawalRequestResult.transactions).toHaveTransaction({
    5 S- M# |7 C" R9 u2 ^
  9.       from: ownerWallet.address,
    $ q/ T0 |" K4 H/ z
  10.       to: myContract.address,5 @' a- \- A  |) \" A' T
  11.       success: false,
    : e, j1 i- P2 R+ m
  12.       exitCode: 104,# e" b! ]. ^$ E7 K
  13.     });% e+ T1 z5 {0 \* c3 @" d3 c
  14.   });
复制代码
  1. throw_unless(104, balance >= withdraw_amount);( F; o% [& \8 n, m: \* `
复制代码
就是这样
几章之后,我们将学习如何构建网络客户端,以便与合约进行交互。
& [& F7 ]& E& S

* U! q( }8 G9 a/ l$ X4 m2 j( n
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则