從 web3.js 呼叫部署的智能合約
我有一個小型測試智能合約,它部署到我的測試網路。我想使用伺服器來呼叫合約中的函式。這是程式碼:payontime.sol
pragma solidity ^0.4.0; contract payontime{ address public remitter; address private remittee; uint value; bool public start; /*Only owner can use these function*/ modifier onlyOwner(){ if(msg.sender != remitter) throw; _; } /*Initialize the owner*/ function payontime(address receiver) payable{ remitter = msg.sender; value = msg.value; remittee = receiver; start = true; if(!remittee.send(value)){ throw; } } function wakeUp() public returns (string){ return "success" ; } function getContractAddr() public returns(address){ return this; } /*Get the remittee*/ function getRemitee() public returns(address){ return remittee; } }
我使用
truffle serve
和一個網頁來新契約。應用程序.js
import { default as Web3} from 'web3'; import { default as contract } from 'truffle-contract' import payontime_artifacts from '../../build/contracts/payontime.json' var payontime = contract(payontime_artifacts); window.App = { sendCoin : function(){ var sender = web3.eth.accounts[0]; var receiver = document.getElementById('receiver').value; var amount = parseInt(document.getElementById('amount').value); web3.eth.getBalance(receiver,function(error,result){ if(!error){ consol.log("Before transfer: " + result ); }else{ console.log("Error: " + error); } }); var newContract = payontime.new(receiver,{from:sender, value:amount}).then( function(myPay){ console.log(myPay.getContractAddr.call()); }).then( function(){ web3.eth.getBalance(receiver,function(error,result){ if(!error){ console.log("After transfer: " + result ); }else{ console.log("Error: " + error); } }); }); } } window.addEventListener('load', function() { // Checking if Web3 has been injected by the browser (Mist/MetaMask) if (typeof web3 !== 'undefined') { console.warn("Using web3 detected from external source. If you find that your accounts don't appear or you have 0 MetaCoin, ensure you've configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask") // Use Mist/MetaMask's provider window.web3 = new Web3(web3.currentProvider); } else { console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask"); // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail) window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); } payontime.setProvider(web3.currentProvider); });
app.js
記錄地址0x1d379f2ab48ad20319e9f81cb45af415aa6f2966
,我想用這個地址wakeUp()
通過payontime.sol
另一個應用程序呼叫index.js
。const Web3 = require('web3'); /* Connect to ethereum node */ const etherUrl = "http://localhost:8545"; const abi = [{"constant":false,"inputs":[],"name":"wakeUp","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"getContractAddr","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"remitter","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"start","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"getRemitee","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"inputs":[{"name":"receiver","type":"address"}],"payable":true,"type":"constructor"}]; let web3 = new Web3(); web3.setProvider(new web3.providers.HttpProvider(etherUrl)); /*Call the function which already deployed on ethereum network Notice: ABI have to modifeid when the smart contract code change*/ var contractInstance = web3.eth.contract(abi).at('0x1d379f2ab48ad20319e9f81cb45af415aa6f2966'); var reply = "false"; reply = contractInstance.wakeUp.call(function(error,result){ if(error){ console.log("Error"); throw error; }else{ return result; } }); console.log(reply);
但是有一個錯誤資訊:
BigNumber Error: new BigNumber() not a base 16 number
我發現它可能是由於 not fully synced引起的。我認為在部署的契約中呼叫該函式時會出現一些問題。那麼如何從 web.js 呼叫已部署的合約呢?
BigNumber() is not a base 16 number 錯誤在許多情況下可能發生,但原因不一定相同。我相信原始文章的問題是使用索引“字元串”類型的事件,我也遇到了。如果我的契約事件將“字元串”類型標記為“索引”,我會得到同樣的錯誤。但是,如果我將“索引”關鍵字限制為“地址”類型,我很好。我正在嘗試查找有關可以在契約事件中“索引”哪些數據類型的文件,但無濟於事。我的直覺是任何可以解析為數字(地址、整數等)的東西都可以。我不認為區塊鏈同步是這裡的問題。所以現在嘗試刪除事件定義中字元串欄位的任何索引,直到他們修復錯誤。
從web3.js 1.0的文件中, 我們可以從 web3js 呼叫方法:
myContract.methods.myMethod(
$$ param1[, param2[, … $$]])
讓我們看看例子
var Web3 = require('web3') var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); const abi = abi_of_contract const Contract = web3.eth.contract(abi) var contractaddress = address_of_deployed_contract const contractInstance = Contract.at(contractaddress) //here I am using default account as first account from the list of addresses in the rpc enabled node web3.eth.defaultAccount = web3.eth.accounts[0] //calling contract function wakeUp() contractInstance.wakeUp( { from: web3.eth.defaultAccount, to: contractaddress });
您得到的錯誤
Error: new BigNumber() not a base 16 number
可能是由於您傳遞的地址。請先將您使用的帳戶設為預設帳戶。它可能會解決您的問題。