This repository contains the backend for TeraEx — a small multi-chain wallet and token management API built with Node.js, Express and MongoDB. This README is written for a developer who is new to the codebase and wants to understand the architecture, how to run it, how the important modules work, and what needs improvement.
- app.js — Express application entrypoint and router mounting
- routes/ — API route definitions (v1 grouped routes)
- models/ — Mongoose schema definitions for users, wallets, tokens and transactions
- tokens/ — token implementation helpers (BTC, ETH, SOL wrappers and helpers)
- utils/ — shared utilities (JWT validation, logging, validators, constants)
- public/ — static assets (frontend build assets, images, styles)
- The server is an Express app using ES modules (
type: modulein package.json). - MongoDB (Mongoose) is used for persistence; the connection string is provided via
process.env.MONGODB_URL. - Authentication is JWT-based. Tokens are expected in the
Authorizationheader (raw token string). - When a user signs up, default wallets for BTC, ETH, SOL, NGN (virtual), and TERA (virtual) are created and saved.
- Token transfer endpoints live under
routes/v1/token_actions(send, buy, receive, sell, swap) — some files are placeholders.
- Node.js (ES Modules)
- Express
- MongoDB with Mongoose
- JSON Web Tokens (jsonwebtoken)
- bcrypt for password hashing
- Winston for logging
- Libraries for blockchain helpers: bitcoinjs-lib, ethers, @solana/web3.js, etc.
- Node.js 18+ (or a recent LTS)
- npm (or yarn)
- A running MongoDB instance (connection URL available to the app)
The app reads configuration from environment variables. Create a .env file in the project root when running locally. Example variables used by the code:
PORT=3009
MONGODB_URL=mongodb://localhost:27017/teraex
APP_SECRET_KEY=your_jwt_secret_here
BTC_RATE=... # optional; used in utilities
BTC_UNIT=... # optional
MAX_TIMEOUT=300000 # request timeout (ms)
Note: Add any provider-specific variables required by the token implementations (for example, RPC endpoints, API keys) in your .env as needed.
Install dependencies and start the server:
npm install
npm run dev # uses nodemon (if you want hot reload)
npm start # run production-styleBy default the server listens on process.env.PORT or 3009.
-
app.js- Entrypoint. Loads environment variables, connects to MongoDB, configures middleware and mounts routes.
- Notes: it serves a static
dist/index.htmlfor any unknown route (app.get('*')). Theapp.set('static', 'public')call appears unused — static files served fromdist.
-
routes/v1index.js— root route, renders the landing ejs view.signup.js— POST/v1/signup— creates a new user and generates default wallets in a transaction.signin.js— POST/v1/signin— validates user credentials and returns a signed JWT.get_wallet_info.js— POST/v1/getWalletInfo(protected) — returns wallet details for a token symbol.get_all_tokens.js,get_users.js— token / user listing routes (some routes use jwt middleware)token_actions/*— send, buy, sell, swap, receive endpoints.send.jshandles BTC/ETH/SOL sends.sell.js,swap.js,receive.jscurrently empty and need implementation.
-
models/users.js— simple users schema: fullname, email, password, isEmailValidatedbitcoin_wallets.js,ethereum_wallets.js,solana_wallets.js— wallet schemas; currently storeprivateKey,mnemonic,publicKeyetc.tera_wallets.js,ngn_wallets.js— virtual wallets for TERA and NGN (fiat/utility balances)tokens.js,token_metadata.js— token metadata and ratestransactions.js— records transactionswithdrawal_accounts.js— withdrawal account information
-
utils/jwt_validator.js— Express middleware that checksAuthorizationheader and verifies token usingAPP_SECRET_KEY. On success it attachesreq.user.utlities.js— input validators, password hashing, token signing helpers and some BTC helper rate functions.logger.js— Winston logger configured to write to console andserver.log.states.js— constants used across responses and flow control (error messages, transaction states, HTTP codes)
-
tokens/- Implementations that create wallets, build and sign transactions for BTC, ETH, SOL. These modules are used by the signup flow and send endpoints.
All request/response examples use JSON and assume the server is running at http://localhost:3009.
- POST /v1/signup
Request body:
{ "fullname": "Alice Example", "email": "alice@example.com", "password": "StrongP@ssw0rd" }Successful response:
{ "error": false, "status": "User Account Created Successfully", "authToken": "<JWT>" }Behaviour: creates user (unique email), hashes password with bcrypt, creates default wallets (BTC, ETH, SOL, NGN, TERA) inside a Mongoose transaction.
- POST /v1/signin
Request body:
{ "email": "alice@example.com", "password": "StrongP@ssw0rd" }Successful response:
{ "error": false, "status": "User Authentication Success", "authToken": "<JWT>" }- POST /v1/getWalletInfo (protected)
Headers:
Authorization: <JWT>
Request body:
{ "token": { "symbol": "BTC" } }Response: returns wallet info for the requested token symbol. The route depends on token-specific helpers in tokens/*.
- POST /v1/tokens/send (protected)
Request body:
{ "txPayload": {
"fromAddress": "...",
"toAddress": "...",
"amount": 0.01,
"tokenSymbol": "ETH"
}
}Response: returns the transaction payload returned by the chain helper or an error state. Implementation supports BTC, ETH, SOL.
-
Private keys and mnemonics are stored in the database (see
bitcoin_wallets,ethereum_wallets,solana_wallets). This is a critical security risk in production. Options to improve:- Encrypt private keys at rest using a strong KMS or environment-derived encryption key.
- Avoid storing full mnemonics/private keys if possible; use custodial/managed signing, hardware security modules (HSM) or sign via ephemeral secure services.
-
jwt_validator.jscurrently usesverifywithout a try/catch. Ifverifythrows, the middleware will crash. Also it returns HTTP status codes300/301which are incorrect for auth errors. Recommended changes:- Wrap
verifyin try/catch and return401 Unauthorizedor403 Forbiddenwith consistent JSON error body.
- Wrap
-
Input validation:
utils/utlities.jscontains validators; the password validator has inconsistent length checks (regex uses {6,20} while code checks >=8). Consider standardizing validators and using a schema validator (Joi, Zod, express-validator).
-
Error handling and HTTP status codes:
- The app often sends an OK (200) response for errors (res.send with error:true). Consider using proper HTTP codes (400, 401, 403, 404, 500) and consistent error shape.
-
Static assets and frontend serving:
app.jsservesdist/index.htmlfor all unknown routes, but also callsapp.set('static', 'public'). Review static serving configuration to match the built frontend folder.
This project currently doesn't include automated tests. I recommend adding:
- Unit tests for
utils/(validators, hashing, JWT helpers) - Integration tests for the signup/signin flows using an in-memory MongoDB (mongodb-memory-server)
- Mocked tests for token send functions to avoid hitting live chains in CI
Quick checklist before merging changes:
- Lint and run type checks (if adding TypeScript)
- Unit tests (happy path + 1-2 edge cases)
- Security review for key storage and environment handling
- Implement
sell.js,swap.js,receive.jsunderroutes/v1/token_actions. - Improve error handling and status codes across the API.
- Move sensitive config like
APP_SECRET_KEYinto a secure vault; do not check secrets into git. - Add request rate-limiting (express-rate-limit), helmet for headers and CORS policy.
- Replace raw JWT in
Authorizationheader withBearer <token>scheme and parse accordingly. - Add logging correlation ids to trace requests across services.
If you want to contribute:
- Fork the repo and create a branch for your feature:
feature/your-name-xyz - Add tests for the new behavior.
- Make changes and ensure linter/tests pass.
- Open a PR describing the change and list any breaking changes.
If you need additional context about the original implementation decisions (why private keys were stored directly, what backend services are expected, etc.) ask the original maintainer or check project management tickets.