-
-
Save nfurfaro/99c63cf4f16610382b06d98a901fb277 to your computer and use it in GitHub Desktop.
Solidity helper function for implementing pagination in PublicLock.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function toBytes32( | |
bytes b | |
) | |
public | |
pure | |
returns (bytes32[]) | |
{ | |
require(b.length >= 32); | |
uint length = b.length / 32 + 1; | |
bytes32 tempBytes32; | |
uint start = 0; | |
uint byteCounter = 0; | |
bytes32[] memory dataChunks = new bytes32[](length); | |
for (uint i = 0; i < b.length; i += 32) { | |
assembly { | |
tempBytes32 := mload(add(add(b, 0x20), start)) | |
} | |
dataChunks[byteCounter] = tempBytes32; | |
start += 32; | |
byteCounter++; | |
} | |
return(dataChunks); | |
} | |
// The idea was that the helper function would be used by this function for pagination: | |
/** | |
* A function which returns a subset of the keys for this Lock as an array | |
* @param _startIndex the index (in `owners` array) from which we begin retrieving keys | |
*/ | |
function getKeysByPage(uint _startIndex) | |
external | |
view | |
returns (uint[], bytes[]) | |
{ | |
require(outstandingKeys() > 0, "No keys to retrieve"); | |
require(_startIndex >= 0 && _startIndex < outstandingKeys(), "Index must be in-bounds"); | |
uint endOfPageIndex; | |
if (_startIndex + 9 > owners.length) { | |
endOfPageIndex = owners.length - 1; | |
} else { | |
endOfPageIndex = _startIndex + 9; | |
} | |
address[] memory ownersByPage = new address[](10); | |
uint[] memory timestampsArray = new uint[](10); | |
bytes[] memory keyDataArray = new bytes[](10); | |
Key memory tempKey; | |
uint pageIndex = 0; | |
// Build the specified set of owners into a new temporary array | |
for (uint256 i = _startIndex; i <= endOfPageIndex; i++) { | |
ownersByPage[pageIndex] = owners[i]; | |
pageIndex++; | |
} | |
// Loop through ownersByPage & build the requested keys into 2 new temporary arrays | |
for (uint256 n = 0; n < ownersByPage.length; n++) { | |
tempKey = keyByOwner[ownersByPage[n]]; | |
timestampsArray[n] = tempKey.expirationTimestamp; | |
keyDataArray[n] = tempKey.data; | |
// keyDataArray[n] = toBytes32(tempKey.data); | |
} | |
return(timestampsArray, keyDataArray); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This was about as far as I got working on implementing pagination for Unlock, with a fixed return size of max 10 items, and an unbounded
data
field of typebytes
in the Key struct. I wasn't able to make it work without enabling "pragma experimental ABIEncoderV2" , which isn't production-ready. Essentially, I was unable to return an array of arrays of 32-byte arrays, which is what this approach would require.// To test this helper function I was doing this:
it('should return the length of the bytes in data', () => {
let data = ['Nick', '1-234-344-5678', 'nfurfaro68@hotmail.com']
return locks['FIRST'].purchaseFor(accounts[0], 'Julien', {
value: Units.convert('0.01', 'eth', 'wei')
})
.then(() => {
return locks['FIRST'].toBytes32(data)
})
.then((result) => {
console.log(result[0].toNumber(10)) // returns 50
console.log(result[1]) // returns [ '0x5b224e69636b222c22312d3233342d3334342d35363738222c226e6675726661',
'0x726f363840686f746d61696c2e636f6d225d0000000000000000000000000000' ]
console.log(
${Web3Utils.toUtf8(result[1][0])}${Web3Utils.toUtf8(result[1][1])}
) // returns ["Nick","1-234-344-5678","nfurfaro68@hotmail.com"]})
})