This is the repository for the Sycamore backend task. I have leveraged a modern tech stack to ensure data precision, system reliability, and maintainability through clean architecture.
This project is built with a focus on long-term scalability and fault tolerance. Here are my key design choices:
-
Domain-Driven Design (DDD): I organized the codebase by feature modules (User, Wallet, Transfer, Interest). This ensures that business logic is encapsulated within its own domain, making the system easier to navigate and scale.
-
Repository Pattern: I used repositories to abstract the data access layer (Sequelize). By injecting repositories into my services rather than models directly, I decoupled business logic from the ORM, facilitating easier unit testing and providing the flexibility to switch data sources in the future.
-
Eventual Consistency via Message Queues: For transaction processing, I opted for Bull Queue (Redis). Instead of processing heavy financial transfers in a single request-response cycle, I queue them. This ensures:
-
Scalability: The system can handle spikes in transaction volume without crashing.
-
Reliability: Built-in retry mechanisms with exponential backoff handle transient database or network failures.
-
User Experience: The API responds immediately, while the heavy lifting happens in the background.
-
Precision Engineering: In fintech, floating-point math is a liability. I used
decimal.jsfor all balance and interest calculations to ensure zero rounding errors.
A standout feature of this wallet is the Automated Interest Accrual.
-
Rate: 27.5% APR (Annual Percentage Rate).
-
Formula: Interest is calculated daily using the following formula:
-
Logic: The service automatically detects leap years (366 days) vs. non-leap years (365 days) to ensure absolute accuracy.
- Docker and Docker Compose
- Node.js 18+ (if running locally)
- Clone the Repository:
git clone https://github.com/Bolu1/simple-wallet.git
cd simple-wallet
- Environment Configuration:
There is an
.env.examplefile included in the root directory. Copy it to create your local environment file:
cp .env.example .env
Update the variables in .env if you have specific port preferences.
3. Start the Application:
You can run the entire stack (PostgreSQL, Redis, NestJS) using Docker:
docker-compose up -d --build
Alternatively, for local development, ensure Postgres and Redis are running, then use npm run start:dev.
To populate your environment with test data (Users and Wallets), use the following command to reach inside the running container:
docker exec -it simple-wallet-app npm run seed:prod
The API follows standard RESTful principles.
- Endpoint:
GET /wallets - Description: Retrieves all wallets associated with the authenticated user. Use this to get the
Wallet IDsneeded for transfers.
- Endpoint:
POST /v1/transfer - Header:
x-idempotency-key: <UUID>(Mandatory to prevent double-spending/duplicate transactions). - Body:
{
"fromWalletId": "2f970b6d-9d8b-475f-859a-4e85d57bc92b",
"toWalletId": "332ebe85-2a12-4b03-adfb-c830587b128e",
"amount": 100
}
The project includes a comprehensive test suite using Jest, covering precision math, leap year edge cases, and queue processing.
# Run all tests
npm test
# Run tests with coverage
npm run test:cov