实现一个合约请求工具

demo地址

https://web03-1252477692.cos.ap-guangzhou.myqcloud.com/utils/eth-contract-request/index.html

实现

import React, {useMemo, useState} from 'react'
import {config, Contract,ChainId, multicallClient} from "@chainstarter/multicall-client.js";
import {Button, Card, Form, Input, message, Select} from "antd";
import {useConnectWallet} from "../../connectors";
import {useWeb3React} from "@web3-react/core";
import {InjectedConnector} from "@web3-react/injected-connector";
import {getContract} from "../../utils";
import ERC721Abi from "../../ABI/ERC721.json";
import ERC20Abi from "../../ABI/erc20.json";
import ERC1155Abi from "../../ABI/ERC1155.json";

import { Radio, Collapse } from 'antd';
import './index.css'
import {cloneDeep} from "lodash";
import web3 from "web3";
import axios from "axios";
const { Panel } = Collapse;
const { TextArea } = Input;
config({
  defaultChainId: ChainId.MATIC,
  allowFailure: false,
})
export const formatAddress = address => address.slice(0, 6) + '...' + address.slice(-3)

export default function MulticallClient(){
  const [chain, setChain] = useState(ChainId.BSC)
  const connectWallet = useConnectWallet()
  const {account, deactivate, library} = useWeb3React()
  const [contractAddress, setContractAddress] = useState('')
  const [abi, setAbi] = useState([])
  const [abiStr, setAbiStr] = useState("")
  const [readAbi, setReadAbi] = useState([])
  const [writeAbi, setWriteAbi] = useState([])
  const [mode, setMode] = useState('read') // read write

  const getAbiApi = () => {
    const contractAddress_ = contractAddress.toLowerCase()
    return {
      [ChainId.BSC] : `https://api.hecoinfo.com/api?module=contract&action=getabi&address=${contractAddress_}&apikey=YourApiKeyToken`,//去相关区块浏览器注册账号获得YourApiKeyToken
      [ChainId.HECO] : `https://api.hecoinfo.com/api?module=contract&action=getabi&address=${contractAddress_}d&apikey=YourApiKeyToken`,
      [ChainId.ETH] : `https://api.etherscan.io/api?module=contract&action=getabi&address=${contractAddress_}&apikey=YourApiKeyToken`,
      [ChainId.MATIC]: `https://api.polygonscan.com/api?module=contract&action=getabi&address=${contractAddress_}&apikey=YourApiKeyToken`
    }[chain]
  }
  const getAbi = () => {
    if (!web3.utils.isAddress(contractAddress)) {
      return alert("请输入正确的合约地址")
    }
    axios.get(getAbiApi()).then(res => {
      try {
        const abi_ = JSON.parse(res.data.result)
        if (Array.isArray(abi_))
        setAbi(abi_)
      } catch (e){

      }
    })
  }


  useMemo(() => {
    const readAbi_ = []
    const writeAbi_ = []
    for (let i = 0; i < abi.length; i++) {
      if (abi[i].type === 'function') {
        if (abi[i].stateMutability === 'view') {
          readAbi_.push(abi[i])
        } else {
          writeAbi_.push(abi[i])
        }
      }
    }
    setReadAbi(readAbi_)
    setWriteAbi(writeAbi_)
  }, [abi])

  useMemo(() => {
    if (!abiStr){
      setAbi([])
    } else {
      try {
        const abi_ = JSON.parse(abiStr)
        if (Array.isArray(abi_))
          setAbi(abi_)
      }catch (e){

      }
    }
  }, [abiStr])

  const onConnectWallMetaMask = () => {
    const supportedChainIds = []
    for (let i in ChainId) {
      supportedChainIds.push(ChainId[i])
    }
    connectWallet(new InjectedConnector({
      supportedChainIds,
    }), chain).then((res) => {

    })
  }
  const changeAbi = (e) => {
    setAbiStr(e.target.value)
  }
  const changeChain = (e) => {
    setChain(e)
    deactivate()
  }

  const onQuery = (params, method) => {
    console.log(params, method)
    if (!web3.utils.isAddress(contractAddress)) {
      return alert("请输入正确的合约地址")
    }
    const params_ = []
    for (const key in params) {
      params_.push(params[key])
    }
    const contract = new Contract(abi, contractAddress, chain)
    multicallClient([contract[method](...params_)]).then(res => {
      console.log(res)
      const readAbi_ = cloneDeep(readAbi)
      for (let i = 0; i < readAbi_.length; i++) {
        if (readAbi_[i].name === method) {
          readAbi_[i].result = typeof res[0] === 'object' ? JSON.stringify(res[0]) : res[0]
          setReadAbi(readAbi_)
          return
        }
      }
    })
  }

  const onWrite = (params, method) => {
    if (!web3.utils.isAddress(contractAddress)) {
      return alert("请输入正确的合约地址")
    }
    if (!account) {
      return alert("请连接钱包")
    }
    const contract = getContract(library, abi, contractAddress)
    const params_ = []
    for (const key in params) {
      params_.push(params[key])
    }
    contract.methods[method](...params_)
      .send({
        from: account
      })
      .on('receipt', async (_, receipt) => {
        message.success('success')
      })
      .on('error', (err, receipt) => {

      })
  }

  const selectAbi = (abi_) => {
    setAbi(abi_)
    setAbiStr(JSON.stringify(abi_))
  }
  return (
    <div className="contract-show-page">
      <div className="contract-show-box">
        <Select defaultValue={chain} style={{width: 180}} onChange={changeChain}>
          <Select.Option value={ChainId.BSC}>BSC({ChainId.BSC})</Select.Option>
          <Select.Option value={ChainId.ETH}>ETH({ChainId.ETH})</Select.Option>
          <Select.Option value={ChainId.MATIC}>MATIC({ChainId.MATIC})</Select.Option>
          <Select.Option value={ChainId.HECO}>HECO({ChainId.HECO})</Select.Option>
        </Select>
        <p style={{margin: '20px 0 0 0'}}>合约地址:</p>
        <div className="contract-address-input"><Input value={contractAddress} onInput={(e) => setContractAddress(e.target.value)}/>  <Button onClick={getAbi}>getAbi</Button></div>

        <p>ABI: <TextArea rows={5} value={abiStr} onInput={changeAbi}/></p>
        <div className="def-abi-btn">
          <span>选择&nbsp;</span>
          <Button size="small" onClick={() => selectAbi(ERC20Abi)}>ERC20</Button>
          <Button size="small" onClick={() => selectAbi(ERC721Abi)}>ERC721</Button>
          <Button size="small" onClick={() => selectAbi(ERC1155Abi)}>ERC1155</Button>
        </div>
        {
          abi.length > 0 && (
            <>
              <Radio.Group onChange={e => setMode(e.target.value)} value={mode} style={{ marginBottom: 8 }} optionType="button"
                           buttonStyle="solid">
                <Radio.Button value="read">Read</Radio.Button>
                <Radio.Button value="write">Write</Radio.Button>
              </Radio.Group>
              {
                mode === 'read' && (
                  <div>
                    <Collapse >
                      {
                        readAbi.map((item, index) => (
                          <Panel header={item.name} key={index}>
                            <Form
                              name="basic"
                              labelCol={{ span: 8 }}
                              wrapperCol={{ span: 16 }}
                              initialValues={{ remember: true }}
                              onFinish={(e) => onQuery(e, item.name)}
                              autoComplete="off"
                            >
                              {
                                item.inputs.map((it, idx) => (
                                  <div style={{marginBottom: '10px'}} key={idx}>
                                    <p>{it.name}({it.type})</p>
                                    <Form.Item name={idx} valuePropName="value" required>
                                      <Input ploceholder={`${it.name}(${it.type})`}/>
                                    </Form.Item>
                                  </div>
                                ))
                              }
                              <Button htmlType="submit">Query</Button>
                              {item.result && <p>{item.result}</p>}
                            </Form>
                          </Panel>
                        ))
                      }
                    </Collapse>
                  </div>
                )
              }
              {
                mode === 'write' && (
                  <div>
                    {
                      !account ? (
                        <Button type="dashed" onClick={onConnectWallMetaMask} danger>连接钱包</Button>
                      ) : <p style={{color: '#1890FF'}}>已连接:{formatAddress(account)}</p>
                    }
                    <Collapse>
                      {
                        writeAbi.map((item, index) => (
                          <Panel header={item.name} key={index}>
                            <Form
                              name="basic"
                              labelCol={{ span: 8 }}
                              wrapperCol={{ span: 16 }}
                              initialValues={{ remember: true }}
                              onFinish={(e) => onWrite(e, item.name)}
                              autoComplete="off"
                            >
                              {
                                item.inputs.map((it, idx) => (
                                  <div style={{marginBottom: '10px'}} key={idx}>
                                    <p>{it.name}({it.type})</p>
                                    <Form.Item required name={idx} valuePropName="value">
                                      <Input ploceholder={`${it.name}(${it.type})`}/>
                                    </Form.Item>
                                  </div>
                                ))
                              }
                              <Button htmlType="submit" type="primary">Write</Button>
                              {item.result && <p>{item.result}</p>}
                            </Form>
                          </Panel>
                        ))
                      }
                    </Collapse>
                  </div>
                )
              }
            </>
          )
        }
      </div>
    </div>
  )
}

在一些没认证的合约,区块链浏览器不显示,但是知道它的abi的话,通过此工具调用是很不错的

### 回答1: 下面是一个简单的 Hyperledger Fabric 2.0 Go语言链码示例: ``` package main import ( "fmt" "github.com/hyperledger/fabric-chaincode-go/shim" pb "github.com/hyperledger/fabric-protos-go/peer" ) // SimpleChaincode example simple Chaincode implementation type SimpleChaincode struct { } func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { fmt.Println("ex02 Init") _, args := stub.GetFunctionAndParameters() var A, B string // Entities var Aval, Bval int // Asset holdings var err error if len(args) != 4 { return shim.Error("Incorrect number of arguments. Expecting 4") } // Initialize the chaincode A = args[0] Aval, err = strconv.Atoi(args[1]) if err != nil { return shim.Error("Expecting integer value for asset holding") } B = args[2] Bval, err = strconv.Atoi(args[3]) if err != nil { return shim.Error("Expecting integer value for asset holding") } fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) // Write the state to the ledger err = stub.PutState(A, []byte(strconv.Itoa(Aval))) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(B, []byte(strconv.Itoa(Bval))) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { fmt.Println("ex02 Invoke") function, args := stub.GetFunctionAndParameters() if function == "invoke" { // Make payment of X units from A to B return t.invoke(stub, args) } else if function == "delete" { // Deletes an entity from its state return t.delete(stub, args) } else if function == "query" { // the old "Query" is now implemtned in invoke return t.query(stub, args) } return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"") } // Transaction makes payment of X units from A to B func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response { var A, B string // Entities var Aval, Bval int // Asset holdings var X int // Transaction value var err error ### 回答2: Hyperledger Fabric 是一个开源的区块链平台,可以用于构建企业级的去中心化应用程序。而 Hyperledger Fabric 2.0 是其最新版本,引入了许多新特性和改进。 编写一个 Hyperledger Fabric 2.0 的 Go 语言链码需要按照一定的流程进行: 1. 准备开发环境:首先,需要安装 Go 语言的开发环境和 Hyperledger Fabric 的相关工具,如 Hyperledger Fabric SDK 和 Hyperledger Fabric CA。 2. 编写链码逻辑:使用 Go 语言编写链码的逻辑,链码是在 Hyperledger Fabric 上运行的智能合约。可以根据项目需求和业务逻辑定义相关的数据结构和函数。 3. 定义链码接口:需要定义链码接口,包括 Init 和 Invoke 两个核心函数。Init 函数用于链码的初始化操作,而 Invoke 函数用于链码的业务逻辑执行。 4. 部署链码:将编写好的链码部署到 Hyperledger Fabric 网络中。可以使用 Hyperledger Fabric SDK 提供的工具和 API 来进行链码的部署操作。 5. 测试链码:编写相应的测试用例,对链码逻辑进行测试。可以使用模拟的 Fabric 网络进行测试,或者与实际的 Fabric 网络交互进行测试。 6. 部署链码应用程序:将编写好的链码应用程序部署到 Hyperledger Fabric 网络上。可以使用 Hyperledger Fabric SDK 提供的工具和 API 来进行链码应用程序的部署操作。 Go 语言是一种高性能的编程语言,适合于开发区块链平台和链码。编写 Hyperledger Fabric 2.0 的 Go 语言链码需要熟悉 Go 语言的基本语法和特性,以及了解 Hyperledger Fabric 的相关知识。通过合理的设计和编码,可以实现各种复杂的业务逻辑和功能。 ### 回答3: 编写一个Hyperledger Fabric 2.0的Go语言链码可以分为以下几个步骤: 1. 准备开发环境:首先,需要在开发机器上安装Go语言和Hyperledger Fabric的相关依赖。可以通过配置Golang环境变量,并使用Golang包管理器安装Fabric的Go SDK。 2. 创建链码项目:使用Go语言的IDE或文本编辑器创建一个新的文件夹,作为链码项目的根目录。 3. 定义链码结构:创建一个新的Go文件,并定义链码结构。链码结构应该实现fabric的Chaincode接口,并实现Init和Invoke两个方法。 4. 实现Init方法:Init方法在链码被实例化时调用,并进行初始化设置。可以在该方法中初始化链码的状态数据和其他必要的准备工作。 5. 实现Invoke方法:Invoke方法在链码接收到调用请求时被调用。在该方法中处理具体的业务逻辑,并根据请求中的操作类型执行相应的操作。 6. 将链码打包:使用Fabric提供的命令行工具将链码打包成压缩文件,以便于后续部署和安装。 7. 部署和安装链码:使用Fabric提供的链码生命周期管理工具,将链码部署到指定的Fabric网络中,并安装到指定的通道上。 8. 实例化链码:在指定的通道上实例化链码,使其可以被其他参与方调用。 9. 调用链码:使用Fabric提供的客户端SDK或命令行工具,向链码发送调用请求,验证链码的功能和逻辑是否正确。 10. 测试链码:编写一些测试用例,用于对链码的功能和性能进行验证。 以上是一个简要的步骤,编写Hyperledger Fabric 2.0的Go语言链码还需要进一步了解链码开发的相关知识和Fabric的API,以有效地实现业务逻辑,并与Fabric网络进行交互。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值