Web3js
web3 - 在 Ropsten Infura 上使用 @truffle/contract 呼叫 sendTransaction 時出錯
我的智能合約已經部署在由 Infura 提供的 Ropsten TestNet 上
0x63865E0F065C7b865e1a2EE4d99C383A414Bec22
。我想使用 NodeJS(v.10.16.1) + Web3(v.1.2.6) + @truffle/contract (v.4.1.11) 發送事務。這是我的 NodeJS 程式碼 -var express = require('express'); var app = express(); var bodyParser = require('body-parser'); var session = require('express-session'); var Web3 = require('web3'); var contract = require("@truffle/contract"); var path = require('path'); var MyContractJSON = require(path.join(__dirname, 'build/contracts/contract.json')); var provider = new Web3.providers.HttpProvider("https://ropsten.infura.io/v3/PROJECT_ID"); var MyContract = contract(MyContractJSON); MyContract.setProvider(provider); const contract_address = "0x63865E0F065C7b865e1a2EE4d99C383A414Bec22"; app.post("/register", function(req, res){ var newUser = req.body.username; var account = req.body.account; req.session.currentUser = account; MyContract.at(contract_address).then(function(instance) { return instance.registerUser.sendTransaction(newUser, {from: account}); }).then(function(result) { console.log(result); res.render("dashboard", {name: newUser, account: account}); }).catch(function(error) { console.log(error); res.redirect("/"); }); });
我收到此錯誤-
sendTransaction
Error: Returned error: The method eth_sendTransaction does not exist/is not available\n at Object.ErrorResponse (...\\node_modules\\web3-core-helpers\\src\\errors.js:29:16)\n at ...\\node_modules\\web3-core-requestmanager\\src\\index.js:140:36\n at XMLHttpRequest.request.onreadystatechange (...\\node_modules\\web3\\node_modules\\web3-providers-http\\src\\index.js:110:13)\n at XMLHttpRequestEventTarget.dispatchEvent (...\\node_modules\\xhr2-cookies\\dist\\xml-http-request-event-target.js:34:22)\n at XMLHttpRequest._setReadyState ...\\node_modules\\xhr2-cookies\\dist\\xml-http-request.js:208:14)\n at XMLHttpRequest._onHttpResponseEnd (...\\node_modules\\xhr2-cookies\\dist\\xml-http-request.js:318:14)\n at IncomingMessage.<anonymous> (...\\node_modules\\xhr2-cookies\\dist\\xml-http-request.js:289:61)\n at IncomingMessage.emit (events.js:203:15)\n at endReadableNT (_stream_readable.js:1145:12)\n at process._tickCallback (internal/process/next_tick.js:63:19)'
我正在使用Metamask (v.7.7.8) 並通過
express-session
. 我知道Infura不支持sendTransaction
,但**@truffle/contract**也不支持sendRawTransaction
。請幫助我使用@truffle/contract 找到更簡單的解決方案。
我根據您在評論中發布的契約創建並編制了一份契約。
我已經將它部署到 Ropsten,然後在 Etherscan 上進行了驗證。
正如你在Etherscan上看到的,它的字節碼包含序列
704f1b94
,它是 function 的函式選擇器registerUser(string)
。正如你在Etherscan上看到的,你的合約的字節碼不包含這個函式選擇器,這意味著你的合約沒有實現這個函式!
這本身就足以讓您的交易恢復。
一些技術說明:
- 您可以通過獲取列印輸出的前 4 個字節(8 個十六進製字元)來生成上面的函式選擇器
console.log(Web3.utils.keccak256("registerUser(string)"));
。- 這是我在 Etherscan 上編譯、部署和驗證的合約:
pragma solidity 0.4.26; contract MyContract { struct user { address id; string name; } uint internal totalUsers = 0; mapping(address => user) internal users; function registerUser(string memory name) public { user storage u = users[msg.sender]; require(keccak256(abi.encodePacked((name))) != keccak256(abi.encodePacked(("")))); if(msg.sender == u.id) { revert("already registered"); } else { users[msg.sender] = user(msg.sender, name); totalUsers++; } } }
- 這是我用來測試合約功能的 NodeJS 腳本:
const Web3 = require("web3"); const PROJECT_ID = process.argv[2]; const PRIVATE_KEY = process.argv[3]; const ABI = [{"type":"function","name":"registerUser","inputs":[{"name":"name","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable","constant":false,"payable":false}]; const ADDR = "0x6285F7CC0cD9D4E5DBB81353276DCc099fa9C6B9"; async function send(web3, account, transaction, value = 0) { const options = { to : transaction._parent._address, data : transaction.encodeABI(), gas : await transaction.estimateGas({from: account.address}), gasPrice: await web3.eth.getGasPrice(), value : value }; const signed = await web3.eth.accounts.signTransaction(options, account.privateKey); const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction); return receipt; } async function run() { const web3 = new Web3("https://ropsten.infura.io/v3/" + PROJECT_ID); const contract = new web3.eth.Contract(ABI, ADDR); const account = web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY); const receipt = await send(web3, account, contract.methods.registerUser("myName")); console.log(receipt); } run();