-
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/web app #4
Merged
Merged
Feat/web app #4
Conversation
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
These can be revealed at any time using `npx remix reveal`
A fontsource package was used so that we self host the font
The root route was added, and the theme was customized with css
- Ethers.js library was added and the chain + wallet linking logic was added. The failure paths were handled with toast messages. Success paths are yet to be handled. - A couple of utils were added: The `TrialResult` type, the `tryItAsync` function, as well as an error code library for UI errors. - \*.dev.\* files were added to gitignore
- A POST request is submitted to /login. This sets the active address in a cookie, helping us - show the address in the navbar on first render - redirect to dashboard for already signed in users navigating to root route (/) - Set up env variables for cookie secrets
The env variables are parsed with zod and made available for use on import
Apart from this, the error returned from '/login' API was modified to conform to the format expected by the error boundary. Namely the error data was returned as a single string instead of an object. We can log additional details separately in our logger. This is only for client facing purposes
Storing the client address on cookie prevents caching the page. So we moved it to localStorage
- This context is made available globally. Since users are likely to login from and access user info from every page. - The fetching of chain info was moved to the root loader. This needs to be cached in order to prevent refetching data that doesn't change so often (chain info)
- Earlier, the user address was fetched from localStorage automatically. This is a good first step, but now we go one step further and try to automatically fetch active address from metamask, and update it in-app. - Memoization was added to AuthContext value - noUncheckedIndexedAccess was enabled to make sure we typecheck on indexing arrays. The associated tweaks were also made.
…ading - Add chain switching request to login flow: This allows us to explicitly fail if user rejects chain switch. - Fix perpetual loading states on login: If users were to fail the login process from metamask, we need to kill the loading state. - Prevent auto-login on explicit logout: If users explicitly log out, signalled by lack of stored user in localStorage, then we don't need to attempt auto login, regardless of whether the metamask is already linked
The style of loading spinner was also fixed
- Cards were added with dummy data - The color of accent css variable was made darker, so that buttons are darker on hover
This was also used in the tests to deploy the contracts
- Dapp info is loaded via env variables, parsed and checked to ensure integrity, and provided in the root loader to be available throughout the app. - The ChainInfo for dev environment was moved to a constants folder
- A useEffect was added, in which we use the dappInfo (provided by root loader) to interact with the smart contract and fetch the user's data. So far only the user staked amount was fetched. - The root loader's path was exported from that `root.tsx` file, to eliminate arbitrary string literals when being used in `useRouteLoaderData` - A dedicated `FinthetixStakingContractHandler` class was added to wrap the contract methods and to contain ABI etc. This is used to fetch the user data
Unexpected should be handled gracefully and not shown to the client. Hence, non-route-errors were replaced with a generic error message
The associated scripts were also added
… class FinthetixStakingContract now uses the factory generated by typechain to infer the abi. This method works even though the factory is not committed because we always run the generator on `postinstall`. Any type errors are automatically caught in the build step.
…ction - Earlier the metamask request was highly coupled to the state functions. Now it has been abstracted to `requestMetamaskAddress` - The `UserInCookie` type was exported for reuse globally
- Now the loader still runs even when user is logged in. This prolongs the loading state to allow for redirect after user is logged in. - The comment in dashboard page useEffect was modified to be more clear. The useEffect is only intended to run when the loading is finished, since only then can we fetch the data for the loaded user.
The dependencies of AuthContext like Metamask and localStorage interaction functions were moved into separate colocated files.
Now this can be used to fetch the loader data from root route, in a typesafe manner
…point This data is reused in many places, so makes sense to move into its own endpoint. This has the added benefit of reducing data over the wire
- All data fetching on /dashboard page can happen only after the user is logged in. So instead of implementing guard checks for this within each component, and fetching at each component, we fetch at the closest common ancestor, which is the /dashboard page `route.tsx` component, and pass it down - A separate flag for loading state was eliminated. We simply nullify the data when new data is loading. So far we don't have a use case where the existing data should be sustained, while the new data is being fetched. We are okay with blowing away the old data as soon as we know it's stale. - We also removed the condition where data is fetched as undefined. This is not an expected case. We are always expecting some kind of data from the backend, even if it is symbolically empty (like an empty array)
- Since this is user agnostic, we benefit from fetching it as early as possible. Hence the RTK Query endpoint was removed, and the fetching was moved to the server side - In order to fetch on the server side, where no signer exists, we needed to extend our `FinthetixStakingContractHandler` abstraction. - For this a `Base` class was created, which contains the logic for handling all the primitive contract handlers. - We created a new readonly abstraction `ReadonlyFinthetixStakingContractHandler` which extends this base class. This is intended to be used on the server side, or wherever user signer is not available(or necessary). - The `FinthetixStakingContractHandler` was also made to be based off of the `Base` class - Since we fetch the `dappInfo` and `chainInfo` on multiple pages now, we moved that into its own function as well, so that it can be reused between loaders. This is necessary since loaders are run in parallel, and data cannot be shared between loaders.
… eslint errors - The renaming of `get` to `fetch` makes more narrative sense, as we never extract the data directly from the `get`-prefixed function. Rather the `get` function acts like a trigger. So we made this cosmetic adjustment - Eslint errors in some config files were fixed
…tixStakingContractHandler References to `super` instance variables were returning undefined. So for simplicity, all `super` referenes were converted to `this`
…ching - The data is now fetched in parallel wherever possible - Also, the current block timestamp logic was slightly changed to be less verbose
- When user changes their active account on metamask, we automatically try to login and fetch info for the new account - All the auto-login logic was moved to a single `AutoLogin` component. This helps colocate the auto-login from localStorage as well as the auto-login when accounts are switched. - A dedicated global state variable was added to the `User` slice for signalling whether the data is from localStorage or not. This makes it more explicit and avoids overlapping resposibilities of the `isLoading` flag. Selectors were also added for the same - The metamask handler class was extended to expose the `window.ethereum` object. This makes sure we go through the required guard checks and error handling before using window.ethereum. - We use dedicated `isUserLoggedIn` selector in index page. This is a redux optimization to minimize rerenders.
…cache The query hook triggers are now prefixed with `trigger` to make it more explicit. Also the `preferCache` setting was explicitly enabled for these triggers on dashboard page.
This abstracts away the complexity, reducing cognitive load on developer
- The navbar was made to be sticky, with a blur and shadow that appears on scroll. We use `IntersectionObserver` API inside a custom hook for this. - The cards were made to have strong borders and in some places rise on hover, similar to the codecademy website
This adds to the user experience
Forward looking change in anticipation of more sections being added to homepage
- Some info as well as useful links were added. Right now the links are hardcoded dummy links - Some styling for the RippleHeroBg was modified so that - The container does not overflow viewport - The animation is continuous(infinite) on larger viewports
- Credits section includes developer info - The Github Icon was moved to a separate component, and an X Icon was added - Github and Developer contact URLs were added and sourced from the constants.ts folder
- Earlier when we made the intersection observerscroll trigger into a custom hook, we forgot to pass the dependencies array. Now this was done - Also, the navbar was made thinner for aesthetic purposes
- Earlier this was hardcoded. The metadata fetch was also moved to the root route, as this is used on multiple routes. - The metadata was extended to contain info on staking reward rate. Accordingly, all references to `FinthetixMetadata` were updated.
…nts` This makes the distinction between the generic type and the utility function more clear
- When users stake/unstake/withdraw-rewards, we show them the link to the block explorer as well, so that they can independently verify their transaction details. - The styling of the toast component was modified to wrap words and thus show the whole contents always
We check if the contract is cooling down, before trying to interact with it. This saves us gas by preventing reverts, and also improves the UX. This is currently done only in a guard check format. This needs to be displayed prominently on the user's dashboard as well, and also needs to be handled better by the frontend
- We need to prevent the user from interacting when the Staking contract is cooling down. - Warnings were added for this purpose. This contains a time counter which updates every second based on how much time is left for cooldown. The cooldown time is currently hardcoded, and needs to be fetched from backend. A new variant was added to the alert component, denoting warning. - Interaction buttons were disabled when cooling down. For this a new `disabled` prop was added to the relevant components. - In order to avoid rerenders, the subcomponents of the dashboard page were memoized using React.memo. So now these don't rerender until the props change, which is either user data change, or the enabling of interaction post cooldown
The cooldown time is fetched as part of the `Finthetix Status`, from the contract via RTK Query endpoint. It is refreshed whenever user tries some interaction. Good thing to note is that if the cooldown check fails when user tries to interact, that interaction will also trigger a refetch of `FinthetixStatus`, causing the _Cooling Down_ banner to be shown correctly.
…actHandler` - This logic is more related to the staking contract than to the RTK query endpoint. So we moved it accordingly. - The contract handler methods were modified so that we can use the cooldown time separate from the overall status. This optimizes data over the wire for that specific method. For eg. when staking, we only need to know whether contract is cooling down. We don't need other status data.
The text was allowed to break freely, in an earlier change. This is being reverted now. The reasons are: - We only wanted to break longer words like the ETH address so that they are not obfuscated. But shorter words were also being broken up as a result of the previous change - The ETH address was only being broken up for unrealistic viewport sizes. So we don't have to handle this condition in our styling
- ChainInfo is now loaded in via env variables, for production server as well. It is parsed and validated at the time of server start, and read by the server when requested by user. - ChainInfo and DappInfo were moved into their own files, with the types, schema and fetchers colocated. This helps reduce cognitive overload in a single file. - Minor style change was made to homepage as well, wherein the `HowItWorks` section was given a top margin, so that it is not visible along with the hero section, when page first loads (especially prominent on mobile sizes).
- Earlier the `Navbar` never actually unmounted; it only stopped rendering the child components. As a result the sticky state was persisting across apparent unmounts, causing the `Navbar` to show sticky style even when it was not stuck. To fix this, we actually unmount the entire `Navbar` component, which also resets the sticky state kept in JS - Also, the _Interaction observer_ was disconnected properly in the useEffect unmount. This was forgotten earlier, leading to multiple interaction observers. - The type in chainInfo was fixed to more closely match the zod schema. Now the type conveys the info that there will always be at least one url.
This is required for testing the deployer script, which is used in tests
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What?
We added a web app frontend for the staking smart contract
Why?
It helps users easily interact with, and understand how staking works in Finthetix.
How?
It uses
Screenshots
Smart Contract Changes
Events
We changed the structure of Events in smart contracts, to more closely match our needs in the frontend dashboard. This means unified events for Staked amount changes, and Reward Balance updates.
Deployer script
We added a deployer script, which is necessary to bootstrap the environment before running the web app locally for development. We added a convenience
make
command to deploy as well:This script was also utilized in the smart contract testing, in order to validate that the script works. As a result we have had to bootstrap the .env file in CI testing (github actions) as well