65 lines
2.0 KiB
Dart
65 lines
2.0 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:shelf/shelf.dart';
|
|
import 'package:shelf_router/shelf_router.dart';
|
|
|
|
import '../cors_headers.dart';
|
|
import '../firebase_auth.dart';
|
|
import '../trading/trading_dev_actions.dart';
|
|
|
|
const String tradingDevBasePath = '/v1/me/trading/dev';
|
|
|
|
/// Dev-only HTTP endpoints to exercise the trading flow without waiting for
|
|
/// real market conditions. Mounted only when `TRADING_DEV_ENDPOINTS_ENABLED=true`.
|
|
///
|
|
/// Endpoints:
|
|
/// * `POST /v1/me/trading/dev/force-fire` — seeds dipped snapshots for the
|
|
/// caller and runs one [TradingPipeline.evaluate] cycle. The next worker
|
|
/// tick (or an immediate SignalR push from `createAndDeliverQuestion`)
|
|
/// surfaces the question in the Flutter UI.
|
|
Handler tradingDevHandler({
|
|
required FirebaseAuthVerifier auth,
|
|
required TradingDevActions devActions,
|
|
}) {
|
|
final Router router = Router();
|
|
|
|
router.post('$tradingDevBasePath/force-fire', (Request request) async {
|
|
final String? firebaseUid = await _verify(auth, request);
|
|
if (firebaseUid == null) {
|
|
return _jsonResponse(401, <String, dynamic>{'error': 'Unauthorized'});
|
|
}
|
|
try {
|
|
final ForceFireResult result = await devActions.forceFireDip(firebaseUid);
|
|
return _jsonResponse(200, result.toJson());
|
|
} catch (e, st) {
|
|
stderr.writeln('trading dev force-fire failed for $firebaseUid: $e\n$st');
|
|
return _jsonResponse(500, <String, dynamic>{'error': 'Internal error'});
|
|
}
|
|
});
|
|
|
|
return (Request request) async {
|
|
if (request.method == 'OPTIONS') {
|
|
return Response.ok('', headers: apiCorsHeaders());
|
|
}
|
|
return router.call(request);
|
|
};
|
|
}
|
|
|
|
Future<String?> _verify(FirebaseAuthVerifier auth, Request request) {
|
|
return auth.verifyBearerToken(
|
|
request.headers['Authorization'] ?? request.headers['authorization'],
|
|
);
|
|
}
|
|
|
|
Response _jsonResponse(int status, Map<String, dynamic> body) {
|
|
return Response(
|
|
status,
|
|
body: jsonEncode(body),
|
|
headers: <String, String>{
|
|
...apiCorsHeaders(),
|
|
'Content-Type': 'application/json',
|
|
},
|
|
);
|
|
}
|