UNPKG

saksh-easy-wallet

Version:

A simple and easy-to-use wallet management system for handling user balances and transactions.

169 lines (127 loc) 5.98 kB
const mongoose = require('mongoose'); const { Schema } = mongoose; const EventEmitter = require('events'); // Define the schema for wallet users const walletUserSchema = new Schema({ email: { type: String, required: true, unique: true }, balance: { type: Map, of: Number, default: {} } }); // Define the schema for wallet transactions const walletTransactionSchema = new Schema({ email: { type: String, required: true }, type: { type: String, required: true }, amount: { type: Number, required: true }, currency: { type: String, required: true }, referenceId: { type: String, required: true }, description: { type: String, required: true }, transactionFee: { type: Number, default: 0 }, date: { type: Date, default: Date.now } }); const logSchema = new mongoose.Schema({ level: { type: String, required: true }, message: { type: String, required: true }, timestamp: { type: Date, default: Date.now }, meta: { type: mongoose.Schema.Types.Mixed } }); const Log = mongoose.model('Log', logSchema); // Create the models const WalletUserModel = mongoose.model('WalletUser', walletUserSchema); const WalletTransactionModel = mongoose.model('WalletTransaction', walletTransactionSchema); class SakshWallet extends EventEmitter { constructor() { super(); this.adminEmail = process.env.ADMIN_EMAIL || 'walletadmin@sakshwallet.com'; } async log(level, message, meta = {}) { const logEntry = new Log({ level, message, meta }); await logEntry.save(); } setAdmin(adminEmail) { this.adminEmail = adminEmail || 'walletadmin@sakshwallet.com'; } async sakshGetBalance(email, currency) { let userAccount = await WalletUserModel.findOne({ email }); if (!userAccount) { userAccount = new WalletUserModel({ email }); await userAccount.save(); } const balance = userAccount.balance.get(currency) || 0; return { email, currency, balance }; } async sakshGetBalanceSummary(email) { let userAccount = await WalletUserModel.findOne({ email }); if (!userAccount) { userAccount = new WalletUserModel({ email }); await userAccount.save(); } return { email, balance: userAccount.balance }; } async updateBalance(email, amount, currency, type, referenceId, description, transactionFee = 0) { let userAccount = await WalletUserModel.findOne({ email }); if (!userAccount) { userAccount = new WalletUserModel({ email }); await userAccount.save(); } const currentBalance = userAccount.balance.get(currency) || 0; const totalAmount = amount + transactionFee; const newBalance = type === 'debit' ? currentBalance - totalAmount : currentBalance + amount; if (type === 'debit' && totalAmount > currentBalance) { return { message: 'Insufficient funds' }; } userAccount.balance.set(currency, newBalance); await userAccount.save(); const transaction = new WalletTransactionModel({ email, type, amount, currency, referenceId, description, transactionFee }); await transaction.save(); if (transactionFee > 0) { await this.sakshCredit(this.adminEmail, transactionFee, currency, referenceId, `Transaction fee for ${description}`); } this.emit(type, { email, amount, currency, newBalance, referenceId, description, transactionFee }); return { message: `${type === 'debit' ? 'Debited' : 'Credited'} ${amount} ${currency}.`, balance: newBalance, transaction }; } async sakshDebit(email, amount, currency, referenceId, description, transactionFee = 0) { return this.updateBalance(email, amount, currency, 'debit', referenceId, description, transactionFee); } async sakshCredit(email, amount, currency, referenceId, description, transactionFee = 0) { await this.log('info', 'Initiating escrow', { email, email, amount, currency, description }); return this.updateBalance(email, amount, currency, 'credit', referenceId, description, transactionFee); } async sakshFundTransfer(senderEmail, receiverEmail, amount, currency, referenceId, description, transactionFee = 0) { // Debit from sender const debitResult = await this.sakshDebit(senderEmail, amount, currency, referenceId, `Transfer to ${receiverEmail}: ${description}`, transactionFee); if (debitResult.message === 'Insufficient funds') { throw new Error('Insufficient funds in sender\'s account'); } // Credit to receiver const creditResult = await this.sakshCredit(receiverEmail, amount, currency, referenceId, `Transfer from ${senderEmail}: ${description}`); return { message: `Transferred ${amount} ${currency} from ${senderEmail} to ${receiverEmail}.`, senderBalance: debitResult.balance, receiverBalance: creditResult.balance, transaction: { senderTransaction: debitResult.transaction, receiverTransaction: creditResult.transaction } }; } async sakshTransactionReport(email) { const transactions = await WalletTransactionModel.find({ email }).sort({ date: -1 }); return transactions.map(tx => ({ type: tx.type, amount: tx.amount, currency: tx.currency, referenceId: tx.referenceId, description: tx.description, transactionFee: tx.transactionFee, date: tx.date })); } } module.exports = SakshWallet;