diff --git a/apps/maestro/src/features/InterchainTokenDeployment/InterchainTokenDeployment.state.ts b/apps/maestro/src/features/InterchainTokenDeployment/InterchainTokenDeployment.state.ts index e3d9d18d1..e71721501 100644 --- a/apps/maestro/src/features/InterchainTokenDeployment/InterchainTokenDeployment.state.ts +++ b/apps/maestro/src/features/InterchainTokenDeployment/InterchainTokenDeployment.state.ts @@ -7,7 +7,7 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { uniq, without } from "rambda"; import { z } from "zod"; -import { useAccount } from "~/lib/hooks"; +import { SUI_CHAIN_ID, useAccount, useChainId } from "~/lib/hooks"; import { logger } from "~/lib/logger"; import { hex64Literal, @@ -26,6 +26,7 @@ const TOKEN_DETAILS_FORM_SCHEMA = z.object({ }); export type TokenDetailsFormState = z.infer; +const MAX_UINT64 = BigInt(2) ** BigInt(64) - BigInt(1); export type DeployAndRegisterTransactionState = | { @@ -86,6 +87,7 @@ function useInterchainTokenDeploymentState( }); const { address } = useAccount(); + const chainId = useChainId(); /** * Generate a random salt on first render @@ -97,6 +99,10 @@ function useInterchainTokenDeploymentState( const salt = generateRandomHash(); tokenDetailsForm.setValue("salt", salt); + + if (chainId === SUI_CHAIN_ID) { + tokenDetailsForm.setValue("tokenDecimals", 9); + } }, // eslint-disable-next-line react-hooks/exhaustive-deps [address] @@ -147,6 +153,10 @@ function useInterchainTokenDeploymentState( // reset form tokenDetailsForm.reset(initialState.tokenDetails); + if (chainId === SUI_CHAIN_ID) { + tokenDetailsForm.setValue("tokenDecimals", 9); + } + tokenDetailsForm.setValue("salt", generateRandomHash()); // tokenDetailsForm.setValue("minter", address); }); diff --git a/apps/maestro/src/features/InterchainTokenDeployment/steps/token-details/TokenDetails.tsx b/apps/maestro/src/features/InterchainTokenDeployment/steps/token-details/TokenDetails.tsx index 5290ba219..a1dcc815a 100644 --- a/apps/maestro/src/features/InterchainTokenDeployment/steps/token-details/TokenDetails.tsx +++ b/apps/maestro/src/features/InterchainTokenDeployment/steps/token-details/TokenDetails.tsx @@ -17,6 +17,7 @@ import { useInterchainTokenDeploymentStateContainer, type TokenDetailsFormState, } from "~/features/InterchainTokenDeployment"; +import { SUI_CHAIN_ID, useChainId } from "~/lib/hooks"; import { isValidEVMAddress, preventNonHexInput, @@ -29,8 +30,11 @@ import { ValidationError, } from "~/ui/compounds/MultiStepForm"; +const MAX_UINT64 = BigInt(2) ** BigInt(64) - BigInt(1); + const TokenDetails: FC = () => { const { state, actions } = useInterchainTokenDeploymentStateContainer(); + const chainId = useChainId(); const { register, handleSubmit, formState, watch } = state.tokenDetailsForm; @@ -40,6 +44,7 @@ const TokenDetails: FC = () => { const isMintable = watch("isMintable"); const minter = watch("minter"); const supply = watch("initialSupply"); + const tokenDecimals = watch("tokenDecimals"); const minterErrorMessage = useMemo(() => { if (!isMintable) { @@ -72,7 +77,18 @@ const TokenDetails: FC = () => { message: "Fixed supply token requires an initial balance", }; } - }, [isMintable, minter, supply]); + + if ( + chainId === SUI_CHAIN_ID && + supply && + BigInt(supply) * BigInt(10) ** BigInt(tokenDecimals) > MAX_UINT64 + ) { + return { + type: "validate", + message: "Supply must be less than 2^64 - 1 for Sui", + }; + } + }, [isMintable, minter, supply, chainId, tokenDecimals]); const isFormValid = useMemo(() => { if (minterErrorMessage || initialSupplyErrorMessage) { diff --git a/apps/maestro/src/lib/hooks/useChainId.ts b/apps/maestro/src/lib/hooks/useChainId.ts index 504413e4e..d281152fb 100644 --- a/apps/maestro/src/lib/hooks/useChainId.ts +++ b/apps/maestro/src/lib/hooks/useChainId.ts @@ -6,7 +6,7 @@ import { useChainId as useWagmiChainId } from "wagmi"; // Sui's chain ID import { NEXT_PUBLIC_NETWORK_ENV } from "~/config/env"; -const SUI_CHAIN_ID = NEXT_PUBLIC_NETWORK_ENV === "mainnet" ? 101 : 103; +export const SUI_CHAIN_ID = NEXT_PUBLIC_NETWORK_ENV === "mainnet" ? 101 : 103; // TODO: check if this is the best way to use chain ids, maybe we should combine it with chain type export function useChainId(): number {