-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: [Hardhat] implement nft support for the json rpc api library and js mock … #173
base: main
Are you sure you want to change the base?
Conversation
53f31d6
to
0303268
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking good, left some questions/comments
src/index.js
Outdated
persistentSlotMapOf(tokenId).store(nrequestedSlot, atob(metadata)); | ||
} | ||
let unresolvedValues = persistentSlotMapOf(tokenId).load(nrequestedSlot); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moreover, not sure this works as intended, since it's going to always write when asked for token uri.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When querying the first slot holding the tokenUri, it will store the values for all slots containing this single string.
test/data/CFNFTFF/getAllowanceForToken_0.0.4436613_0.0.4454450.json
Outdated
Show resolved
Hide resolved
To improve the discussion regarding |
…server (#80) Signed-off-by: Mariusz Jasuwienas <[email protected]>
2d33834
to
d6c17f3
Compare
Signed-off-by: Mariusz Jasuwienas <[email protected]>
src/index.d.ts
Outdated
* @param serialId The serial id of the NFT. | ||
* @param blockNumber | ||
*/ | ||
getNftByTokenIdAndNumber( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: to keep the naming consistent
getNftByTokenIdAndNumber( | |
getNftByTokenIdAndSerial( |
src/slotmap.js
Outdated
/** | ||
* @type {Array<PersistentStorage>} | ||
*/ | ||
const persistentStorage = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually a Map, whose keys are addresses (and blockNumber
, see below), right? We can use a Map
or object to be more explicit and avoid doing the lookup below.
src/slotmap.js
Outdated
/** | ||
* @type {Array<PersistentStorage>} | ||
*/ | ||
const persistentStorage = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move this global state to index.js
.
src/slotmap.js
Outdated
* @returns {PersistentSlotMap} An object with `load` and `store` methods. | ||
*/ | ||
function persistentSlotMapOf(target) { | ||
const found = persistentStorage.filter(occupiedSlot => occupiedSlot.target === target); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about blockNumber
? The key should be target
and blockNumber
because the user can change the blockNumber
.
Signed-off-by: Mariusz Jasuwienas <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review applies to .github/workflows/test.yml
…e index.js file, making the blocknumber part of its key (#80) Signed-off-by: Mariusz Jasuwienas <[email protected]>
@acuarica Thank you for the review! I’ve applied your suggestions - please let me know if everything looks good now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking good, final touches
module.exports = { slotMapOf, packValues }; | ||
/** | ||
* Represents the value in the persistent storage. | ||
* Each token has its own SlotMap. Any value can be assigned to this storage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Each token has its own SlotMap. Any value can be assigned to this storage | |
* Each token and `blockNumber` has its own SlotMap. Any value can be assigned to this storage |
const initialized = this._map.get(key) || new SlotMap(); | ||
if (!this._map.has(key)) { | ||
this._map.set(key, initialized); | ||
} | ||
return initialized; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to avoid the double guard
const initialized = this._map.get(key) || new SlotMap(); | |
if (!this._map.has(key)) { | |
this._map.set(key, initialized); | |
} | |
return initialized; | |
let slotMap = this._map.get(key); | |
if (slotMap === undefined) { | |
slotMap = new SlotMap(); | |
this._map.set(key, slotMap); | |
} | |
return slotMap; |
* @param {string} tokenId | ||
* @param {number} blockNumber | ||
* @param {bigint} slot | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: let's add return type for clarity.
* @param {string} tokenId | ||
* @param {number} blockNumber | ||
*/ | ||
_init(tokenId, blockNumber) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_init(tokenId, blockNumber) { | |
_getSlotMap(tokenId, blockNumber) { |
@@ -274,4 +274,54 @@ function slotMapOf(token) { | |||
return map; | |||
} | |||
|
|||
module.exports = { slotMapOf, packValues }; | |||
/** | |||
* Represents the value in the persistent storage. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is some information in the PR description that would be really useful here. In particular 1. of section "The reason I've used persistent storage here" and section "Why it might be an issue".
We should include that info as a JS doc here.
Description:
Implementing support for NFTs in the JS library for the JSON-RPC mock, as well as in the JSON-RPC server that utilizes this library.
The reason I've used persistent storage here:
We cannot determine which NFT numbers have been minted unless someone specifically queries them. This can be addressed in one of two ways:
Dynamic loading on first access: Load each NFT's details dynamically the first time its slot is queried. Once accessed, store information about the existence of this NFT. This is my current approach. However, this may result in a memory leak/optimisation when a large number of tests or NFT requests are made, as memory is never freed (this is where the name: persistentStorage comes from).
Preloading All NFTs: Load the details of all NFTs each time the token storage is accessed. While this avoids memory leaks, it could lead to excessive memory usage and generate a large number of unnecessary API requests for NFTs that we are not interested about :/ .
Why it might be an issue:
Let's consider scenario where:
We won’t be able to provide the correct result. This is because persistentStorage is only populated when the request for the first slot of the string is made (only then we can deduce the serial NFT number from the slot address). I don't think it's not a critical issue though...
Related issue(s):
#80
Notes for reviewer:
Checklist