Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions apps/frontend/src/components/menus/SettingsMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,21 @@ export const SettingsMenu = () => {
<div className="space-y-2 pt-4">
{isAuthenticated && userEmail && (
<>
<div className="mb-4 px-3 py-2 bg-gray-50 rounded-lg">
<div className="flex items-center gap-2 mb-3">
<div className="mb-4 rounded-lg bg-gray-50 px-3 py-2">
<div className="mb-3 flex items-center gap-2">
<UserCircleIcon className="h-5 w-5 text-gray-600" />
<span className="text-sm font-medium text-gray-900 truncate">{userEmail}</span>
<span className="truncate font-medium text-gray-900 text-sm">{userEmail}</span>
</div>
<button
className="w-full flex items-center justify-center gap-2 px-4 py-2 bg-white border border-gray-300 rounded-lg text-sm font-medium text-gray-700 cursor-pointer hover:bg-gray-50 active:scale-[0.98] transition-all"
className="flex w-full cursor-pointer items-center justify-center gap-2 rounded-lg border border-gray-300 bg-white px-4 py-2 font-medium text-gray-700 text-sm transition-all hover:bg-gray-50 active:scale-[0.98]"
onClick={handleSignOut}
type="button"
>
<ArrowRightOnRectangleIcon className="h-4 w-4" />
{t("menus.settings.signOut")}
</button>
</div>
<div className="border-t border-gray-200 mb-4" />
<div className="mb-4 border-gray-200 border-t" />
</>
)}

Expand Down
4 changes: 2 additions & 2 deletions apps/frontend/src/hooks/quote/schema.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { FiatToken, OnChainToken, RampDirection } from "@vortexfi/shared";
import { FiatToken, OnChainToken, OnChainTokenSymbol, RampDirection } from "@vortexfi/shared";
import { useTranslation } from "react-i18next";
import * as Yup from "yup";
import { useRampDirection } from "../../stores/rampDirectionStore";

export type QuoteFormValues = {
inputAmount: string;
outputAmount?: string;
onChainToken: OnChainToken;
onChainToken: OnChainTokenSymbol;
fiatToken: FiatToken;
slippage?: number;
deadline?: number;
Expand Down
4 changes: 2 additions & 2 deletions apps/frontend/src/hooks/quote/useQuoteService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FiatToken, OnChainToken } from "@vortexfi/shared";
import { FiatToken, OnChainTokenSymbol } from "@vortexfi/shared";
import Big from "big.js";
import { useCallback, useEffect } from "react";
import { useEventsContext } from "../../contexts/events";
Expand All @@ -13,7 +13,7 @@ import { useRampDirection } from "../../stores/rampDirectionStore";
// if you don't want to get a new quote - you get outputAmount through useQuoteStore
// This is not optimal, and introduce too much cognitive load

export const useQuoteService = (inputAmount: string | undefined, onChainToken: OnChainToken, fiatToken: FiatToken) => {
export const useQuoteService = (inputAmount: string | undefined, onChainToken: OnChainTokenSymbol, fiatToken: FiatToken) => {
const { trackEvent } = useEventsContext();
const { selectedNetwork } = useNetwork();
const rampType = useRampDirection();
Expand Down
59 changes: 38 additions & 21 deletions apps/frontend/src/hooks/useRampUrlParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@ import {
AssetHubToken,
DestinationType,
EPaymentMethod,
type EvmNetworks,
EvmToken,
FiatToken,
getEvmTokenConfig,
getEvmTokensLoadedSnapshot,
isNetworkEVM,
Networks,
OnChainToken,
OnChainTokenSymbol,
PaymentMethod,
QuoteResponse,
RampDirection
RampDirection,
subscribeEvmTokensLoaded
} from "@vortexfi/shared";
import Big from "big.js";
import { useCallback, useEffect, useMemo, useRef } from "react";
import { useCallback, useEffect, useMemo, useRef, useSyncExternalStore } from "react";
import { getFirstEnabledFiatToken, isFiatTokenEnabled } from "../config/tokenAvailability";
import { useNetwork } from "../contexts/network";
import { useRampActor } from "../contexts/rampState";
Expand All @@ -33,7 +39,7 @@ interface RampUrlParams {
moneriumCode?: string;
fiat?: FiatToken;
countryCode?: string;
cryptoLocked?: OnChainToken;
cryptoLocked?: OnChainTokenSymbol;
paymentMethod?: PaymentMethod;
walletLocked?: string;
callbackUrl?: string;
Expand All @@ -58,7 +64,7 @@ function findFiatToken(fiatToken?: string): FiatToken | undefined {
return foundToken;
}

function findOnChainToken(tokenStr?: string, networkType?: Networks | string): OnChainToken | undefined {
function findOnChainToken(tokenStr?: string, networkType?: Networks | string): OnChainTokenSymbol | undefined {
if (!tokenStr || !networkType) {
return undefined;
}
Expand All @@ -76,15 +82,15 @@ function findOnChainToken(tokenStr?: string, networkType?: Networks | string): O
const [_, tokenValue] = matchedToken;
return tokenValue as unknown as OnChainToken;
} else {
const evmTokenEntries = Object.entries(EvmToken);
const matchedToken = evmTokenEntries.find(([_, token]) => token.toUpperCase() === tokenStr);

if (!matchedToken) {
return EvmToken.USDC;
if (isNetworkEVM(networkType as Networks)) {
const dynamicConfig = getEvmTokenConfig();
const networkTokens = dynamicConfig[networkType as EvmNetworks];
if (networkTokens && tokenStr in networkTokens) {
return tokenStr;
}
}

const [_, tokenValue] = matchedToken;
return tokenValue as OnChainToken;
return EvmToken.USDC;
}
}

Expand All @@ -108,7 +114,7 @@ const mapFiatToDestination = (fiatToken: FiatToken): DestinationType => {

interface QuoteParams {
inputAmount?: Big;
onChainToken: OnChainToken;
onChainToken: OnChainTokenSymbol;
fiatToken: FiatToken;
selectedNetwork: DestinationType;
rampType: RampDirection;
Expand All @@ -119,8 +125,8 @@ interface QuotePayload {
fromDestination: DestinationType;
toDestination: DestinationType;
inputAmount: string;
inputCurrency: OnChainToken | FiatToken;
outputCurrency: OnChainToken | FiatToken;
inputCurrency: OnChainTokenSymbol | FiatToken;
outputCurrency: OnChainTokenSymbol | FiatToken;
}

const createQuotePayload = (params: QuoteParams): QuotePayload => {
Expand Down Expand Up @@ -171,22 +177,25 @@ export const useRampUrlParams = (): RampUrlParams => {
const params = useMemo(() => new URLSearchParams(window.location.search), []);
const { selectedNetwork } = useNetwork();
const rampDirectionStore = useRampDirection();
const evmTokensLoaded = useSyncExternalStore(subscribeEvmTokensLoaded, getEvmTokensLoadedSnapshot);

const urlParams = useMemo(() => {
const rampDirectionParam = params.get(RampUrlParamsKeys.RAMP_TYPE)?.toUpperCase();
const fiatParam = params.get(RampUrlParamsKeys.FIAT)?.toUpperCase();
const cryptoLockedParam = params.get(RampUrlParamsKeys.CRYPTO_LOCKED)?.toUpperCase();
const countryCodeParam = params.get(RampUrlParamsKeys.COUNTRY_CODE)?.toUpperCase();

const moneriumCode = params.get(RampUrlParamsKeys.MONERIUM_CODE)?.toLowerCase();
const networkParam = params.get(RampUrlParamsKeys.NETWORK)?.toLowerCase();
const providedQuoteId = params.get(RampUrlParamsKeys.PROVIDED_QUOTE_ID)?.toLowerCase();
const paymentMethodParam = params.get(RampUrlParamsKeys.PAYMENT_METHOD)?.toLowerCase() as PaymentMethod | undefined;

const inputAmountParam = params.get(RampUrlParamsKeys.INPUT_AMOUNT);
const partnerIdParam = params.get(RampUrlParamsKeys.PARTNER_ID);
const apiKeyParam = params.get(RampUrlParamsKeys.API_KEY);
const moneriumCode = params.get(RampUrlParamsKeys.MONERIUM_CODE)?.toLowerCase();
const providedQuoteId = params.get(RampUrlParamsKeys.PROVIDED_QUOTE_ID)?.toLowerCase();
const fiatParam = params.get(RampUrlParamsKeys.FIAT)?.toUpperCase();
const cryptoLockedParam = params.get(RampUrlParamsKeys.CRYPTO_LOCKED)?.toUpperCase();
const paymentMethodParam = params.get(RampUrlParamsKeys.PAYMENT_METHOD) as PaymentMethod | undefined;
const walletLockedParam = params.get(RampUrlParamsKeys.WALLET_LOCKED);
const callbackUrlParam = params.get(RampUrlParamsKeys.CALLBACK_URL);
const externalSessionIdParam = params.get(RampUrlParamsKeys.EXTERNAL_SESSION_ID);
const countryCodeParam = params.get(RampUrlParamsKeys.COUNTRY_CODE)?.toUpperCase();

const rampDirection =
rampDirectionParam === RampDirection.BUY || rampDirectionParam === RampDirection.SELL
Expand All @@ -202,6 +211,7 @@ export const useRampUrlParams = (): RampUrlParams => {
callbackUrl: callbackUrlParam || undefined,
countryCode: countryCodeParam || undefined,
cryptoLocked,
evmTokensLoaded,
externalSessionId: externalSessionIdParam || undefined,
fiat,
inputAmount: inputAmountParam || undefined,
Expand All @@ -213,7 +223,8 @@ export const useRampUrlParams = (): RampUrlParams => {
rampDirection,
walletLocked: walletLockedParam || undefined
};
}, [params, rampDirectionStore, selectedNetwork]);
// evmTokensLoaded: triggers re-evaluation of cryptoLocked when dynamic tokens (e.g. WETH, WBTC) finish loading from SquidRouter
}, [params, rampDirectionStore, selectedNetwork, evmTokensLoaded]);

return urlParams;
};
Expand Down Expand Up @@ -411,4 +422,10 @@ export const useSetRampUrlParams = () => {
handleFiatToken,
moneriumCode
]);

useEffect(() => {
if (cryptoLocked) {
setOnChainToken(cryptoLocked);
}
}, [cryptoLocked, setOnChainToken]);
};
12 changes: 7 additions & 5 deletions apps/frontend/src/sections/business/WhyVortexWidget/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,14 @@ export const WhyVortexWidget = () => {

<div className="flex justify-center">
<div className="relative mt-12">
<div className="badge absolute top-[-10px] right-[-20px] z-20 bg-blue-700 text-white">
{t("pages.business.hero.comingSoon")}
</div>
<button className="btn btn-vortex-primary-inverse" disabled>
<a
className="btn btn-vortex-primary"
href="https://api-docs.vortexfinance.co/generate-a-widget-url-with-quote-refresh-21452254e0"
rel="noreferrer"
target="_blank"
>
Get started <ArrowTopRightOnSquareIcon className="h-4 w-4" />
</button>
</a>
</div>
</div>
</div>
Expand Down
11 changes: 6 additions & 5 deletions apps/frontend/src/services/api/quote.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import {
DestinationType,
FiatToken,
getNetworkFromDestination,
OnChainToken,
OnChainTokenSymbol,
PaymentMethod,
QuoteResponse,
RampCurrency,
RampDirection
} from "@vortexfi/shared";
import { apiRequest } from "./api-client";
Expand Down Expand Up @@ -35,8 +36,8 @@ export class QuoteService {
from: DestinationType,
to: DestinationType,
inputAmount: string,
inputCurrency: OnChainToken | FiatToken,
outputCurrency: OnChainToken | FiatToken,
inputCurrency: OnChainTokenSymbol | FiatToken,
outputCurrency: OnChainTokenSymbol | FiatToken,
apiKey?: string,
partnerId?: string,
paymentMethod?: PaymentMethod,
Expand All @@ -52,9 +53,9 @@ export class QuoteService {
countryCode,
from,
inputAmount,
inputCurrency,
inputCurrency: inputCurrency as RampCurrency,
network,
outputCurrency,
outputCurrency: outputCurrency as RampCurrency,
paymentMethod,
rampType,
to
Expand Down
8 changes: 0 additions & 8 deletions apps/frontend/src/services/signingService.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ interface SignerServiceSep10Response {
masterClientPublic: string;
}

type BrlaOfframpState = "BURN" | "MONEY-TRANSFER";
type OfframpStatus = "QUEUED" | "POSTED" | "SUCCESS" | "FAILED";

export enum KycStatus {
PENDING = "PENDING",
REJECTED = "REJECTED",
Expand All @@ -31,11 +28,6 @@ export enum KycStatus {

export type KycStatusType = keyof typeof KycStatus;

interface BrlaOfframpStatus {
type: BrlaOfframpState;
status: OfframpStatus;
}

type TaxIdType = "CPF" | "CNPJ";

export interface RegisterSubaccountPayload {
Expand Down
7 changes: 4 additions & 3 deletions apps/frontend/src/stores/quote/useQuoteFormStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
getOnChainTokenDetails,
Networks,
OnChainToken,
OnChainTokenSymbol,
RampDirection
} from "@vortexfi/shared";
import { create } from "zustand";
Expand Down Expand Up @@ -42,7 +43,7 @@ const defaultOnChainToken =

interface RampFormState {
inputAmount: string;
onChainToken: OnChainToken;
onChainToken: OnChainTokenSymbol;
fiatToken: FiatToken;
lastConstraintDirection: RampDirection;
taxId?: string;
Expand All @@ -52,7 +53,7 @@ interface RampFormState {
interface RampFormActions {
actions: {
setInputAmount: (amount?: string) => void;
setOnChainToken: (token: OnChainToken) => void;
setOnChainToken: (token: OnChainTokenSymbol) => void;
setFiatToken: (token: FiatToken) => void;
setConstraintDirection: (direction: RampDirection) => void;
handleNetworkChange: (network: Networks) => void;
Expand Down Expand Up @@ -93,7 +94,7 @@ export const useQuoteFormStore = create<RampFormState & RampFormActions>()(
setConstraintDirection: (direction: RampDirection) => set({ lastConstraintDirection: direction }),
setFiatToken: (token: FiatToken) => set({ fiatToken: token }),
setInputAmount: (amount?: string) => set({ inputAmount: amount }),
setOnChainToken: (token: OnChainToken) => set({ onChainToken: token }),
setOnChainToken: (token: OnChainTokenSymbol) => set({ onChainToken: token }),
setPixId: (pixId: string) => set({ pixId }),
setTaxId: (taxId: string) => set({ taxId })
}
Expand Down
7 changes: 4 additions & 3 deletions apps/frontend/src/stores/quote/useQuoteStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
EPaymentMethod,
FiatToken,
OnChainToken,
OnChainTokenSymbol,
QuoteError,
QuoteResponse,
RampDirection
Expand All @@ -14,7 +15,7 @@ import { QuoteService } from "../../services/api";

interface QuoteParams {
inputAmount?: Big;
onChainToken: OnChainToken;
onChainToken: OnChainTokenSymbol;
fiatToken: FiatToken;
selectedNetwork: DestinationType;
rampType: RampDirection;
Expand All @@ -27,8 +28,8 @@ interface QuotePayload {
fromDestination: DestinationType;
toDestination: DestinationType;
inputAmount: string;
inputCurrency: OnChainToken | FiatToken;
outputCurrency: OnChainToken | FiatToken;
inputCurrency: OnChainTokenSymbol | FiatToken;
outputCurrency: OnChainTokenSymbol | FiatToken;
}

interface QuoteActions {
Expand Down
4 changes: 2 additions & 2 deletions apps/frontend/src/types/phases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
EphemeralAccount,
FiatToken,
Networks,
OnChainToken,
OnChainTokenSymbol,
PaymentData,
PresignedTx,
QuoteResponse,
Expand All @@ -24,7 +24,7 @@ export interface RampState {

export interface RampExecutionInput {
quote: QuoteResponse;
onChainToken: OnChainToken;
onChainToken: OnChainTokenSymbol;
fiatToken: FiatToken;
sourceOrDestinationAddress: string; // The source address for offramps, destination address for onramps
moneriumWalletAddress?: string; // Only needed for Monerium offramps to non-EVM chains (e.g. Monerium -> Assethub)
Expand Down
5 changes: 2 additions & 3 deletions apps/frontend/src/types/searchParams.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { EPaymentMethod, RampDirection } from "@vortexfi/shared";
import { z } from "zod";

/**
Expand All @@ -22,9 +21,9 @@ export const rampSearchSchema = z.object({
inputAmount: stringOrNumberParam,
network: z.string().optional(),
partnerId: z.string().optional(),
paymentMethod: z.nativeEnum(EPaymentMethod).optional().catch(undefined),
paymentMethod: z.string().optional(),
quoteId: z.string().optional(),
rampType: z.nativeEnum(RampDirection).optional().catch(undefined),
rampType: z.string().optional(),
walletAddressLocked: z.string().optional()
Comment on lines 22 to 27
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing paymentMethod and rampType to z.string() removes validation/normalization. This can cause invalid values (e.g. rampType=foo) to be treated as “present” and make hasAllQuoteRefreshParams skip the quote form incorrectly. Keep schema validation but make it case-insensitive (e.g., preprocess to upper/lower then z.nativeEnum(...).optional().catch(undefined)).

Copilot uses AI. Check for mistakes.
});

Expand Down
Loading