网络公关公司排名,东莞短视频seo需要多少钱,网上卖货软件,娄底网站建设公司有哪些# 概述 智能合约是部署在区块链上的一串代代码#xff0c;通常我们与智能合约的打交道 可以通过前端的Dapp#xff0c;etherscan#xff0c;metamask 等方式。作为开发人员可以通过调用提供的相关包来与之交互#xff0c;如web3.js#xff0c;ether.js , web3.j(java 语言…# 概述 智能合约是部署在区块链上的一串代代码通常我们与智能合约的打交道 可以通过前端的Dappetherscanmetamask 等方式。作为开发人员可以通过调用提供的相关包来与之交互如web3.jsether.js , web3.j(java 语言的包)。那么能否绕过这些东西直接与链发生交互呢当然可以 首先来了解第一个概念区块链节点 任何一台计算机能联网且配置够都可以启动以太坊的客户端来加入区块链加入后这个节点会同步整个链上的状态即通过这个节点就可以获取整个链的状态以及通过这个节点可以改变的状态。 第二个智能合约。简而言之智能合约是在节点上部署的代码用户调用时会在节点上执行。 第三个jsonrpc。jsonrpc 是一个远程调用的协议规范规定了交互时的入参和出参的格式要求。[jsonrpc中文文档](https://wiki.geekdream.com/Specification/json-rpc_2.0.html)
后面以这个合约代码为示例演示交互 javascript // 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 与合约交互
![[Pasted image 20220402114639.png]]
通过 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 的库进行交互 javascript 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](https://eth.wiki/json-rpc/API)
https://eth.wiki/json-rpc/API 上面这几种方式都是比较常规的接下展示一种非常规的操作即通过http请求来交互
javascript 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请求也就没有那么神秘了。