web3使用web3.js发布并执行智能合约

Posted 前端开发小陈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了web3使用web3.js发布并执行智能合约相关的知识,希望对你有一定的参考价值。

前言

昨天我们学习了使用 web3.js 库查询链上区块和交易的用法,今天我们来介绍一下使用 web3.js 与智能合约的交互。在学习本节前,你应该对智能合约有一定的了解。

智能合约的生命周期包括 创建发布执行 以及 销毁

  • 创建:在 Remix 中编写智能合约,编译生成 ABI 和 字节码文件。
  • 发布:对应 Remix 中的 Deploy 按钮的功能,也即 web3.js 中合约实例上的 deploy 方法。
  • 执行:对应web3.js 中合约实例上的 callsend 方法。
  • 销毁:在合约中使用 destruct(address) 方法销毁指定合约。

因此我们在使用 web3.js 与合约交互时也包括这几个步骤。

与合约交互

应用程序二进制接口(ABI)

应用程序二进制接口(ABI)相当于智能合约暴露出来的标准接口,通过这个接口可以将智能合约转换为别的应用程序中的对象实例。通过这个对象实例就可以与智能合约进行交互。

💡 ABI对象实例

  • 函数(functions)* type:函数类型。默认为 function ,也可能是 constructor* stateMutability:状态可变性。* payable* nonpayable* view* pure* inputs,outputs:函数输入输出的参数列表* name:函数名称* 事件(events)* type:event* inputs:输入对象列表,包括 name , type , indexed* anonymous:是否为匿名的

创建合约

在一个合约中,我们可以编写的内容:函数,结构体,构造函数,状态变量,事件,枚举类型等。一个合约想要部署到区块链,需要编译为字节码文件;一个合约想要被外部的应用程序(如DApp)访问,则需要编译为ABI文件,供应用程序调用。

  • 部署合约* 区块链上已经部署了智能合约,通过代码将JS中的合约与链上合约进行关联与交互。* 直接通过JS代码在区块链上部署一个新合约。

💡 部署新合约

  • new web3.eth.Contract(abi[, address]) 创建一个合约对象。* [contract].deploy() 部署合约:// 该过程等价于在Remix上部署合约const abi = [ "inputs": [ "internalType": "uint256", "name": "_number", "type": "uint256" ], "name": "setNumber", "outputs": [], "stateMutability": "nonpayable", "type": "function" , "inputs": [], "name": "getNumber", "outputs": [ "internalType": "uint256", "name": "", "type": "uint256" ], "stateMutability": "view", "type": "function" ]const contract = new web3.eth.Contract(abi, address)const data = '608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80633fb5c1cb1461003b578063f2c9ecd814610057575b600080fd5b6100556004803603810190610050919061009d565b610075565b005b61005f61007f565b60405161006c91906100d9565b60405180910390f35b8060008190555050565b60008054905090565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea26469706673582212206d42283bc640e62ba9095ff6f78d7e4a75272960a2332eff853e9968295e534664736f6c63430008070033' // The data field must be HEX encoded data.contract.deploy(data,).send(from: '0x539CDB50CC507bF167e205d10Df87cd8c1827Af6',gas: 1000000, // GAS LIMITgasPrice: '120000', (err, res) => console.log('res', err, res) // 返回transaction的hash) #### 💡 与链上合约进行关联与交互
const address = '0x8B48aF1b46eFE178014CdD6c90f3DdfbDABC6d67' // 合约部署地址
const myContract = new web3.eth.Contract(abi, address)
console.log(myContract) 

调用合约函数

  • [contract].methods.[myMethod([params...])].call(options[, defaultBlock, callback]) 调用智能合约读(pure/view)函数。* params:函数的参数* options-Object(可选):* from-String(可选):调用交易的地址。* gasPrice(可选):交易的每个gas的价格。* gas(可选):交易的gas限制。
  • [contract].methods.[myMethod([params...])].send(options[, defaultBlock, callback]) 调用写函数,相当于发送了交易。* send方法的options-Object:* from-String:发送人地址* 返回结果触发事件:* transactionHash-String:发送交易且得到交易哈希值后立即触发。* receipt-Object:当收到交易收据时触发。合约收据带有的不是 logs ,而是以事件名为键,以事件本身为属性值的 events 。* confirmation-Number/Object:从区块被挖到的第一个区块确认开始,每次确认都会触发,直到第24次确认。触发时第一个参数为收到的确认数,第二个参数为收到的交易收据。* error:交易发送过程中出错时触发。如果交易被网络拒接且带有交易收据,第二个参数就是该交易收据。
const Web3 = require('web3')

let web3;
if (typeof web3 !== 'undefined') web3 = new Web3(web3.currentProvider);
 else // set the provider you want from Web3.providersweb3 = new Web3(new Web3.providers.HttpProvider("<http://localhost:7545>"));


const abi = [
	
		"inputs": [
			
				"internalType": "uint256",
				"name": "_number",
				"type": "uint256"
			
		],
		"name": "setNumber",
		"outputs": [],
		"stateMutability": "nonpayable",
		"type": "function"
	,
	
		"inputs": [],
		"name": "getNumber",
		"outputs": [
			
				"internalType": "uint256",
				"name": "",
				"type": "uint256"
			
		],
		"stateMutability": "view",
		"type": "function"
	
]
const address = '0xf935e846633aF4b9079c8a63d4d3D5203d437ae1' // 合约部署地址
const myContract = new web3.eth.Contract(abi, address)

myContract.methods.setNumber(123).send(
	from: '0x73538146481643a4bAE6D5A97a407018c14E20C5'
).on('receipt', (data) => 
	console.log(data)
)

myContract.methods.getNumber().call((err, res) => 
	console.log(res)
) 

调用合约事件

事件:将输入参数记录到日志信息中

  • 区块链是一个由区块组成的列表,这些块的内容基本上时交易记录。每个交易都有一个附加的交易日志,事件结果存放在交易日志里。合约发出的事件,可以使用合约地址访问。
  • [myContract].getPastEvents(filter, config[, callback]) 执行事件查询。

总结

现在你已经正式踏入区块链前端的范畴,甚至能够开发简单的 DApp程序。接下来我将会介绍简单使用 Solidity 编写合约,并学习使用 hardhat 框架进行区块链开发。

最后

最近找到一个VUE的文档,它将VUE的各个知识点进行了总结,整理成了《Vue 开发必须知道的36个技巧》。内容比较详实,对各个知识点的讲解也十分到位。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

Web3js - 部署后立即返回智能合约地址

【中文标题】Web3js - 部署后立即返回智能合约地址【英文标题】:Web3js - Return smart contract address immediately after deployment 【发布时间】:2019-03-22 16:11:18 【问题描述】:

我有一个使用 Web3.js 包部署的智能合约。我有一个名为deploySmartContract() 的函数,它可以执行此操作,并且我希望此方法将合约地址返回给调用函数。以下是deploySmartContract() 的 sn-p -

function deploySmartContract(shareName, symbol, maxSupply) 
    var _shareName = shareName;
    var _symbol = symbol;
    var _maxSupply = maxSupply;
    var contractAddr = '';

    var sharesregistry = contractObj.new(
        _shareName,
        _symbol,
        _maxSupply,
        
            from: primaryAccount, 
            data: byteCode, 
            gas: '5000000'
        , function (e, contract)
            console.log(e, contract);
            if (typeof contract.address !== 'undefined') 
                console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
            
        
    );
    console.log(sharesregistry.address);

    return sharesregistry;

除非整个交易完成并在合约被挖掘时执行 return,否则我如何才能让我的 return 语句等待?否则我在调用函数中得到的只是shareregistry 对象的骨架。

在这里,我确认这段代码完美地部署了智能合约。

【问题讨论】:

【参考方案1】:

Checkout API new 方法以及如何同步和异步调用它。您提供了回调函数,这意味着您可以异步运行它。通过删除它,您会强制它等待结果。

【讨论】:

以上是关于web3使用web3.js发布并执行智能合约的主要内容,如果未能解决你的问题,请参考以下文章

使用 web3 js 调用智能合约函数

再深刻理解下web3.js中estimateGas如何计算智能合约消耗的gas量

通过 web3.js 调用智能合约函数没有响应

Web3.js的基本使用(与以太坊智能合约的交互)

部署智能合约时出现节点错误 - Web3.js

在 Web3.js 中使用本地私钥