From 6caba380b229ae6147fcfd6c10302d393d30b9df Mon Sep 17 00:00:00 2001 From: MananTank Date: Thu, 21 Aug 2025 19:26:44 +0000 Subject: [PATCH] [MNY-115] Dashboard: Fix token creation flow not working for custom chains (#7896) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ## PR-Codex overview This PR introduces a new custom hook `useGetV5DashboardChain` and modifies existing components to utilize this hook for chain management, improving code clarity and reducing redundancy. ### Detailed summary - Added `useGetV5DashboardChain` hook in `v5-adapter.ts`. - Updated `LaunchNFT` component to use `useV5DashboardChain`. - Refactored `CreateTokenAssetPageUI` to use `useV5DashboardChain`. - Refactored `CreateNFTPage` to use `getChain` from `useGetV5DashboardChain`. - Refactored `CreateTokenAssetPage` to use `getChain` from `useGetV5DashboardChain`. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` ## Summary by CodeRabbit - Refactor - Unified chain selection across NFT creation, NFT launch, and token creation flows using a single, consistent resolver. - Modernized internals for better compatibility with the latest chain data. - Bug Fixes - Improved reliability of chain selection during deployments and validations, reducing chances of selecting the wrong network. - More consistent behavior when switching chains in forms and launch steps. --- apps/dashboard/src/@/hooks/chains/v5-adapter.ts | 13 ++++++++++++- .../tokens/create/nft/create-nft-page.tsx | 10 ++++------ .../tokens/create/nft/launch/launch-nft.tsx | 8 +++++--- .../create/token/create-token-page-impl.tsx | 16 +++++++++------- .../create/token/create-token-page.client.tsx | 13 +++++++------ 5 files changed, 37 insertions(+), 23 deletions(-) diff --git a/apps/dashboard/src/@/hooks/chains/v5-adapter.ts b/apps/dashboard/src/@/hooks/chains/v5-adapter.ts index 523c0cfe640..eb9d7f12ff3 100644 --- a/apps/dashboard/src/@/hooks/chains/v5-adapter.ts +++ b/apps/dashboard/src/@/hooks/chains/v5-adapter.ts @@ -1,6 +1,6 @@ "use client"; -import { useMemo } from "react"; +import { useCallback, useMemo } from "react"; import type { Chain, ChainMetadata } from "thirdweb/chains"; import { useActiveWalletChain } from "thirdweb/react"; import { useAllChainsData } from "@/hooks/chains/allChains"; @@ -27,6 +27,17 @@ export function useV5DashboardChain( }, [chainId, idToChain]); } +export function useGetV5DashboardChain() { + const { idToChain } = useAllChainsData(); + return useCallback( + (chainId: number) => { + // eslint-disable-next-line no-restricted-syntax + return defineDashboardChain(chainId, idToChain.get(chainId)); + }, + [idToChain], + ); +} + /** * same behavior as v4 `useChain()` but for v5 */ diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsx index eec9177101e..fb77020273f 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/create-nft-page.tsx @@ -1,7 +1,6 @@ "use client"; import { useRef } from "react"; import { - defineChain, encode, getContract, sendAndConfirmTransaction, @@ -25,6 +24,7 @@ import { create7702MinimalAccount } from "thirdweb/wallets/smart"; import { revalidatePathAction } from "@/actions/revalidate"; import { reportContractDeployed } from "@/analytics/report"; import type { Team } from "@/api/team/get-team"; +import { useGetV5DashboardChain } from "@/hooks/chains/v5-adapter"; import { useAddContractToProject } from "@/hooks/project-contracts"; import type { CreateNFTCollectionAllValues } from "./_common/form"; import { CreateNFTPageUI } from "./create-nft-page-ui"; @@ -41,6 +41,7 @@ export function CreateNFTPage(props: { const activeAccount = useActiveAccount(); const addContractToProject = useAddContractToProject(); const contractAddressRef = useRef(undefined); + const getChain = useGetV5DashboardChain(); function getAccount(params: { gasless: boolean }) { if (!activeAccount) { @@ -59,9 +60,7 @@ export function CreateNFTPage(props: { } function getDeployedContract(params: { chain: string }) { - // eslint-disable-next-line no-restricted-syntax - const chain = defineChain(Number(params.chain)); - + const chain = getChain(Number(params.chain)); const contractAddress = contractAddressRef.current; if (!contractAddress) { @@ -89,8 +88,7 @@ export function CreateNFTPage(props: { gasless: params.gasless, }); - // eslint-disable-next-line no-restricted-syntax - const chain = defineChain(Number(collectionInfo.chain)); + const chain = getChain(Number(collectionInfo.chain)); let contractAddress: string; diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx index d8266018083..d9c044a3dd6 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/launch/launch-nft.tsx @@ -7,7 +7,7 @@ import { } from "lucide-react"; import Link from "next/link"; import { useMemo, useRef, useState } from "react"; -import { defineChain, type ThirdwebClient } from "thirdweb"; +import type { ThirdwebClient } from "thirdweb"; import { TokenProvider, TokenSymbol, @@ -35,6 +35,7 @@ import { DialogTitle, } from "@/components/ui/dialog"; import { Skeleton } from "@/components/ui/skeleton"; +import { useV5DashboardChain } from "@/hooks/chains/v5-adapter"; import { parseError } from "@/utils/errorParser"; import { ChainOverview } from "../../_common/chain-overview"; import { StepCard } from "../../_common/step-card"; @@ -308,6 +309,8 @@ export function LaunchNFT(props: { (nft) => nft.price_amount === props.values.nfts[0]?.price_amount, ); + const chain = useV5DashboardChain(Number(formValues.collectionInfo.chain)); + const uniqueAttributes = useMemo(() => { const attributeNames = new Set(); for (const nft of props.values.nfts) { @@ -500,8 +503,7 @@ export function LaunchNFT(props: { {formValues.nfts[0].price_amount}{" "} (undefined); + const getChain = useGetV5DashboardChain(); function getAccount(gasless: boolean) { if (!activeAccount) { @@ -75,8 +76,7 @@ export function CreateTokenAssetPage(props: { throw new Error("Contract address not set"); } - // eslint-disable-next-line no-restricted-syntax - const chain = defineChain(Number(params.chain)); + const chain = getChain(Number(params.chain)); return getContract({ address: contractAddress, @@ -111,10 +111,11 @@ export function CreateTokenAssetPage(props: { Number(params.values.supply) * (salePercent / 100), ); + const chain = getChain(Number(params.values.chain)); + const contractAddress = await createToken({ account, - // eslint-disable-next-line no-restricted-syntax - chain: defineChain(Number(params.values.chain)), + chain: chain, client: props.client, launchConfig: params.values.saleEnabled && saleAmount !== 0 @@ -245,10 +246,11 @@ export function CreateTokenAssetPage(props: { {} as Record, ); + const chain = getChain(Number(params.values.chain)); + const contractAddress = await deployERC20Contract({ account, - // eslint-disable-next-line no-restricted-syntax - chain: defineChain(Number(values.chain)), + chain: chain, client: props.client, params: { description: values.description, diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page.client.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page.client.tsx index c4821bdbf2f..abb334e12ec 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page.client.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/token/create-token-page.client.tsx @@ -5,7 +5,6 @@ import { useQuery } from "@tanstack/react-query"; import { useState } from "react"; import { useForm } from "react-hook-form"; import { - defineChain, getAddress, NATIVE_TOKEN_ADDRESS, type ThirdwebClient, @@ -18,6 +17,7 @@ import { import { reportAssetCreationStepConfigured } from "@/analytics/report"; import type { Team } from "@/api/team/get-team"; import { Spinner } from "@/components/ui/Spinner/Spinner"; +import { useV5DashboardChain } from "@/hooks/chains/v5-adapter"; import { StepCard } from "../_common/step-card"; import { type CreateAssetFormValues, @@ -94,13 +94,15 @@ export function CreateTokenAssetPageUI(props: { reValidateMode: "onChange", }); + const chain = useV5DashboardChain(Number(tokenInfoForm.watch("chain"))); + const isERC20AssetSupportedQuery = useQuery({ - queryKey: ["is-erc20-asset-supported", tokenInfoForm.watch("chain")], + queryKey: ["is-erc20-asset-supported", chain], queryFn: async () => { try { const res = await getDeployedContractFactory({ // eslint-disable-next-line no-restricted-syntax - chain: defineChain(Number(tokenInfoForm.watch("chain"))), + chain: chain, client: props.client, }); return !!res; @@ -114,15 +116,14 @@ export function CreateTokenAssetPageUI(props: { queryFn: async () => { try { return await isPoolRouterEnabled({ - // eslint-disable-next-line no-restricted-syntax - chain: defineChain(Number(tokenInfoForm.watch("chain"))), + chain: chain, client: props.client, }); } catch { return false; } }, - queryKey: ["is-asset-router-enabled", tokenInfoForm.watch("chain")], + queryKey: ["is-asset-router-enabled", chain], }); const defaultSaleMode = isERC20AssetSupportedQuery.data