不同于先前的自动化测试,这篇教程里,我们修改了前端,让用户可以将合约真正部署到共识网络上,并实现自主下注、出拳。 (而这一切都只需要修改前端,也就是说在上一篇教程里,我们后端的Reach合约就已经完整了!)
[Reach教程翻译] Reach是安全简单的Dapp开发语言 让用户可以像开发传统App一样开发DApp 目前使用Reach开发的智能合约可以部署在以太坊、Conflux、Algorand Reach官网 Reach官方文挡
在之前实现的程序中,我们的石头剪刀布会一直运行直到确定最终的赢家为止。在本节中,我们不会改变Reach程序本身。反之,我们会通过修改Javascript前端来打造一个可交互的版本,这个版本将能够在真正的共识网络上运行。
我们将从头开始,再次展示程序的每一行。您会发现这个版本与先前的版本非常相似,但是为了完整起见,我们会显示每一行。
1 import { loadStdlib } from '@reach-sh/stdlib';
2 import * as backend from './build/index.main.mjs';
3 import { ask, yesno, done } from '@reach-sh/stdlib/ask.mjs';
4 const stdlib = loadStdlib(process.env);
5
6 (async () => {
.. // ...
.. // ...
7 const isAlice = await ask(
8 `Are you Alice?`,
9 yesno
10 );
11 const who = isAlice ? 'Alice' : 'Bob';
12
.. // ...
ask
会反复显示问题并提示用户输入,直到得到的输入是 'y' 或 'n'为止。.. // ...
13 console.log(`Starting Rock, Paper, Scissors! as ${who}`);
14
15 let acc = null;
16 const createAcc = await ask(
17 `Would you like to create an account? (only possible on devnet)`,
18 yesno
19 );
20 if (createAcc) {
21 acc = await stdlib.newTestAccount(stdlib.parseCurrency(1000));
22 } else {
23 const secret = await ask(
24 `What is your account secret?`,
25 (x => x)
26 );
27 acc = await stdlib.newAccountFromSecret(secret);
28 }
29
.. // ...
.. // ...
30 let ctc = null;
31 if (isAlice) {
32 ctc = acc.contract(backend);
33 ctc.getInfo().then((info) => {
34 console.log(`The contract is deployed as = ${JSON.stringify(info)}`); });
35 } else {
36 const info = await ask(
37 `Please paste the contract information:`,
38 JSON.parse
39 );
40 ctc = acc.contract(backend, info);
41 }
.. // ...
.. // ...
43 const fmt = (x) => stdlib.formatCurrency(x, 4);
44 const getBalance = async () => fmt(await stdlib.balanceOf(acc));
45
46 const before = await getBalance();
47 console.log(`Your balance is ${before}`);
48
49 const interact = { ...stdlib.hasRandom };
.. // ...
.. // ...
51 interact.informTimeout = () => {
52 console.log(`There was a timeout.`);
53 process.exit(1);
54 };
.. // ...
.. // ...
56 if (isAlice) {
57 const amt = await ask(
58 `How much do you want to wager?`,
59 stdlib.parseCurrency
60 );
61 interact.wager = amt;
62 interact.deadline = { ETH: 100, ALGO: 100, CFX: 1000 }[stdlib.connector];
63 } else {
64 interact.acceptWager = async (amt) => {
65 const accepted = await ask(
66 `Do you accept the wager of ${fmt(amt)}?`,
67 yesno
68 );
69 if (!accepted) {
70 process.exit(0);
71 }
72 };
73 }
.. // ...
wager
,还是定义 acceptWager
方法.. // ...
75 const HAND = ['Rock', 'Paper', 'Scissors'];
76 const HANDS = {
77 'Rock': 0, 'R': 0, 'r': 0,
78 'Paper': 1, 'P': 1, 'p': 1,
79 'Scissors': 2, 'S': 2, 's': 2,
80 };
81
82 interact.getHand = async () => {
83 const hand = await ask(`What hand will you play?`, (x) => {
84 const hand = HANDS[x];
85 if ( hand == null ) {
86 throw Error(`Not a valid hand ${hand}`);
87 }
88 return hand;
89 });
90 console.log(`You played ${HAND[hand]}`);
91 return hand;
92 };
.. // ...
getHand
方法。.. // ...
94 const OUTCOME = ['Bob wins', 'Draw', 'Alice wins'];
95 interact.seeOutcome = async (outcome) => {
96 console.log(`The outcome is: ${OUTCOME[outcome]}`);
97 };
.. // ...
seeOutcome
方法。.. // ...
99 const part = isAlice ? ctc.p.Alice : ctc.p.Bob;
100 await part(interact);
101
102 const after = await getBalance();
103 console.log(`Your balance is now ${after}`);
104
105 done();
106 })();
现在我们可以运行在两个终端分别运行$ ./reach run
来扮演 Alice 和 Bob 。
下面是一组运行的例子:
$ ./reach run
Are you Alice?
y
Starting Rock, Paper, Scissors as Alice
Would you like to create an account? (only possible on devnet)
y
Do you want to deploy the contract? (y/n)
y
The contract is deployed as = "0x132b724e55AEb074C15A5CBb7b8EeE0dBEd45F7b"
Your balance is 999.9999
How much do you want to wager?
10
What hand will you play?
r
You played Rock
The outcome is: Bob wins
Your balance is now 989.9999
另一边:
$ make run-bob
Are you Alice?
n
Starting Rock, Paper, Scissors as Bob
Would you like to create an account? (only possible on devnet)
y
Do you want to deploy the contract? (y/n)
n
Please paste the contract information:
"0x132b724e55AEb074C15A5CBb7b8EeE0dBEd45F7b"`
Your balance is 1000
Do you accept the wager of 10?
y
What hand will you play?
p
You played Paper
The outcome is: Bob wins
Your balance is now 1009.9999
当然,每次运行时的赌注可以不同,部署地址也会不一样。
如果你的版本不能正常运行,看看完整的版本: rps-8-interact/index.rsh 和 rps-8-interact/index.mjs ,并确保您完整地复制了所有内容!
如果我们在两个终端运行的是
$ REACH_CONNECTOR_MODE=ALGO-devnet ./reach run
则相当于在一个私有的 Algorand 测试网运行我们的程序。
连接真正的共识网络也一样简单,例如运行:
$ REACH_CONNECTOR_MODE=ETH-live ETH_NODE_URI="http://some.node.fqdn:8545" ./reach run
您知道了吗? :
是非题 : Reach 帮助你自动化测试DApp,但它不支持构建交互式用户界面
答案是:
否! Reach 不会对使用 Reach 应用程序的前端做任何限制。
欢迎关注Reach微信公众号 并在公众号目录 -> 加入群聊 选择加入官方开发者微信群与官方Discord群 与更多Reach开发者一起学习交流!
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!