IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 区块链 -> 探究与以太坊智能合约的交互调用 -> 正文阅读

[区块链]探究与以太坊智能合约的交互调用

概述

智能合约是部署在区块链上的一串代代码,通常我们与智能合约的打交道 可以通过前端的Dapp,etherscan,metamask 等方式。作为开发人员可以通过调用提供的相关包来与之交互,如web3.js,ether.js , web3.j(java 语言的包)。那么能否绕过这些东西直接与链发生交互呢?当然可以!
首先来了解第一个概念,区块链节点
任何一台计算机(能联网,且配置够),都可以启动以太坊的客户端来加入区块链,加入后这个节点会同步整个链上的状态,即通过这个节点就可以获取整个链的状态以及通过这个节点可以改变的状态。
第二个,智能合约。简而言之,智能合约是在节点上部署的代码,用户调用时会在节点上执行。
第三个,jsonrpc。jsonrpc 是一个远程调用的协议规范,规定了交互时的入参和出参的格式要求。
jsonrpc中文文档

后面以这个,合约代码为示例演示交互

// SPDX-License-Identifier: MIT
pragma solidity =0.8.4;

contract Test {
    uint256 private value;


    function setValue(uint256 _value) public {
        value = _value;
    }

    function getValue() public view returns(uint256){
        return value;
    }
    
}

使用remix 与合约交互

在这里插入图片描述

通过 remix 部署后会出现,可以调用的函数名。这种是最基础的用法

但是当页面刷新后,左下角的可调用的函数名就没了,这种情况下就需要使用 At Address这个按钮了
![[Pasted image 20220402120058.png]]

在代码框只需要提供要调用合约方法的接口,再将要调用的合约放入 At Address的框里,点击按钮,就会出现接口中的方法。这种就是不要合约的实现,只知道方法接口和地址就可以调用了。
合约调用的最核心就是两个东西,一个是部署后的合约地址,另外一个就要方法的接口也就是ABI

使用ethscan 与智能合约交互

另外一种与合约交互的方式,是通过ethscan。这种的前提是,合约代码已经在ethscan上进行开源过了。
![[Pasted image 20220402135533.png]]

其中 Read Contact 是读方法,不需要消耗gas.
Write Contact 是写方法,调用这些方法会改变链上的状态,会消耗gas.

使用web3.js 与合约交互

再有就是通过web3.js 的库进行交互

var fs = require('fs');

var Web3 = require('web3');

const infuraKey = fs.readFileSync("../.infuraKey").toString().trim();

var ethRpcUrl = `https://rinkeby.infura.io/v3/`+infuraKey

var web3 = new Web3(ethRpcUrl);

  

abi = [

{

"inputs": [],

"name": "getValue",

"outputs": [

{

"internalType": "uint256",

"name": "",

"type": "uint256"

}

],

"stateMutability": "view",

"type": "function"

},

{

"inputs": [

{

"internalType": "uint256",

"name": "_value",

"type": "uint256"

}

],

"name": "setValue",

"outputs": [],

"stateMutability": "nonpayable",

"type": "function"

}

]

address = "合约地址"

pk = "钱包私钥"

  

main()

	.then(() => process.exit(0))
	
	.catch(error => {
	
	console.error(error);
	
	process.exit(1);

});

  

async function getValue(){

	var contract = new web3.eth.Contract(abi, address);
	
	var value = await contract.methods.getValue().call();
	
	console.log(value);

}

  
  

async function setValue(){

	value = 123
	
	var contract = new web3.eth.Contract(abi, address);
	
	var encodeABI = await contract.methods.setValue(value).encodeABI();
	
	var signResult = await web3.eth.accounts.signTransaction({
	
	gas: 3000000,
	
	to: address,
	
	data: encodeABI
	
	}, pk);
	
	console.log(signResult);
	
	var result = await web3.eth.sendSignedTransaction(signResult.rawTransaction);
	
	console.log(result);
	
	  

}

  

async function main(){

	await setValue();
	
	await getValue();

}

使用http 请求与智能合约交互

ethreum json rpc API

上面这几种方式都是比较常规的,接下展示一种非常规的操作,即通过http请求来交互

var fs = require('fs');

const fetch = require('node-fetch')

var Web3 = require('web3');

const ethers = require('ethers');

const infuraKey = fs.readFileSync("../.infuraKey").toString().trim();

var ethRpcUrl = `https://rinkeby.infura.io/v3/`+infuraKey

var web3 = new Web3(ethRpcUrl);

abi = [

{

"inputs": [],

"name": "getValue",

"outputs": [

{

"internalType": "uint256",

"name": "",

"type": "uint256"

}

],

"stateMutability": "view",

"type": "function"

},

{

"inputs": [

{

"internalType": "uint256",

"name": "_value",

"type": "uint256"

}

],

"name": "setValue",

"outputs": [],

"stateMutability": "nonpayable",

"type": "function"

}

]

contractAddress = "合约地址"

pk = "钱包私钥"

userAccount = "私钥对应的账户地址"

main()

.then(() => process.exit(0))

.catch(error => {

console.error(error);

process.exit(1);

});

  

async function main(){

	await setValue();
	
	await getValue();

}

  
  

async function getNonce(account){

	let nonce = await web3.eth.getTransactionCount(account);
	
	console.log('nonce = ', nonce)
	
	return nonce;

}

  

async function getValue(){

	// 对方法进行sha3编码,然后取前四个字节
	
	// var methodSign = await web3.utils.keccak256("getValue()").substr(0, 10);
	
	var methodSign = await web3.utils.keccak256("getValue()").substr(0, 10);
	
	  
	
	// console.log(methodSign)
	
	data = methodSign;
	
	// 如果有入参,对入参进行编码
	
	// encodeParams = web3.eth.abi.encodeParameters(['uint256'],[456]);
	
	// 拼接方法名和入参作为jsonrpc的 params中的data字段的数据
	
	// data +=encodeParams.substr(2,encodeParams.length)
	
	console.log(data)
	
	// 构造post 请求的body参数
	
	var input = {"jsonrpc":"2.0","id":3,"method":"eth_call","params":[{"to":contractAddress,"data":data},"latest"]}
	
	// http 可以一次多个请求
	
	var inputs = [input,input]
	
	// 发送post请求
	
	const resp = await fetch(ethRpcUrl, {
	
		method: "POST",
		
		body: JSON.stringify(inputs),
		
		headers: {
		
		"Content-Type": "application/json"
	
	}
	
	});
	
	var rpcResult = await resp.json();
	
	console.log(rpcResult[0].result)
	
	// 用 ethers包中的方法解析返回结果
	
	var ethersResult = await ethers.utils.defaultAbiCoder.decode(['uint256'], rpcResult[0].result)
	
	// 用 web3包中的方法解析防护结果
	
	var decodeResult = await web3.eth.abi.decodeParameters(['uint256'], rpcResult[0].result);
	
	console.log("vaule is "+ethersResult)
	
	console.log("value is "+decodeResult[0])

  

}

  

async function setValue(){

	// 这里借用web3的方法对要发送的内容进行签名
	var contract = new web3.eth.Contract(abi, contractAddress);
	
	value = 456;
	
	var encodeABI = contract.methods.setValue(value).encodeABI();
	
	var signResult = await web3.eth.accounts.signTransaction({
	
	gas: 3000000,
	
	to: contractAddress,
	
	data: encodeABI,
	
	nonce: await getNonce(userAccount)
	
	}, pk);
	
	console.log(signResult);
	
	rawTransaction = signResult.rawTransaction
	
	// 构造post 请求的body参数
	
	var input = {"jsonrpc":"2.0","id":3,"method":"eth_sendRawTransaction","params":[rawTransaction]}
	
	console.log(input)
	
	var inputs = [input]
	
	// 发送post请求
	
	const resp = await fetch(ethRpcUrl, {
	
		method: "POST",
		
		body: JSON.stringify(inputs),
		
		headers: {
		
		"Content-Type": "application/json"
		
		}
	
	});
	
	var rpcResult = await resp.json();
	
	console.log(rpcResult)

}

通过jsonrpc 方式,可以更灵活的与合约进行交互,只要拿到别人的签名信息,只发http请求就可以和链进行交互,至于是谁发送的这个http,就关系不大了。

综述

不管是remix 、etherscan 还是web3.js 这几种方式,本质上都是对jsonrpc方法封装。理解它们的底层交互逻辑,可以让我们更深刻的认识这些技术,从而发现它们还是我们日常使用的http请求,也就没有那么神秘了。

  区块链 最新文章
盘点具备盈利潜力的几大加密板块,以及潜在
阅读笔记|让区块空间成为商品,打造Web3云
区块链1.0-比特币的数据结构
Team Finance被黑分析|黑客自建Token“瞒天
区块链≠绿色?波卡或成 Web3“生态环保”标
期货从入门到高深之手动交易系列D1课
以太坊基础---区块验证
进入以太坊合并的五个数字
经典同态加密算法Paillier解读 - 原理、实现
IPFS/Filecoin学习知识科普(四)
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:27:32  更:2022-04-09 18:27:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:16:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码