Solidity
如何監聽事件以對數組進行排序
我閱讀了這篇關於使用事件偵聽器對鏈外數組進行排序的文章,但是當在打字稿中呼叫數組時,我的數組似乎沒有及時排序。
這是我的契約:
pragma solidity 0.8.4; pragma experimental ABIEncoderV2; contract Test { uint256[] unsortedArr; uint256[] sortedArr; event sort(uint256[]); function addElement(uint256 element) public { unsortedArr.push(element); } function sortOffChain() public returns (uint[] memory) { /*On the backend, the algorithm would look something like this - *event listener listening for sort() *calls sort function in typescript upon getting triggered *calls getSortedData() function with returned value of sort() */ emit sort(unsortedArr); // I want sortedArr below to be sorted by the time the return is called return sortedArr; } function getSortedData(uint256[] memory sortedData) public { sortedArr = sortedData; } // for typescript test function getUnsortedArr() public view returns (uint256[] memory) { return unsortedArr; } function getSortedArr() public view returns (uint256[] memory) { return sortedArr; } }
這是 TypeScript 中事件監聽器的樣子:
async function main() { ; // deploying const Test = await hre.ethers.getContractFactory("Test"); const test = await Test.deploy(); await test.deployed(); console.log("Test deployed to", test.address); // add elements to array await test.addElement(5); await test.addElement(3); await test.addElement(7); await test.addElement(2); await test.addElement(1); await test.addElement(9); // event listener const OffChainResult = await test.sortOffChain(); test.on("sort", (arr: []) => { let arrayForSort = [...arr]; const sortedArr = arrayForSort.sort((n1: number,n2 : number) => n1 - n2); console.log("array sorted"); test.getSortedData(sortedArr); console.log("getSortedData completed"); } ); console.log("output of getSortedData:"); console.log(OffChainResult);
這是我執行腳本時終端中出現的內容:
Test deployed to 0x5FbDB2315678afecb367f032d93F642f64180aa3 output of getSortedData: { hash: '0x40eeca2775e29300e51f3a067c99195f0cf33ee0aac73eaeaf05d826b41c3d4c', type: 2, accessList: [], blockHash: '0xd952eb1b086de3b1ee213fff01b464925670bc6d7e515ac3f7dad3b732471857', blockNumber: 8, transactionIndex: 0, confirmations: 1, from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266', gasPrice: BigNumber { value: "1346048670" }, maxPriorityFeePerGas: BigNumber { value: "1000000000" }, maxFeePerGas: BigNumber { value: "1692097340" }, gasLimit: BigNumber { value: "29021272" }, to: '0x5FbDB2315678afecb367f032d93F642f64180aa3', value: BigNumber { value: "0" }, nonce: 7, data: '0xb8dbac2c', r: '0x621282eec4ac159b052250faa62aa5e954510ba91e841d3477bf0228ecf952d9', s: '0x7d36e86d604b58006dd918efc52babd3f3e61dd9f80e36fa2e3e8a9a03fe5298', v: 1, creates: null, chainId: 31337, wait: [Function (anonymous)] } array sorted getSortedData completed
有兩個問題:(1)在事件偵聽器有機會對數組進行排序並設置為正確的值之前,
getSortedData()
它被呼叫返回一個值;(2)即使數組沒有排序,也應該返回一個空數組,而不是OffChain.
sortOffChain()sortedArr
sortOffChain()`這只是我如何製作事件監聽器的問題嗎?我需要將程式碼行以不同的順序排列嗎?另外,控制台輸出的東西是什麼
OffChainResult
。我還聽說無法驗證要提供給智能合約的排序數組。我如何確保它是?
我必須仔細閱讀您的程式碼,並且我也進行了測試,坦率地說,我從這篇文章中學到了很多東西。因此,首先,您的契約有點問題。既然你想趕上事件,你不需要返回任何東西。即使你這樣做了,你也需要
view
在你的函式中使用。我修改了契約,它看起來像這樣://SPDX-License-Identifier: MIT pragma solidity ^0.8.4; contract Sort { uint256[] unsortedArr; uint256[] sortedArr; event sort(uint256[]); function addElement(uint256 element) public { unsortedArr.push(element); } function sortOffChain() public { emit sort(unsortedArr); } function getSortedData(uint256[] memory sortedData) public { sortedArr = sortedData; } // for typescript test function getUnsortedArr() public view returns (uint256[] memory) { return unsortedArr; } function getSortedArr() public view returns (uint256[] memory) { return sortedArr; } }
繼續前進,您需要更改方法以更改擷取事件的過程。我可能以不同的方式編寫程式碼。你可以在你的最後解決這個問題。它會是這樣的:
function get1DArray(arr: any) { return arr.join().split(","); } it("Event get", async () => { let data = await sort.sortOffChain(); let receipt = await data.wait(); let finalEvent = receipt.events?.find((event) => event.event === "sort"); let unsortedArray = get1DArray(finalEvent?.args); console.log("Unsorted Array: ", unsortedArray); const sortedArray = unsortedArray.sort((n1: number, n2: number) => n1 - n2); console.log("Sorted Array: ", sortedArray); console.log( "Previous Sorted array in contract: ", await sort.getSortedArr() ); await sort.getSortedData(sortedArray); console.log( "New Sorted array in contract: ", (await sort.getSortedArr()).toString() ); });
最好有這個函式
get1DArray
,因為它args
返回一個數組的數組。您將獲得一個使用此鏈下排序的排序數組。