Skip to content

Commit edf5712

Browse files
authored
Merge pull request #754 from JiangWenqi/main
[Translation] Basic Task 3
2 parents a606f40 + 1e1e284 commit edf5712

File tree

6 files changed

+439
-220
lines changed

6 files changed

+439
-220
lines changed

basic/01-web3js-deploy/README-cn.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
中文 / [English](./README-en.md)
1+
中文 / [English](./README.md)
22
## 前言
33
通过本样例代码,使开发者了解合约编译,部署的基本流程,并掌握基本的 web3js 接口使用方法
44

basic/01-web3js-deploy/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[中文](./README.md) / English
1+
[中文](./README-cn.md) / English
22
# Abstract
33
Through this basic task, you can learn the processes of compiling and deploying a smart contract, as well as learn how to use the basic APIs of `web3js`.
44

@@ -42,7 +42,7 @@ Through this basic task, you can learn the processes of compiling and deploying
4242
4343
# Interpret the Code in `index.js`
4444
`index.js` contains the most important part of this task, which includes the following functions:
45-
## 1. Lode the configuration file
45+
## 1. Load the configuration file
4646
For security sake, the private key is not hard-coded, but it can be read as environment variables. When run this task, the `dotenv` plugin will automatically read the configurations in the `.env` file and load them as environment variables, and then you can use the private key and other environment variables via `process.env` .
4747
Here is the code:
4848
```js

basic/02-web3js-transaction/README-cn.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
中文 / [English](./README-en.md)
1+
中文 / [English](./README.md)
22
## 前言
33
通过本样例代码,开发者了解到如何对交易进行签名,发送,接收交易回执,验证交易执行结果。同时,样例也提供了事件监听的逻辑代码,开发者可以了解如何对一个事件进行一次或多次监听
44

basic/02-web3js-transaction/README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
[中文](./README.md) / English
1+
[中文](./README-cn.md) / English
22
# Abstract
33
The demo code provides developers with an overview of how to sign, send, and receive receipt of transactions, and verify the results of their execution. The sample also provides the event monitoring code so that the developer can understand how to listen to an event one or more times.
44

@@ -61,7 +61,7 @@ const contractFile = tempFile.contracts["Incrementer.sol"]["Incrementer"];
6161

6262
### Export `contractFile` Object
6363

64-
If you want to use the `contractFile` object in other `js` files, you can export it.
64+
If you want to use the `contractFile` object in other `js` files, you need to export it.
6565
```js
6666
module.exports = contractFile;
6767
```
@@ -74,7 +74,7 @@ const contractOfIncrementer = require("./compile");
7474
```
7575

7676
### 2. Read private key from environment variables
77-
For security sake, the private key is not hard-coded, but it can be read as environment variables. When run this task, the `dotenv` plugin will automatically read the configurations in the `.env` file and load them as environment variables, and then you can use the private key and other environment variables via `process.env`.
77+
For security’s sake, the private key is not hard-coded, but it can be read as environment variables. When run this task, the `dotenv` plugin will automatically read the configurations in the `.env` file and load them as environment variables, and then you can use the private key and other environment variables via `process.env`.
7878
```js
7979
require("dotenv").config();
8080
const privatekey = process.env.PRIVATE_KEY;
@@ -155,10 +155,10 @@ In previous steps, you built a contract instance, and then deployed the transact
155155
let incrementer = new web3.eth.Contract(abi, deployReceipt.contractAddress);
156156
```
157157

158-
### 11. Invoke the read-only interfaces of a contract
158+
### 11. Use the `view` function of a contract
159159
Whether a contract instance is create by deploying, or by loading, you can interact with the contract once you have an instance of the contract already on the blockchain.
160-
There are two types of contract interfaces: `read-only` and `transaction`. The `read-only` interfaces do not generate blocks, while the `transaction` interfaces will generate the corresponding block data on the blockchain.
161-
For example, after calling the `getNumber` interface of the contract, you will get the public variable number of the contract, and this operation will not charge any fee.
160+
There are two types of contract functions: `view` and without `view`. The functions with `view` promise not to modify the state, while the functions without `view` will generate the corresponding block data on the blockchain.
161+
For example, after calling the `getNumber` function of the contract, you will get the public variable number of the contract, and this operation will not charge any gas.
162162
```js
163163
let number = await incrementer.methods.getNumber().call();
164164
```
@@ -205,13 +205,13 @@ incrementer = new web3Socket.eth.Contract(abi, createReceipt.contractAddress);
205205
#### Listen to Increment event only once
206206
```js
207207
incrementer.once('Increment', (error, event) => {
208-
console.log('I am a onetime event listner, I am going to die now');
208+
console.log('I am a onetime event listener, I am going to die now');
209209
});
210210
```
211211
#### Listen to Increment event continuously
212212
```js
213213
incrementer.events.Increment(() => {
214-
console.log("I am a longlive event listner, I get a event now");
214+
console.log("I am a longlive event listener, I get a event now");
215215
});
216216
```
217217

basic/03-web3js-erc20/README-cn.md

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
中文 / [English](./README.md)
2+
3+
## 前言
4+
5+
本样例演示了 ERC20 合约的基本调用, 让开发者了解 ERC20 合约的基本接口
6+
7+
## SimpleToken 合约功能说明
8+
9+
- IERC20
10+
totalSupply: 获取该合约内总的 ERC20 Token 总量
11+
balanceOf: 获取特定账户的 ERC20 Token 总量
12+
transfer: 向目标账户转移特定数量的 ERC20 Token
13+
allowance: 获取目标账户能够使用的源账户的 ERC20 Token 数量
14+
approve: 向目标账户授权, 可以转移指定额度的 ERC20 Token 数量
15+
transferFrom: ( 第三方调用 ) 从源账户向目标账户转移制定数量的 ERC20 Token
16+
17+
- IERC20Metadata
18+
name: 返回 Token 的名称
19+
symbol: 返回 Token 的符号
20+
decimals: 返回 Token 所支持的精度
21+
22+
## 测试流程
23+
24+
1. 安装依赖
25+
26+
```sh
27+
npm install
28+
```
29+
30+
2. 配置 .env
31+
32+
```sh
33+
cp .env.example .env
34+
35+
## 修改 .env 中的 INFURA_ID 和 PRIVATE_KEY 为实际的值
36+
PRIVATE_KEY=xxxxxxxxxxxxxxxx
37+
INFURA_ID=yyyyyyyy
38+
```
39+
40+
3. 执行测试
41+
42+
```sh
43+
node index.js
44+
```
45+
46+
## compile.js 代码逻辑说明
47+
48+
我们无法直接使用 .sol 文件, 需要把它编译为 bin 文件 ( 二进制文件 ), 因此在代码中需要进行这一步的逻辑处理.
49+
50+
1. 读取文件
51+
第一步, 我们先进行文件的读取, 把 sol 文件加载为 source 变量
52+
53+
```js
54+
// Load contract
55+
const source = fs.readFileSync('SimpleToken.sol', 'utf8');
56+
```
57+
58+
2. 进行合约编译
59+
这里进行编译动作. 把 sol 源码编译为 solidity 对象. 这里需要注意的是不同的 sol 源码版本, 编译的方式可能稍有不同, 这里因为 "SimpleToken.sol" 对应的是 sol 是 0.8.0 版本, 所以我们可以使用如下的方式进行编译
60+
61+
```js
62+
// compile solidity
63+
const input = {
64+
language: 'Solidity',
65+
sources: {
66+
'SimpleToken.sol': {
67+
content: source,
68+
},
69+
},
70+
settings: {
71+
outputSelection: {
72+
'*': {
73+
'*': ['*'],
74+
},
75+
},
76+
},
77+
};
78+
79+
const tempFile = JSON.parse(solc.compile(JSON.stringify(input)));
80+
```
81+
82+
3. 获取二进制对象
83+
在上一步编译成功的 solidity 对象里面包含很多的属性/值, 而我们需要的是其中合约对象, 通过访问对象属性的方式提示 SimpleToken 合约对象
84+
85+
```js
86+
const contractFile = tempFile.contracts['SimpleToken.sol']['SimpleToken'];
87+
```
88+
89+
4. 导出对象
90+
为了能使其他 js 文件使用 SimpleToken 合约对象 , 我们需要对合约对象进行导出
91+
92+
```js
93+
module.exports = contractFile;
94+
```
95+
96+
## index.js 代码逻辑说明
97+
98+
1. 编译合约
99+
导入 compile 文件中的 SimpleToken 合约对象
100+
101+
```js
102+
const contractFile = require('./compile');
103+
```
104+
105+
2. 读取私钥
106+
处于安全考虑, 私钥没有进行硬编码, 而是通过环境变量的方式进行获取. 启动测试时, dotenv 插件自动读取 .env 配置文件中的配置项, 然后加载为环境变量, 之后在代码中可以通过 process.env 读取私钥 ( 也包括其他环境变量 )
107+
108+
```js
109+
require('dotenv').config();
110+
const privatekey = process.env.PRIVATE_KEY;
111+
```
112+
113+
3. 设置收款账户
114+
这里为方便测试, 固定的一个收款账户, 在后续的交易测试中, 会使用这个收款账户进行测试
115+
116+
```js
117+
const receiver = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266';
118+
```
119+
120+
4. 构造 web3 对象
121+
通过 web3 对象可以很方便的发送相应的交易到区块链网络, 同时获取区块链的处理结果.
122+
构造 web3 对象时, 主要需要传入一个参数, 就是对应的区块链网络, 包括 kovan, ropsten , rinkeby 等测试网络, 或是 mainnet 主网.
123+
这里我们使用 kovan 测试网络. 如果没有 kovan 网络的测试币, 可以切换到其他的测试网络.
124+
同时需要注意的是, 这里我们通过 infura 向对应的区块链网络发送交易, 而 INFURA_ID 这个变量值也需要配置在 .env 文件中, 具体如何获取 infura_id, 可自行搜索查找相关文档
125+
126+
```js
127+
const web3 = new Web3(new Web3.providers.HttpProvider('https://kovan.infura.io/v3/' + process.env.INFURA_ID));
128+
```
129+
130+
5. 获取账户地址
131+
在区块链上, 每个用户都有一个对应的账户地址, 而这个账户地址可以通过私钥进行获取. 这里, 我们调用 web3.eth.accounts.privateKeyToAccount 接口, 传入对应的私钥, 就可以获取对应的账户地址
132+
133+
```js
134+
const account = web3.eth.accounts.privateKeyToAccount(privatekey);
135+
const account_from = {
136+
privateKey: account.privateKey,
137+
accountaddress: account.address,
138+
};
139+
```
140+
141+
6. 获取 abi 和 bin
142+
在部署合约的过程中, 我们会用到两个重要的参数, 合约对应的 bytecode 和 abi. 在步骤 1 的时候, 我们导入了编译后的 SimpleToken 合约对象, 通过这个对象, 我们可以获取的合约对应的 bytecode 和 abi
143+
144+
```js
145+
const bytecode = contractFile.evm.bytecode.object;
146+
const abi = contractFile.abi;
147+
```
148+
149+
7. 构造合约实例
150+
在步骤 3 中, 我们获取了 sol 源文件编译后的二进制 和 abi, 这里就可以使用对应的 abi 构造相应的合约实例, 以便在后续中通过合约实例进行交易的发送
151+
152+
```js
153+
const deployContract = new web3.eth.Contract(abi);
154+
```
155+
156+
8. 创建合约交易
157+
调用 deployContract.deploy 接口, 我们创建了部署合约的二进制交易. 这里, 此交易还没有发送到区块链网络, 即合约还没有被创建
158+
159+
```js
160+
const deployTx = deployContract.deploy({
161+
data: bytecode,
162+
arguments: ['DAPPLEARNING', 'DAPP', 0, 10000000],
163+
});
164+
```
165+
166+
9. 交易签名
167+
如下使用私钥对交易进行签名,
168+
169+
```js
170+
const deployTransaction = await web3.eth.accounts.signTransaction(
171+
{
172+
data: deployTx.encodeABI(),
173+
gas: '8000000',
174+
},
175+
account_from.privateKey
176+
);
177+
```
178+
179+
10. 部署合约
180+
这里发送签名后的交易到区块链网络, 同时得到返回的交易回执. 从返回的交易回执中可以得到此次部署的合约的地址
181+
182+
```js
183+
const deployReceipt = await web3.eth.sendSignedTransaction(deployTransaction.rawTransaction);
184+
console.log(`Contract deployed at address: ${deployReceipt.contractAddress}`);
185+
```
186+
187+
11. 构造转账交易
188+
如下构造一个 ERC20 Token 的转账交易, 收款账户为 receiver, 转账金额为 100000
189+
190+
```js
191+
const transferTx = erc20Contract.methods.transfer(receiver, 100000).encodeABI();
192+
```
193+
194+
12. 签名并发送交易
195+
对转账交易进行签名并发送
196+
197+
```js
198+
const transferReceipt = await web3.eth.sendSignedTransaction(transferTransaction.rawTransaction);
199+
```
200+
201+
13. 验证转账后余额
202+
转账成功后, 输出验证下收款账户的余额, 检查余额是否正确
203+
204+
```js
205+
erc20Contract.methods
206+
.balanceOf(receiver)
207+
.call()
208+
.then((result) => {
209+
console.log(`The balance of receiver is ${result}`);
210+
});
211+
```
212+
213+
## 特别说明
214+
215+
- infura 不支持 sendTransaciton,只支持 sendRawTransaction:
216+
- Infura 不会触发 eth_sendTransaction 方法,因为此方法需要 ethereum 节点中未被锁定的账户。
217+
- infura 不支持 eth_sendTransaction 的说明:
218+
- <https://ethereum.stackexchange.com/questions/70853/the-method-eth-sendtransaction-does-not-exist-is-not-available-on-infura>
219+
220+
## 参考文档
221+
222+
- Mocha 实例教程: http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html
223+
- Mocha 技术笔记: https://pcaaron.github.io/pages/fe/block/improve4.html#%E8%B7%91%E6%B5%8B%E8%AF%95
224+
- ERC20 接口及合约说明:https://docs.openzeppelin.com/contracts/2.x/api/token/erc20

0 commit comments

Comments
 (0)