Automated Action 3ef47ed096 Rebuild platform with Node.js, Express.js and TypeScript
Complete rewrite from Python/FastAPI to Node.js stack:

Features implemented:
- User authentication with JWT tokens and role-based access (DEVELOPER/BUYER)
- Blockchain wallet linking and management with Ethereum integration
- Carbon project creation and management for developers
- Marketplace for browsing and purchasing carbon offsets
- Transaction tracking with blockchain integration
- Comprehensive input validation with Joi
- Advanced security with Helmet, CORS, and rate limiting
- Error handling and logging middleware
- Health check endpoint with service monitoring

Technical stack:
- Node.js with Express.js and TypeScript
- Prisma ORM with SQLite database
- Web3.js and Ethers.js for blockchain integration
- JWT authentication with bcrypt password hashing
- Comprehensive validation and security middleware
- Production-ready error handling and logging

Database schema:
- Users with wallet linking capabilities
- Carbon projects with verification status
- Carbon offsets with blockchain token tracking
- Transactions with confirmation details

Environment variables required:
- JWT_SECRET (required)
- DATABASE_URL (optional, defaults to SQLite)
- BLOCKCHAIN_RPC_URL (optional, defaults to localhost)
- NODE_ENV, PORT, CORS_ORIGIN (optional)

Run with: npm install && npm run db:generate && npm run db:migrate && npm run dev
2025-06-20 17:14:37 +00:00

179 lines
4.4 KiB
TypeScript

import { prisma } from '@/utils/database';
import { blockchainService } from './blockchain';
import { WalletResponse, WalletInfo } from '@/types';
export class WalletService {
public async linkWallet(userId: number, walletAddress: string): Promise<WalletResponse> {
try {
// Validate wallet address format
if (!blockchainService.validateWalletAddress(walletAddress)) {
return {
success: false,
walletLinked: false,
message: 'Invalid wallet address format'
};
}
// Check if wallet is already linked to another user
const existingUser = await prisma.user.findFirst({
where: {
walletAddress,
id: { not: userId }
}
});
if (existingUser) {
return {
success: false,
walletLinked: false,
message: 'Wallet address is already linked to another account'
};
}
// Get user
const user = await prisma.user.findUnique({
where: { id: userId }
});
if (!user) {
return {
success: false,
walletLinked: false,
message: 'User not found'
};
}
// Update user wallet information
await prisma.user.update({
where: { id: userId },
data: {
walletAddress,
walletPublicKey: walletAddress // In Ethereum, address is derived from public key
}
});
return {
success: true,
walletLinked: true,
walletAddress,
message: 'Wallet linked successfully'
};
} catch (error) {
console.error('Error linking wallet:', error);
return {
success: false,
walletLinked: false,
message: `Database error: ${error}`
};
}
}
public async unlinkWallet(userId: number): Promise<WalletResponse> {
try {
const user = await prisma.user.findUnique({
where: { id: userId }
});
if (!user) {
return {
success: false,
walletLinked: false,
message: 'User not found'
};
}
if (!user.walletAddress) {
return {
success: false,
walletLinked: false,
message: 'No wallet linked to this account'
};
}
// Clear wallet information
await prisma.user.update({
where: { id: userId },
data: {
walletAddress: null,
walletPublicKey: null
}
});
return {
success: true,
walletLinked: false,
message: 'Wallet unlinked successfully'
};
} catch (error) {
console.error('Error unlinking wallet:', error);
return {
success: false,
walletLinked: false,
message: `Database error: ${error}`
};
}
}
public async getWalletInfo(userId: number): Promise<WalletResponse> {
try {
const user = await prisma.user.findUnique({
where: { id: userId }
});
if (!user) {
return {
success: false,
walletLinked: false,
message: 'User not found'
};
}
if (!user.walletAddress) {
return {
success: true,
walletLinked: false,
walletAddress: undefined,
balance: undefined
};
}
// Get wallet balance from blockchain
const balance = await blockchainService.getWalletBalance(user.walletAddress);
return {
success: true,
walletLinked: true,
walletAddress: user.walletAddress,
balance: balance || undefined
};
} catch (error) {
console.error('Error getting wallet info:', error);
return {
success: false,
walletLinked: false,
message: `Error retrieving wallet information: ${error}`
};
}
}
public generateTestWallet(): { success: boolean; message: string; walletData?: WalletInfo; warning?: string } {
try {
const walletData = blockchainService.generateWallet();
return {
success: true,
message: 'Test wallet generated successfully',
walletData,
warning: 'This is for testing only. Keep private key secure!'
};
} catch (error) {
console.error('Error generating test wallet:', error);
return {
success: false,
message: `Failed to generate test wallet: ${error}`
};
}
}
}
export const walletService = new WalletService();