Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion src/advanced-analytics/advanced-analytics.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,3 @@ import { AnalyticsExportService } from './services/analytics-export/analytics-ex
exports: [AdvancedAnalyticsService],
})
export class AdvancedAnalyticsModule {}

1 change: 0 additions & 1 deletion src/advanced-analytics/advanced-analytics.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,3 @@ describe('AdvancedAnalyticsService', () => {
expect(out.fileName).toMatch(/\.csv$/);
});
});

11 changes: 6 additions & 5 deletions src/advanced-analytics/advanced-analytics.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,16 @@ export class AdvancedAnalyticsService {
userId,
risk,
predictions,
recommendation: this.portfolioRisk.getPortfolioOptimizationRecommendation(
risk,
),
recommendation:
this.portfolioRisk.getPortfolioOptimizationRecommendation(risk),
generatedAt: new Date().toISOString(),
};
}

async exportUserAnalytics(userId: string, format: 'csv' | 'xlsx'): Promise<{
async exportUserAnalytics(
userId: string,
format: 'csv' | 'xlsx',
): Promise<{
mimeType: string;
fileName: string;
buffer: Buffer;
Expand All @@ -58,4 +60,3 @@ export class AdvancedAnalyticsService {
return this.exportService.exportAnalytics(analytics, format);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,3 @@ describe('AnalyticsExportService', () => {
expect(out.buffer.length).toBeGreaterThan(0);
});
});

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Injectable } from '@nestjs/common';
import * as XLSX from 'xlsx';


@Injectable()
export class AnalyticsExportService {
async exportAnalytics(
Expand Down Expand Up @@ -61,4 +60,3 @@ export class AnalyticsExportService {
};
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ describe('PortfolioRiskScoringService', () => {

expect(r.riskScore).toBeGreaterThanOrEqual(0);
expect(r.riskScore).toBeLessThanOrEqual(100);
expect(r.riskLevel).toBe(['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'].includes(r.riskLevel)
? r.riskLevel
: r.riskLevel);
expect(r.riskLevel).toBe(
['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'].includes(r.riskLevel)
? r.riskLevel
: r.riskLevel,
);

expect(r.annualizedVolatility).toBeGreaterThan(0);
expect(r.maxDrawdownEstimate).toBeGreaterThan(0);
Expand Down Expand Up @@ -38,4 +40,3 @@ describe('PortfolioRiskScoringService', () => {
expect(recLow.strategy).toBe('Maintain and optimize returns');
});
});

Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ export class PortfolioRiskScoringService {

// Compose a 0..100 score.
const riskScore = Math.round(
100 * (0.45 * this.clamp(annualizedVolatility / 0.6) + 0.55 * this.clamp(maxDrawdownEstimate / 0.25)),
100 *
(0.45 * this.clamp(annualizedVolatility / 0.6) +
0.55 * this.clamp(maxDrawdownEstimate / 0.25)),
);

const riskLevel = this.toRiskLevel(riskScore);
Expand Down Expand Up @@ -61,7 +63,8 @@ export class PortfolioRiskScoringService {
`Risk level is ${risk.riskLevel} (${risk.riskScore}/100).`,
'Reduce high-volatility exposure and ensure liquidity buffers.',
],
recommendedAction: 'Rebalance: reduce volatility-weighted positions; refresh hedge/insurance coverage.',
recommendedAction:
'Rebalance: reduce volatility-weighted positions; refresh hedge/insurance coverage.',
};
}

Expand All @@ -72,7 +75,8 @@ export class PortfolioRiskScoringService {
`Risk level is ${risk.riskLevel} (${risk.riskScore}/100).`,
'Gradually adjust position sizing and diversify across assets.',
],
recommendedAction: 'Rebalance: shift a portion to lower-volatility assets; monitor within 5 minutes of trades.',
recommendedAction:
'Rebalance: shift a portion to lower-volatility assets; monitor within 5 minutes of trades.',
};
}

Expand All @@ -82,7 +86,8 @@ export class PortfolioRiskScoringService {
`Risk level is ${risk.riskLevel} (${risk.riskScore}/100).`,
'Portfolio risk is within acceptable bounds; focus on execution quality.',
],
recommendedAction: 'Maintain current allocation; optimize trade execution parameters.',
recommendedAction:
'Maintain current allocation; optimize trade execution parameters.',
};
}

Expand All @@ -107,4 +112,3 @@ export class PortfolioRiskScoringService {
return Math.abs(h);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,3 @@ describe('PricePredictionService', () => {
}
});
});

Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,24 @@ export class PricePredictionService {

const predictions: AssetPrediction[] = assets.map((asset, idx) => {
const x = ((seed + idx * 997) % 100000) / 100000; // 0..0.99999
const basePrice = asset.startsWith('BTC') ? 45000 : asset.startsWith('ETH') ? 3200 : 1;
const basePrice = asset.startsWith('BTC')
? 45000
: asset.startsWith('ETH')
? 3200
: 1;
const drift = (x - 0.5) * (asset.startsWith('USDC') ? 0.01 : 0.12);
const predictedPrice = basePrice * (1 + drift);
const confidence = Math.max(0.15, Math.min(0.9, 0.45 + (0.5 - Math.abs(x - 0.5))));
const confidence = Math.max(
0.15,
Math.min(0.9, 0.45 + (0.5 - Math.abs(x - 0.5))),
);

return {
asset,
horizonDays: 7,
predictedPrice: Number(predictedPrice.toFixed(asset.startsWith('USDC') ? 4 : 2)),
predictedPrice: Number(
predictedPrice.toFixed(asset.startsWith('USDC') ? 4 : 2),
),
confidence: Number(confidence.toFixed(3)),
};
});
Expand All @@ -56,4 +65,3 @@ export class PricePredictionService {
return Math.abs(h);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,3 @@ describe('UserBehaviorAnalysisService', () => {
}
});
});

Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,3 @@ export class UserBehaviorAnalysisService {
return Math.abs(h);
}
}

18 changes: 16 additions & 2 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,17 @@ import { LiquidationEvent } from './protection/entities/liquidation-event.entity
import { ProtectionModule } from './protection/protection.module';

// Blockchain — Cross-Chain Bridge (issue #386)
import { BlockchainModule } from './blockchain/blockchain.module';
import { CrossChainBridgeModule } from './blockchain/cross-chain-bridge.module';
import { CrossChainBridge } from './blockchain/entities/cross-chain-bridge.entity';
import { BlockchainTransaction } from './blockchain/entities/blockchain-transaction.entity';
import { WalletAddress } from './blockchain/entities/wallet-address.entity';

// Social Trading — Social Trading Features (issue #396)
import { SocialTradingModule } from './social-trading/social-trading.module';
import { TraderProfile } from './social-trading/entities/trader-profile.entity';
import { CopySubscription } from './social-trading/entities/copy-subscription.entity';

@Module({
imports: [
// ── Core NestJS ──
Expand Down Expand Up @@ -117,7 +123,9 @@ import { WalletAddress } from './blockchain/entities/wallet-address.entity';
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
type: configService.get<string>('DB_TYPE', 'postgres') as 'postgres' | 'sqlite',
type: configService.get<string>('DB_TYPE', 'postgres') as
| 'postgres'
| 'sqlite',
host: configService.get<string>('DB_HOST', 'localhost'),
port: configService.get<number>('DB_PORT', 5432),
username: configService.get<string>('DB_USERNAME', 'postgres'),
Expand Down Expand Up @@ -171,6 +179,9 @@ import { WalletAddress } from './blockchain/entities/wallet-address.entity';
CrossChainBridge,
BlockchainTransaction,
WalletAddress,
// Social Trading (issue #396)
TraderProfile,
CopySubscription,
],
synchronize: configService.get<boolean>('DB_SYNCHRONIZE', true),
logging: configService.get<boolean>('DB_LOGGING', false),
Expand Down Expand Up @@ -210,10 +221,13 @@ import { WalletAddress } from './blockchain/entities/wallet-address.entity';
// ── Notifications Module ──
NotificationsModule,

// ── Social Trading Module (issue #396) ──
SocialTradingModule,

// ── Error Handling ──
ErrorModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
export class AppModule {}
16 changes: 12 additions & 4 deletions src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ export class AuthController {
@Public()
@Post('token/refresh')
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'Rotate refresh token and obtain new access + refresh tokens' })
@ApiOperation({
summary: 'Rotate refresh token and obtain new access + refresh tokens',
})
@ApiResponse({ status: 200, description: 'Tokens refreshed' })
refreshToken(@Body() dto: RefreshTokenDto) {
return this.authService.refreshTokens(dto);
Expand All @@ -118,7 +120,10 @@ export class AuthController {
@Post('password/forgot')
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'Request a password reset link' })
@ApiResponse({ status: 200, description: 'Reset link sent (if email exists)' })
@ApiResponse({
status: 200,
description: 'Reset link sent (if email exists)',
})
forgotPassword(@Body() dto: ForgotPasswordDto) {
return this.authService.forgotPassword(dto);
}
Expand Down Expand Up @@ -190,7 +195,10 @@ export class AuthController {
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'Verify and activate 2FA after setup' })
@ApiResponse({ status: 200, description: '2FA enabled' })
verify2FASetup(@CurrentUser() user: JwtPayload, @Body() dto: Verify2FASetupDto) {
verify2FASetup(
@CurrentUser() user: JwtPayload,
@Body() dto: Verify2FASetupDto,
) {
return this.authService.verify2FASetup(user.sub, dto);
}

Expand All @@ -202,4 +210,4 @@ export class AuthController {
disable2FA(@CurrentUser() user: JwtPayload, @Body() dto: TwoFADto) {
return this.authService.disable2FA(user.sub, dto);
}
}
}
Loading
Loading