diff --git a/frontend/src/components/Ramp/Offramp/index.tsx b/frontend/src/components/Ramp/Offramp/index.tsx index abe788e73..b0d6f5d8f 100644 --- a/frontend/src/components/Ramp/Offramp/index.tsx +++ b/frontend/src/components/Ramp/Offramp/index.tsx @@ -58,8 +58,6 @@ export const Offramp = () => { const fromToken = getOnChainTokenDetailsOrDefault(selectedNetwork, onChainToken); const toToken = getAnyFiatTokenDetails(fiatToken); - useSetRampUrlParams(); - useEffect(() => { if (!fromAmountFieldTouched || debouncedInputAmount !== inputAmount) return; diff --git a/frontend/src/components/Ramp/Onramp/index.tsx b/frontend/src/components/Ramp/Onramp/index.tsx index 32430f8d9..24e676765 100644 --- a/frontend/src/components/Ramp/Onramp/index.tsx +++ b/frontend/src/components/Ramp/Onramp/index.tsx @@ -59,8 +59,6 @@ export const Onramp = () => { const fromToken = getAnyFiatTokenDetails(fiatToken); const toToken = getOnChainTokenDetailsOrDefault(selectedNetwork, onChainToken); - useSetRampUrlParams(); - useEffect(() => { if (!fromAmountFieldTouched || debouncedInputAmount !== inputAmount) return; diff --git a/frontend/src/components/RampSubmitButtons/index.tsx b/frontend/src/components/RampSubmitButtons/index.tsx index 6e9013a84..473cb9490 100644 --- a/frontend/src/components/RampSubmitButtons/index.tsx +++ b/frontend/src/components/RampSubmitButtons/index.tsx @@ -2,7 +2,7 @@ import { FC, useCallback } from 'react'; import Big from 'big.js'; import { useEventsContext } from '../../contexts/events'; import { useFeeComparisonStore } from '../../stores/feeComparison'; -import { useInitializeFailedMessage, useRampSummaryVisible } from '../../stores/rampStore'; +import { useInitializeFailedMessage, useRampExecutionInput, useRampSummaryVisible } from '../../stores/rampStore'; import { useRampValidation } from '../../hooks/ramp/useRampValidation'; import { SwapSubmitButton } from '../buttons/SwapSubmitButton'; import { useFiatToken, useInputAmount, useOnChainToken } from '../../stores/ramp/useRampFormStore'; @@ -20,6 +20,7 @@ export const RampSubmitButtons: FC = ({ toAmount }) => { const { feeComparisonRef } = useFeeComparisonStore(); const { trackEvent } = useEventsContext(); const { getCurrentErrorMessage } = useRampValidation(); + const executionInput = useRampExecutionInput() const initializeFailedMessage = useInitializeFailedMessage(); const isRampSummaryDialogVisible = useRampSummaryVisible(); const inputAmount = useInputAmount(); @@ -53,7 +54,7 @@ export const RampSubmitButtons: FC = ({ toAmount }) => { }; const isSubmitButtonDisabled = Boolean(getCurrentErrorMessage()) || !toAmount || !!initializeFailedMessage; - const isSubmitButtonPending = isRampSummaryDialogVisible; + const isSubmitButtonPending = isRampSummaryDialogVisible || Boolean(executionInput); return (
diff --git a/frontend/src/hooks/offramp/useRampService/useRegisterRamp.ts b/frontend/src/hooks/offramp/useRampService/useRegisterRamp.ts index c17451420..02a10f451 100644 --- a/frontend/src/hooks/offramp/useRampService/useRegisterRamp.ts +++ b/frontend/src/hooks/offramp/useRampService/useRegisterRamp.ts @@ -103,8 +103,16 @@ export const useRegisterRamp = () => { } }; + // Create a process lock for the registration process const { checkLock, verifyLock, releaseLock } = useProcessLock(REGISTER_KEY_LOCAL_STORAGE); + // Create a process lock for the signing process + const { + checkLock: checkSigningLock, + verifyLock: verifySigningLock, + releaseLock: releaseSigningLock, + } = useProcessLock(START_KEY_LOCAL_STORAGE); + // @TODO: maybe change to useCallback useEffect(() => { console.log(`Starting ramp registry process at ${new Date().toISOString()}`); @@ -115,7 +123,7 @@ export const useRegisterRamp = () => { // Alternatively release locks if process was cancelled // This will NOT clean the localStorage right after the process is cancelled // but rather on the first checkLock() call after confirmation. - if (!rampStarted){ + if (!rampStarted) { releaseSigningLock(); releaseLock(); } @@ -206,8 +214,6 @@ export const useRegisterRamp = () => { moonbeamApiComponents.api, ); - console.log('setting ramp state with signed transactions...'); - setRampRegistered(true); setRampState({ quote: executionInput.quote, @@ -232,7 +238,6 @@ export const useRegisterRamp = () => { }); }, [ address, - canRegisterRamp, chainId, checkLock, @@ -244,15 +249,10 @@ export const useRegisterRamp = () => { setRampState, verifyLock, rampKycStarted, + rampStarted, + releaseSigningLock, ]); - // Create a process lock for the signing process - const { - checkLock: checkSigningLock, - verifyLock: verifySigningLock, - releaseLock: releaseSigningLock, - } = useProcessLock(START_KEY_LOCAL_STORAGE); - // This hook is responsible for handling the user signing process once the ramp process is registered. // This is only relevant for offramps. @TODO: Extract this to a separate hook for offramp useEffect(() => { diff --git a/frontend/src/hooks/ramp/schema.ts b/frontend/src/hooks/ramp/schema.ts index 0d650e09b..902c968a7 100644 --- a/frontend/src/hooks/ramp/schema.ts +++ b/frontend/src/hooks/ramp/schema.ts @@ -36,6 +36,7 @@ export function isValidCpf(cpf: string): boolean { // Regex adopted from here https://developers.international.pagseguro.com/reference/pix-key-validation-and-regex-1 const pixKeyRegex = [ cpfRegex, + cnpjRegex, /^\+[1-9][0-9]\d{1,14}$/, // Phone /^(([^<>()[\]\\.,;:\s@"]+(.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, // Email /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/, // Random diff --git a/frontend/src/hooks/ramp/useRampValidation.ts b/frontend/src/hooks/ramp/useRampValidation.ts index 4ab4126e5..2d1324484 100644 --- a/frontend/src/hooks/ramp/useRampValidation.ts +++ b/frontend/src/hooks/ramp/useRampValidation.ts @@ -187,7 +187,6 @@ export const useRampValidation = () => { isDisconnected, isOnramp, quoteLoading, - selectedNetwork, t, inputAmount, fromToken, diff --git a/frontend/src/hooks/useRampUrlParams.ts b/frontend/src/hooks/useRampUrlParams.ts index 5668b1c8e..c4ea14723 100644 --- a/frontend/src/hooks/useRampUrlParams.ts +++ b/frontend/src/hooks/useRampUrlParams.ts @@ -1,8 +1,9 @@ import { useEffect, useMemo, useRef } from 'react'; import { RampDirection } from '../components/RampToggle'; -import { Networks, AssetHubToken, EvmToken, FiatToken, OnChainToken } from 'shared'; +import { AssetHubToken, EvmToken, FiatToken, Networks, OnChainToken } from 'shared'; import { useRampDirectionToggle } from '../stores/rampDirectionStore'; import { useRampFormStoreActions } from '../stores/ramp/useRampFormStore'; +import { useNetwork } from '../contexts/network'; interface RampUrlParams { ramp: RampDirection; @@ -12,6 +13,8 @@ interface RampUrlParams { fromAmount?: string; } +const defaultFiatTokenAmounts: Record = { eurc: '20', ars: '20', brl: '5' }; + function findFiatToken(fiatToken?: string): FiatToken | undefined { if (!fiatToken) { return undefined; @@ -69,6 +72,7 @@ function getNetworkFromParam(param?: string): Networks | undefined { export const useRampUrlParams = (): RampUrlParams => { const params = useMemo(() => new URLSearchParams(window.location.search), []); + const { selectedNetwork } = useNetwork(); const urlParams = useMemo(() => { const rampParam = params.get('ramp')?.toLowerCase(); @@ -79,15 +83,28 @@ export const useRampUrlParams = (): RampUrlParams => { const ramp = rampParam === 'buy' ? RampDirection.ONRAMP : RampDirection.OFFRAMP; + const from = + ramp === RampDirection.OFFRAMP + ? findOnChainToken(fromTokenParam, networkParam || selectedNetwork) + : findFiatToken(fromTokenParam); + const to = + ramp === RampDirection.OFFRAMP + ? findFiatToken(toTokenParam) + : findOnChainToken(toTokenParam, networkParam || selectedNetwork); + + const fromAmount = + ramp === RampDirection.OFFRAMP + ? defaultFiatTokenAmounts[to as FiatToken] + : defaultFiatTokenAmounts[from as FiatToken]; + return { ramp, network: getNetworkFromParam(networkParam), - to: ramp === RampDirection.OFFRAMP ? findFiatToken(toTokenParam) : findOnChainToken(toTokenParam, networkParam), - from: - ramp === RampDirection.OFFRAMP ? findOnChainToken(fromTokenParam, networkParam) : findFiatToken(fromTokenParam), - fromAmount: inputAmountParam || undefined, + from, + to, + fromAmount: inputAmountParam || fromAmount || undefined, }; - }, [params]); + }, [params, selectedNetwork]); return urlParams; }; diff --git a/frontend/src/pages/ramp-form/index.tsx b/frontend/src/pages/ramp-form/index.tsx index 6016796b1..3ba653663 100644 --- a/frontend/src/pages/ramp-form/index.tsx +++ b/frontend/src/pages/ramp-form/index.tsx @@ -9,12 +9,15 @@ import { useRampDirection, useRampDirectionToggle } from '../../stores/rampDirec import { RampDirection, RampToggle } from '../../components/RampToggle'; import { PoweredBy } from '../../components/PoweredBy'; import { Onramp } from '../../components/Ramp/Onramp'; +import { useSetRampUrlParams } from '../../hooks/useRampUrlParams'; export const RampForm = () => { const activeSwapDirection = useRampDirection(); const onSwapDirectionToggle = useRampDirectionToggle(); const offrampKycStarted = useRampKycStarted(); + useSetRampUrlParams(); + return (
diff --git a/frontend/src/stores/ramp/useRampFormStore.ts b/frontend/src/stores/ramp/useRampFormStore.ts index 0a41fa33c..242f42915 100644 --- a/frontend/src/stores/ramp/useRampFormStore.ts +++ b/frontend/src/stores/ramp/useRampFormStore.ts @@ -21,7 +21,7 @@ interface RampFormActions { } export const DEFAULT_RAMP_FORM_STORE_VALUES: RampFormState = { - inputAmount: undefined, + inputAmount: '20', onChainToken: EvmToken.USDC, fiatToken: FiatToken.EURC, taxId: undefined, diff --git a/shared/src/helpers/brla.ts b/shared/src/helpers/brla.ts index 9e50dbd06..1f59e8276 100644 --- a/shared/src/helpers/brla.ts +++ b/shared/src/helpers/brla.ts @@ -2,6 +2,10 @@ * Validates a tax id (CPF) vs a partially masked tax id received from BRLA's pix-info endpoint */ export function validateMaskedNumber(maskedCpf: string, fullCpf: string): boolean { + + maskedCpf = maskedCpf.replace(/[-./]/g, ''); + fullCpf = fullCpf.replace(/[-./]/g, ''); + if (!maskedCpf || !fullCpf) return false; if (maskedCpf.length !== fullCpf.length) throw new Error('Invalid comparison. Lengths do not match.'); @@ -13,4 +17,4 @@ export function validateMaskedNumber(maskedCpf: string, fullCpf: string): boolea } return true; -} +} \ No newline at end of file diff --git a/shared/src/helpers/signUnsigned.ts b/shared/src/helpers/signUnsigned.ts index ad1444dc0..9e2b493d6 100644 --- a/shared/src/helpers/signUnsigned.ts +++ b/shared/src/helpers/signUnsigned.ts @@ -58,8 +58,6 @@ async function signMultipleStellarTransactions( }; // iterate objects of array meta for (const key in signedTx.meta.additionalTxs) { - console.log(`key: ${key}`); - console.log(`value: ${signedTx.meta[key]}`); if (!key.includes(tx.phase)) continue; const extraTransactionUnsigned = signedTx.meta.additionalTxs[key].txData;