diff --git a/src/app/api/bridge/external-account/create-external-account/route.ts b/src/app/api/bridge/external-account/create-external-account/route.ts index a699f390a..e3339c0fb 100644 --- a/src/app/api/bridge/external-account/create-external-account/route.ts +++ b/src/app/api/bridge/external-account/create-external-account/route.ts @@ -68,6 +68,26 @@ export async function POST(request: NextRequest) { const data = await response.json() if (!response.ok) { + if (data.code && data.code == 'duplicate_external_account') { + // in case the bridge account already exists + // + // sending back error responses is not currently common across app + // in how we deliver errors from backend -> frontend + // sends back an object like: + // { + // id: '4c537540-80bf-41dd-a528-dbe39a4', + // code: 'duplicate_external_account', + // message: 'An external account with the same information has already been added for this customer' + // } + // + // TODO: standardize error responses across backend + return new NextResponse(JSON.stringify(data), { + status: response.status, + headers: { + 'Content-Type': 'application/json', + }, + }) + } throw new Error(`HTTP error! status: ${response.status}`) } diff --git a/src/components/Global/LinkAccountComponent/index.tsx b/src/components/Global/LinkAccountComponent/index.tsx index 49ea4f415..729178d81 100644 --- a/src/components/Global/LinkAccountComponent/index.tsx +++ b/src/components/Global/LinkAccountComponent/index.tsx @@ -11,6 +11,7 @@ import Icon from '../Icon' import { useAuth } from '@/context/authContext' import { Divider } from '@chakra-ui/react' import { isIBAN } from 'validator' +import { IBridgeAccount, IResponse } from '@/interfaces' const steps = [{ label: 'Step 1: Enter bank account' }, { label: 'Step 2: Provide details' }] @@ -172,13 +173,25 @@ export const GlobaLinkAccountComponent = ({ accountNumber, onCompleted }: IGloba throw new Error('Customer ID is missing') } - const data = await utils.createExternalAccount( + const response: IResponse = await utils.createExternalAccount( customerId, accountType as 'iban' | 'us', accountDetails, address, accountOwnerName ) + + if (!response.success) { + if (response.data && response.data.code == 'duplicate_external_account' ) { + // bridge account already exists for this IBAN + const errorMessage = 'An external account with the same information has already been added for this customer' + throw new Error(errorMessage) + + } + throw new Error('Creating Bridge account failed') + } + + const data: IBridgeAccount = response.data await utils.createAccount( user?.user?.userId ?? '', @@ -193,7 +206,7 @@ export const GlobaLinkAccountComponent = ({ accountNumber, onCompleted }: IGloba onCompleted ? onCompleted() : setCompletedLinking(true) } catch (error) { console.error('Error during the submission process:', error) - setErrorState({ showError: true, errorMessage: 'An error occurred. Please try again later' }) + setErrorState({ showError: true, errorMessage: String(error)}) } finally { setLoadingState('Idle') } diff --git a/src/interfaces/interfaces.ts b/src/interfaces/interfaces.ts index 36d15ea03..cab68e421 100644 --- a/src/interfaces/interfaces.ts +++ b/src/interfaces/interfaces.ts @@ -2,6 +2,11 @@ import { interfaces as peanutInterfaces } from '@squirrel-labs/peanut-sdk' export type RecipientType = 'address' | 'ens' | 'iban' | 'us' +export interface IResponse { + success: boolean + data?: any +} + export interface IUserBalance { chainId: string address: string diff --git a/src/utils/cashout.utils.ts b/src/utils/cashout.utils.ts index 1d0f5219f..9d76ac2f6 100644 --- a/src/utils/cashout.utils.ts +++ b/src/utils/cashout.utils.ts @@ -172,7 +172,7 @@ export async function createExternalAccount( accountDetails: any, address: any, accountOwnerName: string -): Promise { +): Promise { try { const response = await fetch(`/api/bridge/external-account/create-external-account?customerId=${customerId}`, { method: 'POST', @@ -187,13 +187,36 @@ export async function createExternalAccount( }), }) + const data = await response.json() + if (!response.ok) { + if (data.code && data.code == 'duplicate_external_account') { + // if bridge account already exists for this iban + // but somehow not stored in our DB (this should never happen in + // prod, but can happen if same email used in prod & staging) + // + // returns: not interfaces.IBridgeAccount type, but + // a currently undefined error type on the data field of interfaces.IResponse + // of format: + // { + // id: '4c537540-80bf-41dd-a528-d79a4', + // code: 'duplicate_external_account', + // message: 'An external account with the same information has already been added for this customer' + // } + // + // TODO: HTTP responses need to be standardized client wide + return { + success: false, + data + } as interfaces.IResponse + } throw new Error('Failed to create external account') } - const data = await response.json() - - return data as interfaces.IBridgeAccount + return { + success: true, + data: data as interfaces.IBridgeAccount + } as interfaces.IResponse } catch (error) { console.error('Error:', error) throw new Error(`Failed to create external account. Error: ${error}`)