-
Notifications
You must be signed in to change notification settings - Fork 7
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
Enhancement/1483 chainspacing #1496
Conversation
307c8c7
to
789573e
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.
Left a handful of comments on some implementation details. Would love more eyes and brains on this.
onClick={() => { | ||
onClickView(); | ||
if (closeDrawer) closeDrawer(); | ||
action.resetDAO(); | ||
navigate(DAO_ROUTES.dao.relative(addressPrefix, address)); | ||
}} |
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 super related to this PR, but I snuck this change in here anyway. Basically, made it so that only the button in the search result list is clickable, not the whole element.
✅ Deploy Preview for fractal-dev ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
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.
Nice! Answer to your big question and one requested change in ManageDAOMenu
@@ -45,6 +47,7 @@ export function FavoritesList() { | |||
{favoritesList.map(favorite => ( | |||
<Favorite | |||
key={favorite} | |||
network={addressPrefix} |
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've talked before about revisiting LocalStorage setup. Should a card be made to start noting this?
acb4008
to
b02998b
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.
Left a couple new comments as per my most recent pushed work.
In general, the majority of my new updates tackle:
- Fixing the unintentional bug I introduced in
ManageDAOMenu
(thanks @Da-Colon for finding that) - removing
daoNetwork
from Fractal state, and just using the value fromuseNetworkConfig
instead, throughout the app.
4be13e7
to
86a01a9
Compare
…x from the currently connected network
…o prefix the network to navigation
86a01a9
to
5525e40
Compare
function InvalidSafe() { | ||
const { name } = useNetworkConfig(); | ||
const { t } = useTranslation('common'); | ||
|
||
return ( | ||
<Center | ||
padding="3rem" | ||
textColor="grayscale.100" | ||
> | ||
<VStack> | ||
<Text | ||
paddingTop="3rem" | ||
textStyle="text-6xl-mono-regular" | ||
> | ||
{t('errorSentryFallbackTitle')} | ||
</Text> | ||
<Text>{t('invalidSafe1', { chain: name })}</Text> | ||
<Text paddingBottom="1rem">{t('invalidSafe2')}</Text> | ||
<Button onClick={() => window.location.reload()}>{t('refresh')}</Button> | ||
</VStack> | ||
</Center> | ||
); | ||
} |
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.
Pulled into own File and made generic so we can throw any of the three error types at it
|
||
export default function DAOController() { | ||
const { node } = useFractal(); |
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.
Don't need this
@@ -59,7 +32,6 @@ export default function DAOController() { | |||
return theme; | |||
}, [daoMetadata]); | |||
|
|||
const validSafe = node.safe; |
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.
Don't need this, we simply assume the address is a valid safe until it's not.
if (addressPrefix + daoAddress !== currentValidSafe.current) { | ||
setDAO(addressPrefix, daoAddress); | ||
} |
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.
And now, if we got here, we only want to call setDAO
if we haven't done so yet for the given address
"invalidSafe2": "Please double check the address then try again.", | ||
"wrongNetwork1": "Fractal is currently connected to {{chain}}.", | ||
"wrongNetwork2": "Try switching the app to the correct chain for your Safe.", | ||
"badQueryParam1": "The Safe address in the URL isn't formatted correctly", | ||
"badQueryParam2": "", |
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.
Better error strings for the various kinds of initial loading issues that might occur
|
||
let safeInfo; | ||
|
||
try { | ||
if (!safeAPI) throw new Error('SafeAPI not set'); | ||
|
||
safeInfo = await requestWithRetries( | ||
() => safeAPI.getSafeInfo(utils.getAddress(_daoAddress)), | ||
5, | ||
); | ||
} catch (e) { | ||
reset({ error: true }); | ||
return; | ||
} | ||
setNodeLoading(false); | ||
|
||
if (!safeInfo) { | ||
reset({ error: true }); | ||
return; | ||
} | ||
|
||
// if here, we have a valid Safe! | ||
|
||
action.dispatch({ | ||
type: NodeAction.SET_FRACTAL_MODULES, | ||
payload: await lookupModules(safeInfo.modules), | ||
}); | ||
|
||
action.dispatch({ | ||
type: NodeAction.SET_SAFE_INFO, | ||
payload: safeInfo, | ||
}); |
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 was mostly just a flattening of logic and moving all non-get-data stuff out of this file and back into useDAOController. This useFractalNode hook is now only used for fetching stuff, no more checking if input data is valid, if it's in here (and not undefined) we should use it to go start fetching.
if (skip || addressPrefix === undefined || daoAddress === undefined) { | ||
reset({ error: false }); | ||
return; |
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 skip
is true, that means there was an error with the address or formatting or we're on the wrong network. If addressPrefix of daoAddress is undefined, then damn the App is still standing up. In either case, just reset state and GTFO.
const addressWithPrefix = searchParams.get('dao'); | ||
const validDaoQueryString = /^[^\s:]+:[^\s:]+$/; | ||
|
||
const prefixAndAddress = addressWithPrefix?.split(':'); | ||
const addressPrefix = prefixAndAddress?.[0]; | ||
const daoAddress = prefixAndAddress?.[1]; | ||
|
||
const invalidQuery = | ||
addressWithPrefix === null || | ||
!validDaoQueryString.test(addressWithPrefix) || | ||
!utils.isAddress(daoAddress || ''); | ||
|
||
const { addressPrefix: connectedAddressPrefix } = useNetworkConfig(); | ||
const wrongNetwork = addressPrefix !== connectedAddressPrefix; | ||
|
||
const skip = invalidQuery || wrongNetwork; |
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 fun. Do all the things needed to validate that:
- we have a query string of the correct key
dao
- the value of that key is formatted correctly
- string-without-whitespace followed by ":" followed by string-without-whitespace
- the ethereum address portion is formatted correctly
- right length, checksum is valid if exists, etc
- the network identified in the query param matches the network the app is currently on
- so if the user is trying to load a
sep:0xabc
dao, the app must be on Sepolia
- so if the user is trying to load a
If any of those things fail, we don't try to load anything and show the appropriate error screen.
@Da-Colon @mudrila @tomstuart123 I have just pushed a bunch of fixes and nice QoL improvements, this is ready for review again. @Da-Colon i've addressed all of your comments and done more testing, things seem smooth as butter |
Tried the new netlify link with 4 prior DAOs. TLDR
Mainnet DAO links tried
Sepolia DAO links tried
|
@tomstuart123 the Sepolia links you tried are indeed formatted incorrectly. Notice how they are the new query params, but don't include the network prefix. This is invalid as per this new PR. |
got ya. My bad for not double chekcing the new address. Forgot the new PR had gone to dev Okay now retested with the links below Sepolia All redirected well I also managed to play with two of the error message This appeared when being on ethereum using an old sepolia link both should be working as intended so I'll give this an approve from me. Thanks @adamgall |
…ent/1483-chainspacing
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.
Looks good thanks for the changes!
Closes #1483
Closes #1336
This PR implements
chainspacing
in the URL.All URLs that exist in the context of a Safe have a network ID (same ones that the Safe UI uses) prefixed to the address.
Additionally, error page logic has been separated to clearly identify the two scenarios that might occur for a Safe being unable to be loaded:
Additionally, stronger typing has been enforced in the many places were navigation links exist. This stronger typing required early-exiting rendering attempts where either the network prefix or address are not available yet (e.g. as a Safe is loading), so special review and testing should be taken to ensure that the logical changes around rendering links was implemented correctly.
Testing
Functional changes in this PR include: