Solidity 智能合约和 Hedera Hashgraph Javascript SDK 集成

问题描述 投票:0回答:1

我正在处理以前工作正常的代码库的问题,但现在它无法按预期工作。

背景 智能合约

JobPost
提供了一个去中心化的职位发布平台,允许用户创建、更新和检索职位列表。它引入了两个事件:JobPostCreated 和 JobPostUpdated,用于在作业创建和更新时发出通知,增强合约的透明度并为链下应用程序提供钩子以对这些更改做出反应。

哈希图 JavaScript 脚本: JavaScript 代码与 Hedera 网络交互,以部署 JobPost 合约并与之交互。

问题 我的问题是,当我尝试发布新职位时,它说该职位已成功创建,但每当我尝试获取 javascript 代码时,它都会返回一个空元素,这意味着该职位似乎未成功发布到区块链及其参数。

源代码片段

智能合约:

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

pragma experimental ABIEncoderV2;

contract JobPost {
    struct Job {
        uint256 jobId;
        string jobTitle;
        string paymentMethod;
        string accountId;
        address account;
    }

    enum paymentMethods {
        CASH,
        DEBIT,
        CREDIT,
        CRYPTO
    }

    event JobPostCreated(
        uint256 jobId,
        string jobTitle,
        string paymentMethod,
        string accountId,
        address account
    );

    event JobPostUpdated(
        uint256 _jobId,
        string _jobTitle,
        string _paymentMethod,
        address _account,
        string _accountId
    );

    // mapping(uint => Job) JobsByIndex;
    mapping(address => Job[]) JobsByAccount;
    uint256 public jobCounter = 0;

    constructor() {}

    function newJobPostByAccount(
        string memory _jobTitle,
        string memory _paymentMethod,
        string memory _accountId
    ) public {
        jobCounter++;
        JobsByAccount[msg.sender].push(
            Job({
                jobId: jobCounter,
                jobTitle: _jobTitle,
                paymentMethod: _paymentMethod,
                accountId: _accountId,
                account: msg.sender
            })
        );

        emit JobPostCreated(
            jobCounter,
            _jobTitle,
            _paymentMethod,
            _accountId,
            msg.sender
        );
    }

    function getOneJobPostByAccount2(
        address _account,
        uint256 _jobId
    )
        public
        view
        returns (
            address account,
            string memory accountId,
            uint256 jobId,
            string memory jobTitle,
            string memory paymentMethod
        )
    {
        // require(_account <= jobCounter);
        Job[] storage jobs = JobsByAccount[_account];
        for (uint256 index = 0; index < jobs.length; index++) {
            if (jobs[index].jobId == _jobId) {
                return (
                    jobs[index].account,
                    jobs[index].accountId,
                    jobs[index].jobId,
                    jobs[index].jobTitle,
                    jobs[index].paymentMethod
                );
            }
        }
    }

    function getOneJobPostByAccount(
        address _account,
        uint256 _jobId
    ) public view returns (Job memory job) {
        // require(_account <= jobCounter);
        Job[] storage jobs = JobsByAccount[_account];
        for (uint256 index = 0; index < jobs.length; index++) {
            if (jobs[index].jobId == _jobId) {
                return (jobs[index]);
            }
        }
        // return (0,"","",0x0);
    }

    function updateJobPostByAccount(
        uint256 _jobId,
        string memory _jobTitle,
        string memory _paymentMethod,
        address _account,
        string memory _accountId
    ) public {
        Job[] storage jobs = JobsByAccount[_account];
        require(_jobId <= jobCounter);
        // require(jobs, "This user does not exist");
        require(jobs.length > 0, "No Job post exists for this user");
        for (uint256 i = 0; i < jobs.length; i++) {
            if (jobs[i].jobId == _jobId) {
                jobs[i].jobTitle = _jobTitle;
                jobs[i].paymentMethod = _paymentMethod;
                jobs[i].account = _account;
                jobs[i].accountId = _accountId;
            }
        }
        emit JobPostUpdated(
            _jobId,
            _jobTitle,
            _paymentMethod,
            _account,
            _accountId
        );
    }

    function getAllJobsByAccount(
        address _account
    ) public view returns (Job[] memory) {
        Job[] storage jobs = JobsByAccount[_account];
        // require(jobs.length > 0, "No Job post exists for this user");
        if (jobs.length > 0) {
            return jobs;
        } else {
            Job[] memory emptyJobs;
            return emptyJobs;
        }
    }
}

Javascript代码

console.clear();
require("dotenv").config({ path: "../.env" });

const {
  Client,
  AccountId,
  PrivateKey,
  Hbar,
  FileCreateTransaction,
  FileAppendTransaction,
  ContractCallQuery,
  ContractCreateTransaction,
  ContractFunctionParameters,
  ContractExecuteTransaction,
} = require("@hashgraph/sdk");
const fs = require("fs");

const Web3 = require("web3");
const web3 = new Web3();

// console.log(process.env.HEDERA_ACCOUNT_ID);
const operatorId = process.env.HEDERA_ACCOUNT_ID;
const operatorKey = PrivateKey.fromStringECDSA(process.env.HEDERA_PRIVATE_KEY);

const bytecode = require("../build/contracts/JobPost.json", "utf8").bytecode;
const abi = require("../build/contracts/JobPost.json", "utf8").abi;
let bytecodeFileId;

const client = Client.forTestnet().setOperator(operatorId, operatorKey);

// Deploy the smart Contract to Hedera (createContractBytecodeFileId + uploadByteCode + instantiateContract)
await deploySmartContract(client, operatorKey, bytecode, 3000000, 10);

// Create a New Job Post
await newJobPostByAccount(
  client,
  contractId,
  operatorId,
  "Job Post #1",
  "CASH"
);

// Get One Job Post By Account
await getOneJobPostByAccount2(
  client,
  "getOneJobPostByAccount2",
  contractId,
  operatorId,
  2
);

async function newJobPostByAccount(
  _client,
  _contractId,
  _accountId,
  _title,
  _paymentMethod,
  _gas = 3000000
) {
  const contractExecTx = await new ContractExecuteTransaction()
    .setContractId(_contractId)
    .setGas(_gas)
    .setFunction(
      "newJobPostByAccount",
      new ContractFunctionParameters()
        .addString(_title)
        .addString(_paymentMethod)
        .addString(_accountId)
    );
  const contractExecSubmit = await contractExecTx.execute(_client);
  const contractExecRx = await contractExecSubmit.getReceipt(_client);
  console.log(contractExecRx);
  console.log(`\nCREATING A NEW JOB POST ======= \n`);
  console.log(`- New Job Post Created: ${contractExecRx.status.toString()}`);
  console.log(`\nRETRIEVE A JOB POST BY ACCOUNT ======= \n`);
}

async function decodeFunctionResult(functionName, resultAsBytes) {
  const functionAbi = abi.find(
    (func) => func.name === functionName && func.type === "function"
  );
  const functionParameters = functionAbi.outputs;
  const resultHex = "0x".concat(Buffer.from(resultAsBytes).toString("hex"));
  const result = await web3.eth.abi.decodeParameters(
    functionParameters,
    resultHex
  );
  return result;
}

async function getOneJobPostByAccount2(
  _client,
  _functionName,
  _contractId,
  _accountId,
  _jobId,
  _gas = 100000,
  _queryPaymentInHBars = 2
) {
  const contractQuery = await new ContractCallQuery()
    //Set the gas for the query
    .setGas(_gas)
    //Set the contract ID to return the request for
    .setContractId(_contractId)
    //Set the contract function to call
    .setFunction(
      _functionName,
      new ContractFunctionParameters()
        .addAddress(AccountId.fromString(_accountId).toSolidityAddress())
        .addUint256(_jobId)
    )
    //Set the query payment for the node returning the request
    //This value must cover the cost of the request otherwise will fail
    .setQueryPayment(new Hbar(_queryPaymentInHBars));

  //Submit to a Hedera network
  const contractExec = await contractQuery.execute(_client);
  // console.log(contractExec);
  console.log(`\nRETRIEVE A JOB POST BY ACCOUNT ======= \n`);
  console.log(
    `- New Job Post Account Owner: ${await contractExec.getString(0)}`
  );
  // console.log(`- New Job Post Created2: ${await contractExec.getString(1)}`)
  console.log(`- New Job Post Title: ${await contractExec.getString(2)}`);
  console.log(
    `- New Job Post Payment Method: ${await contractExec.getString(3)}`
  );
  const res = await decodeFunctionResult(_functionName, contractExec.bytes);
  console.log(res[0]);
  return res[0];
}

控制台输出

下面是已部署合约的链接以及我的控制台输出的内容

👉https://hashscan.io/testnet/contract/0.0.3767523

javascript solidity smartcontracts hedera-hashgraph
1个回答
0
投票

问题在于

AccountId.fromString(_accountId).toSolidityAddress()
的使用。如果您使用实际的 EVM 地址进行更改,JavaScript 代码将按预期工作 (
0xdfad8138e04c7932c26c0a37d3711fa9165704f1
)。

toSolidityAddress()
功能是静态的,不访问网络。因此,它仅适用于非 EVM 本机帐户,将帐户 ID 转换为十六进制值。

例如,这个

0.0.5102042
只是一个具有ED25519密钥的随机帐户,其EVM地址源自帐户ID;它是
0x00000000000000000000000000000000004dd9da
,并且可以离线计算。

在您的情况下,您使用的是 EVM 本机帐户,因此地址是从公钥而不是帐户 ID 派生的,因此无法使用

toSolidityAddress()
函数,因为它将返回不正确的值。

关于行为更改 - 以前可以工作,但现在不行 - 可能是由于第一次使用非 EVM 本机帐户所致。在这种情况下,

toSolidityAddress()
不兼容问题就没有出现。

© www.soinside.com 2019 - 2024. All rights reserved.