-
-
Notifications
You must be signed in to change notification settings - Fork 183
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
Add detection params (userAddress, chainId) and remove duplicate source of truth #636
Conversation
@@ -353,10 +365,7 @@ export class CollectibleDetectionController extends BaseController< | |||
} | |||
|
|||
/* istanbul ignore else */ | |||
if ( | |||
!ignored && | |||
requestedSelectedAddress === this.config.selectedAddress |
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.
Interesting, so this condition was only added on the CollectibleDetectionController
and not in the CollectiblesController
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.
Left some small comments
}); | ||
collectiblesController.configure({ selectedAddress }); |
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 know these are unit tests so we don't need to test the integration points with other Controllers but I generally like to use the upstream method where the piece of state we're subscribed to actually changes (in this case it would be preferences.setSelectedAddress(selectedAddress)). I think it makes our network of assumptions safer but I'm open to being convinced otherwise! Thoughts @Gudahtt @wachunei @gantunesr
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.
If we wanted to test this robustly we'd do both. I'd rather us migrate to using the new base controller than waste our time doing that though, because we don't really want configure
to be public API like this.
Following your suggestion would be better at least in that it'd be more compatible with BaseControllerV2 when we do migrate.
expect(collectiblesController.state.ignoredCollectibles).toHaveLength(0); | ||
collectiblesController.removeAndIgnoreCollectible( | ||
'0x1d963688fe2209a98db35c67a041524822cf04ff', | ||
'0x1d963688FE2209A98dB35C67A041524822Cf04ff', |
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.
just curious why was the checksum change here necessary?
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.
Not really, I did it without noticing 😅
@@ -131,6 +132,7 @@ export interface ApiCollectibleCollection { | |||
export interface CollectibleDetectionConfig extends BaseConfig { | |||
interval: number; | |||
networkType: NetworkType; | |||
chainId: `0x${string}` | `${number}` | number; |
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.
Whoa! I didn't know you could do string interpolated types! So cool
return; | ||
} | ||
|
||
await safelyExecute(async () => { | ||
const apiCollectibles = await this.getOwnerCollectibles(); | ||
const apiCollectibles = await this.getOwnerCollectibles(selectedAddress); |
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'm not understanding what we achieve by getting selectedAddress
in detectCollectibles
and passing it in to getOwnerCollectibles
rather than just pulling selectedAddress
off config in getOwnerCollectibles
?
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.
We just want to avoid grabbing it in different places to make sure it does not change along the execution of the procedure
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 think in general I don't like the pattern of replacing undefined
with an empty array because it maintains the default value of the collectibles
and collectibleContracts
subset state values. I think it ends up causing more confusion. Open to be convinced otherwise though!
collectiblesController.state.allCollectibleContracts[selectedAddress][ | ||
chainId | ||
], | ||
).toHaveLength(0); |
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.
Should we remove the key rather than just remove the item from the array when there are no more left for the address/chainId combo?
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 agree that this would be nicer, so that the behaviour after adding and removing a collectible matches the initial behaviour. Leaves us with less cases to test, and it's simpler for anyone using this state. I don't want to block on it though.
Co-authored-by: Alex Donesky <adonesky@gmail.com>
Co-authored-by: Alex Donesky <adonesky@gmail.com>
Co-authored-by: Alex Donesky <adonesky@gmail.com>
I updated the About this: I think it makes sense to prune empty nodes, is it something we do usually? I'd defer decision to you guys that are more familiar with controllers conventions. |
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.
LGTM
So these "detection params", what purpose do these serve? Is this so that the chainID/address at time of detection is preserved, so that the NFT is assigned correctly if the user switches accounts/networks while the detection was still being processed? I didn't see the problem this was meant to solve explained anywhere. |
Yes, exactly that |
); | ||
await this.addCollectible(address, token_id, collectibleMetadata, { | ||
userAddress: selectedAddress, | ||
chainId: chainId as string, |
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: We should not need to cast here. If it's possible for this to be something other than a string, we need to deal with that here. If it's not, then the type is wrong and we should fix that instead.
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.
The chain ID normalization above is responsible for this. It is guaranteed to be a string here but the normalization is done in a way TypeScript's inference is having trouble with. I've just prototyped a solution that I can prepare as a follow up PR later.
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.
Basically it's to move the normalization to a utility function, and adjust the conditions to help TypeScript's inference along a bit better, and add a "throw" case for invalid chain IDs.
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 see, this type and normalization is also present in the GasFeeController
, so we can use that util there.
this.configure({ networkType: provider.type }); | ||
this.configure({ | ||
networkType: provider.type, | ||
chainId: provider.chainId as CollectibleDetectionConfig['chainId'], |
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: Ideally we'd parse this here to guarantee that the chain ID is the expected type, rather than cast. Or propagate this new chain ID type into the network controller as well. I guess we can do that later.
@@ -228,6 +229,7 @@ export class CollectibleDetectionController extends BaseController< | |||
this.defaultConfig = { | |||
interval: DEFAULT_INTERVAL, | |||
networkType: MAINNET, | |||
chainId: '1', |
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: I don't object to doing this for now, since the default networkType
is MAINNET
already, so this is a pre-existing issue. But we shouldn't be setting a default network at all, we can get the true current network from the network controller by passing in a getNetworkState
function to the constructor.
This could lead to bugs where something runs initially before the first network state update, and uses the wrong network.
Overall looks good! I'm very glad to see that duplicate state removed. It would have been better to do this in two separate PRs, but what's done is done. I can take another look when conflicts are resolved. |
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
@Gudahtt Conflicts are resolved 👌 |
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.
LGTM!
…ce of truth (#636) Co-authored-by: Alex Donesky <adonesky@gmail.com> Co-authored-by: Mark Stacey <markjstacey@gmail.com>
…ce of truth (#636) Co-authored-by: Alex Donesky <adonesky@gmail.com> Co-authored-by: Mark Stacey <markjstacey@gmail.com>
Description
REMOVED
collectibles
andcollectibleContracts
are removed fromCollectiblesController
state.FIXED:
boolean
to an object containingaddress
andchainId
that was used to autodetect.Checklist
Issue
Related MetaMask/metamask-mobile#3335