新公司入职以来一直在做dapp,学习了不少区块链相关的知识,做个笔记,防止以后忘了。
1.合约初始化
开发时,通常负责合约的同事会给前端一个abi文件和一串合约地址,地址是一串hesh,比如:0x4E0fa131e95b71d7932115a451737a960841B78d,在咱们初始化合约的时候,它用来匹配在区块链上运行的合约。
我理解上,合约开发和后端开发其实差不多,区块链上运行的合约就像服务器上运行的后端程序,合约地址即后端服务地址
abi文件是一个json文件,比如:
[
{ "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, { "indexed": true, "internalType": "address", "name": "spender", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Approval", "type": "event" },]
它描述了这个合约有哪些前端可以调用的方法(具体参数解释请自行查阅资料)。
有了abi和合约地址以后,我们就可以初始化合约了,以我用的web3为例:
import Web3 from 'web3'
// 初始化钱包对象,providAddress代表区块链的服务器地址,比如以太坊主链的地址是www.xxx....等
// 有关主链的概念,不懂请自行查阅资料
const web3 = new Web3(providAddress)
// 通过上一个步骤,得到web3对象,代表我们已经连上主链,下一步是要找到主链上运行的我们项目的合约
// contractAddress就是合约地址,
const managerContract = Web3.eth.Contract(abi, contractAddress)
// 合约初始化完毕
managerContract就是我们需要的合约对象了,具体调用不细说了。
2.钱包
通常dapp应用都是基于metamask开发的,少部分还兼容其他钱包,这里只以metamask为例,不管是pc浏览器钱包插件还是移动端钱包内置浏览器,目前运行环境基本一致,所以咱只要需要查看metamask的API就行了。
提醒:在此之前,建议稍微了解一下浏览器插件的工作原理和一些区块链的基础概念。
在浏览器钱包插件安装之后,每次页面加载,钱包会向页面注入web3信息,让页面可以获取用户的钱包信息,比如各种代币余额和地址,具体请查看metamask api文档(他们的文档迭代很快。。。坑了我不少次)
重要提示1:钱包插件向浏览器页面注入信息需要时间。
它和页面本身的初始化是异步的,有可能页面初始化完毕,我们创建合约的时候,钱包还没有初始化完毕,那么我们在调用合约的时候会出现一些奇怪的问题,比如:报错,提示你钱包地址不存在。。。
只要你初始化合约的时候,钱包没有初始化完毕,就会有这个问题,和你调用合约的时间无关。解决的办法也简单,每次调用的合约的时候,重新初始化一次就可以(Web3.eth.Contract)
这里需要注意的是,window.onload是没用的。
3.发起交易
有两种方式:
1、只需要地址,发起交易需要用户钱包弹窗确认交易,最常用,不多说。
2、使用密匙发起交易,这个前端很少用,因为用到它就表示密匙要出现在前端,这太危险了,这里贴一下交易代码,当时找了很多都不管用
const Tx = require('ethereumjs-tx');const Web3Utils = require('web3-utils');
let nonce = await web3.eth.getTransactionCount( adminAddress, // 发起交易的账户地址 'pending' );
web3.eth.sendTransaction( { from: adminAddress, // 转账的账户 to: address2, // 收款的账户 value: Web3Utils.toHex(value * window.defaultUnit), // 转账的数额,defaultUnit通常是pow(10,18),不懂请查询:代币基础单位wei gas: Web3Utils.toHex(1000000), // 不懂gas和gasprice请自行查阅资料 gasPrice: Web3Utils.toHex(1000000000), nonce: Web3Utils.toHex(nonce), data: managerContract.methods .someMethods(parameter) // 发起交易的具体合约方法 .encodeABI(); }, setIn );
// 监听交易结果 async function setIn(err, hashTx) { if (err != null) { fn(err, null); } web3.eth.getTransactionReceipt(hashTx, (err2, res) => { if (err2 != null || res != null) { fn(err2, res); } else { setTimeout(() => { setIn(null, hashTx); }, 50); } }); }
有点记不清了,有什么问题可以留言呀,这玩意资料太少了,基本要翻墙找,出问题就头疼。