Web3js

如何與我的 ropsten 智能合約互動

  • March 19, 2020

我已經在網上尋找了幾個小時來了解如何與契約進行互動,但我還沒有找到一種有效的方法來做到這一點。我的合約部署在0x09B81faA7fB51E5Af79b0241243e58297aC84158ropsten 網路上。我只想知道如何呼叫我的方法

   function getChallengeNumber() public view returns (bytes32) {
       return challengeNumber;
   }

function mint(uint256 nonce, bytes32 challenge_digest) public returns (bool success) {

顯然我可以與 ropsten 進行互動,但我想設置一個腳本,可以找到 PoW 方法“mint”的解決方案,然後在找到解決方案時推送解決方案。

我發現了一堆零散的解釋,但沒有一個接近全面的解釋。我可以通過混音與它互動。我想出瞭如何使用 python 呼叫不改變網路狀態的方法,但我還沒有找到任何方式以可持續的方式與我的合約互動。

任何指導將不勝感激。


建立@goodvibrations 答案。因為我只有一個我正在使用的 JSON 文件,所以我稍微改變了更新方法。

async function deploy(web3, account, gasPrice, contractName, contractArgs) {
   const json_file  = fs.readFileSync(ARTIFACTS_DIR + contractName + ".json", {encoding: "utf8"});
   const json_obj = JSON.parse(json_file);
   const abi = json_obj['abi'];
   const bin = json_obj['bytecode'];
   const contract = new web3.eth.Contract(JSON.parse(abi));
   const options = {data: "0x" + bin}  //arguments: contractArgs}; <-- I got rid of this because my constructor doesn't accept any arguments
   const transaction = contract.deploy(options);
   const receipt = await send(web3, account, gasPrice, transaction);
   return new web3.eth.Contract(JSON.parse(abi), receipt.contractAddress);
}

但現在我得到一個新的錯誤。

(node:5672) UnhandledPromiseRejectionWarning: Error: Provider not set or invalid
   at Object.InvalidProvider (~/node_modules/web3/node_modules/web3-core-helpers/src/errors.js:38:16)
   at RequestManager.send (~/node_modules/web3/node_modules/web3-core-requestmanager/src/index.js:128:32)
   at sendRequest (~/node_modules/web3/node_modules/web3-core-method/src/index.js:705:42)
   at Eth.send [as getGasPrice] (/home/lnielsen/node_modules/web3/node_modules/web3-core-method/src/index.js:726:13)

我誤解了實施嗎?

你可以這樣做:

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

const NODE_ADDRESS  = process.argv[2];
const PRIVATE_KEY   = process.argv[3];
const CONTRACT_NAME = process.argv[4];

const ARTIFACTS_DIR = __dirname + "<path to your bin/abi folder relative to this script>";
const MIN_GAS_LIMIT = 100000; // increase this if necessary

async function scan(message) {
   process.stdout.write(message);
   return await new Promise(function(resolve, reject) {
       process.stdin.resume();
       process.stdin.once("data", function(data) {
           process.stdin.pause();
           resolve(data.toString().trim());
       });
   });
}

async function getGasPrice(web3) {
   while (true) {
       const nodeGasPrice = await web3.eth.getGasPrice();
       const userGasPrice = await scan(`Enter gas-price or leave empty to use ${nodeGasPrice}: `);
       if (/^\d+$/.test(userGasPrice))
           return userGasPrice;
       if (userGasPrice == "")
           return nodeGasPrice;
       console.log("Illegal gas-price");
   }
}

async function getTransactionReceipt(web3) {
   while (true) {
       const hash = await scan("Enter transaction-hash or leave empty to retry: ");
       if (/^0x([0-9A-Fa-f]{64})$/.test(hash)) {
           const receipt = await web3.eth.getTransactionReceipt(hash);
           if (receipt)
               return receipt;
           console.log("Invalid transaction-hash");
       }
       else if (hash) {
           console.log("Illegal transaction-hash");
       }
       else {
           return null;
       }
   }
}

async function send(web3, account, gasPrice, transaction, value = 0) {
   while (true) {
       try {
           const options = {
               to      : transaction._parent._address,
               data    : transaction.encodeABI(),
               gas     : Math.max(await transaction.estimateGas({from: account.address}), MIN_GAS_LIMIT),
               gasPrice: gasPrice ? gasPrice : await getGasPrice(web3),
               value   : value,
           };
           const signed  = await web3.eth.accounts.signTransaction(options, account.privateKey);
           const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction);
           return receipt;
       }
       catch (error) {
           console.log(error.message);
           const receipt = await getTransactionReceipt(web3);
           if (receipt)
               return receipt;
       }
   }
}

async function deploy(web3, account, gasPrice, contractName, contractArgs) {
   const abi = fs.readFileSync(ARTIFACTS_DIR + contractName + ".abi", {encoding: "utf8"});
   const bin = fs.readFileSync(ARTIFACTS_DIR + contractName + ".bin", {encoding: "utf8"});
   const contract = new web3.eth.Contract(JSON.parse(abi));
   const options = {data: "0x" + bin, arguments: contractArgs};
   const transaction = contract.deploy(options);
   const receipt = await send(web3, account, gasPrice, transaction);
   return new web3.eth.Contract(JSON.parse(abi), receipt.contractAddress);
}

async function run() {
   const web3 = new Web3(NODE_ADDRESS);

   const gasPrice = await getGasPrice(web3);
   const account  = web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY);

   const myContract = await deploy(web3, account, gasPrice, CONTRACT_NAME, [arg1, arg2]);
   console.log(CONTRACT_NAME, "deployed at", myContract._address);

   const receipt = await send(web3, account, gasPrice, myContract.mint(arg3, arg4));
   console.log("Mint receipt:", JSON.stringify(receipt, null, 4));

   const challengeNumber = await myContract.methods.getChallengeNumber().call();
   console.log(Web3.utils.hexToAscii(challengeNumber));

   if (web3.currentProvider.constructor.name == "WebsocketProvider")
       web3.currentProvider.connection.close();
}

run();

然後從命令行呼叫它,例如:

node MyScript.js https://ropsten.infura.io/v3/<MyProjectId> <MyPrivateKey> <MyContractName>

經測試:

  • NodeJS v10.16.0
  • Web3.js v1.2.1

注意:

  • 我使用arg1/arg2作為傳遞給契約建構子的參數作為範例,因為您沒有指定有多少以及要將它們設置為什麼值
  • 我使用arg3/arg4作為傳遞給合約mint函式的參數作為範例,因為您沒有指定要將它們設置為的值

參考您更新的問題:

const abi = json_obj['abi'];
const bin = json_obj['bytecode'];
const contract = new web3.eth.Contract(JSON.parse(abi));
const options = {data: "0x" + bin}; // , arguments: contractArgs};
// I got rid of this because my constructor doesn't accept any arguments
  1. 化妝品:在 Javascript 中,你可以做json_obj.abijson_obj.bytecode
  2. arguments可選:您可以使用,而不是完全省略arguments: []
  3. 你的問題:json_obj.bytecode已經開始了0x,所以"0x" + bin改為bin

引用自:https://ethereum.stackexchange.com/questions/80568