-
Notifications
You must be signed in to change notification settings - Fork 1
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/my token interaction #9
base: master
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThe recent changes introduce a comprehensive update to enhance token interactions, transaction history fetching, and environment variable management in the application. Changes
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 as PR comments)
Additionally, you can add CodeRabbit Configration 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.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files ignored due to path filters (3)
package.json
is excluded by:!**/*.json
pnpm-lock.yaml
is excluded by:!**/*.yaml
src/abis/mytoken.json
is excluded by:!**/*.json
Files selected for processing (7)
- src/App.tsx (4 hunks)
- src/components/MyTokenScreen.tsx (1 hunks)
- src/components/SwapTokensScreen.tsx (4 hunks)
- src/components/UnsupportedNetworkScreen.tsx (1 hunks)
- src/hooks/useMyToken.ts (1 hunks)
- src/store/appSlice.ts (1 hunks)
- src/utils/constants.ts (2 hunks)
Additional comments: 10
src/components/UnsupportedNetworkScreen.tsx (1)
- 30-30: The addition of
textAlign: 'center'
to theBox
component is a good UI enhancement for aligning content in the center. This change improves the visual presentation and user experience on unsupported networks.src/App.tsx (2)
- 10-10: The import of
MyTokenScreen
aligns with the PR objectives to enhance the application's token management functionalities. Good addition.- 66-66: The inclusion of
MyTokenScreen
in the application's navigation logic is a significant enhancement, enabling users to interact with and manage their tokens directly. This change effectively integrates the new screen into the app.src/utils/constants.ts (2)
- 75-75: The addition of
SEPOLIA_CHAIN_ID
is appropriate for supporting interactions with the Sepolia testnet, facilitating development and testing.- 92-92: Introducing a constant for
MY_TOKEN
with a specific contract address is a good practice for managing contract interactions, making the code more readable and maintainable.src/store/appSlice.ts (1)
- 13-13: Adding
MY_TOKEN
to theAppScreen
enum is a necessary step for integrating the newMyTokenScreen
into the application's navigation logic. This change supports the PR's objectives of enhancing token management functionalities.src/components/SwapTokensScreen.tsx (4)
- 14-16: The introduction of
useIsNetworkSupported
hook andUnsupportedNetworkScreen
component inSwapTokensScreen
is a good practice for handling network support checks and improving user experience on unsupported networks.- 25-30: Adding a
StyledGoToMyTokenButton
with specific styling enhances the UI consistency and user experience by providing a visually distinct button for navigating to theMyTokenScreen
.- 78-99: The conditional rendering based on
chainId
for theStyledGoToMyTokenButton
, using aTooltip
to indicate availability only for Sepolia, is a thoughtful UI enhancement. It guides users effectively and prevents confusion on unsupported networks.- 96-120: The conditional rendering to display either the
UnsupportedNetworkScreen
or the swap tokens interface based on network support is a crucial enhancement. It ensures users are informed and guided correctly when their network is not supported, improving the overall user experience.
…nto feat/my-token-interaction
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 Status
Actionable comments generated: 1
Configuration used: CodeRabbit UI
Files selected for processing (3)
- src/App.tsx (4 hunks)
- src/components/MyTokenScreen.tsx (1 hunks)
- src/hooks/useMyToken.ts (1 hunks)
Files skipped from review as they are similar to previous changes (2)
- src/App.tsx
- src/hooks/useMyToken.ts
Additional comments: 2
src/components/MyTokenScreen.tsx (2)
- 1-13: The imports are well-organized, separating external libraries, hooks, utilities, and components. This organization enhances readability and maintainability.
- 19-26: The
StyledTxButton
component is a good example of customizing Material UI components using thestyled
API. This approach keeps the styling consistent and reusable across different parts of the application.
src/components/MyTokenScreen.tsx
Outdated
size="small" | ||
name="amount" | ||
placeholder="amount" | ||
value={values.amount} | ||
onChange={handleChange} | ||
/> | ||
</Box> | ||
</Box> | ||
</Form> | ||
)} | ||
</Formik> | ||
|
||
<Formik | ||
initialValues={{ | ||
to: '', | ||
amount: '', | ||
}} | ||
onSubmit={({ to, amount }) => { | ||
if (!isAddress(to) || !amount) { | ||
showSnackbar({ | ||
message: 'Invalid address or amount', | ||
severity: 'error', | ||
}); | ||
} else { | ||
mint({ | ||
to, | ||
amount: parseUnits(amount, 18), | ||
}); | ||
} | ||
}} | ||
> | ||
{({ values, handleChange, handleSubmit }) => ( | ||
<Form onSubmit={handleSubmit} style={{ width: '100%' }}> | ||
<Box display={'flex'} justifyContent={'space-between'} alignItems={'center'} gap={4}> | ||
<StyledTxButton variant="contained" type="submit"> | ||
{'mint'} | ||
</StyledTxButton> | ||
<Box display={'flex'} flexDirection={'column'} gap={1}> | ||
<TextField size="small" name="to" placeholder="address" value={values.to} onChange={handleChange} /> | ||
<TextField | ||
size="small" | ||
name="amount" | ||
placeholder="amount" | ||
value={values.amount} | ||
onChange={handleChange} | ||
/> | ||
</Box> | ||
</Box> | ||
</Form> | ||
)} | ||
</Formik> | ||
<Formik | ||
initialValues={{ | ||
from: '', | ||
amount: '', | ||
}} | ||
onSubmit={({ from, amount }) => { | ||
if (!isAddress(from) || !amount) { | ||
showSnackbar({ | ||
message: 'Invalid address or amount', | ||
severity: 'error', | ||
}); | ||
} else { | ||
burnFrom({ | ||
from, | ||
amount: parseUnits(amount, 18), | ||
}); | ||
} | ||
}} | ||
> | ||
{({ values, handleChange, handleSubmit }) => ( | ||
<Form onSubmit={handleSubmit} style={{ width: '100%' }}> | ||
<Box display={'flex'} justifyContent={'space-between'} alignItems={'center'} gap={4}> | ||
<StyledTxButton variant="contained" type="submit"> | ||
{'burnFrom'} | ||
</StyledTxButton> | ||
<Box display={'flex'} flexDirection={'column'} gap={1}> | ||
<TextField | ||
size="small" | ||
name="from" | ||
placeholder="address" | ||
value={values.from} | ||
onChange={handleChange} | ||
/> | ||
<TextField | ||
size="small" | ||
name="amount" | ||
placeholder="amount" | ||
value={values.amount} | ||
onChange={handleChange} | ||
/> | ||
</Box> | ||
</Box> | ||
</Form> | ||
)} | ||
</Formik> | ||
</Box> | ||
</Box> | ||
</Box> | ||
); |
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 MyTokenScreen
component is comprehensive, covering various aspects of token management. However, there are several areas where improvements can be made for better maintainability, readability, and performance:
-
Code Duplication in Formik Components: There's noticeable duplication in the Formik components used for managing the blacklist, transferring tokens, minting, and burning. Consider abstracting the common logic into a reusable component or function to reduce duplication and improve maintainability.
-
Error Handling: While the
showSnackbar
function is used to display errors for invalid addresses or amounts, consider adding more robust error handling for the asynchronous operations performed by the hooks (e.g.,transfer
,mint
,burnFrom
,manageBlackList
). This could involve catching errors from these operations and displaying appropriate error messages to the user. -
Validation Logic: The validation for addresses and amounts is performed inline within the
onSubmit
functions of the Formik components. Extracting this validation logic into a separate utility function or using Formik's validation schema feature could improve code readability and reusability. -
UI Feedback for Asynchronous Operations: There's no UI feedback (e.g., loading indicators or disabled buttons) provided to the user during the execution of asynchronous operations like transferring, minting, or burning tokens. Implementing such feedback could enhance the user experience by making the application feel more responsive and informative.
-
Hardcoded Strings: There are several hardcoded strings throughout the component (e.g.,
'addToBlackList'
,'removeFromBlackList'
,'transfer'
,'mint'
,'burnFrom'
). Moving these strings to a constants file could improve maintainability and make it easier to support multiple languages in the future. -
Use of Magic Numbers: The number
18
is used as a magic number in multiple places for formatting and parsing units. Consider defining this as a constant to improve readability and maintainability.
- {formatUnits(value || 0, 18)}
+ const DECIMALS = 18;
+ {formatUnits(value || 0, DECIMALS)}
-
Styling Consistency: Ensure that the styling across different Formik components is consistent. For example, the style attribute is used directly in one of the Formik components but not in others. Consider using styled components or a consistent approach to applying styles.
-
Accessibility: Ensure that form elements have associated labels for better accessibility. This can be achieved by using the
InputLabel
component from Material UI or thearia-label
attribute.
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.
export const MyTokenScreen = (): JSX.Element => { | |
const { account } = useWeb3React(); | |
const { showSnackbar } = useSnackbar(); | |
const { data: details, isLoading: isDetailsLoading } = useMyTokenDetails(); | |
const { data: isAdmin, isLoading: isAdminLoading } = useIsAdmin(account); | |
const { data: isBlackListed, isLoading: isBlackListedLoading } = useIsBlackListed(account); | |
const { data: balanceOf, isLoading: isBalanceOfLoading } = useBalanceOf(account); | |
const { data: allowance, isLoading: isAllowanceLoading } = useAllowance(account); | |
const { mutate: transfer } = useTransfer(); | |
const { mutate: mint } = useMint(); | |
const { mutate: burnFrom } = useBurnFrom(); | |
const { mutate: manageBlackList } = useManageBlackList(); | |
return ( | |
<Box display={'flex'} flexDirection={'column'} gap={6}> | |
<Box> | |
Basic details: | |
{isDetailsLoading ? ( | |
<CircularProgress size={20} thickness={8} /> | |
) : ( | |
Object.entries(details || {}).map(([key, value]) => ( | |
<Box key={`${key}_${value}`}> | |
<Typography key={key} display="inline" color={(theme) => theme.palette.info.main}> | |
{key}: | |
</Typography>{' '} | |
<Typography display="inline" fontWeight={700}> | |
{key === 'totalSupply' ? formatUnits(value || 0, 18) : value.toString()} | |
</Typography> | |
</Box> | |
)) | |
)} | |
</Box> | |
<Box> | |
{getEllipsisString(account)}: | |
<Box> | |
<Typography display="inline" color={(theme) => theme.palette.info.main}> | |
{'hasRole(ADMIN_ROLE):'} | |
</Typography>{' '} | |
{isAdminLoading ? ( | |
<CircularProgress size={20} thickness={8} /> | |
) : isAdmin ? ( | |
<Typography display="inline" fontWeight={700} color={(theme) => theme.palette.success.main}> | |
{'true'} | |
</Typography> | |
) : ( | |
<Typography display="inline" fontWeight={700} color={(theme) => theme.palette.info.main}> | |
{'false'} | |
</Typography> | |
)} | |
</Box> | |
<Box> | |
<Typography display="inline" color={(theme) => theme.palette.info.main}> | |
{'blackList:'} | |
</Typography>{' '} | |
{isBlackListedLoading ? ( | |
<CircularProgress size={20} thickness={8} /> | |
) : isBlackListed ? ( | |
<Typography display="inline" fontWeight={700} color={(theme) => theme.palette.error.main}> | |
{'true'} | |
</Typography> | |
) : ( | |
<Typography display="inline" fontWeight={700} color={(theme) => theme.palette.success.main}> | |
{'false'} | |
</Typography> | |
)} | |
</Box> | |
<Box> | |
<Typography display="inline" color={(theme) => theme.palette.info.main}> | |
{'balanceOf:'} | |
</Typography>{' '} | |
{isBalanceOfLoading ? ( | |
<CircularProgress size={20} thickness={8} /> | |
) : ( | |
<Typography display="inline" fontWeight={700}> | |
{formatUnits(balanceOf || 0, 18)} | |
</Typography> | |
)} | |
</Box> | |
<Box> | |
<Typography display="inline" color={(theme) => theme.palette.info.main}> | |
{'allowance:'} | |
</Typography>{' '} | |
{isAllowanceLoading ? ( | |
<CircularProgress size={20} thickness={8} /> | |
) : ( | |
<Typography display="inline" fontWeight={700}> | |
{formatUnits(allowance || 0, 18)} | |
</Typography> | |
)} | |
</Box> | |
<Box display={'flex'} flexDirection={'column'} gap={2}> | |
<Formik | |
initialValues={{ | |
account: '', | |
}} | |
onSubmit={({ account }) => { | |
if (!isAddress(account)) { | |
showSnackbar({ | |
message: 'Invalid address', | |
severity: 'error', | |
}); | |
} else { | |
manageBlackList({ | |
action: 'add', | |
account, | |
}); | |
} | |
}} | |
> | |
{({ values, handleChange, handleSubmit }) => ( | |
<Form onSubmit={handleSubmit}> | |
<Box display={'flex'} justifyContent={'space-between'} alignItems={'center'} gap={4}> | |
<StyledTxButton variant="contained" type="submit"> | |
{'addToBlackList'} | |
</StyledTxButton> | |
<Box display={'flex'} flexDirection={'column'} gap={1}> | |
<TextField | |
size="small" | |
name="account" | |
placeholder="address" | |
value={values.account} | |
onChange={handleChange} | |
/> | |
</Box> | |
</Box> | |
</Form> | |
)} | |
</Formik> | |
<Formik | |
initialValues={{ | |
account: '', | |
}} | |
onSubmit={({ account }) => { | |
if (!isAddress(account)) { | |
showSnackbar({ | |
message: 'Invalid address', | |
severity: 'error', | |
}); | |
} else { | |
manageBlackList({ | |
action: 'remove', | |
account, | |
}); | |
} | |
}} | |
> | |
{({ values, handleChange, handleSubmit }) => ( | |
<Form onSubmit={handleSubmit}> | |
<Box display={'flex'} justifyContent={'space-between'} alignItems={'center'} gap={4}> | |
<StyledTxButton variant="contained" type="submit"> | |
{'removeFromBlackList'} | |
</StyledTxButton> | |
<Box display={'flex'} flexDirection={'column'} gap={1}> | |
<TextField | |
size="small" | |
name="account" | |
placeholder="address" | |
value={values.account} | |
onChange={handleChange} | |
/> | |
</Box> | |
</Box> | |
</Form> | |
)} | |
</Formik> | |
<Formik | |
initialValues={{ | |
to: '', | |
amount: '', | |
}} | |
onSubmit={({ to, amount }) => { | |
if (!isAddress(to) || !amount) { | |
showSnackbar({ | |
message: 'Invalid address or amount', | |
severity: 'error', | |
}); | |
} else { | |
transfer({ | |
to, | |
amount: parseUnits(amount, 18), | |
}); | |
} | |
}} | |
> | |
{({ values, handleChange, handleSubmit }) => ( | |
<Form onSubmit={handleSubmit} style={{ width: '100%' }}> | |
<Box display={'flex'} justifyContent={'space-between'} alignItems={'center'} gap={4}> | |
<StyledTxButton variant="contained" type="submit"> | |
{'transfer'} | |
</StyledTxButton> | |
<Box display={'flex'} flexDirection={'column'} gap={1}> | |
<TextField size="small" name="to" placeholder="address" value={values.to} onChange={handleChange} /> | |
<TextField | |
size="small" | |
name="amount" | |
placeholder="amount" | |
value={values.amount} | |
onChange={handleChange} | |
/> | |
</Box> | |
</Box> | |
</Form> | |
)} | |
</Formik> | |
<Formik | |
initialValues={{ | |
to: '', | |
amount: '', | |
}} | |
onSubmit={({ to, amount }) => { | |
if (!isAddress(to) || !amount) { | |
showSnackbar({ | |
message: 'Invalid address or amount', | |
severity: 'error', | |
}); | |
} else { | |
mint({ | |
to, | |
amount: parseUnits(amount, 18), | |
}); | |
} | |
}} | |
> | |
{({ values, handleChange, handleSubmit }) => ( | |
<Form onSubmit={handleSubmit} style={{ width: '100%' }}> | |
<Box display={'flex'} justifyContent={'space-between'} alignItems={'center'} gap={4}> | |
<StyledTxButton variant="contained" type="submit"> | |
{'mint'} | |
</StyledTxButton> | |
<Box display={'flex'} flexDirection={'column'} gap={1}> | |
<TextField size="small" name="to" placeholder="address" value={values.to} onChange={handleChange} /> | |
<TextField | |
size="small" | |
name="amount" | |
placeholder="amount" | |
value={values.amount} | |
onChange={handleChange} | |
/> | |
</Box> | |
</Box> | |
</Form> | |
)} | |
</Formik> | |
<Formik | |
initialValues={{ | |
from: '', | |
amount: '', | |
}} | |
onSubmit={({ from, amount }) => { | |
if (!isAddress(from) || !amount) { | |
showSnackbar({ | |
message: 'Invalid address or amount', | |
severity: 'error', | |
}); | |
} else { | |
burnFrom({ | |
from, | |
amount: parseUnits(amount, 18), | |
}); | |
} | |
}} | |
> | |
{({ values, handleChange, handleSubmit }) => ( | |
<Form onSubmit={handleSubmit} style={{ width: '100%' }}> | |
<Box display={'flex'} justifyContent={'space-between'} alignItems={'center'} gap={4}> | |
<StyledTxButton variant="contained" type="submit"> | |
{'burnFrom'} | |
</StyledTxButton> | |
<Box display={'flex'} flexDirection={'column'} gap={1}> | |
<TextField | |
size="small" | |
name="from" | |
placeholder="address" | |
value={values.from} | |
onChange={handleChange} | |
/> | |
<TextField | |
size="small" | |
name="amount" | |
placeholder="amount" | |
value={values.amount} | |
onChange={handleChange} | |
/> | |
</Box> | |
</Box> | |
</Form> | |
)} | |
</Formik> | |
</Box> | |
</Box> | |
</Box> | |
); | |
export const MyTokenScreen = (): JSX.Element => { | |
const { account } = useWeb3React(); | |
const { showSnackbar } = useSnackbar(); | |
const { data: details, isLoading: isDetailsLoading } = useMyTokenDetails(); | |
const { data: isAdmin, isLoading: isAdminLoading } = useIsAdmin(account); | |
const { data: isBlackListed, isLoading: isBlackListedLoading } = useIsBlackListed(account); | |
const { data: balanceOf, isLoading: isBalanceOfLoading } = useBalanceOf(account); | |
const { data: allowance, isLoading: isAllowanceLoading } = useAllowance(account); | |
const { mutate: transfer } = useTransfer(); | |
const { mutate: mint } = useMint(); | |
const { mutate: burnFrom } = useBurnFrom(); | |
const { mutate: manageBlackList } = useManageBlackList(); | |
const DECIMALS = 18; | |
return ( | |
<Box display={'flex'} flexDirection={'column'} gap={6}> | |
<Box> | |
Basic details: | |
{isDetailsLoading ? ( | |
<CircularProgress size={20} thickness={8} /> | |
) : ( | |
Object.entries(details || {}).map(([key, value]) => ( | |
<Box key={`${key}_${value}`}> | |
<Typography key={key} display="inline" color={(theme) => theme.palette.info.main}> | |
{key}: | |
</Typography>{' '} | |
<Typography display="inline" fontWeight={700}> | |
{key === 'totalSupply' ? formatUnits(value || 0, DECIMALS) : value.toString()} | |
</Typography> | |
</Box> | |
)) | |
)} | |
</Box> | |
<Box> | |
{getEllipsisString(account)}: | |
<Box> | |
<Typography display="inline" color={(theme) => theme.palette.info.main}> | |
{'hasRole(ADMIN_ROLE):'} | |
</Typography>{' '} | |
{isAdminLoading ? ( | |
<CircularProgress size={20} thickness={8} /> | |
) : isAdmin ? ( | |
<Typography display="inline" fontWeight={700} color={(theme) => theme.palette.success.main}> | |
{'true'} | |
</Typography> | |
) : ( | |
<Typography display="inline" fontWeight={700} color={(theme) => theme.palette.info.main}> | |
{'false'} | |
</Typography> | |
)} | |
</Box> | |
<Box> | |
<Typography display="inline" color={(theme) => theme.palette.info.main}> | |
{'blackList:'} | |
</Typography>{' '} | |
{isBlackListedLoading ? ( | |
<CircularProgress size={20} thickness={8} /> | |
) : isBlackListed ? ( | |
<Typography display="inline" fontWeight={700} color={(theme) => theme.palette.error.main}> | |
{'true'} | |
</Typography> | |
) : ( | |
<Typography display="inline" fontWeight={700} color={(theme) => theme.palette.success.main}> | |
{'false'} | |
</Typography> | |
)} | |
</Box> | |
<Box> | |
<Typography display="inline" color={(theme) => theme.palette.info.main}> | |
{'balanceOf:'} | |
</Typography>{' '} | |
{isBalanceOfLoading ? ( | |
<CircularProgress size={20} thickness={8} /> | |
) : ( | |
<Typography display="inline" fontWeight={700}> | |
{formatUnits(balanceOf || 0, DECIMALS)} | |
</Typography> | |
)} | |
</Box> | |
<Box> | |
<Typography display="inline" color={(theme) => theme.palette.info.main}> | |
{'allowance:'} | |
</Typography>{' '} | |
{isAllowanceLoading ? ( | |
<CircularProgress size={20} thickness={8} /> | |
) : ( | |
<Typography display="inline" fontWeight={700}> | |
{formatUnits(allowance || 0, DECIMALS)} | |
</Typography> | |
)} | |
</Box> | |
<Box display={'flex'} flexDirection={'column'} gap={2}> | |
<Formik | |
initialValues={{ | |
account: '', | |
}} | |
onSubmit={({ account }) => { | |
if (!isAddress(account)) { | |
showSnackbar({ | |
message: 'Invalid address', | |
severity: 'error', | |
}); | |
} else { | |
manageBlackList({ | |
action: 'add', | |
account, | |
}); | |
} | |
}} | |
> | |
{({ values, handleChange, handleSubmit }) => ( | |
<Form onSubmit={handleSubmit}> | |
<Box display={'flex'} justifyContent={'space-between'} alignItems={'center'} gap={4}> | |
<StyledTxButton variant="contained" type="submit"> | |
{'addToBlackList'} | |
</StyledTxButton> | |
<Box display={'flex'} flexDirection={'column'} gap={1}> | |
<TextField | |
size="small" | |
name="account" | |
placeholder="address" | |
value={values.account} | |
onChange={handleChange} | |
/> | |
</Box> | |
</Box> | |
</Form> | |
)} | |
</Formik> | |
<Formik | |
initialValues={{ | |
account: '', | |
}} | |
onSubmit={({ account }) => { | |
if (!isAddress(account)) { | |
showSnackbar({ | |
message: 'Invalid address', | |
severity: 'error', | |
}); | |
} else { | |
manageBlackList({ | |
action: 'remove', | |
account, | |
}); | |
} | |
}} | |
> | |
{({ values, handleChange, handleSubmit }) => ( | |
<Form onSubmit={handleSubmit}> | |
<Box display={'flex'} justifyContent={'space-between'} alignItems={'center'} gap={4}> | |
<StyledTxButton variant="contained" type="submit"> | |
{'removeFromBlackList'} | |
</StyledTxButton> | |
<Box display={'flex'} flexDirection={'column'} gap={1}> | |
<TextField | |
size="small" | |
name="account" | |
placeholder="address" | |
value={values.account} | |
onChange={handleChange} | |
/> | |
</Box> | |
</Box> | |
</Form> | |
)} | |
</Formik> | |
<Formik | |
initialValues={{ | |
to: '', | |
amount: '', | |
}} | |
onSubmit={({ to, amount }) => { | |
if (!isAddress(to) || !amount) { | |
showSnackbar({ | |
message: 'Invalid address or amount', | |
severity: 'error', | |
}); | |
} else { | |
transfer({ | |
to, | |
amount: parseUnits(amount, DECIMALS), | |
}); | |
} | |
}} | |
> | |
{({ values, handleChange, handleSubmit }) => ( | |
<Form onSubmit={handleSubmit} style={{ width: '100%' }}> | |
<Box display={'flex'} justifyContent={'space-between'} alignItems={'center'} gap={4}> | |
<StyledTxButton variant="contained" type="submit"> | |
{'transfer'} | |
</StyledTxButton> | |
<Box display={'flex'} flexDirection={'column'} gap={1}> | |
<TextField size="small" name="to" placeholder="address" value={values.to} onChange={handleChange} /> | |
<TextField | |
size="small" | |
name="amount" | |
placeholder="amount" | |
value={values.amount} | |
onChange={handleChange} | |
/> | |
</Box> | |
</Box> | |
</Form> | |
)} | |
</Formik> | |
<Formik | |
initialValues={{ | |
to: '', | |
amount: '', | |
}} | |
onSubmit={({ to, amount }) => { | |
if (!isAddress(to) || !amount) { | |
showSnackbar({ | |
message: 'Invalid address or amount', | |
severity: 'error', | |
}); | |
} else { | |
mint({ | |
to, | |
amount: parseUnits(amount, DECIMALS), | |
}); | |
} | |
}} | |
> | |
{({ values, handleChange, handleSubmit }) => ( | |
<Form onSubmit={handleSubmit} style={{ width: '100%' }}> | |
<Box display={'flex'} justifyContent={'space-between'} alignItems={'center'} gap={4}> | |
<StyledTxButton variant="contained" type="submit"> | |
{'mint'} | |
</StyledTxButton> | |
<Box display={'flex'} flexDirection={'column'} gap={1}> | |
<TextField size="small" name="to" placeholder="address" value={values.to} onChange={handleChange} /> | |
<TextField | |
size="small" | |
name="amount" | |
placeholder="amount" | |
value={values.amount} | |
onChange={handleChange} | |
/> | |
</Box> | |
</Box> | |
</Form> | |
)} | |
</Formik> | |
<Formik | |
initialValues={{ | |
from: '', | |
amount: '', | |
}} | |
onSubmit={({ from, amount }) => { | |
if (!isAddress(from) || !amount) { | |
showSnackbar({ | |
message: 'Invalid address or amount', | |
severity: 'error', | |
}); | |
} else { | |
burnFrom({ | |
from, | |
amount: parseUnits(amount, DECIMALS), | |
}); | |
} | |
}} | |
> | |
{({ values, handleChange, handleSubmit }) => ( | |
<Form onSubmit={handleSubmit} style={{ width: '100%' }}> | |
<Box display={'flex'} justifyContent={'space-between'} alignItems={'center'} gap={4}> | |
<StyledTxButton variant="contained" type="submit"> | |
{'burnFrom'} | |
</StyledTxButton> | |
<Box display={'flex'} flexDirection={'column'} gap={1}> | |
<TextField | |
size="small" | |
name="from" | |
placeholder="address" | |
value={values.from} | |
onChange={handleChange} | |
/> | |
<TextField | |
size="small" | |
name="amount" | |
placeholder="amount" | |
value={values.amount} | |
onChange={handleChange} | |
/> | |
</Box> | |
</Box> | |
</Form> | |
)} | |
</Formik> | |
</Box> | |
</Box> | |
</Box> | |
); |
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 Status
Actionable comments generated: 3
Configuration used: CodeRabbit UI
Files selected for processing (5)
- src/components/MyTokenScreen.tsx (1 hunks)
- src/hooks/useMyToken.ts (1 hunks)
- src/hooks/useTransactionHistory.tsx (1 hunks)
- src/utils/constants.ts (2 hunks)
- src/utils/env.ts (1 hunks)
Files skipped from review as they are similar to previous changes (3)
- src/components/MyTokenScreen.tsx
- src/hooks/useMyToken.ts
- src/utils/constants.ts
Additional comments: 2
src/hooks/useTransactionHistory.tsx (2)
- 1-4: The import statements are well-organized, and importing necessary utilities from external libraries and local files is done correctly. This ensures that the hook has access to all the required functionalities.
- 7-33: The
useTransactionHistory
hook is well-implemented, making good use of theuseQuery
hook from@tanstack/react-query
for fetching transaction history. The configuration for caching and stale time is appropriate, enhancing the performance by reducing unnecessary API calls.
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 Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (1)
- src/components/MyTokenScreen.tsx (1 hunks)
Files skipped from review as they are similar to previous changes (1)
- src/components/MyTokenScreen.tsx
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 Status
Actionable comments generated: 2
Configuration used: CodeRabbit UI
Files selected for processing (1)
- src/hooks/useMyToken.ts (1 hunks)
Additional comments: 9
src/hooks/useMyToken.ts (9)
- 33-60: The
useMyTokenDetails
hook fetches details about the token such as name, symbol, decimals, and totalSupply. It's important to ensure that the hook correctly handles cases wheremyToken
might be null or the contract calls fail.Ensure that the contract calls within this hook are properly handled in case of failure (e.g., the contract method returns
undefined
or throws an error). This might involve adding error handling logic or ensuring that the UI can gracefully handle incomplete or missing data.
- 63-72: The
useIsAdmin
hook checks if a given address has the admin role. It's crucial to ensure that the role checking mechanism is secure and correctly implemented.Verify that the
myToken?.hasRole?.(myToken?.ADMIN_ROLE?.(), address)
call correctly checks for the admin role and consider handling cases wheremyToken
oraddress
might be undefined to prevent runtime errors.
- 75-84: The
useIsBlackListed
hook checks if a given address is blacklisted. Similar touseIsAdmin
, it's important to ensure that the blacklist checking mechanism is secure and correctly implemented.Confirm that the
myToken?.blackList?.(address)
call correctly checks for blacklisted addresses and consider adding error handling for cases wheremyToken
oraddress
might be undefined.
- 87-95: The
useBalanceOf
hook fetches the token balance of a given address. Ensuring accuracy and security in balance queries is essential.Ensure that the
myToken?.balanceOf?.(address)
call accurately fetches the token balance and consider adding error handling for cases wheremyToken
oraddress
might be undefined.
- 98-106: The
useAllowance
hook checks the allowance of a token for a given address. It's important to ensure that the allowance checking mechanism is secure and correctly implemented.Verify that the
myToken?.allowance?.(address, address)
call correctly checks for token allowance and consider handling cases wheremyToken
oraddress
might be undefined to prevent runtime errors.
- 109-126: The
useManageBlackList
hook allows adding or removing addresses from the blacklist. It's crucial to ensure that this functionality is secure and only accessible to authorized users.Confirm that the blacklist management functionality is properly secured and consider adding more detailed error handling to provide users with specific feedback based on the error encountered.
- 129-145: The
useTransfer
hook enables token transfers. Ensuring the security and correctness of token transfers is paramount.Ensure that the
myToken?.transfer?.(to, amount)
call correctly performs token transfers and consider adding error handling for cases wheremyToken
,to
, oramount
might be undefined or invalid.
- 148-164: The
useMint
hook allows minting new tokens. It's important to ensure that this functionality is secure and only accessible to authorized users.Verify that the minting functionality is properly secured and consider adding more detailed error handling to provide users with specific feedback based on the error encountered.
- 167-183: The
useBurnFrom
hook enables burning tokens from a specified address. Ensuring the security and correctness of token burning is crucial.Ensure that the
myToken?.burnFrom?.(from, amount)
call correctly performs token burning and consider adding error handling for cases wheremyToken
,from
, oramount
might be undefined or invalid.
import { MY_TOKEN } from '~/utils/constants'; | ||
import { useSnackbar } from './useSnackbar'; | ||
|
||
// the most of this hooks probably will be deleted after pdp |
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 comment on line 10 mentions that most of these hooks will probably be deleted after PDP (Product Development Phase). It's important to track such TODOs or temporary comments to ensure they are addressed before moving to production.
Would you like me to help track this task or remind you to review these hooks before production deployment?
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore | ||
// todo: need to fix type mismatch between ethers and @web3-react | ||
provider.getSigner(), |
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 use of @ts-ignore
to bypass TypeScript type checking is generally discouraged as it can hide potential type mismatches or errors. It's mentioned that there's a need to fix a type mismatch between ethers and @web3-react. It's crucial to address this issue properly to ensure type safety and avoid runtime errors.
Consider resolving the type mismatch by defining appropriate types or using type assertions that are more specific than @ts-ignore
. This approach will help maintain type safety and code quality.
Summary by CodeRabbit