-
Notifications
You must be signed in to change notification settings - Fork 13
fix: request pay issues #443
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
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
📝 WalkthroughWalkthroughThe changes introduce a new Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 7
🧹 Outside diff range and nitpick comments (16)
src/constants/loadingStates.consts.ts (1)
11-11
: LGTM! Consider adding a comment for clarity.The addition of the 'Awaiting route fulfillment' state aligns well with the PR objectives, particularly in improving state handling for request pay functionality. This new state provides a more granular representation of the loading process, which is beneficial for cross-chain payments and route fetching scenarios.
Consider adding a brief comment above the
LoadingStates
type definition to explain its purpose and usage. This would help developers understand the context and importance of these states, especially with the new addition. For example:/** * Represents the various loading states in the application, * particularly for request pay and transaction processes. * Used to provide detailed feedback during asynchronous operations. */ export type LoadingStates = ...src/components/Global/AddressLink/index.tsx (2)
7-18
: LGTM with a suggestion: Consider improving error handling for ENS resolution.The use of React hooks and the logic for handling different address types are well-implemented. However, there's room for improvement in error handling for ENS resolution.
Consider adding error handling for the ENS resolution process. Here's a suggested improvement:
utils.resolveFromEnsName(address).then((resolvedAddress) => { if (!resolvedAddress) return setUrl(`https://debank.com/profile/${resolvedAddress}`) -}) +}).catch((error) => { + console.error('Error resolving ENS name:', error) + // Optionally, set a fallback URL or show an error state +})This change will help catch and log any errors that occur during ENS resolution, improving the robustness of the component.
19-25
: LGTM with a minor suggestion: Consider adding an aria-label for better accessibility.The conditional rendering logic is well-implemented, and the use of the Next.js Link component for external links is appropriate. The printableAddress utility ensures consistent address formatting.
To improve accessibility, consider adding an aria-label to the Link component:
<Link className="cursor-pointer underline" href={url} target="_blank" + aria-label={`View profile for ${utils.printableAddress(address)} on Debank`} > {utils.printableAddress(address)} </Link>
This change will provide more context for screen reader users about the link's purpose and destination.
src/components/Dashboard/components/MobileComponent.tsx (2)
48-50
: LGTM: Enhanced address rendering with AddressLink.The implementation of
AddressLink
for rendering addresses improves the UI and aligns with the PR objectives. This change enhances the user experience by potentially making addresses interactive.Consider adding a brief comment explaining the fallback logic:
<label> - From: <AddressLink address={linkDetail.address ?? address} /> + From: <AddressLink address={linkDetail.address ?? address} /> {/* Use linkDetail.address if available, otherwise fall back to the address prop */} </label>
Line range hint
1-105
: LGTM: Overall component structure and logic.The changes to the
MobileItemComponent
are well-integrated and don't disrupt the existing functionality. The component effectively handles various transaction types and statuses, providing a good user experience.Consider enhancing accessibility by adding appropriate ARIA labels to interactive elements, especially in the modal. For example:
<div className="flex h-12 w-full items-center gap-2 px-4 text-sm font-bold transition-colors last:mb-0 hover:bg-n-3/10 disabled:cursor-not-allowed disabled:bg-n-4 disabled:hover:bg-n-4/90 dark:hover:bg-white/20 " + role="button" + aria-label="Refund transaction" > <div className="text-h8" onClick={() => { linkDetail.link && router.push(`/${linkDetail?.link.split('://')[1].split('/')[1]}`) }} > Refund </div> </div>This would improve the component's accessibility without affecting its current functionality.
src/context/tokenSelector.context.tsx (1)
69-69
: LGTM: Improved token price fetching with proper state managementThe changes to
fetchAndSetTokenPrice
correctly manage theisFetchingTokenData
state. Setting it totrue
at the beginning andfalse
in thefinally
block ensures accurate status reflection throughout the operation, even in case of errors.Consider using a try-catch-finally structure for better error handling:
try { setIsFetchingTokenData(true); // ... existing code ... } catch (error) { console.error('Error fetching token price:', error); // Handle the error appropriately } finally { setIsFetchingTokenData(false); }This structure allows for more specific error handling while still ensuring the fetching status is reset.
Also applies to: 100-101
src/components/Request/Pay/Pay.tsx (4)
3-3
: Consider using more specific imports for context.The addition of
useContext
and the context module is good for centralized state management. However, importing the entire context module might lead to less specific imports.Consider importing only the specific context you need:
-import * as context from '@/context' +import { loadingStateContext } from '@/context'This approach can lead to better code readability and potentially smaller bundle sizes.
Also applies to: 10-10
25-25
: Approved: Good use of context for centralized loading state management.The addition of
loadingStateContext
aligns well with the PR objectives of refactoring state handling. This change will help in managing loading states across components more efficiently.Consider destructuring the context value directly in the
useContext
call for cleaner code:-const { setLoadingState } = useContext(context.loadingStateContext) +const { setLoadingState } = useContext(loadingStateContext)This assumes you've made the change suggested in the previous comment to import
loadingStateContext
directly.
60-60
: Approved: Good addition of loading state management.Setting the loading state to 'Idle' after navigation is a good practice. It ensures that the UI reflects the correct state after each step.
Consider wrapping the
setLoadingState
call in auseEffect
hook to ensure it runs after the state update has been applied:+useEffect(() => { + setLoadingState('Idle') +}, [step]) -setLoadingState('Idle')This approach ensures that the loading state is updated after the step change has been fully processed.
70-70
: Approved: Consistent loading state management in navigation.The addition of
setLoadingState('Idle')
inhandleOnPrev
ensures consistent behavior withhandleOnNext
. This is good for maintaining a predictable UI state during navigation.As suggested for
handleOnNext
, consider using auseEffect
hook here as well:+useEffect(() => { + setLoadingState('Idle') +}, [step]) -setLoadingState('Idle')This ensures that the loading state is updated after the step change has been fully processed, maintaining consistency across both navigation functions.
src/components/Dashboard/index.tsx (3)
188-188
: LGTM: AddressLink component integration.The AddressLink component is correctly implemented, replacing the previous address rendering. This change aligns with the PR objectives to introduce links for shortened addresses, improving the user interface.
Consider adding a brief comment explaining the fallback logic for the address prop, as it might not be immediately clear to other developers why there are multiple fallbacks.
-<AddressLink address={link.address ?? address ?? ''} /> +{/* Use link address if available, fallback to connected wallet address, or empty string as last resort */} +<AddressLink address={link.address ?? address ?? ''} />
Line range hint
70-72
: Fix dependency array in useEffect hook.The dependency array for this useEffect hook is commented out, which could lead to unnecessary re-renders and potential bugs. Uncomment and include the correct dependencies.
Apply this change:
- // }, [currentPage, dashboardData]) +}, [currentPage, dashboardData, fetchLinkDetailsAsync])Make sure to include all variables used inside the effect that may change over time.
Line range hint
1-265
: Consider performance optimizations.The Dashboard component handles complex state management and rendering logic. To improve performance, consider the following optimizations:
- Memoize child components to prevent unnecessary re-renders.
- Use
useMemo
for expensive computations like filtering and sorting.- Implement virtualization for long lists to improve rendering performance.
Here's an example of how you could memoize a child component:
import React, { memo } from 'react'; const MobileItemComponent = memo(({ linkDetail, address }: { linkDetail: LinkDetail, address: string }) => { // Component logic here }); export default MobileItemComponent;Then, in the Dashboard component:
import MobileItemComponent from './MobileItemComponent'; // ... inside the render method {filteredDashboardData .slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage) .map((link) => ( <MobileItemComponent key={(link.link ?? link.txHash ?? '') + Math.random()} linkDetail={link} address={address ?? ''} /> ))}This change can help reduce unnecessary re-renders of the mobile items when the parent component updates.
src/components/Claim/Link/Onchain/Confirm.view.tsx (2)
188-188
: LGTM: Improved recipient address display with AddressLink component.The use of the
AddressLink
component enhances the UI and aligns with the PR objectives. It likely provides a more interactive and consistent way of displaying addresses across the application.Consider adding a brief comment explaining the fallback logic:
<AddressLink address={recipient.name ?? recipient.address ?? ''} /> {/* Uses recipient's name if available, falls back to address, or empty string as last resort */}
Line range hint
93-109
: Consider addressing the commented-out useEffect hook.There's a commented-out
useEffect
hook that appears to be responsible for fetching and setting the file type based on the attachment URL. If this functionality is no longer needed, it would be cleaner to remove it entirely. If it's still required but currently problematic, consider creating a separate issue to track its implementation.If the functionality is no longer needed, you can safely remove this commented-out code. If it's still required but currently problematic, please create a separate issue to track its implementation and add a TODO comment explaining why it's commented out:
// TODO: Implement file type detection for attachments (Issue #XXX) // useEffect(() => { // ... // }, [attachment?.attachmentUrl])src/components/Profile/Components/TableComponent.tsx (1)
112-112
: LGTM: Improved address display using AddressLink component.The replacement of
utils.printableAddress
with theAddressLink
component enhances the presentation of addresses in the history tab. This change aligns with the PR objectives and likely improves user interaction with address fields.Consider adding a brief comment explaining the purpose of the
AddressLink
component for better code documentation.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (12)
- src/components/Claim/Link/Onchain/Confirm.view.tsx (2 hunks)
- src/components/Dashboard/components/MobileComponent.tsx (2 hunks)
- src/components/Dashboard/index.tsx (2 hunks)
- src/components/Global/AddressLink/index.tsx (1 hunks)
- src/components/Profile/Components/TableComponent.tsx (2 hunks)
- src/components/Profile/index.tsx (2 hunks)
- src/components/Request/Pay/Pay.tsx (4 hunks)
- src/components/Request/Pay/Views/Initial.view.tsx (10 hunks)
- src/components/Request/Pay/Views/Success.view.tsx (3 hunks)
- src/constants/loadingStates.consts.ts (1 hunks)
- src/context/tokenSelector.context.tsx (6 hunks)
- src/utils/general.utils.ts (1 hunks)
🧰 Additional context used
📓 Learnings (3)
src/components/Request/Pay/Views/Initial.view.tsx (5)
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#410 File: src/components/Request/Pay/Views/Initial.view.tsx:87-93 Timestamp: 2024-10-08T20:13:42.967Z Learning: When refactoring to eliminate code duplication, prioritize readability and consider whether the change significantly improves the code. If it doesn't enhance readability or maintainability, it's acceptable to keep the existing code structure.
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#410 File: src/components/Request/Pay/Views/Initial.view.tsx:87-93 Timestamp: 2024-10-03T14:57:44.520Z Learning: When refactoring to eliminate code duplication, prioritize readability and consider whether the change significantly improves the code. If it doesn't enhance readability or maintainability, it's acceptable to keep the existing code structure.
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#422 File: src/components/Request/Pay/Views/Initial.view.tsx:76-78 Timestamp: 2024-10-08T20:13:44.480Z Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(estimatedGasCost, 3)` return strings, ensuring consistent return types for `calculatedFee`.
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#422 File: src/components/Request/Pay/Views/Initial.view.tsx:76-78 Timestamp: 2024-10-07T15:28:25.280Z Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(estimatedGasCost, 3)` return strings, ensuring consistent return types for `calculatedFee`.
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#422 File: src/components/Request/Pay/Views/Initial.view.tsx:76-78 Timestamp: 2024-10-08T20:13:42.967Z Learning: In `src/components/Request/Pay/Views/Initial.view.tsx`, both `txFee` and `utils.formatTokenAmount(estimatedGasCost, 3)` return strings, ensuring consistent return types for `calculatedFee`.
src/components/Request/Pay/Views/Success.view.tsx (3)
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#409 File: src/components/Request/Pay/Views/Success.view.tsx:23-23 Timestamp: 2024-10-03T12:52:52.740Z Learning: In the `SuccessView` component, `transactionHash` remains constant because we are in a success view, so it's unnecessary to include it in the dependency array of `useEffect` hooks.
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#409 File: src/components/Request/Pay/Views/Success.view.tsx:23-23 Timestamp: 2024-10-08T20:13:42.967Z Learning: In the `SuccessView` component, `transactionHash` remains constant because we are in a success view, so it's unnecessary to include it in the dependency array of `useEffect` hooks.
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#409 File: src/components/Request/Pay/Views/Success.view.tsx:23-23 Timestamp: 2024-10-08T20:13:44.480Z Learning: In the `SuccessView` component, `transactionHash` remains constant because we are in a success view, so it's unnecessary to include it in the dependency array of `useEffect` hooks.
src/context/tokenSelector.context.tsx (4)
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#413 File: src/context/tokenSelector.context.tsx:118-123 Timestamp: 2024-10-08T20:13:42.967Z Learning: In the `TokenContextProvider` component within `src/context/tokenSelector.context.tsx`, in the TypeScript React application, when data changes and before calling `fetchAndSetTokenPrice`, it is necessary to reset `selectedTokenData`, `selectedTokenPrice`, `selectedTokenDecimals`, and `inputDenomination` to discard stale data.
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#413 File: src/context/tokenSelector.context.tsx:118-123 Timestamp: 2024-10-04T13:40:16.067Z Learning: In the `TokenContextProvider` component within `src/context/tokenSelector.context.tsx`, in the TypeScript React application, when data changes and before calling `fetchAndSetTokenPrice`, it is necessary to reset `selectedTokenData`, `selectedTokenPrice`, `selectedTokenDecimals`, and `inputDenomination` to discard stale data.
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#404 File: src/context/tokenSelector.context.tsx:121-121 Timestamp: 2024-10-08T20:13:42.967Z Learning: In `TokenContextProvider` within `tokenSelector.context.tsx`, when token data is loaded from preferences, it's acceptable to set `isTokenPriceFetchingComplete` to `true` because the token data is already available.
Learnt from: jjramirezn PR: peanutprotocol/peanut-ui#404 File: src/context/tokenSelector.context.tsx:121-121 Timestamp: 2024-10-03T09:57:43.885Z Learning: In `TokenContextProvider` within `tokenSelector.context.tsx`, when token data is loaded from preferences, it's acceptable to set `isTokenPriceFetchingComplete` to `true` because the token data is already available.
🔇 Additional comments (19)
src/components/Global/AddressLink/index.tsx (3)
1-6
: LGTM: Imports and component declaration are well-structured.The imports and component declaration follow React and TypeScript best practices. The use of typed props enhances code reliability.
28-28
: LGTM: Component export is correct.The default export of the AddressLink component follows standard React component export patterns.
1-28
: Overall assessment: Well-implemented component with minor suggestions for improvement.The AddressLink component is well-structured and aligns with the PR objectives of improving the user interface. It effectively handles both regular Ethereum addresses and ENS names, providing a more interactive experience for users.
Key strengths:
- Proper use of React hooks for state management and side effects.
- Conditional rendering based on address validity.
- Integration with Next.js Link component for external links.
Suggestions for improvement:
- Enhanced error handling for ENS resolution.
- Improved accessibility with aria-labels.
These minor enhancements will further increase the robustness and accessibility of the component.
src/components/Dashboard/components/MobileComponent.tsx (1)
2-2
: LGTM: New import for AddressLink component.The addition of the
AddressLink
import is consistent with the PR objectives to enhance the presentation of addresses. This change aligns well with the overall goal of improving the user interface.src/context/tokenSelector.context.tsx (4)
28-28
: LGTM: New state variable added to contextThe addition of
isFetchingTokenData
to the context is appropriate. This boolean state will allow components to react to the token data fetching status, improving the overall user experience.
43-43
: LGTM: State management for isFetchingTokenDataThe
isFetchingTokenData
state is correctly initialized and provided in the context value. This implementation allows proper management and distribution of the token data fetching status throughout the application.Also applies to: 151-151
Line range hint
111-116
: LGTM: Improved state management in useEffectThe changes in the
useEffect
hook improve the state management before fetching token data:
- Setting
isFetchingTokenData
totrue
before initiating the fetch is consistent with the overall state management approach.- Resetting
selectedTokenData
,selectedTokenPrice
,selectedTokenDecimals
, andinputDenomination
before fetching aligns with the previously learned best practice of discarding stale data.These changes ensure that the component always starts with a clean slate when fetching new token data, preventing potential issues with outdated information.
Line range hint
1-157
: Summary: Improved token data fetching and state managementThe changes in this file consistently implement the new
isFetchingTokenData
state, enhancing the overall state management and potentially improving the user experience. The modifications:
- Add
isFetchingTokenData
to the context and component state.- Properly manage the fetching status in the
fetchAndSetTokenPrice
function.- Reset relevant state variables before initiating a new fetch in the
useEffect
hook.These improvements align with best practices for managing asynchronous operations and preventing stale data issues. The only suggestion for improvement is to consider using a try-catch-finally structure in the
fetchAndSetTokenPrice
function for more robust error handling.Overall, these changes should lead to a more responsive and reliable token selection experience for users.
src/components/Request/Pay/Pay.tsx (1)
Line range hint
1-190
: Overall, good improvements to state management and code organization.The changes in this file align well with the PR objectives of refactoring state handling and improving the request pay flow. The introduction of the loading state context and its usage in navigation functions is a positive step towards more centralized and efficient state management.
A few minor suggestions have been made to further improve code quality:
- More specific imports for the context module.
- Direct destructuring of the context value in the
useContext
call.- Using
useEffect
for setting the loading state after navigation to ensure it runs after state updates are applied.These changes contribute to better code organization, readability, and potentially more predictable behavior. Great work on improving the component's structure and state management!
src/components/Dashboard/index.tsx (2)
6-6
: LGTM: New import for AddressLink component.The import statement for the AddressLink component is correctly placed and follows the existing import structure.
Line range hint
1-265
: Summary of Dashboard component reviewThe changes made to the Dashboard component, particularly the integration of the AddressLink component, align well with the PR objectives and improve the user interface. The implementation is correct and maintains the existing functionality.
However, there are a few areas for improvement:
- The useEffect hook on line 70 needs its dependency array fixed to prevent potential bugs and unnecessary re-renders.
- The component could benefit from performance optimizations, such as memoization and virtualization, to handle large datasets more efficiently.
- Some parts of the code, like the address fallback logic, could use additional comments for clarity.
Overall, the changes are positive, but addressing these points would further enhance the component's performance and maintainability.
src/components/Claim/Link/Onchain/Confirm.view.tsx (2)
3-3
: LGTM: New import for AddressLink component.The import statement for the
AddressLink
component is correctly placed and follows the existing import structure. This global component will likely improve consistency in how addresses are displayed across the application.
Line range hint
1-324
: Summary: Improved address display enhances UI consistency.The changes in this file successfully introduce the
AddressLink
component for displaying recipient addresses. This modification aligns with the PR objectives of introducing links for shortened addresses and improves UI consistency. The implementation is clean and doesn't introduce any apparent issues.Key improvements:
- Added import for the
AddressLink
component.- Updated the recipient address display to use the new component.
These changes contribute to a more interactive and consistent user interface across the application.
src/components/Profile/Components/TableComponent.tsx (2)
6-6
: LGTM: New import for AddressLink component.The addition of the
AddressLink
import is appropriate and aligns with the component's updated rendering logic for addresses.
Line range hint
1-252
: Overall assessment: Positive improvement to address display.The changes to the
TableComponent
successfully integrate the newAddressLink
component for improved address display in the history tab. This enhancement aligns with the PR objectives and the AI-generated summary, providing a more user-friendly interface for address interaction.The modifications are minimal and focused, maintaining the overall structure and functionality of the component while improving a specific aspect of the user interface.
src/components/Profile/index.tsx (2)
4-4
: New import statement looks good.The
AddressLink
component is correctly imported from the relative path. This follows good practices for organizing and importing local components.
565-565
: Great improvement in address display!The replacement of
utils.printableAddress(referral.address)
with<AddressLink address={referral.address} />
enhances the user interface by providing a more interactive way to display addresses. This change aligns well with the PR objective of introducing links for shortened addresses, potentially improving user experience and functionality.src/utils/general.utils.ts (1)
238-242
: Good addition to the formatting utilitiesThe new
formatAmountWithSignificantDigits
function is a valuable addition to the utility file. It complements the existing formatting functions and follows the established coding style. Consider implementing the suggested improvements to make it more robust and user-friendly.src/components/Request/Pay/Views/Success.view.tsx (1)
83-100
: Overall, great improvements to user feedback and transaction handlingThe updates to the loading states and messages enhance the user experience by providing clear indications of the transaction status. The use of the
AddressLink
component improves address presentation.
const isButtonDisabled = useMemo(() => { | ||
return ( | ||
viewState === ViewState.LOADING || | ||
viewState === ViewState.ERROR || | ||
(viewState === ViewState.READY_TO_PAY && !calculatedFee) | ||
) | ||
}, [viewState, isLoading, calculatedFee]) | ||
|
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.
Remove unnecessary dependency isLoading
from isButtonDisabled
's dependency array
In the isButtonDisabled
useMemo, isLoading
is included in the dependency array but is not used within the function. This can lead to unnecessary re-executions of the useMemo. Consider removing isLoading
from the dependency array.
Apply this diff to fix the issue:
- }, [viewState, isLoading, calculatedFee])
+ }, [viewState, calculatedFee])
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const isButtonDisabled = useMemo(() => { | |
return ( | |
viewState === ViewState.LOADING || | |
viewState === ViewState.ERROR || | |
(viewState === ViewState.READY_TO_PAY && !calculatedFee) | |
) | |
}, [viewState, isLoading, calculatedFee]) | |
const isButtonDisabled = useMemo(() => { | |
return ( | |
viewState === ViewState.LOADING || | |
viewState === ViewState.ERROR || | |
(viewState === ViewState.READY_TO_PAY && !calculatedFee) | |
) | |
}, [viewState, calculatedFee]) |
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.
Good Job overall - particularly like the AddressLink component
I feel like the request payment views are quite complex and have a lot of state and state dependencies that can go wrong and are hard to reason about - any idea on how we can make this simpler?
State management and flow is something that have to be done once and then forget, I agree that right now is far from ideal. Maybe mapping the states and transitions and then implementing that would help, due to the reactive nature of React (lol) special attention have to be paid to the transition Here is an example only for one view (the pay one) and without labelling the transitions (that's the tricky part) stateDiagram-v2
[*] --> Initial
Initial --> Loading
Loading --> Error
Loading --> ReadyToClaim
Error --> Loading
ReadyToClaim --> Loading
ReadyToClaim --> [*]
|
Also