From e916210d7c151c942c62738cec2e28141cfdbb5c Mon Sep 17 00:00:00 2001 From: Kacper Szarkiewicz Date: Wed, 30 Apr 2025 16:17:42 +0200 Subject: [PATCH 01/13] add token disable config in the frontend --- frontend/src/config/tokenAvailability.ts | 44 ++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 frontend/src/config/tokenAvailability.ts diff --git a/frontend/src/config/tokenAvailability.ts b/frontend/src/config/tokenAvailability.ts new file mode 100644 index 000000000..5dced3f74 --- /dev/null +++ b/frontend/src/config/tokenAvailability.ts @@ -0,0 +1,44 @@ +import { FiatToken } from 'shared'; +import { DEFAULT_FIAT_TOKEN } from '../stores/ramp/useRampFormStore'; + +export interface TokenAvailabilityConfig { + enabled: boolean; + disabledReason?: string; +} + +// This is our central configuration for token availability +export const fiatTokenAvailability: Record = { + [FiatToken.EURC]: { + enabled: false, + disabledReason: 'Improving your EUR exit - back shortly! ', + }, + [FiatToken.ARS]: { + enabled: true, + }, + [FiatToken.BRL]: { + enabled: true, + }, +}; + +export function isFiatTokenEnabled(token: FiatToken): boolean { + return fiatTokenAvailability[token]?.enabled ?? false; +} + +export function isFiatTokenDisabled(token: FiatToken): boolean { + return fiatTokenAvailability[token]?.enabled === false; +} + +export function getTokenDisabledReason(token: FiatToken): string | undefined { + return fiatTokenAvailability[token]?.disabledReason; +} + +export function getEnabledFiatTokens(): FiatToken[] { + return Object.entries(fiatTokenAvailability) + .filter(([_, config]) => config.enabled) + .map(([token]) => token as FiatToken); +} + +export function getFirstEnabledFiatToken(): FiatToken { + const enabledTokens = getEnabledFiatTokens(); + return enabledTokens.length > 0 ? enabledTokens[0] : DEFAULT_FIAT_TOKEN; +} From 649f081edfb8f6b1fdf64479441c163626b71fd3 Mon Sep 17 00:00:00 2001 From: Kacper Szarkiewicz Date: Wed, 30 Apr 2025 16:18:12 +0200 Subject: [PATCH 02/13] add DEFAULT_RAMP_DIRECTION --- frontend/src/stores/rampDirectionStore.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/stores/rampDirectionStore.ts b/frontend/src/stores/rampDirectionStore.ts index 4949585e8..f05d16c8d 100644 --- a/frontend/src/stores/rampDirectionStore.ts +++ b/frontend/src/stores/rampDirectionStore.ts @@ -1,13 +1,15 @@ import { create } from 'zustand'; import { RampDirection } from '../components/RampToggle'; +export const DEFAULT_RAMP_DIRECTION = RampDirection.ONRAMP; + export interface RampDirectionStore { activeDirection: RampDirection; onToggle: (direction: RampDirection) => void; } export const useRampDirectionStore = create((set) => ({ - activeDirection: RampDirection.ONRAMP, + activeDirection: DEFAULT_RAMP_DIRECTION, onToggle: (direction: RampDirection) => set({ activeDirection: direction }), })); From 0f189a1b159c0e011cd1c1021fee30e56b76520f Mon Sep 17 00:00:00 2001 From: Kacper Szarkiewicz Date: Wed, 30 Apr 2025 16:18:33 +0200 Subject: [PATCH 03/13] add DEFAULT values for rampFormStore --- frontend/src/stores/ramp/useRampFormStore.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/src/stores/ramp/useRampFormStore.ts b/frontend/src/stores/ramp/useRampFormStore.ts index be8ac81fa..8838d77b9 100644 --- a/frontend/src/stores/ramp/useRampFormStore.ts +++ b/frontend/src/stores/ramp/useRampFormStore.ts @@ -1,6 +1,11 @@ import { create } from 'zustand'; import { EvmToken, FiatToken, Networks, OnChainToken } from 'shared'; +export const DEFAULT_FIAT_TOKEN = FiatToken.BRL; +export const DEFAULT_BRL_AMOUNT = '5'; +export const DEFAULT_EURC_AMOUNT = '20'; +export const DEFAULT_ARS_AMOUNT = '20'; + interface RampFormState { inputAmount?: string; onChainToken: OnChainToken; @@ -23,9 +28,9 @@ interface RampFormActions { const storedNetwork = localStorage.getItem('SELECTED_NETWORK') export const DEFAULT_RAMP_FORM_STORE_VALUES: RampFormState = { - inputAmount: '20', + inputAmount: DEFAULT_BRL_AMOUNT, onChainToken: storedNetwork !== null && storedNetwork === Networks.AssetHub ? EvmToken.USDC : EvmToken.USDT, - fiatToken: FiatToken.EURC, + fiatToken: DEFAULT_FIAT_TOKEN, taxId: undefined, pixId: undefined, }; From 71e700ffe3db02108d7caaf44adaf2bfb1dcc710 Mon Sep 17 00:00:00 2001 From: Kacper Szarkiewicz Date: Wed, 30 Apr 2025 16:19:11 +0200 Subject: [PATCH 04/13] add handling for disabled tokens in the url param --- frontend/src/hooks/useRampUrlParams.ts | 29 ++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/frontend/src/hooks/useRampUrlParams.ts b/frontend/src/hooks/useRampUrlParams.ts index 33616cb1d..16fb2c3c8 100644 --- a/frontend/src/hooks/useRampUrlParams.ts +++ b/frontend/src/hooks/useRampUrlParams.ts @@ -1,9 +1,10 @@ import { useEffect, useMemo, useRef } from 'react'; import { RampDirection } from '../components/RampToggle'; import { AssetHubToken, EvmToken, FiatToken, Networks, OnChainToken } from 'shared'; -import { useRampDirection, useRampDirectionToggle } from '../stores/rampDirectionStore'; -import { useRampFormStoreActions } from '../stores/ramp/useRampFormStore'; +import { DEFAULT_RAMP_DIRECTION, useRampDirection, useRampDirectionToggle } from '../stores/rampDirectionStore'; +import { DEFAULT_ARS_AMOUNT, DEFAULT_BRL_AMOUNT, DEFAULT_EURC_AMOUNT, useRampFormStoreActions } from '../stores/ramp/useRampFormStore'; import { useNetwork } from '../contexts/network'; +import { isFiatTokenEnabled, getFirstEnabledFiatToken } from '../config/tokenAvailability'; interface RampUrlParams { ramp: RampDirection; @@ -13,7 +14,7 @@ interface RampUrlParams { fromAmount?: string; } -const defaultFiatTokenAmounts: Record = { eurc: '20', ars: '20', brl: '5' }; +const defaultFiatTokenAmounts: Record = { eurc: DEFAULT_EURC_AMOUNT, ars: DEFAULT_ARS_AMOUNT, brl: DEFAULT_BRL_AMOUNT }; function findFiatToken(fiatToken?: string): FiatToken | undefined { if (!fiatToken) { @@ -83,7 +84,7 @@ export const useRampUrlParams = (): RampUrlParams => { const inputAmountParam = params.get('fromAmount'); const ramp = - rampParam === undefined ? rampDirection : rampParam === 'buy' ? RampDirection.ONRAMP : RampDirection.OFFRAMP; + rampParam === undefined ? rampDirection : rampParam === 'sell' ? RampDirection.OFFRAMP : rampParam === 'buy' ? RampDirection.ONRAMP : DEFAULT_RAMP_DIRECTION; const from = ramp === RampDirection.OFFRAMP @@ -120,17 +121,33 @@ export const useSetRampUrlParams = () => { const hasInitialized = useRef(false); + const handleFiatToken = (token: FiatToken) => { + if (isFiatTokenEnabled(token)) { + setFiatToken(token); + } else { + setFiatToken(getFirstEnabledFiatToken()); + } + }; + useEffect(() => { if (hasInitialized.current) return; onToggle(ramp); if (to) { - ramp === RampDirection.OFFRAMP ? setFiatToken(to as FiatToken) : setOnChainToken(to as OnChainToken); + if (ramp === RampDirection.OFFRAMP) { + handleFiatToken(to as FiatToken); + } else { + setOnChainToken(to as OnChainToken); + } } if (from) { - ramp === RampDirection.OFFRAMP ? setOnChainToken(from as OnChainToken) : setFiatToken(from as FiatToken); + if (ramp === RampDirection.OFFRAMP) { + setOnChainToken(from as OnChainToken); + } else { + handleFiatToken(from as FiatToken); + } } if (fromAmount) { From 251d45e9734d3d60d0703eefdce622c7b4290d35 Mon Sep 17 00:00:00 2001 From: Kacper Szarkiewicz Date: Wed, 30 Apr 2025 16:19:49 +0200 Subject: [PATCH 05/13] add handling disabled tokens in SelectionModal --- frontend/src/components/InputKeys/SelectionModal.tsx | 7 +++++++ frontend/src/components/Ramp/Onramp/index.tsx | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/InputKeys/SelectionModal.tsx b/frontend/src/components/InputKeys/SelectionModal.tsx index 744eeee6a..d3602a13a 100644 --- a/frontend/src/components/InputKeys/SelectionModal.tsx +++ b/frontend/src/components/InputKeys/SelectionModal.tsx @@ -13,6 +13,7 @@ import { OnChainTokenDetails, stellarTokenConfig, } from 'shared'; +import { isFiatTokenDisabled } from '../../config/tokenAvailability'; import { useOnchainTokenBalances } from '../../hooks/useOnchainTokenBalances'; import { useNetwork } from '../../contexts/network'; @@ -69,6 +70,12 @@ function TokenSelectionList() { const rampDirection = useRampDirection(); const handleTokenSelect = (token: OnChainToken | FiatToken) => { + + const isFiatToken = Object.values(FiatToken).includes(token as FiatToken); + if (isFiatToken && isFiatTokenDisabled(token as FiatToken)) { + return; + } + if (rampDirection === RampDirection.ONRAMP) { if (tokenSelectModalType === 'from') { setFiatToken(token as FiatToken); diff --git a/frontend/src/components/Ramp/Onramp/index.tsx b/frontend/src/components/Ramp/Onramp/index.tsx index 24e676765..ce4e633f1 100644 --- a/frontend/src/components/Ramp/Onramp/index.tsx +++ b/frontend/src/components/Ramp/Onramp/index.tsx @@ -20,7 +20,6 @@ import { RampTerms } from '../../RampTerms'; import { useValidateTerms } from '../../../stores/termsStore'; import { useRampModalActions } from '../../../stores/rampModalStore'; import { useInputAmount, useOnChainToken, useFiatToken } from '../../../stores/ramp/useRampFormStore'; -import { useSetRampUrlParams } from '../../../hooks/useRampUrlParams'; import { RampFeeCollapse } from '../../RampFeeCollapse'; import { RampSubmitButtons } from '../../RampSubmitButtons'; import { useInitializeFailedMessage } from '../../../stores/rampStore'; From e76481bd334c65a052f640e588560577ff6c7b76 Mon Sep 17 00:00:00 2001 From: Kacper Szarkiewicz Date: Wed, 30 Apr 2025 16:20:13 +0200 Subject: [PATCH 06/13] add handling for disabled tokens in SelectionModal ListItem --- .../InputKeys/PoolListItem/index.tsx | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/InputKeys/PoolListItem/index.tsx b/frontend/src/components/InputKeys/PoolListItem/index.tsx index 7d9b564f5..a892654fc 100644 --- a/frontend/src/components/InputKeys/PoolListItem/index.tsx +++ b/frontend/src/components/InputKeys/PoolListItem/index.tsx @@ -1,6 +1,7 @@ +import { OnChainToken, FiatToken, isOnChainToken, OnChainTokenDetails, isFiatToken } from 'shared'; import { CheckIcon } from '@heroicons/react/20/solid'; +import { isFiatTokenDisabled, getTokenDisabledReason } from '../../../config/tokenAvailability'; import { useGetAssetIcon } from '../../../hooks/useGetAssetIcon'; -import { OnChainToken, FiatToken, isOnChainToken, OnChainTokenDetails } from 'shared'; import { TokenDefinition } from '../SelectionModal'; import { UserBalance } from '../../UserBalance'; interface PoolListItemProps { @@ -14,12 +15,17 @@ export function PoolListItem({ token, isSelected, onSelect }: PoolListItemProps) const showBalance = isOnChainToken(token.type); + const isDisabled = isFiatToken(token.type) && isFiatTokenDisabled(token.type); + const disabledReason = isFiatToken(token.type) && isDisabled ? getTokenDisabledReason(token.type) : undefined; + return (