Web3js
使用節點儲存/檢索數據不起作用
我嘗試了一些簡單的方法,在智能合約中儲存和檢索數據,但是當我想檢索數據時,什麼都沒有返回。
solc 版本是 0.4.24 web3 版本是 1.2
堅固性程式碼:
pragma solidity ^0.4.24; contract tbdocs { address owner; string testData; constructor() public { owner = msg.sender; } function getOwner() public view returns (address) { return owner; } function setTestData(string data) public returns (string) { testData = data; return testData; } function getTestData() public view returns (string) { return testData; } }
節點JS程式碼:
const path = require('path'); const fs = require('fs'); const Web3 = require('web3'); // Version 1.2 const solc = require('solc'); // Version 0.4.24 async function compileAndDeplot() { const simplePath = path.resolve(__dirname, 'contracts', 'simpleStore.sol'); const sourceSolidity = fs.readFileSync(simplePath, 'utf8'); const contract = solc.compile(sourceSolidity, 1).contracts[':tbdocs'] const byteCode = contract.bytecode; const abi = JSON.parse(contract.interface); console.log('Compiled.'); const web3 = new Web3('http://localhost:8545'); const accounts = await web3.eth.getAccounts(); const address = accounts[0]; console.log('Using account: ' + address); var myContract = new web3.eth.Contract(abi) var contractDeployed = await myContract.deploy({ data: byteCode }).send({ from: address, gas: '2900000' }, function (error, transactionHash) { console.log('Transaction hash: ' + transactionHash); }); const contractAddress = contractDeployed.options.address; console.log('Contract deployed at: ' + contractAddress); console.log('\nCalling methods: ') var result = await contractDeployed.methods.getOwner().call(); console.log('\tgetOwner: ' + result); // Works contractDeployed.methods.setTestData('testing store data').call() .then(result => { console.log('\tSet: ' + result); contractDeployed.methods.getTestData().call() .then(data => { console.log('\tGet: ' + data); }); }) } compileAndDeplot();
現在並使用 ganache-cli 進行測試,但使用 geth 的結果相同。
ganache-cli -u 0 -l 1000000000
範例輸出:
Compiled. Using account: 0xdf6c7a3c1d19DfEF9bae7fC1328f182D781f6631 Transaction hash: 0xad8d9f164d7ec16522eab2a17c8d2c4253f52d0b648a7921b63c6b8bb863f9de Contract deployed at: 0x0Aa3916BD95B5C02E8ee44c4E9ccf5FAaa328a0a Calling methods: getOwner: 0xdf6c7a3c1d19DfEF9bae7fC1328f182D781f6631 Set: testing store data Get:
可以看出,get 是空的。
契約工作正常,可以在這裡測試:
感謝任何提示。
這都是錯誤的:
var result = await contractDeployed.methods.getOwner().call(); console.log('\tgetOwner: ' + result); // Works contractDeployed.methods.setTestData('testing store data').call() .then(result => { console.log('\tSet: ' + result); contractDeployed.methods.getTestData().call() .then(data => { console.log('\tGet: ' + data); }); });
var result
您聲明的第一個不會在您的程式碼中進一步使用。這是因為函式的回調
setTestData
使用了完全相同名稱的變數(在行中.then(result => {
)。另請注意,函式
setTestData
不是恆定的(也不pure
是view
)。因此,當你在鏈上呼叫它時(即從這個合約或從另一個合約)你可以依賴它的返回值,當你在鏈下呼叫它時你不能依賴它的返回值(即從 web3腳本),它將返回交易雜湊。
最後(並且在另一個答案中也指出),因為這個函式不是恆定的,你應該使用
send
而不是call
.由於您無論如何都在使用
async
/await
方案,因此您也可以這樣做:var result = await contractDeployed.methods.getOwner().call(); console.log('\tgetOwner: ' + result); var options = {from: address, gas: ...}; await contractDeployed.methods.setTestData('testing store data').send(options); var data = await contractDeployed.methods.getTestData().call(); console.log('\tGet: ' + data);