-
Notifications
You must be signed in to change notification settings - Fork 537
[TOOL-4531] Dashboard: Add Token Asset creation wizard #7081
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
base: main
Are you sure you want to change the base?
[TOOL-4531] Dashboard: Add Token Asset creation wizard #7081
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #7081 +/- ##
=======================================
Coverage 55.61% 55.61%
=======================================
Files 902 902
Lines 58177 58177
Branches 4085 4085
=======================================
Hits 32356 32356
Misses 25716 25716
Partials 105 105
🚀 New features to boost your workflow:
|
size-limit report 📦
|
7f8c64d
to
c37589e
Compare
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/form.ts
Outdated
Show resolved
Hide resolved
c37589e
to
dbe4965
Compare
...ard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx
Outdated
Show resolved
Hide resolved
1dc928b
to
b5e5f6e
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.
Actionable comments posted: 2
♻️ Duplicate comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx (1)
111-114
: 🛠️ Refactor suggestionForm values may require explicit validation before launch
When combining form values for the launch step, there's no validation that both forms are valid. The previous review comments mentioned this issue.
<LaunchTokenStatus client={props.client} onPrevious={() => { setStep("distribution"); }} createTokenFunctions={props.createTokenFunctions} + validateForms={async () => { + const [infoValid, distValid] = await Promise.all([ + tokenInfoForm.trigger(), + tokenDistributionForm.trigger() + ]); + return infoValid && distValid; + }} values={{ ...tokenInfoForm.getValues(), ...tokenDistributionForm.getValues(), }} />Adding a validation function that can be called before launching would ensure both forms are valid at the time of launch.
🧹 Nitpick comments (3)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx (3)
3-6
: Clean up empty importsThere are several empty imports that should be removed or populated with actual imports:
-import {} from "@/components/blocks/multi-step-status/multi-step-status"; -import {} from "@/components/ui/dialog"; -import {} from "lucide-react"; +// Import specific components if needed, or remove these linesEmpty imports add unnecessary noise to the codebase and can be confusing for other developers.
48-48
: Consider making the default chain ID configurableThe code uses a hardcoded fallback of "1" (Ethereum mainnet) when no active chain is detected. This might not be the intended default for all use cases.
-chain: activeChain?.id ? activeChain.id.toString() : "1", +chain: activeChain?.id ? activeChain.id.toString() : process.env.NEXT_PUBLIC_DEFAULT_CHAIN_ID || "1",This would make the default chain configurable via environment variables.
78-118
: Consider adding error boundaries and loading statesThe component doesn't include error handling for potential API failures or loading states during transitions between steps or form submissions.
Consider wrapping the main component or each step with an error boundary component and adding loading indicators during transitions or API calls to improve user experience.
import { ErrorBoundary } from 'react-error-boundary'; import { LoadingSpinner } from '@/components/ui/loading-spinner'; // Then in your render method: <ErrorBoundary fallback={<div>Something went wrong</div>}> {isLoading && <LoadingSpinner />} {!isLoading && ( // Your existing UI code )} </ErrorBoundary>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (34)
apps/dashboard/src/@/components/blocks/distribution-chart.tsx
(1 hunks)apps/dashboard/src/@/components/blocks/multi-step-status/multi-step-status.stories.tsx
(1 hunks)apps/dashboard/src/@/components/blocks/multi-step-status/multi-step-status.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/index.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/supply-layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/DeployedContractsPageHeader.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/DeployViaCLIOrImportCard.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/DeployedContractsPage.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/getProjectContracts.ts
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/getSortedDeployedContracts.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/cards.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-card.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.stories.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-airdrop.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-distribution.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-sale.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/form.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/launch/launch-token.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/token-info-fieldset.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/tracking.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/components/ProjectSidebarLayout.tsx
(3 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/connect/account-abstraction/factories/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/hooks/project-contracts.ts
(1 hunks)apps/dashboard/src/components/contract-components/contract-deploy-form/custom-contract.tsx
(1 hunks)apps/dashboard/src/components/contract-components/import-contract/modal.tsx
(7 hunks)apps/dashboard/src/components/contract-components/tables/contract-table.stories.tsx
(6 hunks)apps/dashboard/src/components/contract-components/tables/contract-table.tsx
(6 hunks)apps/dashboard/src/contract-ui/components/solidity-inputs/address-input.tsx
(3 hunks)apps/dashboard/src/global.css
(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/supply-layout.tsx
- apps/dashboard/src/contract-ui/components/solidity-inputs/address-input.tsx
🚧 Files skipped from review as they are similar to previous changes (31)
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/connect/account-abstraction/factories/page.tsx
- apps/dashboard/src/app/(app)/account/contracts/_components/DeployViaCLIOrImportCard.tsx
- apps/dashboard/src/global.css
- apps/dashboard/src/app/(app)/account/contracts/_components/DeployedContractsPage.tsx
- apps/dashboard/src/app/(app)/account/contracts/DeployedContractsPageHeader.tsx
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/components/ProjectSidebarLayout.tsx
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/index.tsx
- apps/dashboard/src/app/(app)/account/contracts/_components/getSortedDeployedContracts.tsx
- apps/dashboard/src/components/contract-components/contract-deploy-form/custom-contract.tsx
- apps/dashboard/src/app/(app)/account/contracts/_components/getProjectContracts.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/hooks/project-contracts.ts
- apps/dashboard/src/@/components/blocks/multi-step-status/multi-step-status.stories.tsx
- apps/dashboard/src/components/contract-components/tables/contract-table.stories.tsx
- apps/dashboard/src/components/contract-components/tables/contract-table.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/cards.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/page.tsx
- apps/dashboard/src/@/components/blocks/distribution-chart.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.stories.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/page.tsx
- apps/dashboard/src/components/contract-components/import-contract/modal.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-sale.tsx
- apps/dashboard/src/@/components/blocks/multi-step-status/multi-step-status.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-card.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/launch/launch-token.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-distribution.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-airdrop.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/form.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/tracking.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/token-info-fieldset.tsx
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: Size
- GitHub Check: Analyze (javascript)
🔇 Additional comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx (1)
31-119
: Overall component structure looks goodThe overall structure of the component follows good practices:
- Clearly defined step-based UI with appropriate component separation
- Proper use of React Hook Form with Zod validation
- Clean separation of form definition and rendering
- Good prop typing with ThirdwebClient and CreateTokenFunctions
...ard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx
Show resolved
Hide resolved
...ard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx
Show resolved
Hide resolved
b5e5f6e
to
8f7ed62
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.
Actionable comments posted: 0
♻️ Duplicate comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx (2)
85-87
: Add form validation before proceeding to next stepCurrently, the code transitions to the next step without validating that the current form is valid. This could lead to incomplete or invalid data being used later in the flow.
onNext={() => { + // Validate form before proceeding + tokenInfoForm.trigger().then((isValid) => { + if (isValid) { setStep("distribution"); + } + }); }}
99-101
: Add form validation before proceeding to launch stepSimilar to the previous step transition, there's no validation before moving to the launch step.
onNext={() => { + // Validate form before proceeding + tokenDistributionForm.trigger().then((isValid) => { + if (isValid) { setStep("launch"); + } + }); }}
🧹 Nitpick comments (3)
apps/dashboard/src/@/actions/revalidate.ts (1)
1-10
: Good implementation of a Next.js server action, but consider adding error handling.The implementation correctly uses the "use server" directive and properly wraps the Next.js
revalidatePath
function. However, there are a few improvements that could make this more robust:
- Add error handling with try/catch to gracefully handle any failures
- Return a success/failure status to inform the caller about the outcome
- Include JSDoc comments to document the function's purpose and usage
Here's a suggested improvement:
"use server"; import { revalidatePath } from "next/cache"; + /** + * Server action to revalidate a specific path in the Next.js cache + * @param path - The path to revalidate + * @param type - Whether to revalidate just the page or the entire layout + * @returns A result object indicating success or failure + */ export async function revalidatePathAction( path: string, type: "page" | "layout", ) { + try { revalidatePath(path, type); + return { success: true }; + } catch (error) { + console.error("Failed to revalidate path:", error); + return { + success: false, + error: error instanceof Error ? error.message : "Unknown error" + }; + } }apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx (2)
3-6
: Remove unused importsSeveral imports are declared but not used in the component:
-import {} from "@/components/blocks/multi-step-status/multi-step-status"; -import {} from "@/components/ui/dialog"; -import {} from "lucide-react";Empty import statements should be removed to keep the code clean and improve maintainability.
114-116
: Consider using a memoized combined form values objectThe form values are combined on every render of the launch step. For performance optimization, consider memoizing this object:
+const combinedFormValues = React.useMemo(() => ({ + ...tokenInfoForm.getValues(), + ...tokenDistributionForm.getValues(), +}), [tokenInfoForm, tokenDistributionForm]); {step === "launch" && ( <LaunchTokenStatus client={props.client} onLaunchSuccess={props.onLaunchSuccess} onPrevious={() => { setStep("distribution"); }} createTokenFunctions={props.createTokenFunctions} - values={{ - ...tokenInfoForm.getValues(), - ...tokenDistributionForm.getValues(), - }} + values={combinedFormValues} /> )}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (35)
apps/dashboard/src/@/actions/revalidate.ts
(1 hunks)apps/dashboard/src/@/components/blocks/distribution-chart.tsx
(1 hunks)apps/dashboard/src/@/components/blocks/multi-step-status/multi-step-status.stories.tsx
(1 hunks)apps/dashboard/src/@/components/blocks/multi-step-status/multi-step-status.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/index.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/supply-layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/DeployedContractsPageHeader.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/DeployViaCLIOrImportCard.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/DeployedContractsPage.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/getProjectContracts.ts
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/getSortedDeployedContracts.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/cards.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-card.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.stories.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-airdrop.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-distribution.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-sale.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/form.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/launch/launch-token.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/token-info-fieldset.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/tracking.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/components/ProjectSidebarLayout.tsx
(3 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/connect/account-abstraction/factories/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/hooks/project-contracts.ts
(1 hunks)apps/dashboard/src/components/contract-components/contract-deploy-form/custom-contract.tsx
(1 hunks)apps/dashboard/src/components/contract-components/import-contract/modal.tsx
(7 hunks)apps/dashboard/src/components/contract-components/tables/contract-table.stories.tsx
(6 hunks)apps/dashboard/src/components/contract-components/tables/contract-table.tsx
(6 hunks)apps/dashboard/src/contract-ui/components/solidity-inputs/address-input.tsx
(3 hunks)apps/dashboard/src/global.css
(1 hunks)
✅ Files skipped from review due to trivial changes (3)
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/supply-layout.tsx
- apps/dashboard/src/contract-ui/components/solidity-inputs/address-input.tsx
- apps/dashboard/src/@/components/blocks/multi-step-status/multi-step-status.tsx
🚧 Files skipped from review as they are similar to previous changes (30)
- apps/dashboard/src/app/(app)/account/contracts/DeployedContractsPageHeader.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/connect/account-abstraction/factories/page.tsx
- apps/dashboard/src/global.css
- apps/dashboard/src/app/(app)/account/contracts/_components/DeployViaCLIOrImportCard.tsx
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx
- apps/dashboard/src/components/contract-components/contract-deploy-form/custom-contract.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/hooks/project-contracts.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/components/ProjectSidebarLayout.tsx
- apps/dashboard/src/app/(app)/account/contracts/_components/DeployedContractsPage.tsx
- apps/dashboard/src/app/(app)/account/contracts/_components/getSortedDeployedContracts.tsx
- apps/dashboard/src/components/contract-components/tables/contract-table.stories.tsx
- apps/dashboard/src/app/(app)/account/contracts/_components/getProjectContracts.ts
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/index.tsx
- apps/dashboard/src/@/components/blocks/distribution-chart.tsx
- apps/dashboard/src/components/contract-components/tables/contract-table.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.stories.tsx
- apps/dashboard/src/components/contract-components/import-contract/modal.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/cards.tsx
- apps/dashboard/src/@/components/blocks/multi-step-status/multi-step-status.stories.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-card.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-sale.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-distribution.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/tracking.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/launch/launch-token.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/token-info-fieldset.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-airdrop.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/form.ts
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: Size
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx (1)
31-121
: LGTM: Well-structured multi-step form implementationThe overall implementation of this multi-step form is clean and well-structured. The component:
- Manages state for the current step
- Uses React Hook Form with Zod validation
- Separates concerns into different form sections
- Provides a clear interface for token creation functions
This modular approach will make the code easier to maintain and extend.
8f7ed62
to
580efa7
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.
Actionable comments posted: 0
♻️ Duplicate comments (6)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-airdrop.tsx (3)
53-56
:⚠️ Potential issueImprove totalAirdropSupply calculation to handle non-numeric quantities
The current implementation could result in NaN if any quantity is non-numeric, which would break the total calculation.
- const totalAirdropSupply = airdropAddresses.reduce( - (acc, curr) => acc + Number(curr.quantity), - 0, - ); + const totalAirdropSupply = airdropAddresses.reduce((acc, curr) => { + const qty = Number(curr.quantity); + return acc + (Number.isFinite(qty) ? qty : 0); + }, 0);
193-200
: 🛠️ Refactor suggestionAdd quantity validation in CSV parser
The CSV parser doesn't validate if quantities are valid numbers, which could lead to issues in calculations.
const csvParser = (items: AirdropAddressInput[]): AirdropAddressInput[] => { return items .map(({ address, quantity }) => ({ address: (address || "").trim(), - quantity: (quantity || "1").trim(), + quantity: (quantity || "1").trim(), + hasInvalidQuantity: isNaN(Number((quantity || "1").trim())) })) .filter(({ address }) => address !== ""); };
430-430
: 🛠️ Refactor suggestionAdd validation display for invalid quantity values
The table displays validation for invalid addresses but doesn't indicate if quantities are non-numeric.
- <TableCell>{item.quantity}</TableCell> + <TableCell> + {!isNaN(Number(item.quantity)) ? ( + item.quantity + ) : ( + <div className="flex flex-row items-center gap-2"> + <CircleAlertIcon className="size-4 text-red-500" /> + <span className="font-bold text-red-500"> + {item.quantity} + </span> + </div> + )} + </TableCell>apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/token-info-fieldset.tsx (3)
100-110
: Handle chain data load errorsThe SingleNetworkSelector lacks explicit handling for loading and error states from chain data fetching.
You should update the chain selection to handle error states and provide feedback to users when chain data fails to load.
#!/bin/bash # Check SingleNetworkSelector implementation for error handling rg -n "export function SingleNetworkSelector" -A30 -B10 --glob "*.tsx" apps/dashboard/src/@/components
48-57
: 🛠️ Refactor suggestionAdd error handling for file uploads
The FileInput component lacks explicit error handling for file uploads (size limits, format validation).
<FileInput accept={{ "image/*": [] }} value={form.watch("image")} setValue={(file) => form.setValue("image", file, { shouldTouch: true, }) } + maxSizeInBytes={5 * 1024 * 1024} // 5MB limit + onError={(error) => { + form.setError("image", { + type: "manual", + message: error.message + }); + }} className="rounded-lg border-border bg-background transition-all duration-200 hover:border-active-border hover:bg-background" />
176-191
: 🛠️ Refactor suggestionAdd URL validation for social URLs
The social URL field should validate that the input is a properly formatted URL.
<FormField control={form.control} name={`socialUrls.${index}.url`} render={({ field }) => ( <FormItem className="flex-1"> <FormControl> <Input {...field} placeholder="https://..." aria-label="Platform URL" + type="url" /> </FormControl> <FormMessage /> </FormItem> )} />
Also ensure your form schema includes URL validation for these fields.
🧹 Nitpick comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx (1)
274-304
: Consider handling zero-division edge case in sale allocationIf
totalSupply
is 0, calculating percentages could lead to unexpected results. Consider adding a guard clause to handle this edge case.const salePercent = formValues.saleEnabled ? Number(formValues.saleAllocationPercentage) : 0; const totalSupply = Number(formValues.supply); + // Guard against zero supply + if (totalSupply <= 0) { + throw new Error("Total supply must be greater than zero"); + } const totalSupplyWei = toUnits(totalSupply.toString(), 18);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (35)
apps/dashboard/src/@/actions/revalidate.ts
(1 hunks)apps/dashboard/src/@/components/blocks/distribution-chart.tsx
(1 hunks)apps/dashboard/src/@/components/blocks/multi-step-status/multi-step-status.stories.tsx
(1 hunks)apps/dashboard/src/@/components/blocks/multi-step-status/multi-step-status.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/index.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx
(1 hunks)apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/supply-layout.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/DeployedContractsPageHeader.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/DeployViaCLIOrImportCard.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/DeployedContractsPage.tsx
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/getProjectContracts.ts
(1 hunks)apps/dashboard/src/app/(app)/account/contracts/_components/getSortedDeployedContracts.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/cards.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-card.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.stories.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-airdrop.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-distribution.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-sale.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/form.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/launch/launch-token.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/token-info-fieldset.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/tracking.ts
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/components/ProjectSidebarLayout.tsx
(3 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/connect/account-abstraction/factories/page.tsx
(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/hooks/project-contracts.ts
(1 hunks)apps/dashboard/src/components/contract-components/contract-deploy-form/custom-contract.tsx
(1 hunks)apps/dashboard/src/components/contract-components/import-contract/modal.tsx
(7 hunks)apps/dashboard/src/components/contract-components/tables/contract-table.stories.tsx
(6 hunks)apps/dashboard/src/components/contract-components/tables/contract-table.tsx
(6 hunks)apps/dashboard/src/contract-ui/components/solidity-inputs/address-input.tsx
(3 hunks)apps/dashboard/src/global.css
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- apps/dashboard/src/@/components/blocks/multi-step-status/multi-step-status.tsx
🚧 Files skipped from review as they are similar to previous changes (31)
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/components/supply-layout.tsx
- apps/dashboard/src/app/(app)/account/contracts/_components/DeployViaCLIOrImportCard.tsx
- apps/dashboard/src/app/(app)/account/contracts/DeployedContractsPageHeader.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/connect/account-abstraction/factories/page.tsx
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_layout/primary-dashboard-button.tsx
- apps/dashboard/src/app/(app)/account/contracts/_components/DeployedContractsPage.tsx
- apps/dashboard/src/global.css
- apps/dashboard/src/@/actions/revalidate.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/hooks/project-contracts.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/components/ProjectSidebarLayout.tsx
- apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/index.tsx
- apps/dashboard/src/app/(app)/account/contracts/_components/getProjectContracts.ts
- apps/dashboard/src/components/contract-components/contract-deploy-form/custom-contract.tsx
- apps/dashboard/src/components/contract-components/tables/contract-table.stories.tsx
- apps/dashboard/src/@/components/blocks/multi-step-status/multi-step-status.stories.tsx
- apps/dashboard/src/app/(app)/account/contracts/_components/getSortedDeployedContracts.tsx
- apps/dashboard/src/@/components/blocks/distribution-chart.tsx
- apps/dashboard/src/components/contract-components/tables/contract-table.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.stories.tsx
- apps/dashboard/src/contract-ui/components/solidity-inputs/address-input.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-card.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-sale.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/launch/launch-token.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/cards.tsx
- apps/dashboard/src/components/contract-components/import-contract/modal.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/distribution/token-distribution.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/tracking.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/page.tsx
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/form.ts
🧰 Additional context used
🧠 Learnings (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx (2)
Learnt from: MananTank
PR: thirdweb-dev/js#7081
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx:160-165
Timestamp: 2025-05-20T19:03:35.954Z
Learning: The `claimTo` function in Thirdweb's ERC20 extension does not require converting the quantity to the smallest units (using toUnits) as it handles unit conversion internally or works with the units as provided.
Learnt from: MananTank
PR: thirdweb-dev/js#7081
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx:110-118
Timestamp: 2025-05-20T18:54:15.781Z
Learning: In the thirdweb dashboard's token asset creation flow, the `transferBatch` function from `thirdweb/extensions/erc20` accepts the raw quantity values from the form without requiring explicit conversion to wei using `toUnits()`. The function appears to handle this conversion internally or is designed to work with the values in the format they're already provided.
🧬 Code Graph Analysis (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx (8)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/hooks/project-contracts.ts (1)
useAddContractToProject
(6-47)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/form.ts (1)
CreateAssetFormValues
(93-94)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/tracking.ts (2)
getTokenDeploymentTrackingData
(1-14)getTokenStepTrackingData
(17-29)apps/dashboard/src/lib/defineDashboardChain.ts (1)
defineDashboardChain
(6-20)apps/dashboard/src/constants/addresses.ts (2)
DEFAULT_FEE_BPS_NEW
(11-11)DEFAULT_FEE_RECIPIENT
(7-8)packages/thirdweb/src/exports/thirdweb.ts (2)
getContract
(69-69)sendAndConfirmTransaction
(140-140)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page.client.tsx (1)
CreateTokenAssetPageUI
(31-121)apps/dashboard/src/@/actions/revalidate.ts (1)
revalidatePathAction
(5-10)
⏰ Context from checks skipped due to timeout of 90000ms (5)
- GitHub Check: Unit Tests
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Size
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx (4)
46-116
: Well-structured token deployment function with good error handlingThe
deployContract
function properly handles wallet connection checks, tracks deployment attempts through analytics, processes user inputs, and includes thorough error handling with the try/catch pattern.
149-162
: Correctly implementing batch token transferThe implementation correctly uses the
transferBatch
function without explicitly converting quantities to smallest units, as confirmed by the retrieved learnings that the function handles unit conversion internally.
220-231
: Token minting implementation follows correct patternBased on the retrieved learnings, the
claimTo
function correctly handles the token quantity without needing explicit conversion to the smallest units.
348-353
: Path revalidation ensures UI consistency after token launchGood use of
revalidatePathAction
to refresh the assets page after successful token launch, ensuring the UI stays in sync with backend state.
580efa7
to
5b55a2b
Compare
PR-Codex overview
This PR focuses on enhancements to the asset management features in the application, including the creation and tracking of tokens, improved UI elements, and additional validation for forms.
Detailed summary
deploymentType
andcontractType
properties in various components.revalidatePathAction
for server-side path revalidation.zod
.Summary by CodeRabbit
New Features
Improvements
Bug Fixes
Documentation
Chores