Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: created the getCurrentExpense route #55

Merged
merged 21 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3f55f46
feat: created the getCurrentExpense route
raizo07 Apr 13, 2024
3fbdbe9
fix: fix format and lint errors
raizo07 Apr 15, 2024
0d1da66
Merge branch 'main' into feat/getCurrentExpense
raizo07 Apr 15, 2024
28162ac
feat: wrote a test for getCurrentExpense.ts
raizo07 Apr 15, 2024
6558416
fix: Updated getExpense query and test
raizo07 Apr 16, 2024
93a8d2d
Merge branch 'feat/getCurrentExpense' of https://github.com/raizo07/v…
raizo07 Apr 16, 2024
f1aecf0
Merge branch 'main' into feat/getCurrentExpense
raizo07 Apr 16, 2024
ff735af
fix: fix format and lint errors
raizo07 Apr 16, 2024
18893c5
Merge branch 'main' of https://github.com/raizo07/vault into feat/get…
raizo07 Apr 16, 2024
6c8b11b
updated query
raizo07 Apr 17, 2024
f30489e
updated the test to use transaction hash and createdAt
raizo07 Apr 17, 2024
8d02628
Merge branch 'main' into feat/getCurrentExpense
raizo07 Apr 17, 2024
a6040da
added the suggested changes
raizo07 Apr 17, 2024
21c250b
Merge branch 'feat/getCurrentExpense' of https://github.com/raizo07/v…
raizo07 Apr 17, 2024
63297f5
applied requested changes
raizo07 Apr 17, 2024
5f11c18
changed amount format from Hexadecimal
raizo07 Apr 17, 2024
c66dfdb
updated the amount in test file
raizo07 Apr 18, 2024
9c077b3
used viem to format number values
raizo07 Apr 18, 2024
41a9554
Merge branch 'main' into feat/getCurrentExpense
raizo07 Apr 18, 2024
39fe650
test(backend): fix last test getCurrentExpense
0xLucqs Apr 18, 2024
01d4dd9
Merge branch 'main' into feat/getCurrentExpense
0xLucqs Apr 19, 2024
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
45 changes: 45 additions & 0 deletions backend/src/routes/getCurrentExpense.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { sql } from 'drizzle-orm';
import { and, between, eq, gte } from 'drizzle-orm/pg-core/expressions';
import type { FastifyInstance } from 'fastify';

import { usdcBalance, usdcTransfer } from '@/db/schema';
import { addressRegex } from '.';

export function getCurrentExpenseRoute(fastify: FastifyInstance) {
fastify.get('/get_current_expense', async (request, reply) => {
const { address } = request.query as { address?: string };

if (!address) {
return reply.status(400).send({ error: 'Address is required.' });
}
// Validate address format
if (!addressRegex.test(address)) {
return reply.status(400).send({ error: 'Invalid address format.' });
}

try {
const currentDate = new Date();
// Calculate the date 7 days ago
const sevenDaysAgo = new Date(currentDate);
sevenDaysAgo.setDate(currentDate.getDate() - 7);
// Use Drizzle ORM to find expense by address
const expenses = await fastify.db
.select()
.from(usdcTransfer)
.where(
and(eq(usdcTransfer.fromAddress, address), gte(usdcTransfer.createdAt, sevenDaysAgo)),
);

// Calculate the sum of amounts
const totalAmount = expenses.reduce(
(acc, curr) => acc + Number.parseFloat(curr.amount || '0'),
raizo07 marked this conversation as resolved.
Show resolved Hide resolved
0,
);

return reply.send({ cumulated_expense: totalAmount });
raizo07 marked this conversation as resolved.
Show resolved Hide resolved
} catch (error) {
console.error(error);
return reply.status(500).send({ error: 'Internal server error' });
}
});
}
2 changes: 2 additions & 0 deletions backend/src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { sql } from 'drizzle-orm';
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';

import { getBalanceRoute } from './getBalance';
import { getCurrentExpenseRoute } from './getCurrentExpense';
import { getHistoricalBalanceRoute } from './getHistoricalBalance';
import { getTransactionHistory } from './getTransactionHistory';
import { getRegisterRoute } from './register';
Expand All @@ -12,6 +13,7 @@ export const addressRegex = /^0x0[0-9a-fA-F]{63}$/;
export function declareRoutes(fastify: FastifyInstance) {
getStatusRoute(fastify);
getBalanceRoute(fastify);
getCurrentExpenseRoute(fastify);
getTransactionHistory(fastify);
getRegisterRoute(fastify);
getHistoricalBalanceRoute(fastify);
Expand Down
109 changes: 109 additions & 0 deletions backend/test/getCurrentExpense.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { PostgreSqlContainer, type StartedPostgreSqlContainer } from '@testcontainers/postgresql';
import type { FastifyInstance } from 'fastify';
import { afterAll, beforeAll, describe, expect, test } from 'vitest';

import { buildApp } from '@/app';

import * as schema from '../src/db/schema';
describe('/get_current_expense route', () => {
let container: StartedPostgreSqlContainer;
let app: FastifyInstance;
const testAddress = '0x004babd76a282efdd30b97c8a98b0f2e4ebb91e81b3542bfd124c086648a07af';
const amount = 1000.0;
raizo07 marked this conversation as resolved.
Show resolved Hide resolved
const transactionHash = '0x040d8bb0da6fdfb7825567920fceb1bee209cde3310b1548d17d06cde847348c';

const getDate = (daysDifference?: number): Date => {
if (daysDifference) {
const date = new Date();
const formatDate = new Date(date);
formatDate.setDate(date.getDate() - daysDifference);
return formatDate;
}
const currentDate = new Date();
return currentDate;
};

beforeAll(async () => {
container = await new PostgreSqlContainer().start();
const connectionUri = container.getConnectionUri();
app = buildApp({
database: {
connectionString: connectionUri,
},
app: {
port: 8080,
},
});

await app.ready();
// Insert transfer to mock address

await app.db.insert(schema.usdcTransfer).values({
transferId: `${transactionHash}_1`,
fromAddress: testAddress,
amount: amount.toString(),
createdAt: getDate(10),
});

await app.db.insert(schema.usdcTransfer).values({
transferId: `${transactionHash}_2`,
fromAddress: testAddress,
amount: amount.toString(),
createdAt: getDate(),
});

await app.db.insert(schema.usdcTransfer).values({
transferId: `${transactionHash}_3`,
fromAddress: testAddress,
amount: amount.toString(),
createdAt: getDate(),
});
});

afterAll(async () => {
await app.close();
await container.stop();
});

test('should return the expense for a valid address', async () => {
const response = await app.inject({
method: 'GET',
url: `/get_current_expense?address=${testAddress}`,
});

expect(response.statusCode).toBe(200);
expect(response.json()).toHaveProperty('cumulated_expense', 2000);
});

test('should return error, invalid address format', async () => {
const invalidAddress = '0x0';
const response = await app.inject({
method: 'GET',
url: `/get_current_expense?address=${invalidAddress}`,
});

expect(response.statusCode).toBe(400);
expect(response.json()).toHaveProperty('error', 'Invalid address format.');
});

test('should return error, no address provided', async () => {
const response = await app.inject({
method: 'GET',
url: '/get_current_expense',
});

expect(response.statusCode).toBe(400);
expect(response.json()).toHaveProperty('error', 'Address is required.');
});

test('should return 0, unknown address', async () => {
const unknownAddress = '0x004babd76a282efdd30b97c8a98b0f2e4ebb91e81b3542bfd124c086648a07ae';
const response = await app.inject({
method: 'GET',
url: `/get_current_expense?address=${unknownAddress}`,
});

expect(response.statusCode).toBe(200);
expect(response.json()).toHaveProperty('cumulated_expense', '0x0');
0xLucqs marked this conversation as resolved.
Show resolved Hide resolved
});
});