当前位置: 首页 > 工具软件 > Smart.js > 使用案例 >

web3.js基础知识简单汇总

秦城
2023-12-01

使用JavaScript 来开发 DApp时,很多时候需要使用到 web3.js。当然,也可以选择使用ethers.js

 web3基础知识和社区术语:

  • Web3:web3.js 是一个库集合,可以使用 HTTP、IPC 或 WebSocket 与本地或远程以太坊节点进行交互的库。它是以太坊区块链 Ethereum blockchain 和你的智能合约 Smart Contracts 之间的连接。

  • 以太坊 Ethereum:一个去中心化的开源区块链 blockchain,允许用户通过创建智能合约 creating smart contracts 与网络进行交互。它的原生加密货币是以太币。就市值而言,以太币是仅次于比特币的第二大最有价值的加密货币。它由 Vitalik Buterin 于 2013 年创建。

  • 智能合约 Smart Contracts :它们是存储在区块链上的计算机程序 computer programs ,在满足预定条件时运行。智能合约是用 Solidity 语言编写的。

  • 去中心化 Decentralized :数据状态不由中央实体 central entity、平台 platform 或个人 individual 收集

  • 区块链:区块链网络是一种点对点连接,其中信息在多个设备之间共享,几乎不可能被黑客入侵。它是一种记录信息的系统,其方式使得很难或不可能更改保存在网络上的信息。

  • Solidity:一种用于编写智能合约 writing smart contracts 的面向对象 object-oriented 的编程语言。它用于在各种区块链平台上实施智能合约,最著名的是以太坊。Solidity 的语法类似于 javascript。要了解 Solidity,最好有 javascript 等编程语言的背景。直接跳入 Solidity 是一个坏主意

  • Dapp:代表去中心化应用程序 Decentralized App 。它们是在去中心化网络或区块链上运行其后端代码(主要用 Solidity 编写的智能合约)的应用程序。可以使用 react、vue 或 Angular 等前端框架构建 Dapps。

以太坊的节点

整个合约代码的执行需要一个虚拟机环境,所以选择安装一个实现了以太坊虚拟机的节点,EtherumJS TestRPC 它在执行交易时是实时返回,可以快速验证新写的代码,当出现错误时,也能即时反馈

npm install -g ethereumjs-testrpc

通过testrpc命令来启动了,启动与大多数以太坊节点一样,运行在localhost:8545

引入 web3.js

将 web3.js 引入到项目中

//npm
npm install web3

//yarn
yarn add web3

//js
dist/web3.min.js

provider

首先创建一个 web3 的实例,设置一个 provider,可以支持MetaMask(小狐狸),会有提供一个web3.currentProvider 检查 Web3.givenProvider ,如果属性为 null 再连接本地或远程的节点

mist也有一个内置,需要先检查是否web3实例已存在,这样是为了避免重复设置的情况

//引入web3
const Web3 = require('web3');

//检查方法1  Web3.givenProvider 当前环境的原生 provider 会被浏览器设置
//web3.givenProvider 将返回浏览器设置的原生 provider 集,返回 null 再连接本地或远程的节点
const web3 = new Web3(Web3.givenProvider || "ws://localhost:8545");

//检查方法2  
if (typeof web3 !== 'undefined') {
    //创建一个 web3 的实例,返回值 Object: 当前在用的 provider 或者 null;
	web3 = new Web3(web3.currentProvider);
} else {
    //因为不能用于订阅,HTTP provider 官方已经**不推荐使用**
	web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}


//3
if(!web3.currentProvider)
    web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));

Callbacks 

所有函数默认使用同步的HTTP的请求,如果你想发起一个异步的请求。大多数函数允许传一个跟在参数列表后的可选的回调函数来支持异步。回调函数支持error first callback的风格

web3.eth.getBlock(48, function(error, result){
    if(!error)
        console.log(result)
    else
        console.error(error);
})

Promises 

大多数的 web3 对象允许将一个回调函数作为最后一个函数参数传入,同时会返回一个promise 用于链式函数调用。以太坊作为区块链具有不同级别的确定性,因此需要返回一个动作的多个“阶段”,为了满足要求 web3.eth.sendTransaction 函数返回一个“promiEvent” ,PromiEvents 的工作方式与添加了on,onceoff功能的普通 Promise 类似。通过这种方式,开发人员可以监听其他事件,例如“receipt”或“transactionHash”

web3.eth.sendTransaction({from: '0x123...', data: '0x432...'})
.once('transactionHash', function(hash){ ... })
.once('receipt', function(receipt){ ... })
.on('confirmation', function(confNumber, receipt){ ... })
.on('error', function(error){ ... })
.then(function(receipt){
    // will be fired once the receipt is mined
});

json接口

json 接口是描述以太坊智能合约的应用程序二进制接口 (ABI)的 json 对象。

使用这个 json 接口 web3.js 能够使用 web3.eth.Contract 对象创建表示智能合约及其方法和事件的JavaScript 对象

批量请求

可以允许将多个请求放入队列,并一次执行

注意:批量请求并不会更快,在某些情况下,同时发起多个请求,由于是异步的,会变得更快。但这里的批量请求主要目的是用来保证请求的串行执行

//1
var batch = web3.createBatch();
batch.add(web3.eth.getBalance.request('0x0000000000000000
			000000000000000000000000 ', '
			latest ', callback)); 
			batch.add(web3.eth.contract(abi).at(address).balance.request(a ddress, callback2)); batch.execute();

//2

var contract = new web3.eth.Contract(abi, address);

var batch = new web3.BatchRequest();
batch.add(web3.eth.getBalance.request('0x0000000000000000000000000000000000000000', 'latest', callback));
batch.add(contract.methods.balance(address).call.request({from: '0x0000000000000000000000000000000000000000'}, callback2));
batch.execute();

Bloom Filters

布隆过滤器是一种概率性的、节省空间的数据结构,用于快速检查集合成员。型数据集中能够快速测试某个元素当前是否在该集中,可以大大减少我们必须进行的数据库查询的数量

web3.utils

该包为以太坊 dapps 和其他 web3.js 包提供实用功能。是Web3类的静态可访问属性也是Web3实例的属性

使用web3.js编译,发布,调用的完整源码

//源码来源于:http://me.tryblockchain.org/
let Web3 = require('web3');
let web3;

if (typeof web3 !== 'undefined') {
    web3 = new Web3(web3.currentProvider);
} else {
    // set the provider you want from Web3.providers
    web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}

let from = web3.eth.accounts[0];

//编译合约
let source = "pragma solidity ^0.4.0;contract Calc{  /*区块链存储*/  uint count;  /*执行会写入数据,所以需要`transaction`的方式执行。*/  function add(uint a, uint b) returns(uint){    count++;    return a + b;  }  /*执行不会写入数据,所以允许`call`的方式执行。*/  function getCount() constant returns (uint){    return count;  }}";
let calcCompiled = web3.eth.compile.solidity(source);

console.log(calcCompiled);
console.log("ABI definition:");
console.log(calcCompiled["info"]["abiDefinition"]);

//得到合约对象
let abiDefinition = calcCompiled["info"]["abiDefinition"];
let calcContract = web3.eth.contract(abiDefinition);

//2. 部署合约

//2.1 获取合约的代码,部署时传递的就是合约编译后的二进制码
let deployCode = calcCompiled["code"];

//2.2 部署者的地址,当前取默认账户的第一个地址。
let deployeAddr = web3.eth.accounts[0];

//2.3 异步方式,部署合约
let myContractReturned = calcContract.new({
    data: deployCode,
    from: deployeAddr
}, function(err, myContract) {
    if (!err) {
        // 注意:这个回调会触发两次
        //一次是合约的交易哈希属性完成
        //另一次是在某个地址上完成部署

        // 通过判断是否有地址,来确认是第一次调用,还是第二次调用。
        if (!myContract.address) {
            console.log("contract deploy transaction hash: " + myContract.transactionHash) //部署合约的交易哈希值

            // 合约发布成功后,才能调用后续的方法
        } else {
            console.log("contract deploy address: " + myContract.address) // 合约的部署地址

            //使用transaction方式调用,写入到区块链上
            myContract.add.sendTransaction(1, 2,{
                from: deployeAddr
            });

            console.log("after contract deploy, call:" + myContract.getCount.call());
        }

        // 函数返回对象`myContractReturned`和回调函数对象`myContract`是 "myContractReturned" === "myContract",
        // 所以最终`myContractReturned`这个对象里面的合约地址属性也会被设置。
        // `myContractReturned`一开始返回的结果是没有设置的。
    }
});

//注意,异步执行,此时还是没有地址的。
console.log("returned deployed didn't have address now: " + myContractReturned.address);

//使用非回调的方式来拿到返回的地址,但你需要等待一段时间,直到有地址,建议使用上面的回调方式。
/*
setTimeout(function(){
  console.log("returned deployed wait to have address: " + myContractReturned.address);
  console.log(myContractReturned.getCount.call());
}, 20000);
*/

//如果你在其它地方已经部署了合约,你可以使用at来拿到合约对象
//calcContract.at(["0x50023f33f3a58adc2469fc46e67966b01d9105c4"]);

   

 类似资料: