Skip to content

Commit

Permalink
Merge pull request #987 from 0x-stan/main
Browse files Browse the repository at this point in the history
task01 upgrade web3.js to 4.x
  • Loading branch information
liberhe authored Sep 12, 2023
2 parents 1b95f5e + 2e1a8c5 commit 92cf34a
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 88 deletions.
12 changes: 6 additions & 6 deletions basic/01-web3js-deploy/README-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
- 本样例发送交易到 Infura , 需要创建相应的 Infura Project, 可以参考如下资料进行创建
https://ithelp.ithome.com.tw/articles/10202794 在成功创建 Infura Project 后,可以获取相应的PROJECT ID

- 本样例中,需要自己来生成私钥。可通过多种方式来生成私钥。常见的方式是通过Metamask。可参考《精通以太坊》或其他文档安装: https://www.bookstack.cn/read/ethereum_book-zh/spilt.4.77adf5064f4455e8.md 安装完成后,连接到 Goerli 测试网络,点击账户详情-导出私钥,获得创建的测试账号的私钥PRIVATE_KEY。
- 本样例中,需要自己来生成私钥。可通过多种方式来生成私钥。常见的方式是通过Metamask。可参考《精通以太坊》或其他文档安装: https://www.bookstack.cn/read/ethereum_book-zh/spilt.4.77adf5064f4455e8.md 安装完成后,连接到 Sepolia 测试网络,点击账户详情-导出私钥,获得创建的测试账号的私钥PRIVATE_KEY。

-goerli 测试网络中的测试账号充值。上一步开立的账号中,余额为0, 可通过faucets来充值: https://faucets.chain.link/ 每次冲入0.1Eth。
-sepolia 测试网络中的测试账号充值。上一步开立的账号中,余额为0, 可通过faucets来充值: https://faucets.chain.link/ 每次冲入0.1Eth。

- 为方便代码测试, 在 .env 中放入私钥和Infura Project ID,格式为 "PRIVATE_KEY=xxxx" "INFURA_ID=yyyyyyyy", index.js代码会自动从中读取, 样例文件可参考 .env.example

Expand Down Expand Up @@ -92,13 +92,13 @@ const abi = contractFile.abi;

4) 构造 web3 对象
通过 web3 对象可以很方便的发送相应的交易到区块链网络, 同时获取区块链的处理结果.
构造 web3 对象时, 主要需要传入一个参数, 就是对应的区块链网络, 包括 goerli 等测试网络, 或是 mainnet 主网.
这里我们使用 goerli 测试网络. 如果没有 goerli 网络的测试币, 可以切换到其他的测试网络.
构造 web3 对象时, 主要需要传入一个参数, 就是对应的区块链网络, 包括 sepolia 等测试网络, 或是 mainnet 主网.
这里我们使用 sepolia 测试网络. 如果没有 sepolia 网络的测试币, 可以切换到其他的测试网络.
同时需要注意的是, 这里我们通过 infura 向对应的区块链网络发送交易, 而 INFURA_ID 这个变量值也需要配置在 .env 文件中, 具体如何获取 infura_id, 可自行搜索查找相关文档
```js
// Create web3 with goerli provider,you can change goerli to other testnet
// Create web3 with sepolia provider,you can change sepolia to other testnet
const web3 = new Web3(
"https://goerli.infura.io/v3/" + process.env.INFURA_ID
"https://sepolia.infura.io/v3/" + process.env.INFURA_ID
);
```

Expand Down
116 changes: 63 additions & 53 deletions basic/01-web3js-deploy/README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,36 @@
[中文](./README-cn.md) / English

# Abstract

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`.

# Preparation
- You need to create a project on [Infura](https://infura.io), and get the `PROJECT ID`, change your `ENDPOINTS` to `Goerli`;

- You need to create a project on [Infura](https://infura.io), and get the `PROJECT ID`, change your `ENDPOINTS` to `Sepolia`;

- Create an account on `MetaMask`, which is a browser extension;
1. Get a wallet `address`, and the private key;
2. Go `Settings` - `advanced` and open `Show test networks`;
- Select `Goerli`, and record this address
3. Top up your account through [faucets](https://faucets.chain.link) or others web services;
4. Wait for minutes, and see the balance on `MetaMask`

1. Get a wallet `address`, and the private key;
2. Go `Settings` - `advanced` and open `Show test networks`;
- Select `Sepolia`, and record this address
3. Top up your account through [faucets](https://faucets.chain.link) or others web services;
4. Wait for minutes, and see the balance on `MetaMask`

- Create a `.env` file, and add the following lines:
```text
PRIVATE_KEY=YOUR_PRIVATE_KEY
INFURA_ID=YOUR_PROJECT_ID
```
| Note: You can check the `.env.example` file.

```text
PRIVATE_KEY=YOUR_PRIVATE_KEY
INFURA_ID=YOUR_PROJECT_ID
```

| Note: You can check the `.env.example` file.

- If you know Chinese, you can check these tasks on [BILIBILI](https://www.bilibili.com/video/BV1Y44y1r7E6/).

# Getting Started

## Understanding The Functions of the [Smart Contract](Incrementer.sol)

- `Constructor`: The constructor function of the smart contract, which is called when the contract is deployed, at the same time it will initialize the `number` to `_initialNumber`;
- `increment`: The function of incrementing the `number` by given `_value`;
- `rest`: The function of resetting the `number` to 0;
Expand All @@ -34,122 +41,125 @@ Through this basic task, you can learn the processes of compiling and deploying
1. Install dependencies: `npm install`
2. Copy the configuration file: `cp .env.example .env`
3. Edit the configuration file: `vim .env`, copy your project ID and private key to the `.env` file
```text
PRIVATE_KEY=YOUR_PRIVATE_KEY
INFURA_ID=YOUR_PROJECT_ID
```
```text
PRIVATE_KEY=YOUR_PRIVATE_KEY
INFURA_ID=YOUR_PROJECT_ID
```
4. Run the `index.js` file: `node index.js`

# Interpret the Code in `index.js`

`index.js` contains the most important part of this task, which includes the following functions:

## 1. Load the configuration file

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` .
Here is the code:

```js
require("dotenv").config();
require('dotenv').config();
const privatekey = process.env.PRIVATE_KEY;
```

## 2. Compile the smart contract file

You can not use `.sol` files directly, you need to compile it to binary file firstly.

### Load the smart contract file `Incrementer.sol` into `source` variable.

```js
// Load contract
const source = fs.readFileSync("Incrementer.sol", "utf8");
const source = fs.readFileSync('Incrementer.sol', 'utf8');
```

#### Compile the smart contract file

```js
const input = {
language: "Solidity",
language: 'Solidity',
sources: {
"Incrementer.sol": {
'Incrementer.sol': {
content: source,
},
},
settings: {
outputSelection: {
"*": {
"*": ["*"],
'*': {
'*': ['*'],
},
},
},
};

const tempFile = JSON.parse(solc.compile(JSON.stringify(input)));
```

| Note: The version of solidity in this task is `0.8.0`, different versions may have different compile ways.

## 3. Get the `bytecode` and `abi`

```js
const contractFile = tempFile.contracts["Incrementer.sol"]["Incrementer"];
const contractFile = tempFile.contracts['Incrementer.sol']['Incrementer'];

// Get bin & abi
const bytecode = contractFile.evm.bytecode.object;
const abi = contractFile.abi;
```
```

## 4. Create the `web3` instance

`web3` is the main API of the `web3js` library. It is used to interact with the blockchain.

```js
// Create web3 with goerli provider,you can change goerli to other testnet
const web3 = new Web3(
"https://goerli.infura.io/v3/" + process.env.INFURA_ID
);
// Create web3 with sepolia provider,you can change sepolia to other testnet
const web3 = new Web3('https://sepolia.infura.io/v3/' + process.env.INFURA_ID);
```

| Note: The `INFURA_ID` is the `PROJECT ID` of the `Infura` project you created in **Preparation** part.

## 5. Get the `account` address

On blockchain, each user has a `address`, which is unique for others, and you can get the `address` by the private key. In this task, you can use to `web3.eth.accounts.privateKeyToAccount` API to get your `account` address by passing the private key as a parameter.

```js
// Create account from privatekey
const account = web3.eth.accounts.privateKeyToAccount(privatekey);
const account_from = {
privateKey: privatekey,
accountAddress: account.address,
};
const accounts = web3.eth.accounts.wallet.add(privatekey);
```

## 6. Get contract instance

In the 3rd step, you got the `bytecode` and `abi`, so you can create the contract instance by the `abi`

```js
// Create contract instance
const deployContract = new web3.eth.Contract(abi);
```

## 7. Create the `deploy` transaction

```js
// Create Tx
const deployTx = deployContract.deploy({
data: bytecode,
arguments: [5],
data: '0x' + bytecode,
arguments: [0], // Pass arguments to the contract constructor on deployment(_initialNumber in Incremental.sol)
});

```
## 8. Sign the `deploy` transaction
Use your private key to sign the `deploy` transaction.
```js
const deployTransaction = await web3.eth.accounts.signTransaction(
{
data: deployTx.encodeABI(),
gas: 8000000,
},
account_from.privateKey
);
```

## 8. Deploy your smart contract

Use your private key to sign the `deploy` transaction.

## 9. Deploy your smart contract
Send your `deploy` transaction to the blockchain. You will receive a receipt, and get this contract address from the receipt.
```js
const deployReceipt = await web3.eth.sendSignedTransaction(
deployTransaction.rawTransaction
);
console.log(`Contract deployed at address: ${deployReceipt.contractAddress}`);
const tx = await deployTx.send({
from: accounts[0].address,
gas,
// gasPrice: 10000000000,
});
```

# References

- Web3js Official Documents: https://web3js.readthedocs.io/en/v1.2.11/getting-started.html
- Code and Examples: https://docs.moonbeam.network/getting-started/local-node/deploy-contract/
- Code and Examples: https://docs.moonbeam.network/getting-started/local-node/deploy-contract/
- How to use web3js: https://www.dappuniversity.com/articles/web3-js-intro
- Nodejs APIs Documents: http://nodejs.cn/api/fs.html
52 changes: 27 additions & 25 deletions basic/01-web3js-deploy/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
let Web3 = require('web3');
let { Web3 } = require('web3');
let solc = require('solc');
let fs = require('fs');

// Get privatekey from environment
require('dotenv').config();
const privatekey = process.env.PRIVATE_KEY;
let privatekey = process.env.PRIVATE_KEY;
if (privatekey.slice(0, 2) !== '0x') privatekey = '0x' + privatekey;

// Load contract
const source = fs.readFileSync('Incrementer.sol', 'utf8');
Expand All @@ -26,22 +27,18 @@ const input = {
},
};

const tempFile = JSON.parse(solc.compile(JSON.stringify(input)));
const contractFile = tempFile.contracts['Incrementer.sol']['Incrementer'];
const compiledCode = JSON.parse(solc.compile(JSON.stringify(input)));
const contractFile = compiledCode.contracts['Incrementer.sol']['Incrementer'];

// Get bin & abi
const bytecode = contractFile.evm.bytecode.object;
const abi = contractFile.abi;

// Create web3 with goerli provider,you can change goerli to other testnet
const web3 = new Web3('https://goerli.infura.io/v3/' + process.env.INFURA_ID);
// Create web3 with sepolia provider,you can change sepolia to other testnet
const web3 = new Web3('https://sepolia.infura.io/v3/' + process.env.INFURA_ID);

// Create account from privatekey
const account = web3.eth.accounts.privateKeyToAccount(privatekey);
const account_from = {
privateKey: privatekey,
accountAddress: account.address,
};
const accounts = web3.eth.accounts.wallet.add(privatekey);

/*
-- Deploy Contract --
Expand All @@ -52,24 +49,29 @@ const Deploy = async () => {

// Create Tx
const deployTx = deployContract.deploy({
data: bytecode,
data: '0x' + bytecode,
arguments: [0], // Pass arguments to the contract constructor on deployment(_initialNumber in Incremental.sol)
});

// Sign Tx
const deployTransaction = await web3.eth.accounts.signTransaction(
{
data: deployTx.encodeABI(),
gas: 8000000,
},
account_from.privateKey
);

const deployReceipt = await web3.eth.sendSignedTransaction(deployTransaction.rawTransaction);
// optionally, estimate the gas that will be used for development and log it
const gas = await deployTx.estimateGas({
from: accounts,
});
console.log('estimated gas:', gas);

// Your deployed contrac can be viewed at: https://goerli.etherscan.io/address/${deployReceipt.contractAddress}
// You can change goerli in above url to your selected testnet.
console.log(`Contract deployed at address: ${deployReceipt.contractAddress}`);
try {
// Deploy the contract to the Ganache network
// Your deployed contrac can be viewed at: https://sepolia.etherscan.io/address/${tx.options.address}
// You can change sepolia in above url to your selected testnet.
const tx = await deployTx.send({
from: accounts[0].address,
gas,
// gasPrice: 10000000000,
});
console.log('Contract deployed at address: ' + tx.options.address);
} catch (error) {
console.error(error);
}
};

// We recommend this pattern to be able to use async/await everywhere
Expand Down
6 changes: 2 additions & 4 deletions basic/01-web3js-deploy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
"author": "",
"license": "ISC",
"dependencies": {
"dotenv": "^10.0.0",
"fs": "0.0.1-security",
"ganache-cli": "^6.12.2",
"dotenv": "^16.3.1",
"solc": "0.8.0",
"web3": "^1.3.5"
"web3": "^4.0.3"
}
}
Binary file modified docs/imgs/wechat-group-helper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 92cf34a

Please sign in to comment.