From b2c945caa1f1544714aa66a6bdd70a1375d3e773 Mon Sep 17 00:00:00 2001 From: Kacper Szarkiewicz Date: Fri, 24 Apr 2026 16:45:29 +0200 Subject: [PATCH 1/5] Update AlfredpayFiatAccountFields and AlfredpayAddFiatAccountRequest for v2 API --- .../shared/src/endpoints/alfredpay.endpoints.ts | 10 +++++----- packages/shared/src/services/alfredpay/types.ts | 14 ++++++++------ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/shared/src/endpoints/alfredpay.endpoints.ts b/packages/shared/src/endpoints/alfredpay.endpoints.ts index d1b0890c7..3cce9a5e5 100644 --- a/packages/shared/src/endpoints/alfredpay.endpoints.ts +++ b/packages/shared/src/endpoints/alfredpay.endpoints.ts @@ -91,17 +91,17 @@ export interface AlfredpayAddFiatAccountRequest { country: string; type: AlfredpayFiatAccountType; accountNumber: string; - accountType: string; - accountName: string; - accountBankCode: string; - accountAlias?: string; - networkIdentifier?: string; + accountType?: string; + accountName?: string; + accountBankCode?: string; routingNumber?: string; bankStreet?: string; bankCity?: string; bankState?: string; bankCountry?: string; bankPostalCode?: string; + documentType?: string; + documentNumber?: string; } export interface AlfredpayAddFiatAccountResponse { diff --git a/packages/shared/src/services/alfredpay/types.ts b/packages/shared/src/services/alfredpay/types.ts index 54e6e7d75..d2d7fc8b4 100644 --- a/packages/shared/src/services/alfredpay/types.ts +++ b/packages/shared/src/services/alfredpay/types.ts @@ -310,17 +310,19 @@ export enum AlfredpayFiatAccountType { export interface AlfredpayFiatAccountFields { accountNumber: string; accountType: string; - accountName: string; - accountBankCode: string; - accountAlias: string; - networkIdentifier: string; + accountName?: string; + routingNumber?: string; bankStreet?: string; bankCity?: string; bankState?: string; bankCountry?: string; bankPostalCode?: string; - routingNumber?: string; - isExternal?: boolean; + isExternal: boolean; + metadata?: { + accountHolderName?: string; + documentType?: string; + documentNumber?: string; + }; } export interface CreateAlfredpayFiatAccountRequest { From 32cfd3754b180b1a9d93fb8b086b188715ccb3cf Mon Sep 17 00:00:00 2001 From: Kacper Szarkiewicz Date: Fri, 24 Apr 2026 16:45:47 +0200 Subject: [PATCH 2/5] Build per-type fiatAccountFields in addFiatAccount for v2 Alfredpay API --- .../api/controllers/alfredpay.controller.ts | 56 +++++++++++++++---- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/apps/api/src/api/controllers/alfredpay.controller.ts b/apps/api/src/api/controllers/alfredpay.controller.ts index 20383b353..2138b035f 100644 --- a/apps/api/src/api/controllers/alfredpay.controller.ts +++ b/apps/api/src/api/controllers/alfredpay.controller.ts @@ -652,9 +652,14 @@ export class AlfredpayController { accountType, accountName, accountBankCode, - accountAlias, routingNumber, - networkIdentifier + bankStreet, + bankCity, + bankState, + bankCountry, + bankPostalCode, + documentType, + documentNumber } = req.body as AlfredpayAddFiatAccountRequest; const userId = req.userId!; @@ -667,16 +672,45 @@ export class AlfredpayController { return res.status(404).json({ error: "Alfredpay customer not found" }); } + const alfredpayFiatAccountType = type as AlfredpayFiatAccountType; + + let fiatAccountFields; + if (alfredpayFiatAccountType === AlfredpayFiatAccountType.SPEI) { + fiatAccountFields = { + accountNumber, + accountType: "CLABE", + isExternal: true, + metadata: { accountHolderName: accountName } + }; + } else if (alfredpayFiatAccountType === AlfredpayFiatAccountType.ACH) { + fiatAccountFields = { + accountName: accountBankCode, + accountNumber, + accountType: accountType ?? "", + isExternal: true, + metadata: { accountHolderName: accountName, documentNumber, documentType } + }; + } else { + // BANK_USA + fiatAccountFields = { + accountName: accountBankCode, + accountNumber, + accountType: accountType ?? "", + bankCity, + bankCountry, + bankPostalCode, + bankState, + bankStreet, + routingNumber + }; + } + const alfredpayService = AlfredpayApiService.getInstance(); - const result = await alfredpayService.createFiatAccount(alfredPayCustomer.alfredPayId, type as AlfredpayFiatAccountType, { - accountAlias: accountAlias ?? "", - accountBankCode, - accountName, - accountNumber, - accountType: accountType ?? "", - networkIdentifier: networkIdentifier ?? "", - routingNumber - }); + const result = await alfredpayService.createFiatAccount( + alfredPayCustomer.alfredPayId, + alfredpayFiatAccountType, + fiatAccountFields + ); res.json(result); } catch (error) { From 31a8c4efc37b40952949297572eb2a221bdb733b Mon Sep 17 00:00:00 2001 From: Kacper Szarkiewicz Date: Fri, 24 Apr 2026 16:46:36 +0200 Subject: [PATCH 3/5] Update fiat account forms and validation for v2 Alfredpay API --- .../SummaryStep/FiatAccountSelector.tsx | 2 +- .../SummaryStep/USOnrampDetails.tsx | 10 ++--- .../src/constants/fiatAccountForms.ts | 38 +++++++++++++------ .../src/constants/fiatAccountMethods.ts | 4 +- .../AccountCardDeck.tsx | 8 ++-- .../RegisterFiatAccountScreen.tsx | 23 ++++++----- apps/frontend/src/translations/en.json | 16 ++++++-- apps/frontend/src/translations/pt.json | 16 ++++++-- 8 files changed, 77 insertions(+), 40 deletions(-) diff --git a/apps/frontend/src/components/widget-steps/SummaryStep/FiatAccountSelector.tsx b/apps/frontend/src/components/widget-steps/SummaryStep/FiatAccountSelector.tsx index c8f14b868..68b5f2520 100644 --- a/apps/frontend/src/components/widget-steps/SummaryStep/FiatAccountSelector.tsx +++ b/apps/frontend/src/components/widget-steps/SummaryStep/FiatAccountSelector.tsx @@ -9,7 +9,7 @@ import { useAlfredpayFiatAccounts } from "../../../hooks/alfredpay/useFiatAccoun import { DropdownSelector } from "../../ui/DropdownSelector"; function accountLabel(account: AlfredpayFiatAccount) { - return account.fiatAccountFields.accountAlias || account.fiatAccountFields.accountBankCode; + return account.fiatAccountFields.accountName || account.fiatAccountFields.metadata?.accountHolderName; } function AccountOption({ diff --git a/apps/frontend/src/components/widget-steps/SummaryStep/USOnrampDetails.tsx b/apps/frontend/src/components/widget-steps/SummaryStep/USOnrampDetails.tsx index c76470ac9..72f393f3e 100644 --- a/apps/frontend/src/components/widget-steps/SummaryStep/USOnrampDetails.tsx +++ b/apps/frontend/src/components/widget-steps/SummaryStep/USOnrampDetails.tsx @@ -71,7 +71,7 @@ export const USOnrampDetails: FC = () => { <>
-

{t("components.SummaryPage.USOnrampDetails.title")}

+

{t("components.SummaryPage.USOnrampDetails.title")}

{t("components.SummaryPage.USOnrampDetails.instruction", "Use these bank details to complete your ACH transfer.")}

@@ -93,15 +93,15 @@ export const USOnrampDetails: FC = () => { const display = displayValue(value, fallbackValue); return (
-

{label}

-

{display}

+

{label}

+

{display}

{copyable && display !== fallbackValue && ( - + )}
); diff --git a/apps/frontend/src/constants/fiatAccountForms.ts b/apps/frontend/src/constants/fiatAccountForms.ts index 0adb9bd23..8e236c32f 100644 --- a/apps/frontend/src/constants/fiatAccountForms.ts +++ b/apps/frontend/src/constants/fiatAccountForms.ts @@ -47,6 +47,7 @@ export const FORMS: Record = { field: "accountType", label: "components.fiatAccountForms.accountType", options: [ + { label: "components.fiatAccountForms.options.corriente", value: "CORRIENTE" }, { label: "components.fiatAccountForms.options.ahorro", value: "AHORRO" }, { label: "components.fiatAccountForms.options.nequi", value: "NEQUI" } ], @@ -54,16 +55,10 @@ export const FORMS: Record = { type: "select" }, { field: "accountName", label: "components.fiatAccountForms.accountName", required: true, type: "text" }, - { field: "accountAlias", label: "components.fiatAccountForms.accountAlias", required: false, type: "text" } + { field: "documentType", label: "components.fiatAccountForms.documentType", required: true, type: "text" }, + { field: "documentNumber", label: "components.fiatAccountForms.documentNumber", required: true, type: "text" } ], SPEI: [ - { - field: "accountBankCode", - label: "components.fiatAccountForms.bankName", - placeholder: "components.fiatAccountForms.placeholders.bankNameMx", - required: true, - type: "text" - }, { field: "accountNumber", label: "components.fiatAccountForms.clabe", @@ -71,8 +66,7 @@ export const FORMS: Record = { required: true, type: "text" }, - { field: "accountName", label: "components.fiatAccountForms.accountName", required: true, type: "text" }, - { field: "accountAlias", label: "components.fiatAccountForms.accountAlias", required: false, type: "text" } + { field: "accountName", label: "components.fiatAccountForms.accountName", required: true, type: "text" } ], WIRE: [ { field: "accountBankCode", label: "components.fiatAccountForms.bankName", required: true, type: "text" }, @@ -84,7 +78,27 @@ export const FORMS: Record = { type: "text" }, { field: "accountNumber", label: "components.fiatAccountForms.accountNumber", required: true, type: "text" }, - { field: "accountName", label: "components.fiatAccountForms.accountName", required: true, type: "text" }, - { field: "accountAlias", label: "components.fiatAccountForms.accountAlias", required: false, type: "text" } + { + field: "accountType", + label: "components.fiatAccountForms.accountType", + options: [ + { label: "components.fiatAccountForms.options.checking", value: "CHECKING" }, + { label: "components.fiatAccountForms.options.saving", value: "SAVING" } + ], + required: true, + type: "select" + }, + { field: "bankStreet", label: "components.fiatAccountForms.bankStreet", required: true, type: "text" }, + { field: "bankCity", label: "components.fiatAccountForms.bankCity", required: true, type: "text" }, + { field: "bankState", label: "components.fiatAccountForms.bankState", required: true, type: "text" }, + { + field: "bankCountry", + hint: "components.fiatAccountForms.hints.bankCountry", + label: "components.fiatAccountForms.bankCountry", + placeholder: "components.fiatAccountForms.placeholders.bankCountry", + required: true, + type: "text" + }, + { field: "bankPostalCode", label: "components.fiatAccountForms.bankPostalCode", required: true, type: "text" } ] }; diff --git a/apps/frontend/src/constants/fiatAccountMethods.ts b/apps/frontend/src/constants/fiatAccountMethods.ts index da49cda51..b516c2331 100644 --- a/apps/frontend/src/constants/fiatAccountMethods.ts +++ b/apps/frontend/src/constants/fiatAccountMethods.ts @@ -17,8 +17,8 @@ export const ALFREDPAY_COUNTRY_METHODS: CountryFiatAccountConfig[] = [ country: "US", countryName: "United States", currency: "USD", - offramp: ["ACH", "WIRE"], - onramp: ["ACH", "WIRE"] + offramp: ["WIRE"], + onramp: ["WIRE"] }, { country: "MX", diff --git a/apps/frontend/src/pages/alfredpay/FiatAccountRegistration/AccountCardDeck.tsx b/apps/frontend/src/pages/alfredpay/FiatAccountRegistration/AccountCardDeck.tsx index 0af7d914c..fda2e030e 100644 --- a/apps/frontend/src/pages/alfredpay/FiatAccountRegistration/AccountCardDeck.tsx +++ b/apps/frontend/src/pages/alfredpay/FiatAccountRegistration/AccountCardDeck.tsx @@ -24,9 +24,9 @@ function FrontCardContent({ const { t } = useTranslation(); const { fiatAccountFields, type, fiatAccountId } = account; const accountType = resolveAccountTypeKey(type, country); - const label = fiatAccountFields.accountAlias || fiatAccountFields.accountBankCode; + const label = fiatAccountFields.accountName || fiatAccountFields.metadata?.accountHolderName; const last4 = fiatAccountFields.accountNumber.slice(-4); - const sub = `${fiatAccountFields.accountBankCode} ••••${last4}`; + const sub = `${fiatAccountFields.accountName ?? fiatAccountFields.metadata?.accountHolderName} ••••${last4}`; return (
{t("components.fiatAccountMethods.accountOwner")} - {fiatAccountFields.accountName} + {fiatAccountFields.metadata?.accountHolderName}
onDelete(fiatAccountId)} /> @@ -58,7 +58,7 @@ function BackCardContent({ account, country, index }: { account: AlfredpayFiatAc const accountType = resolveAccountTypeKey(type, country); const bg = index === 1 ? "bg-gray-50" : "bg-gray-100"; const last4 = fiatAccountFields.accountNumber.slice(-4); - const sub = `${fiatAccountFields.accountBankCode} ••••${last4}`; + const sub = `${fiatAccountFields.accountName ?? fiatAccountFields.metadata?.accountHolderName} ••••${last4}`; return (
diff --git a/apps/frontend/src/pages/alfredpay/FiatAccountRegistration/RegisterFiatAccountScreen.tsx b/apps/frontend/src/pages/alfredpay/FiatAccountRegistration/RegisterFiatAccountScreen.tsx index 4c89ac562..7327b2093 100644 --- a/apps/frontend/src/pages/alfredpay/FiatAccountRegistration/RegisterFiatAccountScreen.tsx +++ b/apps/frontend/src/pages/alfredpay/FiatAccountRegistration/RegisterFiatAccountScreen.tsx @@ -47,8 +47,11 @@ function buildZodSchema( if (f.field === "accountNumber" && accountType === "ACH") { schema = z.string().regex(/^\d{4,17}$/, t("components.fiatAccountRegistration.validation.accountNumber")); } + if (f.field === "accountNumber" && accountType === "ACH_COL") { + schema = z.string().regex(/^\d{10,11}$/, t("components.fiatAccountRegistration.validation.accountNumber")); + } if (f.field === "accountNumber" && accountType === "WIRE") { - schema = z.string().regex(/^\d{4,17}$/, t("components.fiatAccountRegistration.validation.accountNumber")); + schema = z.string().regex(/^\d{8,34}$/, t("components.fiatAccountRegistration.validation.accountNumber")); } if (f.field === "accountAlias") { schema = z.string().max(40, t("components.fiatAccountRegistration.validation.nickname")).optional(); @@ -79,34 +82,34 @@ export function RegisterFiatAccountScreen({ country, accountType, onSuccess }: R const onSubmit = async (data: Record) => { const { - accountAlias, accountBankCode, accountName, accountNumber, accountType: accountTypeField, - networkIdentifier, routingNumber, bankStreet, bankCity, bankState, bankCountry, - bankPostalCode + bankPostalCode, + documentType, + documentNumber } = data as Record; try { await addFiatAccount.mutateAsync({ - accountAlias, - accountBankCode: accountBankCode ?? "", - accountName: accountName ?? "", + accountBankCode, + accountName, accountNumber: accountNumber ?? "", - accountType: accountTypeField ?? "", + accountType: accountTypeField, bankCity, bankCountry, bankPostalCode, bankState, bankStreet, country, - networkIdentifier, + documentNumber, + documentType, routingNumber, type: alfredType }); @@ -182,7 +185,7 @@ export function RegisterFiatAccountScreen({ country, accountType, onSuccess }: R /> )} - {f.hint && {f.hint}} + {f.hint && {t(f.hint)}} {errors[f.field] && {errors[f.field]?.message as string}}
))} diff --git a/apps/frontend/src/translations/en.json b/apps/frontend/src/translations/en.json index 526a53daa..95ada6f6a 100644 --- a/apps/frontend/src/translations/en.json +++ b/apps/frontend/src/translations/en.json @@ -340,21 +340,31 @@ "yourQuote": "Your quote" }, "fiatAccountForms": { - "accountAlias": "Nickname (optional)", "accountName": "Account Holder Name", "accountNumber": "Account Number", "accountType": "Account Type", + "bankCity": "Bank City", + "bankCountry": "Bank Country", "bankName": "Bank Name", + "bankPostalCode": "Bank Postal Code", + "bankState": "Bank State", + "bankStreet": "Bank Street", "clabe": "CLABE (18 digits)", + "documentNumber": "Document Number", + "documentType": "Document Type", + "hints": { + "bankCountry": "Use the 3-letter country code, e.g. USA" + }, "options": { "ahorro": "Savings (Ahorro)", "checking": "Checking", + "corriente": "Checking (Corriente)", "nequi": "Nequi", - "savings": "Savings" + "saving": "Savings" }, "placeholders": { "accountNumberCo": "10 or 11-digit account number", - "bankNameMx": "e.g. BBVA, Santander, Banamex", + "bankCountry": "e.g. USA", "clabe": "e.g. 032180000118359719", "routingNumber": "e.g. 021000021" }, diff --git a/apps/frontend/src/translations/pt.json b/apps/frontend/src/translations/pt.json index e73d496af..604f11437 100644 --- a/apps/frontend/src/translations/pt.json +++ b/apps/frontend/src/translations/pt.json @@ -341,21 +341,31 @@ "yourQuote": "Sua cotação" }, "fiatAccountForms": { - "accountAlias": "Apelido (opcional)", "accountName": "Nome do Titular da Conta", "accountNumber": "Número da Conta", "accountType": "Tipo de Conta", + "bankCity": "Cidade do Banco", + "bankCountry": "País do Banco", "bankName": "Nome do Banco", + "bankPostalCode": "CEP do Banco", + "bankState": "Estado do Banco", + "bankStreet": "Rua do Banco", "clabe": "CLABE (18 dígitos)", + "documentNumber": "Número do Documento", + "documentType": "Tipo de Documento", + "hints": { + "bankCountry": "Use o código de 3 letras do país, ex. USA" + }, "options": { "ahorro": "Poupança (Ahorro)", "checking": "Corrente", + "corriente": "Corrente (Corriente)", "nequi": "Nequi", - "savings": "Poupança" + "saving": "Poupança" }, "placeholders": { "accountNumberCo": "Número de conta de 10 ou 11 dígitos", - "bankNameMx": "ex. BBVA, Santander, Banamex", + "bankCountry": "ex. USA", "clabe": "ex. 032180000118359719", "routingNumber": "ex. 021000021" }, From 6a0ec754da72fbb048e593291625a5d519c0883a Mon Sep 17 00:00:00 2001 From: Kacper Szarkiewicz Date: Fri, 24 Apr 2026 16:46:45 +0200 Subject: [PATCH 4/5] update favicon config --- apps/frontend/index.html | 10 +++++----- .../{ => public}/android-chrome-192x192.png | Bin .../{ => public}/android-chrome-512x512.png | Bin apps/frontend/{ => public}/apple-touch-icon.png | Bin apps/frontend/{ => public}/favicon-16x16.png | Bin apps/frontend/{ => public}/favicon-32x32.png | Bin apps/frontend/{ => public}/favicon.ico | Bin apps/frontend/{ => public}/site.webmanifest | 4 ++-- 8 files changed, 7 insertions(+), 7 deletions(-) rename apps/frontend/{ => public}/android-chrome-192x192.png (100%) rename apps/frontend/{ => public}/android-chrome-512x512.png (100%) rename apps/frontend/{ => public}/apple-touch-icon.png (100%) rename apps/frontend/{ => public}/favicon-16x16.png (100%) rename apps/frontend/{ => public}/favicon-32x32.png (100%) rename apps/frontend/{ => public}/favicon.ico (100%) rename apps/frontend/{ => public}/site.webmanifest (72%) diff --git a/apps/frontend/index.html b/apps/frontend/index.html index 7538c5a9e..0ab58518c 100644 --- a/apps/frontend/index.html +++ b/apps/frontend/index.html @@ -2,11 +2,11 @@ - - - - - + + + + + Vortex diff --git a/apps/frontend/android-chrome-192x192.png b/apps/frontend/public/android-chrome-192x192.png similarity index 100% rename from apps/frontend/android-chrome-192x192.png rename to apps/frontend/public/android-chrome-192x192.png diff --git a/apps/frontend/android-chrome-512x512.png b/apps/frontend/public/android-chrome-512x512.png similarity index 100% rename from apps/frontend/android-chrome-512x512.png rename to apps/frontend/public/android-chrome-512x512.png diff --git a/apps/frontend/apple-touch-icon.png b/apps/frontend/public/apple-touch-icon.png similarity index 100% rename from apps/frontend/apple-touch-icon.png rename to apps/frontend/public/apple-touch-icon.png diff --git a/apps/frontend/favicon-16x16.png b/apps/frontend/public/favicon-16x16.png similarity index 100% rename from apps/frontend/favicon-16x16.png rename to apps/frontend/public/favicon-16x16.png diff --git a/apps/frontend/favicon-32x32.png b/apps/frontend/public/favicon-32x32.png similarity index 100% rename from apps/frontend/favicon-32x32.png rename to apps/frontend/public/favicon-32x32.png diff --git a/apps/frontend/favicon.ico b/apps/frontend/public/favicon.ico similarity index 100% rename from apps/frontend/favicon.ico rename to apps/frontend/public/favicon.ico diff --git a/apps/frontend/site.webmanifest b/apps/frontend/public/site.webmanifest similarity index 72% rename from apps/frontend/site.webmanifest rename to apps/frontend/public/site.webmanifest index 085af57de..0e55f1192 100644 --- a/apps/frontend/site.webmanifest +++ b/apps/frontend/public/site.webmanifest @@ -4,12 +4,12 @@ "icons": [ { "sizes": "192x192", - "src": "/frontend/android-chrome-192x192.png", + "src": "/android-chrome-192x192.png", "type": "image/png" }, { "sizes": "512x512", - "src": "/frontend/android-chrome-512x512.png", + "src": "/android-chrome-512x512.png", "type": "image/png" } ], From 18bf98731df97f92639211bf9836a09b695ff0d8 Mon Sep 17 00:00:00 2001 From: Marcel Ebert Date: Fri, 24 Apr 2026 18:35:01 +0200 Subject: [PATCH 5/5] Small fix for `undefined` --- .../components/widget-steps/SummaryStep/FiatAccountSelector.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/src/components/widget-steps/SummaryStep/FiatAccountSelector.tsx b/apps/frontend/src/components/widget-steps/SummaryStep/FiatAccountSelector.tsx index e4fe2759f..6e3c3a7e3 100644 --- a/apps/frontend/src/components/widget-steps/SummaryStep/FiatAccountSelector.tsx +++ b/apps/frontend/src/components/widget-steps/SummaryStep/FiatAccountSelector.tsx @@ -79,7 +79,7 @@ export function FiatAccountSelector() { ? (resolveAccountTypeKey(selectedAccount.type, country) ?? null) : null; const Icon = accountType ? ACCOUNT_TYPE_ICONS[accountType] : null; - const last4 = selectedAccount.accountNumber.slice(-4); + const last4 = selectedAccount?.accountNumber.slice(-4); const triggerContent = selectedAccount ? ( <>