Skip to content
Merged
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
81 changes: 42 additions & 39 deletions api/src/api/controllers/brla.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Request, Response } from 'express';
import { validateMaskedNumber } from 'shared';
import { BrlaEndpoints } from 'shared/src/endpoints/brla.endpoints';
import httpStatus from 'http-status';
import { BrlaApiService } from '../services/brla/brlaApiService';
import { eventPoller } from '../..';
import { generateReferenceLabel } from '../services/brla/helpers';
Expand Down Expand Up @@ -37,18 +38,18 @@ function handleApiError(error: unknown, res: Response, apiMethod: string): void
const errorMessageString = splitError[1];
try {
const details = JSON.parse(errorMessageString);
res.status(400).json({ error: 'Invalid request', details });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Invalid request', details });
} catch (e) {
// The error was not encoded as JSON
res.status(400).json({ error: 'Invalid request', details: errorMessageString });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Invalid request', details: errorMessageString });
}
} else {
res.status(400).json({ error: 'Invalid request', details: error.message });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Invalid request', details: error.message });
}
return;
}

res.status(500).json({
res.status(httpStatus.INTERNAL_SERVER_ERROR).json({
error: 'Server error',
details: error instanceof Error ? error.message : 'Unknown error',
});
Expand All @@ -75,18 +76,18 @@ export const getBrlaUser = async (
const { taxId } = req.query;

if (!taxId) {
res.status(400).json({ error: 'Missing taxId query parameters' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Missing taxId query parameters' });
return;
}

const brlaApiService = BrlaApiService.getInstance();
const subaccount = await brlaApiService.getSubaccount(taxId);
if (!subaccount) {
res.status(404).json({ error: 'Subaccount not found' });
res.status(httpStatus.NOT_FOUND).json({ error: 'Subaccount not found' });
return;
}
if (subaccount.kyc.level < 1) {
res.status(400).json({ error: 'KYC invalid' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'KYC invalid' });
return;
}

Expand All @@ -105,22 +106,22 @@ export const getBrlaUserRemainingLimit = async (
const { taxId } = req.query;

if (!taxId) {
res.status(400).json({ error: 'Missing taxId query parameter' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Missing taxId query parameter' });
return;
}

const brlaApiService = BrlaApiService.getInstance();
const subaccount = await brlaApiService.getSubaccount(taxId);

if (!subaccount) {
res.status(404).json({ error: 'Subaccount not found' });
res.status(httpStatus.NOT_FOUND).json({ error: 'Subaccount not found' });
return;
}

const totalLimit = subaccount.kyc.limits;
const usedLimit = await brlaApiService.getSubaccountUsedLimit(subaccount.id);
if (!usedLimit) {
res.status(404).json({ error: 'Limits not found' });
res.status(httpStatus.NOT_FOUND).json({ error: 'Limits not found' });
return;
}

Expand Down Expand Up @@ -152,7 +153,7 @@ export const triggerBrlaOfframp = async (
const subaccount = await brlaApiService.getSubaccount(taxId);

if (!subaccount) {
res.status(404).json({ error: 'Subaccount not found' });
res.status(httpStatus.NOT_FOUND).json({ error: 'Subaccount not found' });
return;
}

Expand All @@ -162,17 +163,17 @@ export const triggerBrlaOfframp = async (

// validate the recipient's taxId with partial information
if (!validateMaskedNumber(pixKeyData.taxId, receiverTaxId)) {
res.status(400).json({ error: 'Invalid pixKey or receiverTaxId' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Invalid pixKey or receiverTaxId' });
return;
}
} catch (error) {
res.status(400).json({ error: 'Invalid pixKey or receiverTaxId' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Invalid pixKey or receiverTaxId' });
return;
}

const { limitBurn } = subaccount.kyc.limits;
if (Number(amount) > limitBurn) {
res.status(400).json({ error: 'Amount exceeds limit' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Amount exceeds limit' });
return;
}

Expand All @@ -182,7 +183,7 @@ export const triggerBrlaOfframp = async (
amount: Number(amount),
taxId: receiverTaxId,
});
res.status(200).json({ offrampId });
res.status(httpStatus.OK).json({ offrampId });
return;
} catch (error) {
handleApiError(error, res, 'triggerOfframp');
Expand All @@ -197,21 +198,21 @@ export const getOfframpStatus = async (
const { taxId } = req.query;

if (!taxId) {
res.status(400).json({ error: 'Missing taxId' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Missing taxId' });
return;
}

const brlaApiService = BrlaApiService.getInstance();
const subaccount = await brlaApiService.getSubaccount(taxId);
if (!subaccount) {
res.status(400).json({ error: 'Subaccount not found' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Subaccount not found' });
return;
}

const lastEventCached = await eventPoller.getLatestEventForUser(subaccount.id);

if (!lastEventCached) {
res.status(404).json({ error: `No status events found for ${taxId}` });
res.status(httpStatus.NOT_FOUND).json({ error: `No status events found for ${taxId}` });
return;
}

Expand All @@ -220,11 +221,11 @@ export const getOfframpStatus = async (
lastEventCached.subscription !== 'BURN' &&
lastEventCached.subscription !== 'BALANCE-UPDATE'
) {
res.status(404).json({ error: `No offramp status event found for ${taxId}` });
res.status(httpStatus.NOT_FOUND).json({ error: `No offramp status event found for ${taxId}` });
return;
}

res.status(200).json({
res.status(httpStatus.OK).json({
type: lastEventCached.subscription,
status: lastEventCached.data.status,
});
Expand All @@ -243,7 +244,7 @@ export const createSubaccount = async (
const taxId = taxIdType === 'CNPJ' ? cnpj : cpf;

if (!taxId) {
res.status(400).json({ error: 'Missing cpf or cnpj' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Missing cpf or cnpj' });
return;
}

Expand All @@ -258,30 +259,32 @@ export const createSubaccount = async (
// Extra validation for company fields
if (taxIdType === 'CNPJ') {
if (!req.body.companyName) {
res.status(400).json({ error: 'Missing companyName' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Missing companyName' });
return;
}
if (!req.body.cpf) {
res.status(400).json({ error: 'Missing cpf. Partner cpf is required' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Missing cpf. Partner cpf is required' });
return;
}
if (startDate === '') {
res.status(400).json({ error: 'Missing startDate' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Missing startDate' });
return;
}
}

const subaccount = await brlaApiService.getSubaccount(taxId);
if (subaccount && subaccount.kyc.level !== 0) {
res.status(400).json({ error: 'Subaccount already created' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Subaccount already created' });
return;
} else if (subaccount && subaccount.kyc.level === 0) {
}

if (subaccount && subaccount.kyc.level === 0) {
logger.info('Subaccount Payload', subaccountPayload);

await brlaApiService.retryKYC(subaccount.id, subaccountPayload);

lastInteractionMap.set(subaccount.id, Date.now());
res.status(200).json({ subaccountId: '' });
res.status(httpStatus.OK).json({ subaccountId: '' });
return;
}

Expand All @@ -305,14 +308,14 @@ export const fetchSubaccountKycStatus = async (
const { taxId } = req.query;

if (!taxId) {
res.status(400).json({ error: 'Missing taxId' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Missing taxId' });
return;
}

const brlaApiService = BrlaApiService.getInstance();
const subaccount = await brlaApiService.getSubaccount(taxId);
if (!subaccount) {
res.status(400).json({ error: 'Subaccount not found' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Subaccount not found' });
return;
}

Expand All @@ -338,7 +341,7 @@ export const fetchSubaccountKycStatus = async (
return;
}

res.status(200).json({
res.status(httpStatus.OK).json({
type: lastEventCached.subscription,
status: lastEventCached.data.kycStatus,
level: lastEventCached.data.level,
Expand Down Expand Up @@ -371,19 +374,19 @@ export const getPayInCode = async (
const brlaApiService = BrlaApiService.getInstance();
const subaccount = await brlaApiService.getSubaccount(taxId);
if (!subaccount) {
res.status(404).json({ error: 'Subaccount not found' });
res.status(httpStatus.NOT_FOUND).json({ error: 'Subaccount not found' });
return;
}

if (subaccount.kyc.level < 1) {
res.status(400).json({ error: 'KYC invalid' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'KYC invalid' });
return;
}

const { limitMint } = subaccount.kyc.limits;

if (Number(amount) > limitMint) {
res.status(400).json({ error: 'Amount exceeds limit' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Amount exceeds limit' });
return;
}

Expand All @@ -393,7 +396,7 @@ export const getPayInCode = async (
referenceLabel: generateReferenceLabel(receiverAddress),
});

res.status(200).json(brCode);
res.status(httpStatus.OK).json(brCode);
} catch (error) {
handleApiError(error, res, 'triggerOnramp');
}
Expand All @@ -419,14 +422,14 @@ export const validatePixKey = async (
const { pixKey } = req.query;

if (!pixKey) {
res.status(400).json({ error: 'pixKey must be provided' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'pixKey must be provided' });
return;
}

const brlaApiService = BrlaApiService.getInstance();
await brlaApiService.validatePixKey(pixKey);

res.status(200).json({ valid: true });
res.status(httpStatus.OK).json({ valid: true });
} catch (error) {
handleApiError(error, res, 'validatePixKey');
}
Expand Down Expand Up @@ -454,19 +457,19 @@ export const startKYC2 = async (
const subaccount = await brlaApiService.getSubaccount(taxId);

if (!subaccount) {
res.status(404).json({ error: 'Subaccount not found' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Subaccount not found'});
return;
}

if (subaccount.kyc.level !== 1) {
res.status(400).json({ error: 'KYC invalid. User must have a valid KYC level 1 status' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'KYC invalid. User must have a valid KYC level 1 status' });
return;
}

const kycLevel2Response = await kycService.requestKycLevel2(subaccount.id, documentType);

lastInteractionMap.set(subaccount.id, Date.now());
res.status(200).json({ uploadUrls: kycLevel2Response });
res.status(httpStatus.OK).json({ uploadUrls: kycLevel2Response });
} catch (error) {
handleApiError(error, res, 'startKYC2');
}
Expand Down
7 changes: 4 additions & 3 deletions api/src/api/controllers/googleSpreadSheet.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dotenv/config';
import { Request, Response } from 'express';
import httpStatus from 'http-status';
import { config } from '../../config/vars';
import {
initGoogleSpreadsheet,
Expand Down Expand Up @@ -40,17 +41,17 @@ export async function storeDataInGoogleSpreadsheet(
if (!sheet) {
throw new APIError({
message: 'Failed to store data. Sheet unavailable.',
status: 500,
status: httpStatus.INTERNAL_SERVER_ERROR,
isPublic: true,
});
}

await appendData(sheet, req.body);
return res.status(200).json({ message: 'Data stored successfully' });
return res.status(httpStatus.OK).json({ message: 'Data stored successfully' });
} catch (error) {
console.error('Error in storeData:', error);
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
return res.status(500).json({
return res.status(httpStatus.INTERNAL_SERVER_ERROR).json({
error: 'Failed to store data',
details: errorMessage,
});
Expand Down
5 changes: 3 additions & 2 deletions api/src/api/controllers/moonbeam.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { moonbeam } from 'viem/chains';
import { privateKeyToAccount } from 'viem/accounts';
import Big from 'big.js';
import { Request, Response } from 'express';
import httpStatus from 'http-status';

import { MoonbeamEndpoints } from 'shared/src/endpoints/moonbeam.endpoints';
import {
Expand Down Expand Up @@ -63,12 +64,12 @@ export const executeXcmController = async (
return;
} catch (error) {
console.error('Error executing XCM:', error);
res.status(400).json({ error: 'Invalid transaction' });
res.status(httpStatus.BAD_REQUEST).json({ error: 'Invalid transaction' });
return;
}
} catch (error) {
console.error('Error executing XCM:', error);
res.status(500).json({ error: 'Internal Server Error' });
res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ error: 'Internal Server Error' });
}
};

Expand Down
7 changes: 4 additions & 3 deletions api/src/api/controllers/pendulum.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Big from 'big.js';
import { AccountInfo } from '@polkadot/types/interfaces';
import { Request, Response } from 'express';
import httpStatus from 'http-status';

import { StellarTokenConfig, TOKEN_CONFIG, XCMTokenConfig } from 'shared';
import { PendulumEndpoints } from 'shared/src/endpoints/pendulum.endpoints';
Expand All @@ -24,7 +25,7 @@ export const fundEphemeralAccountController = async (
const networkName = 'pendulum';

if (!ephemeralAddress) {
res.status(400).send({ error: 'Invalid request parameters' });
res.status(httpStatus.BAD_REQUEST).send({ error: 'Invalid request parameters' });
return;
}

Expand All @@ -34,11 +35,11 @@ export const fundEphemeralAccountController = async (
res.json({ status: 'success', data: undefined });
return;
}
res.status(500).send({ error: 'Funding error' });
res.status(httpStatus.INTERNAL_SERVER_ERROR).send({ error: 'Funding error' });
return;
} catch (error) {
console.error('Error funding ephemeral account:', error);
res.status(500).send({ error: 'Internal Server Error' });
res.status(httpStatus.INTERNAL_SERVER_ERROR).send({ error: 'Internal Server Error' });
}
};

Expand Down
Loading
Loading