Web3js
如何與我的 ropsten 智能合約互動
我已經在網上尋找了幾個小時來了解如何與契約進行互動,但我還沒有找到一種有效的方法來做到這一點。我的合約部署在
0x09B81faA7fB51E5Af79b0241243e58297aC84158
ropsten 網路上。我只想知道如何呼叫我的方法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
- 化妝品:在 Javascript 中,你可以做
json_obj.abi
和json_obj.bytecode
arguments
可選:您可以使用,而不是完全省略arguments: []
- 你的問題:
json_obj.bytecode
已經開始了0x
,所以"0x" + bin
改為bin