diff --git "a/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-1.png" "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-1.png" new file mode 100644 index 0000000..7745c23 Binary files /dev/null and "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-1.png" differ diff --git "a/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-2.png" "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-2.png" new file mode 100644 index 0000000..b6c508a Binary files /dev/null and "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-2.png" differ diff --git "a/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-3.png" "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-3.png" new file mode 100644 index 0000000..64cf423 Binary files /dev/null and "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-3.png" differ diff --git "a/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-4.png" "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-4.png" new file mode 100644 index 0000000..6010f4f Binary files /dev/null and "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-4.png" differ diff --git "a/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-5.png" "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-5.png" new file mode 100644 index 0000000..a494292 Binary files /dev/null and "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image-5.png" differ diff --git "a/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image.png" "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image.png" new file mode 100644 index 0000000..869363b Binary files /dev/null and "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/image.png" differ diff --git "a/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/readme.md" "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/readme.md" new file mode 100644 index 0000000..6854f2b --- /dev/null +++ "b/Geth\346\240\207\345\207\206\345\220\257\345\212\250\346\250\241\345\274\217\345\237\272\346\234\254\346\223\215\344\275\234/readme.md" @@ -0,0 +1,99 @@ +一:准备 genesis.json 文件 + +文件内容如下: + +``` +{ + "config": { + "chainId": 2008, + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 0, + "londonBlock": 0 + }, + "alloc": {}, + "coinbase": "0x0000000000000000000000000000000000000000", + "difficulty": "0x20000", + "extraData": "", + "gasLimit": "0x2fefd8", + "nonce": "0x0000000000000042", + "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "timestamp": "0x00" +} +``` + +二:命令行启动(标准模式) + +2.1 打开 cmd(管理员模式),进入到 geth 所在的文件夹 + +2.2 执行命令 ```geth --datadir data init genesis.json``` + +![alt text](image.png) + +————此页面代表执行成功 + +注意:此时,geth 文件夹中出现了 data 文件夹: + +![alt text](image-1.png) + +2.3 执行命令 + +```geth --datadir ./data --networkid 2008 --port 30303 --http --http.addr 0.0.0.0 --http.vhosts "_" --http.api "db,net,eth,web3,personal" --http.corsdomain "_" --snapshot=false --allow-insecure-unlock``` + +四个要注意的细节: + +● "--datadir ./data",与 2.2 命令结合起来看,代表要将区块的数据放入哪个文件夹,因此两处命令的文件夹名称必须一致 + +● networkid 一定要和 genesis.json 中的 chainId 参数一致 + +● 与 http 相关的所有参数可以不写,如果不写,将无法和 MetaMask 等钱包进行交互(之前的版本使用的是 rpc,后来改成了 http) + +● --allow-insecure--unlock 参数可以不写,如果不写,意味着每次转账都需要先解锁账户,这个后面会再次提到 + +![alt text](image-2.png) + +————此页面代表执行成功 + +2.4 +新打开一个 cmd(管理员模式),无需进入 geth 所在文件夹,直接执行命令:```geth attach ipc:\\.\pipe\geth.ipc``` + +特别注意:之前的那个 cmd 不能关闭 + +————此页面代表执行成功 + +![alt text](image-3.png) + +至此,标准模式下的 Geth 已启动,私链已初始化完成 + +一些补充: + +1. Geth 关闭后,如何重启 + +经常有朋友把 geth 关了后,就不知道怎么重启了,这里统一做个说明 + +● 如下有两个界面: + +上面这个界面称为 A,下面称为 B + +![alt text](image-4.png) + +![alt text](image-5.png) + +——如果仅关闭 A: + +重启方案:以管理员模式打开 cmd,无需进入到 geth 文件夹,直接输入 ```geth attach ipc:\\.\pipe\geth.ipc``` + +——如果 A 与 B 都关了: + +重启方案:以管理员模式打开 cmd,进入 geth 文件夹,再输入:```geth --datadir ./data --networkid 2008 --port 30303 --http --http.addr 0.0.0.0 --http.vhosts "_" --http.api "db,net,eth,web3,personal" --http.corsdomain "_" --snapshot=false --allow-insecure-unlock``` + +然后,用管理员模式打开一个新的 cmd,无需进入 geth 文件夹,直接输入 ```geth attach ipc:\\.\pipe\geth.ipc``` + +——如果仅关闭 B:此情况不存在,因为把 B 关了 A 就不运行了,等于 A 也同时被关了 diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-1.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-1.png" new file mode 100644 index 0000000..e22709f Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-1.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-10.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-10.png" new file mode 100644 index 0000000..b621d65 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-10.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-11.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-11.png" new file mode 100644 index 0000000..4374a1e Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-11.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-12.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-12.png" new file mode 100644 index 0000000..6488a10 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-12.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-13.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-13.png" new file mode 100644 index 0000000..a5f4368 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-13.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-14.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-14.png" new file mode 100644 index 0000000..08ee8fd Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-14.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-15.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-15.png" new file mode 100644 index 0000000..fab5876 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-15.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-16.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-16.png" new file mode 100644 index 0000000..6e46c66 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-16.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-17.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-17.png" new file mode 100644 index 0000000..48332c0 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-17.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-18.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-18.png" new file mode 100644 index 0000000..85ae07f Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-18.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-19.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-19.png" new file mode 100644 index 0000000..8aae9ef Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-19.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-2.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-2.png" new file mode 100644 index 0000000..324ff2c Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-2.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-20.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-20.png" new file mode 100644 index 0000000..75a29c9 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-20.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-21.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-21.png" new file mode 100644 index 0000000..ce97b84 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-21.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-22.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-22.png" new file mode 100644 index 0000000..bb0523e Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-22.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-23.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-23.png" new file mode 100644 index 0000000..b800a0f Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-23.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-3.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-3.png" new file mode 100644 index 0000000..918bb9b Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-3.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-4.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-4.png" new file mode 100644 index 0000000..a528f73 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-4.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-5.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-5.png" new file mode 100644 index 0000000..d7dd6a5 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-5.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-6.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-6.png" new file mode 100644 index 0000000..b8e3426 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-6.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-7.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-7.png" new file mode 100644 index 0000000..63b9274 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-7.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-8.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-8.png" new file mode 100644 index 0000000..afc85bf Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-8.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-9.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-9.png" new file mode 100644 index 0000000..fe1ba83 Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image-9.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image.png" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image.png" new file mode 100644 index 0000000..448b36e Binary files /dev/null and "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/image.png" differ diff --git "a/Geth\347\247\201\351\223\276\346\220\255\345\273\272/readme.md" "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/readme.md" new file mode 100644 index 0000000..9a1a7dc --- /dev/null +++ "b/Geth\347\247\201\351\223\276\346\220\255\345\273\272/readme.md" @@ -0,0 +1,171 @@ +一:账户相关 + +我们先执行账户查询的操作:`eth.accounts` + +![alt text](image.png) + +发现什么也没有,是因为我们还没有在自己的私链上创建或导入以太坊地址 + +![alt text](image-1.png) + +好的,我们现在来创建一个,执行命令:`personal.newAccount()`,然后输入密码,确认密码,即可生成新的以太坊地址 + +再次执行`eth.accounts`,发现已经有了一个地址 + +![alt text](image-2.png) + +新生成的地址肯定是没有钱的,通过以下两行命令都可以获取到该账户的余额 + +`eth.getBalance("以太坊地址")` + +`eth.getBalance(eth.accounts[0])`,刚刚生成的地址保存在 eth.accounts 数组中 + +![alt text](image-3.png) + +——对于私链中第一个地址,默认为 eth.coinbase,因此还有另外一种获取余额的方式: + +`eth.getBalance(eth.coinbase)` + +![alt text](image-4.png) + +二:挖矿相关 + +账户里没有钱(以太坊)怎么办,两个方法:一个让其他地址转钱,另一个方法是挖矿 + +当然,由于这条区块链是新搭建的,链上还没有生成任何的币(其他以太坊地址的币与此链并不相通,因为链 ID 不同),因此我们先来尝试挖矿的方法: + +执行命令`miner.start()`,这里返回"null"是正常现象 + +![alt text](image-5.png) + +然后在另一个 cmd 中,发现正在疯狂地更新数据: + +![alt text](image-6.png) + +出现红色箭头所指的特殊符号,代表挖矿成功(emmmm,发现挖矿如此快其实是之前在 genesis.json 文件中初始定义的挖矿难度太低导致的,如果想折磨自己的话,可以把难度值调大一点) + +现在我们把挖矿关停,执行命令:`miner.stop()`,这里返回"null"也是正常现象 + +![alt text](image-7.png) + +———其实还可以多线程挖矿:`miner.start(5)`,这里同时开五个线程,然后发现其实可能没什么茑用,除非你的电脑是四核/八核及以上 CPU + +挖了这么多区块,可以用 `eth.blockNumber`来查询以下当前的区块高度 + +![alt text](image-8.png) + +有了币,我们再来获取一下余额: + +![alt text](image-9.png) + +这余额数字那么大,根本数不过来,但其实这个余额是用"wei"单位来表示的(1 ETH = 1e18 Wei),因此要去掉 18 个 0 + +执行命令:`web3.fromWei(eth.getBalance(eth.accounts[0]),'ether')`,即可将余额用 ETH 单位来表示 + +![alt text](image-10.png) + +三:转账/交易相关 + +我们要在此链上发布一笔转账,这里就转钱给自己的 MetaMask 账户吧 + +——算了算了,这样太快了,还是先用本地存储的账户来先测试一下 + +新填一个账户: + +![alt text](image-11.png) + +通过以下命令执行转账操作:三个参数 from,to,value + +`eth.sendTransaction({from: eth.accounts[0],to:eth.accounts[1],value:web3.toWei(10,'ether')})` + +然后尴尬地发现居然报错了: + +![alt text](image-12.png) + +原因是 from 账户没有被解锁(unlock),为了保证转账的发起者不是别人而是自己,需要先对账户进行解锁(其实是身份核验) + +执行如下命令,然后输入密码,即可解锁(返回 true) + +`personal.unlockAccount(eth.accounts[0])` + +![alt text](image-13.png) + +再次执行转账命令: + +![alt text](image-14.png) + +出现绿色的一串 16 进制数,代表成功,这一串数字是交易哈希 + +——如果没有出现,可以检查下是否余额足够 + +但是,这只是生成了交易,还没有将交易的数据上链 + +因此,挖矿吧: + +![alt text](image-15.png) + +然后,就可以在刚刚挖到的第一个区块找到这笔交易了 + +我们通过:`eth.getBlock(区块号)`命令来获取某区块的所有数据,我这边是 265 + +![alt text](image-16.png) + +看到"transactions"这一行,发现里面存储了刚刚那笔交易的哈希 + +——如果 transactions 没有数据,原因就是交易不在该区块中,区块号没有找对 + +除此之外,还可以通过以下命令获取到交易的具体信息: + +`eth.getTransaction("交易哈希")` + +![alt text](image-17.png) + +很好,现在你已经知道如何发起一笔转账并查询交易数据了,接下来再用 MetaMask 钱包来过一下瘾 + +四:与 MetaMask 交互 + +首先,你得有一个 MetaMask 的钱包,没有就先下载一个 + +先要导入本地的 "localhost" 网络: + +![alt text](image-18.png) + +发现这儿没有,需要自己添加 + +![alt text](image-19.png) + +除了链 ID 写自己 genesis.json 里的 chainId 外,其他直接照填 + +————然后就可以发起转账了 + +![alt text](image-20.png) + +——可能出现了账户又被 unlock 了,这个时候需要再解锁一下 from 账户 + +交易完成后,发现 MetaMask 多了几个 ETH: + +![alt text](image-21.png) + +当然,这不是主网的 ETH 啦,是刚刚自己搭建的区块链上的 ETH + +五:其他操作: + +5.1 换一个人挖矿 + +刚刚上面的操作,挖矿只能是 eth.coinbase 这个账户在挖,现在我们打算换一个账户: + +就换我们自己 MetaMask 的账户来挖吧: + +首先执行如下操作: + +`miner.setEtherbase("地址")` + +返回 true 后再进行挖矿: + +![alt text](image-22.png) + +然后发现钱包多了好多 ETH,刚刚还是 10 个的 + +![alt text](image-23.png) + +———以后的智能合约测试直接用本地自己搭建的链就行了,因为有用不完的 ETH diff --git "a/Web3.js\345\267\245\347\250\213/readme.md" "b/Web3.js\345\267\245\347\250\213/readme.md" new file mode 100644 index 0000000..872b62b --- /dev/null +++ "b/Web3.js\345\267\245\347\250\213/readme.md" @@ -0,0 +1,515 @@ + +# 前言:Solidity+Web3.js = Dapp,Geth=测试环境 +Solidity:提供智能合约,即核心的业务逻辑
web3.js:与区块链上的智能合约进行交互(读写数据),并可通过编写前端代码(Javascript/Typescript,html,css)设计交互网页(用户页面)的工具
Geth:提供一条测试链,进行合约功能测试的工具 + +——现在我们来在Web3.js上部署合约并实现交互(调用/修改)吧 + +# 一:需要准备的东西 + +## 1.1 安装node.js(以win10)为例 + +### 1.1.1 下载node.js + +- 进入node.js官网: + +[下载 | Node.js](https://nodejs.org/zh-cn/download/) + +- 选择**"长期维护版本"**的window安装包 + +![捕获8.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661174812108-8e086a08-4077-425d-a853-29ca53d2ae80.png#averageHue=%23b5cfad&clientId=ua3557398-4c52-4&from=ui&id=u58cfdda9&originHeight=324&originWidth=592&originalType=binary&ratio=1&rotation=0&showTitle=false&size=30048&status=done&style=none&taskId=ue845007a-3511-4508-bfb5-2ebb8ffc6c7&title=) + +- 下载完后,点击安装,**设置安装路径**,然后下面的这个要勾上:
![捕获9.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661175036985-17c739f1-7179-472c-b136-e9e189af6718.png#averageHue=%23edece9&clientId=ua3557398-4c52-4&from=ui&id=u1af5963d&originHeight=261&originWidth=491&originalType=binary&ratio=1&rotation=0&showTitle=false&size=18581&status=done&style=none&taskId=u7f2c3281-da13-49b3-a6cd-da1db4c5153&title=) +- 检查是否安装成功:打开cmd,分别执行:`node -v`和`npm -v`,只要能顺利获取到版本,意味着安装成功 + +![捕获10.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661175238054-905d21c3-c005-44dc-a822-f84f28f25e4b.png#averageHue=%2300130c&clientId=ua3557398-4c52-4&from=ui&id=u83262c88&originHeight=136&originWidth=371&originalType=binary&ratio=1&rotation=0&showTitle=false&size=4052&status=done&style=none&taskId=uaeff1c87-bc33-4be5-9790-2fe45effedf&title=) + +### 1.1.2 配置node.js环境 + +- 管理员模式打开一个全新的cmd +- 进入到自己node.js的安装目录,即:`cd 安装目录` +- 创建两个文件夹,分别是 node_global、node_cache,表示node.js的全局路径、缓存路径 ,执行:`mkdir node_global`和`mkdir node_cache` +- 启用刚创建的两个路径: + +`npm config set prefix "安装路径\node_global"`
`npm config set prefix "安装路径\node_cache"` + +- 左下角直接搜索env,或者右键打开"我的电脑"中的属性,进入到高级环境变量 +- 新建一个"系统环境"变量:NODE_PATH
变量名:NODE_PATH
变量值:安装路径\node_global\node_modules + +![捕获15.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661175965722-d4c4c2fd-8a0d-4856-93e2-9fa96b571bd4.png#averageHue=%23998360&clientId=ua3557398-4c52-4&from=ui&id=u7a1397de&originHeight=603&originWidth=1789&originalType=binary&ratio=1&rotation=0&showTitle=false&size=414601&status=done&style=none&taskId=u6494b893-009f-4f68-94d1-0ebacee6a52&title=) + +- 在系统变量Path里添加%NODE_PATH% + +![捕获20.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661176112558-7fdfd655-9789-4866-99df-aca9e4a9bc66.png#averageHue=%23f2efee&clientId=ua3557398-4c52-4&from=ui&id=u3b5b456a&originHeight=649&originWidth=1133&originalType=binary&ratio=1&rotation=0&showTitle=false&size=84606&status=done&style=none&taskId=u25dead74-c836-440c-a3f3-91331dd6402&title=) + +- 将安装路径\node_global添加到"用户变量"的Path里 + +![捕获36.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661176294624-3e8b2d11-91a2-4856-9ff9-4c1709ef90b3.png#averageHue=%23f2f1ef&clientId=ua3557398-4c52-4&from=ui&id=u41df5cc3&originHeight=602&originWidth=1152&originalType=binary&ratio=1&rotation=0&showTitle=false&size=99355&status=done&style=none&taskId=u704efa82-b0bd-4f8e-9b45-c195da298cd&title=) + +### 1.1.3 设置镜像源 + +- 管理员模式打开一个新的cmd,执行`npm config set registry https://registry.npm.taobao.org` +- 查看镜像源:`npm config get registry` + + +## 1.2 合约的ABI文件和Web3Deploy文件 + +- 打开Remix,随便找个合约部署 +- 部署成功后找到Compilation Details + +![捕获39.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661177170633-60275cf3-b442-401c-aaa6-7ab45e11e100.png#averageHue=%233d4056&clientId=ua3557398-4c52-4&from=ui&id=u81a294ba&originHeight=267&originWidth=359&originalType=binary&ratio=1&rotation=0&showTitle=false&size=17147&status=done&style=none&taskId=u9a086ccb-5d30-45d7-8b48-da0a7481e92&title=) + +- 复制ABI和WEB3DEPLOY并分别保存,后面有用 + +![捕获40.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661177187695-6db8df69-5e3b-443b-beda-669f5fa2255c.png#averageHue=%23242538&clientId=ua3557398-4c52-4&from=ui&id=u70deaefc&originHeight=314&originWidth=417&originalType=binary&ratio=1&rotation=0&showTitle=false&size=13065&status=done&style=none&taskId=uf982933a-4028-4563-8546-c7ea52b89a1&title=) + + +## 1.3 Geth搭建一条测试链 + +- 提前准备好两个账户 +- 提前挖点自己搭建的链的测试币 + + +# 二:Web3.js上部署合约 + +## 2.1 新建并启动Web3.js工程 + +- **管理员模式**新打开一个cmd,执行:`mkdir Web3Project`,即创建一个名为"Web3Project"的文件夹 + +![捕获66.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661178449919-92f29f0a-1203-488a-9246-757550f64484.png#averageHue=%2300130c&clientId=ua3557398-4c52-4&from=ui&id=u2447ca29&originHeight=86&originWidth=377&originalType=binary&ratio=1&rotation=0&showTitle=false&size=4163&status=done&style=none&taskId=u68ceea9a-a2f7-4695-9ccc-76f06d68dd3&title=) + +- **管理员模式**打开Vscode,打开刚刚创建的文件夹 + +(路径为:C:/Windows/system32/Web3Project) + +- Vscode内打开一个终端,执行`npm install web3`命令 + +![捕获70.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661179161054-88622039-099a-4123-b8b8-4da0c0d7b5b8.png#averageHue=%23242322&clientId=ua3557398-4c52-4&from=ui&height=142&id=uf9338c6a&originHeight=170&originWidth=719&originalType=binary&ratio=1&rotation=0&showTitle=false&size=26787&status=done&style=none&taskId=u5c3bcde3-b0fc-4292-b00c-8449caafbba&title=&width=599) + +- 新建一个名为"deploy.js"的文件,并将以下三行代码写进去: + +`var Web3 = require('web3');`
(文件当前有web3对象吗?没有就创建一个)
`var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));`
(将web3对象连接到“http://localhost:8545”)
`web3.eth.getAccounts().then(console.log);`
(如果上面的...8545连接成功,会将在Geth中搭建的测试链中的所有地址打印在终端) +```javascript +var Web3 = require('web3'); +var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); +web3.eth.getAccounts().then(console.log); +``` + +- 在Vscode的终端执行命令:`node deploy.js` + +——会发现将自己Geth搭建的测试链中的所有地址打印出了出来(当然,前提是这条测试链中你已经创建了至少一个地址)
![捕获99.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661179609942-de8ed0fc-5e76-4e9e-a08a-4140d5aa9cf2.png#averageHue=%23222120&clientId=ua3557398-4c52-4&from=ui&id=u66f49034&originHeight=153&originWidth=671&originalType=binary&ratio=1&rotation=0&showTitle=false&size=33507&status=done&style=none&taskId=u9079750a-5c33-4cc2-9c93-f5a4e2c8a70&title=)
——注意,必须要先启用这条私链,才可以执行上述命令,否则会报错:
![捕获102.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661179979173-e51e80da-cd3f-430e-b3fa-fd17fe5c0b13.png#averageHue=%23292826&clientId=ua3557398-4c52-4&from=ui&id=u462f0377&originHeight=302&originWidth=940&originalType=binary&ratio=1&rotation=0&showTitle=false&size=106668&status=done&style=none&taskId=u0ffc0792-701a-468a-963c-854ed3a2994&title=) + + +## 2.2 合约部署 +——在deploy.js上继续编写代码: + +- 将之前复制的合约的WEB3DEPLOY文件(顾名思义,就是WEB3部署文件)粘贴到deploy.js(注意,前面三行不要删) + +——这个我的某个合约的WEB3DEPLOY文件(修改后的)
![捕获206.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661183245552-9cec350e-1287-48f9-853b-da18df991363.png#averageHue=%23252120&clientId=ua3557398-4c52-4&from=ui&id=btizR&originHeight=534&originWidth=1016&originalType=binary&ratio=1&rotation=0&showTitle=false&size=185889&status=done&style=none&taskId=u0a601109-e622-48db-beb0-c7f9f62bb0c&title=) + +- 只需改动两个地方,①:from中的地址要改成Geth搭建的测试链的第一个地址的具体地址**(不能表达成web3.eth.accounts[0])**;②:WEB3DEPLOY文件复制过来后,要在末尾加上图示矩形中这两行,**否则合约在Web3.js上部署后拿不到合约地址** +- data中的数据就是合约的bytecode字节码,粘进去一般会报错,需要修改Vscode中的一个参数: + +![捕获130.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661181047668-b66a37bf-f323-455e-ae02-43a2307bb1a1.png#averageHue=%23c0ac7b&clientId=ua3557398-4c52-4&from=ui&height=180&id=u18264ac9&originHeight=217&originWidth=782&originalType=binary&ratio=1&rotation=0&showTitle=false&size=43190&status=done&style=none&taskId=u402c42fa-0244-4096-8757-5b023cc0592&title=&width=649)
——修改方法:打开vscode的设置,输入“editor.maxTokenizationLineLength”参数,并将其修改为"1e+36"![捕获140.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661181144324-8d786dd8-ddab-494d-8f9b-a92f1b889270.png#averageHue=%23282726&clientId=ua3557398-4c52-4&from=ui&height=269&id=u7deb0962&originHeight=337&originWidth=863&originalType=binary&ratio=1&rotation=0&showTitle=false&size=35555&status=done&style=none&taskId=u2dad0d06-896f-47d2-8d46-bdb959b124a&title=&width=688) + +- 如果合约包含构造参数,就改动代码的"arguments"参数: + +![捕获200.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661182412480-b83b60cc-5a2a-43c9-b7b5-5869d49ce334.png#averageHue=%23252120&clientId=ua3557398-4c52-4&from=ui&id=u9afb68c7&originHeight=521&originWidth=912&originalType=binary&ratio=1&rotation=0&showTitle=false&size=96045&status=done&style=none&taskId=u8f4ed942-a079-4585-9a91-6a2dc700abf&title=)
———假设某份合约里定义了:合约创建时要传入两个构造参数,分别是name(代币名)和totalSupply(代币总供应量),那么应先在deploy.js文件的最上面定义这两个变量,然后才在arguments中写入两个变量的值
**————"deploy.js"完整代码:** +```javascript +var _name; +var _totalSupply; +var Web3 = require('web3'); +var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); +web3.eth.getAccounts().then(console.log); +var fabi01Contract = new web3.eth.Contract([{ "inputs": [{ "internalType": "string", "name": "_name", "type": "string" }, { "internalType": "uint256", "name": "_totalSupply", "type": "uint256" }], "stateMutability": "nonpayable", "type": "constructor" }, { "anonymous": false, "inputs": [{ "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "tokens", "type": "uint256" }], "name": "Transfer", "type": "event" }, { "inputs": [{ "internalType": "address", "name": "_address", "type": "address" }], "name": "balanceOf", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "decimals", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "name", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "totalSupply", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [{ "internalType": "address", "name": "_receiver", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" }], "name": "transfer", "outputs": [{ "internalType": "bool", "name": "success", "type": "bool" }], "stateMutability": "nonpayable", "type": "function" }]); +var fabi01 = fabi01Contract.deploy({ + data: '0x60806040523480156200001157600080fd5b506040516200108f3803806200108f8339818101604052810190620000379190620002f9565b8160009081620000489190620005a0565b506012600281905550600254600a6200006291906200080a565b816200006f91906200085b565b60018190555080600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6001546040516200011b9190620008cd565b60405180910390a35050620008ea565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620001948262000149565b810181811067ffffffffffffffff82111715620001b657620001b56200015a565b5b80604052505050565b6000620001cb6200012b565b9050620001d9828262000189565b919050565b600067ffffffffffffffff821115620001fc57620001fb6200015a565b5b620002078262000149565b9050602081019050919050565b60005b838110156200023457808201518184015260208101905062000217565b60008484015250505050565b6000620002576200025184620001de565b620001bf565b90508281526020810184848401111562000276576200027562000144565b5b6200028384828562000214565b509392505050565b600082601f830112620002a357620002a26200013f565b5b8151620002b584826020860162000240565b91505092915050565b6000819050919050565b620002d381620002be565b8114620002df57600080fd5b50565b600081519050620002f381620002c8565b92915050565b6000806040838503121562000313576200031262000135565b5b600083015167ffffffffffffffff8111156200033457620003336200013a565b5b62000342858286016200028b565b92505060206200035585828601620002e2565b9150509250929050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680620003b257607f821691505b602082108103620003c857620003c76200036a565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620004327fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82620003f3565b6200043e8683620003f3565b95508019841693508086168417925050509392505050565b6000819050919050565b6000620004816200047b6200047584620002be565b62000456565b620002be565b9050919050565b6000819050919050565b6200049d8362000460565b620004b5620004ac8262000488565b84845462000400565b825550505050565b600090565b620004cc620004bd565b620004d981848462000492565b505050565b5b818110156200050157620004f5600082620004c2565b600181019050620004df565b5050565b601f82111562000550576200051a81620003ce565b6200052584620003e3565b8101602085101562000535578190505b6200054d6200054485620003e3565b830182620004de565b50505b505050565b600082821c905092915050565b6000620005756000198460080262000555565b1980831691505092915050565b600062000590838362000562565b9150826002028217905092915050565b620005ab826200035f565b67ffffffffffffffff811115620005c757620005c66200015a565b5b620005d3825462000399565b620005e082828562000505565b600060209050601f83116001811462000618576000841562000603578287015190505b6200060f858262000582565b8655506200067f565b601f1984166200062886620003ce565b60005b8281101562000652578489015182556001820191506020850194506020810190506200062b565b868310156200067257848901516200066e601f89168262000562565b8355505b6001600288020188555050505b505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008160011c9050919050565b6000808291508390505b60018511156200071557808604811115620006ed57620006ec62000687565b5b6001851615620006fd5780820291505b80810290506200070d85620006b6565b9450620006cd565b94509492505050565b60008262000730576001905062000803565b8162000740576000905062000803565b816001811462000759576002811462000764576200079a565b600191505062000803565b60ff84111562000779576200077862000687565b5b8360020a91508482111562000793576200079262000687565b5b5062000803565b5060208310610133831016604e8410600b8410161715620007d45782820a905083811115620007ce57620007cd62000687565b5b62000803565b620007e38484846001620006c3565b92509050818404811115620007fd57620007fc62000687565b5b81810290505b9392505050565b60006200081782620002be565b91506200082483620002be565b9250620008537fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846200071e565b905092915050565b60006200086882620002be565b91506200087583620002be565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615620008b157620008b062000687565b5b828202905092915050565b620008c781620002be565b82525050565b6000602082019050620008e46000830184620008bc565b92915050565b61079580620008fa6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806306fdde031461005c57806318160ddd1461007a578063313ce5671461009857806370a08231146100b6578063a9059cbb146100e6575b600080fd5b610064610116565b6040516100719190610474565b60405180910390f35b6100826101a4565b60405161008f91906104af565b60405180910390f35b6100a06101aa565b6040516100ad91906104af565b60405180910390f35b6100d060048036038101906100cb919061052d565b6101b0565b6040516100dd91906104af565b60405180910390f35b61010060048036038101906100fb9190610586565b6101f9565b60405161010d91906105e1565b60405180910390f35b600080546101239061062b565b80601f016020809104026020016040519081016040528092919081815260200182805461014f9061062b565b801561019c5780601f106101715761010080835404028352916020019161019c565b820191906000526020600020905b81548152906001019060200180831161017f57829003601f168201915b505050505081565b60015481565b60025481565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600081600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101561027d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610274906106a8565b60405180910390fd5b81600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054106103dd5781600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461031291906106f7565b9250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610368919061072b565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516103cc91906104af565b60405180910390a3600190506103de565b5b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561041e578082015181840152602081019050610403565b60008484015250505050565b6000601f19601f8301169050919050565b6000610446826103e4565b61045081856103ef565b9350610460818560208601610400565b6104698161042a565b840191505092915050565b6000602082019050818103600083015261048e818461043b565b905092915050565b6000819050919050565b6104a981610496565b82525050565b60006020820190506104c460008301846104a0565b92915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006104fa826104cf565b9050919050565b61050a816104ef565b811461051557600080fd5b50565b60008135905061052781610501565b92915050565b600060208284031215610543576105426104ca565b5b600061055184828501610518565b91505092915050565b61056381610496565b811461056e57600080fd5b50565b6000813590506105808161055a565b92915050565b6000806040838503121561059d5761059c6104ca565b5b60006105ab85828601610518565b92505060206105bc85828601610571565b9150509250929050565b60008115159050919050565b6105db816105c6565b82525050565b60006020820190506105f660008301846105d2565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061064357607f821691505b602082108103610656576106556105fc565b5b50919050565b7f536f7272792c796f75722062616c616e63652069736e277420656e6f75676800600082015250565b6000610692601f836103ef565b915061069d8261065c565b602082019050919050565b600060208201905081810360008301526106c181610685565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061070282610496565b915061070d83610496565b9250828203905081811115610725576107246106c8565b5b92915050565b600061073682610496565b915061074183610496565b9250828201905080821115610759576107586106c8565b5b9291505056fea264697066735822122097991a00d8a0c1e2779afb5eea275599ccf6b545868b33c466fb55bcad0792d264736f6c63430008100033', + arguments: [ + _name = "CHC", + _totalSupply = "21000000", + ] +}).send({ + from: '0x4C5B3fc298Cc00f2f5A6E06232D403cB9C5bD9Ba', + gas: '4700000' +}, function (e, contract) { + console.log(e, contract); + if (typeof contract.address !== 'undefined') { + console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash); + } +}).then(function (contract) { + console.log("Contract address:", contract.options.address); +}); +``` + +- 接下来正式执行合约部署,输入命令:`node deploy.js` + +![捕获203.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661182650086-f22240ae-cdaa-4ef1-8aa9-b5e1d15832ed.png#averageHue=%23292725&clientId=ua3557398-4c52-4&from=ui&id=uebd019a0&originHeight=305&originWidth=876&originalType=binary&ratio=1&rotation=0&showTitle=false&size=139771&status=done&style=none&taskId=u3bfa8fae-3530-4dd5-80ee-81c3310efe6&title=)
——发现这里报了一个错,原因是部署合约的账户没有解锁
——解决方法:管理员模式新打开一个cmd,执行命令:`geth attach ipc:\\.\pipe\geth.ipc`,然后执行:`personal.unlockAccount(eth.accounts[0])`,输入密码即可解锁 + +- 解锁后再次执行命令:`node deploy.js` + +——出现下图这种情况代表智能合约交易创建成功:
![捕获233.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661182922937-3a2852d9-c638-4825-8d41-6754714e5574.png#averageHue=%23222121&clientId=ua3557398-4c52-4&from=ui&id=u286b5b25&originHeight=230&originWidth=951&originalType=binary&ratio=1&rotation=0&showTitle=false&size=73801&status=done&style=none&taskId=u6d2459c3-7621-4836-afa4-29d2afadc97&title=) + +- 但是还没有成功上链,因此在之前打开的cmd终端执行`miner.start()`,即挖矿 + +——成功界面如下,箭头所指的即为合约地址,**注意保存**
![捕获306.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661183449850-e7f44d06-daaf-4fed-8488-14d1b9eb0fa7.png#averageHue=%23252423&clientId=ua3557398-4c52-4&from=ui&id=u7b580372&originHeight=213&originWidth=957&originalType=binary&ratio=1&rotation=0&showTitle=false&size=94432&status=done&style=none&taskId=ud543a7cc-7141-4c02-b0aa-72015b39c8f&title=) + + +##
+ +# 三:Web3.js上调用合约 +——————说明:这仅仅只是一个简易的demo,目的是熟悉过程 + +## 3.1 node.js安装express框架 + +- 直接在Vscode终端执行命令(还是在当前目录下):`npm install -g express` +- 继续在Vscode终端执行命令:`npm install express-generator -g` + +![捕获300.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661184305438-142bef12-29a4-4518-af2f-a2b5e41ea3c7.png#averageHue=%23262523&clientId=ua3557398-4c52-4&from=ui&id=u337af169&originHeight=313&originWidth=1101&originalType=binary&ratio=1&rotation=0&showTitle=false&size=99746&status=done&style=none&taskId=u5817c70d-efc7-4d03-a270-1bc5f0f007f&title=) + + +## 3.2 新建合约调用工程 + +- 执行命令:`express -e contractTest`,然后会发现"Web3Project"文件夹下立马多了一个名为"contractTest"的文件夹 +- 在vscode终端执行:`cd contractTest`;`npm install`;`npm install web3` + +——出现以下界面代表执行成功
![捕获400.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661184758273-ef8acf2e-0a01-42b2-87e9-4f5d76ca90b8.png#averageHue=%232b2925&clientId=ua3557398-4c52-4&from=ui&id=u8f98fc7f&originHeight=644&originWidth=1383&originalType=binary&ratio=1&rotation=0&showTitle=false&size=297875&status=done&style=none&taskId=u279ea58b-3d0a-4a7c-a9b9-f073d99d968&title=) + + +## 3.3 修改文件 + +### 3.3.1 修改"app.js"文件 +app.js,这个文件是使合约能够进行网页调用的"入口程序" +> ``app.js(全部粘贴,无需改动,不同合约此文件都一样,当然只是demo啦) + +```javascript +var createError = require('http-errors'); +var express = require('express'); +var path = require('path'); +var cookieParser = require('cookie-parser'); +var logger = require('morgan'); + +var indexRouter = require('./routes/index'); +var usersRouter = require('./routes/users'); + +var app = express(); +var ejs = require('ejs'); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.engine('.html', ejs.__express); +app.set('view engine', 'html'); +// app.set('view engine', 'ejs'); + +app.use(logger('dev')); +app.use(express.json()); +app.use(express.urlencoded({ extended: false })); +app.use(cookieParser()); +app.use(express.static(path.join(__dirname, 'public'))); + +app.use('/', indexRouter); +app.use('/users', usersRouter); + +// catch 404 and forward to error handler +app.use(function (req, res, next) { + next(createError(404)); +}); + +// error handler +app.use(function (err, req, res, next) { + // set locals, only providing error in development + res.locals.message = err.message; + res.locals.error = req.app.get('env') === 'development' ? err : {}; + + // render the error page + res.status(err.status || 500); + res.render('error'); +}); + +module.exports = app; +``` + +### 3.3.2 (初步)修改route目录下的index.js +index.js,这个文件是用来进行合约调用的"调用命令文件",用户所有可以在Dapp中实现的"获取合约状态信息"和"修改合约状态"的等等操作都在此文件被定义 +```javascript +var express = require('express'); +var router = express.Router(); + +var Web3 = require('web3'); +var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); + +web3.eth.getAccounts().then(console.log); + +/* GET home page. */ +router.get('/', function(req, res, next) { + res.render('index', { title: 'Express' }); +}); + +module.exports = router; +``` + +### 3.3.3 在view的目录下新建index.html +index.html,这个文件是DAPP的前端展示文件,页面会呈现给用户什么东西都在这个文件实现(当然,还得有css文件啦,但demo搞得这么花里胡哨意义不大,那些东西都是前端人员去解决的) +```javascript + + + + + 调用合约 + + + + +

调用合约

+ + + +``` +——在vscode终端执行:`npm start`,如果能成功执行,即可进行后面的**3.4**
![捕获436.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661187031048-e575b633-901a-427d-8f3e-ce7c673ae95e.png#averageHue=%23212020&clientId=u1ef706a1-5452-4&from=ui&id=ue5614f23&originHeight=289&originWidth=818&originalType=binary&ratio=1&rotation=0&showTitle=false&size=45382&status=done&style=none&taskId=ub4c8b473-9b96-431c-ae9a-4c051c56f71&title=) + + +## 3.4 核心:修改index.js文件 +前面说过,index.js文件,是用来进行合约调用的"调用命令文件",用户所有可以在Dapp中实现的"获取合约状态信息"和"修改合约状态"的等等操作都在此文件被定义
————先提供一份简单的合约:
**这合约随便写的,你很容易会发现合约没有权限设置,甚至连安全数学都没搞,突出一个离谱**
emmm,你可能还发现第18行代码有错误:应该改为(`balance[msg.sender] = totalSupply`),没有那条下划线......(这里是我故意写错的,目的后面再说) +```javascript +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.16; +interface ERC20 { + function balanceOf(address _address) external view returns (uint); + function transfer(address _receiver, uint amount) external returns (bool success); + event Transfer(address indexed from, address indexed to, uint tokens); +} + +contract fabi01 is ERC20 { + string public name ; + uint public totalSupply ; + uint public decimals; + mapping(address=>uint) balance; + constructor(string memory _name, uint256 _totalSupply) { + name = _name; + decimals = 18; + totalSupply = _totalSupply * 10**decimals; + balance[msg.sender] = _totalSupply; + emit Transfer(address(0), msg.sender, totalSupply); + } + + function balanceOf(address _address) public view returns(uint) { + return(balance[_address]); + } + + function transfer(address _receiver, uint amount) public returns(bool success) { + if(balance[msg.sender] < amount) { + revert("Sorry, your balance is insufficient"); + } + if(balance[msg.sender] >= amount) { + balance[msg.sender] -= amount; + balance[_receiver] += amount; + emit Transfer(msg.sender, _receiver, amount); + return true; + } + } +} +``` +——现在转移至index.js文件进行修改: + +- **首先**,在index.js定义要调用的合约 + +### 3.4.1 定义要调用的合约 +`var myContract = new web3.eth.Contract(合约的ABI文件,合约地址)`
合约的地址和ABI文件前面已经保存了,直接复制粘贴过来即可 +```javascript +var express = require('express'); +var router = express.Router(); + +var Web3 = require('web3'); +var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); + +web3.eth.getAccounts().then(console.log); + +var myContract = new web3.eth.Contract( + [ + { + "inputs": [ + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_totalSupply", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokens", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], '0xad15CF6527970B9769BB6b6b9dF39B7e0f5868d3' +) +``` + +- **后面的修改就完全自由了,取决于合约的具体功能:** +- **我们合约的每种功能都举个例子:** + +### 3.4.2 call方法: +call方法针对的是合约里的"view"和"pure"修饰的状态变量或函数:
`myContract.methods.合约里的函数名(参数1, 参数2...).call({(可选)from:_, gasPrice:_, gasLimit:_}, function(error, result){_}).then((可选:执行其他逻辑)console log)`
其中,call里面的参数可以一个都没有;`function(error, result){_}`,这个是可选的回调函数,其第二个参数为合约方法的执行结果,第一个参数为错误对象的返回值
——说这么多没用,这里直接举两个例子: +```javascript +//example 1 +myContract.methods.name().call({ + //这里的name()函数在合约纸面上是没有定义的,但合约里定义了一个名为name的状态变量,并且用了 + //public去修饰,solidity规定:只要状态变量用public去修饰,就会生成与状态变量同名的函数 + from: '0x475adc73ebec71d14ca6f40350eb920591b006d6', + gasPrice: '4700000', + //from, gasPrice, gasLimit三个参数是可选参数,可以一个都不写 +}, function (error, result) { + console.log(error, result) + //这个function(error, result){___}的执行逻辑是:如果能成功获取到name()的值,error就 + //等于null,console.log(error, result)会打印 null 和 name 的结果;如果前面获取不到 + //name()的返回值,就会将错误传入error,最终程序打印出error的具体信息 +}).then(console.log); //最后这个console.log打印的是name()的结果 + + +//example 2 +myContract.methods.totalSupply().call({ + //想要获取合约内代币的总量 + from: '0x475adc73ebec71d14ca6f40350eb920591b006d6' +}, function (error, result) { + if (error === null) { + console.log("result1:", result) + } +}).then( + //如果上面的部分代码都执行成功,会继续执行合约里的balanceOf(address _address)函数 + myContract.methods.balanceOf('0x4c5b3fc298cc00f2f5a6e06232d403cb9c5bd9ba').call() + //将获取到的代币余额规定为balance参数,以便最后格式化输出该账户的代币余额 + .then(function (balance) { + (console.log("result2:", balance)) + })); +``` +——执行截图:
项目方的余额比总供应量少了18个0(自合约发布起,还没有进行过任何一次转账),这个bug前面提到过了,目的是为了演示上面的js代码具体的运行逻辑是怎样的
那么问题来了:这个项目可操控的合约代币数量(实际总供应量)有多少个呢?答案是只有零点零零零.......二一个,而不是2100万个,异常的稀缺是吧
![捕获99.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661265319545-26c9e91b-e4b0-4483-b934-d155e37fc631.png#averageHue=%23202020&clientId=u37f4934e-7008-4&from=ui&id=u2653a013&originHeight=305&originWidth=645&originalType=binary&ratio=1&rotation=0&showTitle=false&size=38673&status=done&style=none&taskId=uabdfa48a-f7ec-423c-a230-129e8547222&title=)
——你可能会遇到这种截图:
就是输出顺序与"index.js"中的代码顺序是不一致的,这个很正常。因为有".then()"函数的存在,".then()"是要等前面的代码拿到区块链上的数据才被执行的,即异步调用。
![捕获100.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661265736118-54f0a693-e69e-49c2-8af4-e73979613796.png#averageHue=%23212020&clientId=u37f4934e-7008-4&from=ui&id=ue0010526&originHeight=288&originWidth=650&originalType=binary&ratio=1&rotation=0&showTitle=false&size=38685&status=done&style=none&taskId=u8a218f8c-1ba5-4c41-84e2-a08cb82c7c1&title=) + +### 3.4.3 send方法: +只要是需要改变区块链上的状态的,统一都用send,比如本篇用到的合约中的transfer(address _receiver,uint amount)函数,向其他地址发送合约代币,是需要改变"balance"这个状态变量的
——send( )方法与call( )方法类似:
`myContract.methods.合约里的函数名(参数1, 参数2...).send({(必选)from:_, (后面三个为可选)gasPrice:_, gasLimit:_, value:_(这个value指的是发送的ETH的数量,不是合约的代币数量)}, function(error, result){_}).then((可选:执行其他逻辑)console log)`
直接上代码: +```javascript +//example: +myContract.methods.transfer('0x475adc73ebec71d14ca6f40350eb920591b006d6', 10000).send( + { from: '0x4c5b3fc298cc00f2f5a6e06232d403cb9c5bd9ba', + //从 '0x4c5b3fc298cc00f2f5a6e06232d403cb9c5bd9ba' 地址转10000(往前移18个0)个合约代币 + //给'0x475adc73ebec71d14ca6f40350eb920591b006d6' + /*value: '6000000000000000000':这个的意思是可以在一笔交易里既转合约的代币, + 又转ETH,但很尴尬,我这里的合约代码没有写payable相关的函数,无法演示*/ + }).then(console.log); + + +//下面的这几行用来查看'0x475adc73ebec71d14ca6f40350eb920591b006d6'的合约代币余额 +/*但是要注意(很重要):第一次执行的时候地址的代币余额还是0,不会变为10000,因为异步调用的问题,修改合约的状态是需要挖矿的,需要的时间肯定比call方法获取到代币的余额慢,还没等balance状态修改完毕,就已经输出结果了;同样的,第二次执行时代币余额为10000,而不是20000 +*/ +myContract.methods.balanceOf('0x475adc73ebec71d14ca6f40350eb920591b006d6').call() + .then(function (balance) { + console.log("eth.accounts[1]的CHC代币余额是:", balance); + }); +``` +————两次运行对比:
![捕获102.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661269615050-05438e1e-62d4-4bc2-bcfa-c40821ff4cc5.png#averageHue=%23212020&clientId=u37f4934e-7008-4&from=ui&id=u5ec17ad1&originHeight=380&originWidth=686&originalType=binary&ratio=1&rotation=0&showTitle=false&size=63766&status=done&style=none&taskId=u59f1bc97-33bd-4674-ab32-3f219149325&title=)
![捕获103.PNG](https://cdn.nlark.com/yuque/0/2022/png/28544794/1661269621513-b7c4b6a0-a05a-4a8b-8bd0-ffdd7c7dfa60.png#averageHue=%23212120&clientId=u37f4934e-7008-4&from=ui&height=369&id=u8f16b087&originHeight=392&originWidth=730&originalType=binary&ratio=1&rotation=0&showTitle=false&size=89727&status=done&style=none&taskId=u1addf43b-a149-462f-8259-cd88d73ae17&title=&width=688) +