diff --git a/packages/web-wallet/src/components/CreateTokenDialog.tsx b/packages/web-wallet/src/components/CreateTokenDialog.tsx index 6f428819..01d21533 100644 --- a/packages/web-wallet/src/components/CreateTokenDialog.tsx +++ b/packages/web-wallet/src/components/CreateTokenDialog.tsx @@ -4,14 +4,15 @@ import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { useWallet } from '../contexts/WalletContext'; +import { useFeatureToggle } from '../contexts/FeatureToggleContext'; import { useInvokeSnap } from '@hathor/snap-utils'; -import { helpersUtils, tokensUtils, constants } from '@hathor/wallet-lib'; +import { helpersUtils, tokensUtils, constants, TokenVersion } from '@hathor/wallet-lib'; import { formatAmount, amountToCents } from '../utils/hathor'; import { readOnlyWalletWrapper } from '../services/ReadOnlyWalletWrapper'; import { getAddressForMode } from '../utils/addressMode'; -// TODO: Re-enable when fee token feature is ready -// import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select'; import { useToast } from '@/hooks/use-toast'; +import { Info } from 'lucide-react'; interface CreateTokenDialogProps { isOpen: boolean; @@ -103,6 +104,7 @@ const CreateTokenDialog: React.FC = ({ isOpen, onClose } } | null>(null); const { registerToken, balances, addressMode } = useWallet(); + const { isFeeTokensEnabled } = useFeatureToggle(); const invokeSnap = useInvokeSnap(); const { toast } = useToast(); @@ -114,8 +116,7 @@ const CreateTokenDialog: React.FC = ({ isOpen, onClose } handleSubmit, formState: { errors }, watch, - // TODO: Re-enable when fee token feature is ready - // setValue, + setValue, reset, } = useForm({ resolver: zodResolver(createTokenSchema), @@ -134,16 +135,22 @@ const CreateTokenDialog: React.FC = ({ isOpen, onClose } const isNFT = watch('isNFT'); const amount = watch('amount'); - // TODO: Re-enable when fee token feature is ready - // const tokenType = watch('tokenType'); + const tokenType = watch('tokenType'); + + // Determine if this is a fee-based token (no deposit required) + const isFeeBasedToken = isFeeTokensEnabled && tokenType === 'fee' && !isNFT; // Calculate 1% HTR deposit (1 HTR per 100 tokens) // For every 100 tokens, 1 HTR (100 cents) deposit is required // Formula: (tokens / 100) * 100 cents = tokens * 1 cent + // Fee-based tokens don't require a deposit const depositInCents = useMemo(() => { try { if (!amount || amount === '0') return 0n; + // Fee-based tokens don't require a deposit + if (isFeeBasedToken) return 0n; + let amountInBaseUnits: bigint; if (isNFT) { // NFTs: whole numbers only, 1 NFT = 0.01 HTR (1 base unit) @@ -160,7 +167,7 @@ const CreateTokenDialog: React.FC = ({ isOpen, onClose } } catch { return 0n; } - }, [amount, isNFT]); + }, [amount, isNFT, isFeeBasedToken]); // Check if user has insufficient balance const hasInsufficientBalance = useMemo(() => { @@ -172,15 +179,14 @@ const CreateTokenDialog: React.FC = ({ isOpen, onClose } setError(null); try { + // Determine if this is a fee-based token creation + const isCreatingFeeToken = isFeeTokensEnabled && data.tokenType === 'fee' && !data.isNFT; + // Derive mint/melt settings // For NFTs: use the checkbox values - // For regular tokens: based on token type (deposit = true, fee = false) - const createMint = data.isNFT - ? (data.createMintAuthority || false) - : data.tokenType === 'deposit'; - const createMelt = data.isNFT - ? (data.createMeltAuthority || false) - : data.tokenType === 'deposit'; + // For regular tokens: use the checkbox values + const createMint = data.createMintAuthority || false; + const createMelt = data.createMeltAuthority || false; // Get addresses based on address mode const changeAddress = await getAddressForMode(addressMode, readOnlyWalletWrapper); @@ -193,7 +199,7 @@ const CreateTokenDialog: React.FC = ({ isOpen, onClose } ? BigInt(data.amount) : amountToCents(data.amount); - // Prepare RPC params matching createTokenRpcSchema + // Prepare RPC params const params = { name: data.name, symbol: data.symbol, @@ -207,6 +213,7 @@ const CreateTokenDialog: React.FC = ({ isOpen, onClose } allow_external_melt_authority_address: false, data: data.isNFT && data.nftData ? [data.nftData] : null, address: mintAddress, // Mint address where tokens are sent + ...(isCreatingFeeToken && { token_version: TokenVersion.FEE }), }; // Call RPC @@ -533,8 +540,8 @@ const CreateTokenDialog: React.FC = ({ isOpen, onClose } - {/* TODO: Re-enable Token Type dropdown when fee token feature is ready */} - {/* {!isNFT && ( + {/* Token Type dropdown - only shown when fee tokens feature is enabled */} + {isFeeTokensEnabled && !isNFT && (
@@ -575,22 +582,35 @@ const CreateTokenDialog: React.FC = ({ isOpen, onClose }
- )} */} + )} {/* Deposit Display */} - {amount && depositInCents > 0n && ( + {amount && parseFloat(amount) > 0 && (
-

- DEPOSIT: {formatAmount(depositInCents, false)} HTR -

-

- TOTAL: {formatAmount(depositInCents, false)} HTR ({formatAmount(htrBalance, false)} HTR AVAILABLE) -

+ {isFeeBasedToken ? ( + <> +

+ DEPOSIT: No deposit required +

+

+ Fee-based tokens charge 1 HTR per transaction output instead of requiring an upfront deposit. +

+ + ) : depositInCents > 0n && ( + <> +

+ DEPOSIT: {formatAmount(depositInCents, false)} HTR +

+

+ TOTAL: {formatAmount(depositInCents, false)} HTR ({formatAmount(htrBalance, false)} HTR AVAILABLE) +

+ + )}
)} - {/* Insufficient Balance Warning */} - {hasInsufficientBalance && amount && parseFloat(amount) > 0 && ( + {/* Insufficient Balance Warning - only for deposit-based tokens */} + {hasInsufficientBalance && !isFeeBasedToken && amount && parseFloat(amount) > 0 && (
@@ -610,7 +630,7 @@ const CreateTokenDialog: React.FC = ({ isOpen, onClose } {/* Create Button */}