Solidity

返回一個結構並通過 Web3 讀取

  • June 12, 2021

我正在使用結構映射將數據儲存在我的契約中。

例如,假設我正在儲存由員工 ID 映射的員工資訊(姓名/地址/薪水)。

通過網路前端,我希望能夠指定一個員工 ID,並在我的契約中呼叫一個函式(使用 Web3.JS)來返回員工資訊。

如果返回結構,我如何訪問數據。那可能嗎?

概括

將結構的欄位作為單獨的返回變數返回。

**編輯:**截至 2021 年,可以直接返回結構。看到這個答案


例子

我正在使用以下命令在本地開發區塊鏈中執行此程式碼:

geth --datadir ~/devdata --dev --nodiscover \
 --mine --minerthreads 1 --port 30301      \
 --maxpeers 0 --verbosity 3 --rpc console

您的 Web 前端應該能夠發送事務以插入使用者,並呼叫函式來獲取使用者數量和使用者資訊。

樣本契約

contract SalaryInfo {
   struct User {
       uint salaryId;
       string name;
       string userAddress;
       uint salary;
   }
   User[] public users;

   function addUser(uint _salaryId, string _name, string _userAddress, uint _salary) public returns(uint) {
       users.length++;
       users[users.length-1].salaryId = _salaryId;
       users[users.length-1].name = _name;
       users[users.length-1].userAddress = _userAddress;
       users[users.length-1].salary = _salary;
       return users.length;
   }

   function getUsersCount() public constant returns(uint) {
       return users.length;
   }

   function getUser(uint index) public constant returns(uint, string, string, uint) {
       return (users[index].salaryId, users[index].name, users[index].userAddress, users[index].salary);
   }
}

扁平化原始碼

我使用stripCrLf方法(來自How to load Solidity source file into geth)將格式化的原始碼轉換為可以插入geth控制台的單行。或者,搜尋將從程式碼中刪除換行符的網頁。然後將您的程式碼分配給 JavaScript 變數:

> var salaryInfoSource='contract SalaryInfo { struct User { uint salaryId; string name; string userAddress; uint salary; } User[] public users; function addUser(uint _salaryId, string _name, string _userAddress, uint _salary) public returns(uint) { users.length++; users[users.length-1].salaryId = _salaryId; users[users.length-1].name = _name; users[users.length-1].userAddress = _userAddress; users[users.length-1].salary = _salary; return users.length; } function getUsersCount() public constant returns(uint) { return users.length; } function getUser(uint index) public constant returns(uint, string, string, uint) { return (users[index].salaryId, users[index].name, users[index].userAddress, users[index].salary); }}'

將合約插入區塊鏈

編譯程式碼:

> var salaryInfoCompiled = web3.eth.compile.solidity(salaryInfoSource);

將程式碼載入到區塊鏈中:

> var salaryInfoContract = web3.eth.contract(salaryInfoCompiled.SalaryInfo.info.abiDefinition);
> var salaryInfo = salaryInfoContract.new({from:web3.eth.accounts[0], data: salaryInfoCompiled.SalaryInfo.code, gas: 1000000}, 
 function(e, contract) {
   if (!e) {
     if(!contract.address) {
       console.log("Contract transaction send: TransactionHash: " + 
         contract.transactionHash + " waiting to be mined...");
     } else {
       console.log("Contract mined! Address: " + contract.address);
       console.log(contract);
     }
   }
 }
)

等待以下消息表明合約已被探勘:

I0505 09:12:15.712867   27030 xeth.go:1026] Tx(0x7747500b881c8da44efbc3b5d1c2c762f1cd52d2dd74050edbfed10e51a29d8a) created: 0x0bb1d7a6b31f7a7e23e6d902bac0eb5f9c721c54
Contract transaction send: TransactionHash: 0x7747500b881c8da44efbc3b5d1c2c762f1cd52d2dd74050edbfed10e51a29d8a waiting to be mined...
...
Contract mined! Address: 0x0bb1d7a6b31f7a7e23e6d902bac0eb5f9c721c54
[object Object]

插入使用者

在這裡,我們將 2 個使用者添加到合約中:

> salaryInfo.addUser(123, "User 123", "123 drive way, the uncentralised kingdom", 100, {from:web3.eth.accounts[0], data: salaryInfoCompiled.SalaryInfo.code, gas: 500000});
"0x7c22797d6b7717beb398a65159b1009fba3bbc9e4917ee1584bed60ea74eac11"
> salaryInfo.addUser(234, "User 234", "234 drive way, the uncentralised kingdom", 200, {from:web3.eth.accounts[0], data: salaryInfoCompiled.SalaryInfo.code, gas: 500000});
"0xed197c9a6fbc70c19cc95bcdc6943e38736c080052e9e1a4f7562216d6de4c78"

檢索數據

讓我們獲取使用者數:

> var numberOfUsers = salaryInfo.getUsersCount();
undefined
> numberOfUsers
2

讓我們獲取第一個使用者的資訊:

> salaryInfo.getUser(0)
[123, "User 123", "123 drive way, the uncentralised kingdom", 100]

第二個使用者:

> var user2 = salaryInfo.getUser(1);
undefined

> user2
[234, "User 234", "234 drive way, the uncentralised kingdom", 200]

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