Skip to content

Instantly share code, notes, and snippets.

@nfurfaro
Last active January 9, 2019 04:19
Show Gist options
  • Save nfurfaro/99c63cf4f16610382b06d98a901fb277 to your computer and use it in GitHub Desktop.
Save nfurfaro/99c63cf4f16610382b06d98a901fb277 to your computer and use it in GitHub Desktop.
Solidity helper function for implementing pagination in PublicLock.sol
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);
}
@nfurfaro
Copy link
Author

nfurfaro commented Jan 9, 2019

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 type bytes 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"]
})
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment