diff --git a/.gitignore b/.gitignore index c2658d7d..c0ccd346 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ node_modules/ +logs/ +dist/ +.env +.DS_Store +*.log +*.csv diff --git a/dist/controllers/marketRatesController.d.ts b/dist/controllers/marketRatesController.d.ts deleted file mode 100644 index 8fad6b74..00000000 --- a/dist/controllers/marketRatesController.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { Request, Response } from "express"; -export declare const getRate: (req: Request, res: Response) => Promise> | undefined>; -export declare const getAllRates: (req: Request, res: Response) => Promise; -//# sourceMappingURL=marketRatesController.d.ts.map \ No newline at end of file diff --git a/dist/controllers/marketRatesController.d.ts.map b/dist/controllers/marketRatesController.d.ts.map deleted file mode 100644 index 9bac38ba..00000000 --- a/dist/controllers/marketRatesController.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"marketRatesController.d.ts","sourceRoot":"","sources":["../../src/controllers/marketRatesController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAK5C,eAAO,MAAM,OAAO,GAAU,KAAK,OAAO,EAAE,KAAK,QAAQ,4DA2BxD,CAAC;AAEF,eAAO,MAAM,WAAW,GAAU,KAAK,OAAO,EAAE,KAAK,QAAQ,kBAc5D,CAAC"} \ No newline at end of file diff --git a/dist/controllers/marketRatesController.js b/dist/controllers/marketRatesController.js deleted file mode 100644 index bbe67fdf..00000000 --- a/dist/controllers/marketRatesController.js +++ /dev/null @@ -1,49 +0,0 @@ -import { MarketRateService } from "../services/marketRate"; -const marketRateService = new MarketRateService(); -export const getRate = async (req, res) => { - try { - const { currency } = req.params; - if (!currency || typeof currency !== "string") { - return res.status(400).json({ - success: false, - error: "Currency parameter is required and must be a string", - }); - } - const result = await marketRateService.getRate(currency); - if (result.success) { - res.json({ - success: true, - data: result.data, - }); - } - else { - res.status(404).json({ - success: false, - error: result.error, - }); - } - } - catch (error) { - res.status(500).json({ - success: false, - error: error instanceof Error ? error.message : "Internal server error", - }); - } -}; -export const getAllRates = async (req, res) => { - try { - const results = await marketRateService.getAllRates(); - const rates = results.filter((result) => result.success).map((result) => result.data); - res.json({ - success: true, - data: rates, - }); - } - catch (error) { - res.status(500).json({ - success: false, - error: error instanceof Error ? error.message : "Internal server error", - }); - } -}; -//# sourceMappingURL=marketRatesController.js.map \ No newline at end of file diff --git a/dist/controllers/marketRatesController.js.map b/dist/controllers/marketRatesController.js.map deleted file mode 100644 index 940d1b5c..00000000 --- a/dist/controllers/marketRatesController.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"marketRatesController.js","sourceRoot":"","sources":["../../src/controllers/marketRatesController.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,EAAE,CAAC;AAElD,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;IAC3D,IAAI,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;QAChC,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC9C,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBAC1B,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,qDAAqD;aAC7D,CAAC,CAAC;QACL,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,GAAG,CAAC,IAAI,CAAC;gBACP,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,MAAM,CAAC,IAAI;aAClB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,MAAM,CAAC,KAAK;aACpB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB;SACxE,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;IAC/D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,WAAW,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtF,GAAG,CAAC,IAAI,CAAC;YACP,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB;SACxE,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts deleted file mode 100644 index 72752437..00000000 --- a/dist/index.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare const app: import("express-serve-static-core").Express; -export default app; -//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/index.d.ts.map b/dist/index.d.ts.map deleted file mode 100644 index 2d925cb4..00000000 --- a/dist/index.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAmCA,QAAA,MAAM,GAAG,6CAAY,CAAC;AA0ItB,eAAe,GAAG,CAAC"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js deleted file mode 100644 index a5443de2..00000000 --- a/dist/index.js +++ /dev/null @@ -1,145 +0,0 @@ -import express from "express"; -import { createServer } from "http"; -import cors from "cors"; -import dotenv from "dotenv"; -import morgan from "morgan"; -import { Horizon } from "@stellar/stellar-sdk"; -import marketRatesRouter from "./routes/marketRates"; -import historyRouter from "./routes/history"; -import priceUpdatesRouter from "./routes/priceUpdates"; -import prisma from "./lib/prisma"; -import { initSocket } from "./lib/socket"; -import { SorobanEventListener } from "./services/sorobanEventListener"; -import { multiSigSubmissionService } from "./services/multiSigSubmissionService"; -// Load environment variables -dotenv.config(); -// Validate required environment variables -const requiredEnvVars = ["STELLAR_SECRET", "DATABASE_URL"]; -const missingEnvVars = []; -for (const envVar of requiredEnvVars) { - if (!process.env[envVar]) { - missingEnvVars.push(envVar); - } -} -if (missingEnvVars.length > 0) { - console.error("❌ Missing required environment variables:"); - missingEnvVars.forEach((varName) => console.error(` - ${varName}`)); - console.error("\nPlease set these variables in your .env file and restart the server."); - process.exit(1); -} -const app = express(); -const PORT = process.env.PORT || 3000; -// Horizon server for health checks -const stellarNetwork = process.env.STELLAR_NETWORK || "TESTNET"; -const horizonUrl = stellarNetwork === "PUBLIC" - ? "https://horizon.stellar.org" - : "https://horizon-testnet.stellar.org"; -const horizonServer = new Horizon.Server(horizonUrl); -// Middleware -app.use(morgan("dev")); -app.use(cors()); -app.use(express.json()); -// Routes -app.use("/api/market-rates", marketRatesRouter); -app.use("/api/history", historyRouter); -app.use("/api/price-updates", priceUpdatesRouter); -// Health check endpoint -app.get("/health", async (req, res) => { - const checks = { - database: false, - horizon: false, - }; - // Check database connectivity - try { - await prisma.$queryRaw `SELECT 1`; - checks.database = true; - } - catch { - checks.database = false; - } - // Check Stellar Horizon reachability - try { - await horizonServer.root(); - checks.horizon = true; - } - catch { - checks.horizon = false; - } - const healthy = checks.database && checks.horizon; - res.status(healthy ? 200 : 503).json({ - success: healthy, - message: healthy - ? "All systems operational" - : "One or more services unavailable", - timestamp: new Date().toISOString(), - checks, - }); -}); -// Root endpoint -app.get("/", (req, res) => { - res.json({ - success: true, - message: "StellarFlow Backend API", - version: "1.0.0", - endpoints: { - health: "/health", - marketRates: { - allRates: "/api/market-rates/rates", - singleRate: "/api/market-rates/rate/:currency", - health: "/api/market-rates/health", - currencies: "/api/market-rates/currencies", - cache: "/api/market-rates/cache", - clearCache: "POST /api/market-rates/cache/clear", - }, - }, - }); -}); -// Error handling middleware -app.use((err, req, res, next) => { - console.error("Unhandled error:", err); - res.status(500).json({ - success: false, - error: "Internal server error", - }); -}); -// 404 handler -app.use("*", (req, res) => { - res.status(404).json({ - success: false, - error: "Endpoint not found", - }); -}); -// Start server -const httpServer = createServer(app); -initSocket(httpServer); -httpServer.listen(PORT, () => { - console.log(`🌊 StellarFlow Backend running on port ${PORT}`); - console.log(`📊 Market Rates API available at http://localhost:${PORT}/api/market-rates`); - console.log(`🏥 Health check at http://localhost:${PORT}/health`); - console.log(`🔌 Socket.io ready for dashboard connections`); - // Start Soroban event listener to track confirmed on-chain prices - try { - const eventListener = new SorobanEventListener(); - eventListener.start().catch((err) => { - console.error("Failed to start event listener:", err); - }); - console.log(`👂 Soroban event listener started`); - } - catch (err) { - console.warn("Event listener not started:", err instanceof Error ? err.message : err); - } - // Start multi-sig submission service if enabled - if (process.env.MULTI_SIG_ENABLED === "true") { - try { - multiSigSubmissionService.start().catch((err) => { - console.error("Failed to start multi-sig submission service:", err); - }); - console.log(`🔐 Multi-Sig submission service started`); - } - catch (err) { - console.warn("Multi-sig submission service not started:", err instanceof Error ? err.message : err); - } - } -}); -export default app; -//# sourceMappingURL=index.js.map diff --git a/dist/index.js.map b/dist/index.js.map deleted file mode 100644 index 6a2a9ecf..00000000 --- a/dist/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/prisma.d.ts b/dist/lib/prisma.d.ts deleted file mode 100644 index 57e77c95..00000000 --- a/dist/lib/prisma.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export declare const prisma: any; -export default prisma; -//# sourceMappingURL=prisma.d.ts.map \ No newline at end of file diff --git a/dist/lib/prisma.d.ts.map b/dist/lib/prisma.d.ts.map deleted file mode 100644 index 9b9cd933..00000000 --- a/dist/lib/prisma.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../../src/lib/prisma.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,MAAM,KAA+C,CAAC;AAMnE,eAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/dist/lib/prisma.js b/dist/lib/prisma.js deleted file mode 100644 index 5b9abbcd..00000000 --- a/dist/lib/prisma.js +++ /dev/null @@ -1,10 +0,0 @@ -// Prisma Client Singleton -// Prevents multiple instances during development hot-reloading -import { PrismaClient } from "@prisma/client"; -const globalForPrisma = globalThis; -export const prisma = globalForPrisma.prisma ?? new PrismaClient(); -if (process.env.NODE_ENV !== "production") { - globalForPrisma.prisma = prisma; -} -export default prisma; -//# sourceMappingURL=prisma.js.map \ No newline at end of file diff --git a/dist/lib/prisma.js.map b/dist/lib/prisma.js.map deleted file mode 100644 index ef4fb4a4..00000000 --- a/dist/lib/prisma.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"prisma.js","sourceRoot":"","sources":["../../src/lib/prisma.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,+DAA+D;AAE/D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,eAAe,GAAG,UAEvB,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAG,eAAe,CAAC,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;AAEnE,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;IAC1C,eAAe,CAAC,MAAM,GAAG,MAAM,CAAC;AAClC,CAAC;AAED,eAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/dist/lib/socket.d.ts b/dist/lib/socket.d.ts deleted file mode 100644 index 2a10687a..00000000 --- a/dist/lib/socket.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { Server } from "socket.io"; -export declare function initSocket(server: import("http").Server): Server; -export declare function getIO(): Server; -//# sourceMappingURL=socket.d.ts.map \ No newline at end of file diff --git a/dist/lib/socket.d.ts.map b/dist/lib/socket.d.ts.map deleted file mode 100644 index cee56ab2..00000000 --- a/dist/lib/socket.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../src/lib/socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAInC,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE,MAAM,GAAG,MAAM,CAahE;AAED,wBAAgB,KAAK,IAAI,MAAM,CAG9B"} \ No newline at end of file diff --git a/dist/lib/socket.js b/dist/lib/socket.js deleted file mode 100644 index 04106fa6..00000000 --- a/dist/lib/socket.js +++ /dev/null @@ -1,18 +0,0 @@ -import { Server } from "socket.io"; -let io = null; -export function initSocket(server) { - io = new Server(server, { - cors: { origin: "*" }, - }); - io.on("connection", (socket) => { - console.log(`🔌 Client connected: ${socket.id}`); - socket.on("disconnect", () => console.log(`🔌 Client disconnected: ${socket.id}`)); - }); - return io; -} -export function getIO() { - if (!io) - throw new Error("Socket.io not initialized"); - return io; -} -//# sourceMappingURL=socket.js.map \ No newline at end of file diff --git a/dist/lib/socket.js.map b/dist/lib/socket.js.map deleted file mode 100644 index 94aff09a..00000000 --- a/dist/lib/socket.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"socket.js","sourceRoot":"","sources":["../../src/lib/socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,IAAI,EAAE,GAAkB,IAAI,CAAC;AAE7B,MAAM,UAAU,UAAU,CAAC,MAA6B;IACtD,EAAE,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE;QACtB,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE;KACtB,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE;QAC7B,OAAO,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE,CAC3B,OAAO,CAAC,GAAG,CAAC,2BAA2B,MAAM,CAAC,EAAE,EAAE,CAAC,CACpD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACtD,OAAO,EAAE,CAAC;AACZ,CAAC"} \ No newline at end of file diff --git a/dist/logic/outlierFilter.d.ts b/dist/logic/outlierFilter.d.ts deleted file mode 100644 index 5ef468ed..00000000 --- a/dist/logic/outlierFilter.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Outlier Detection Filter for Exchange Rates - * Detects and removes manipulated/extreme prices using Interquartile Range (IQR) method - * - * Example: [750, 752, 900] → Q1=750, Q3=752, IQR=2, upper=752+1.5*2=755 → keeps 750,752 (ignores 900 if tuned) - */ -export declare function filterOutliers(prices: number[], multiplier?: number): number[]; -export declare function isOutlier(price: number, prices: number[], multiplier?: number): boolean; -/** - * Calculate percentage deviation from median - */ -export declare function percentDeviation(price: number, median: number): number; -//# sourceMappingURL=outlierFilter.d.ts.map \ No newline at end of file diff --git a/dist/logic/outlierFilter.d.ts.map b/dist/logic/outlierFilter.d.ts.map deleted file mode 100644 index 7903ec18..00000000 --- a/dist/logic/outlierFilter.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"outlierFilter.d.ts","sourceRoot":"","sources":["../../src/logic/outlierFilter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,UAAU,GAAE,MAAY,GAAG,MAAM,EAAE,CAyBnF;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,UAAU,GAAE,MAAY,GAAG,OAAO,CAG5F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtE"} \ No newline at end of file diff --git a/dist/logic/outlierFilter.js b/dist/logic/outlierFilter.js deleted file mode 100644 index 396f339f..00000000 --- a/dist/logic/outlierFilter.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Outlier Detection Filter for Exchange Rates - * Detects and removes manipulated/extreme prices using Interquartile Range (IQR) method - * - * Example: [750, 752, 900] → Q1=750, Q3=752, IQR=2, upper=752+1.5*2=755 → keeps 750,752 (ignores 900 if tuned) - */ -export function filterOutliers(prices, multiplier = 1.5) { - if (prices.length < 3) { - // Need at least 3 prices for meaningful outlier detection - return prices.filter(p => p > 0 && !isNaN(p)); - } - const validPrices = prices.filter(p => p > 0 && !isNaN(p) && isFinite(p)); - if (validPrices.length < 3) - return validPrices; - const sorted = [...validPrices].sort((a, b) => a - b); - const n = sorted.length; - const q1Index = Math.floor((n + 1) / 4); - const q3Index = Math.floor(3 * (n + 1) / 4); - const q1 = sorted[q1Index]; - const q3 = sorted[q3Index]; - const iqr = q3 - q1; - const lowerFence = q1 - multiplier * iqr; - const upperFence = q3 + multiplier * iqr; - const filtered = sorted.filter(price => price >= lowerFence && price <= upperFence); - // Fallback: if too few remain (< 2), return all valid - return filtered.length >= 2 ? filtered : validPrices; -} -export function isOutlier(price, prices, multiplier = 1.5) { - const filtered = filterOutliers(prices, multiplier); - return !filtered.includes(price); -} -/** - * Calculate percentage deviation from median - */ -export function percentDeviation(price, median) { - return Math.abs((price - median) / median) * 100; -} -//# sourceMappingURL=outlierFilter.js.map \ No newline at end of file diff --git a/dist/logic/outlierFilter.js.map b/dist/logic/outlierFilter.js.map deleted file mode 100644 index 1b8cd00c..00000000 --- a/dist/logic/outlierFilter.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"outlierFilter.js","sourceRoot":"","sources":["../../src/logic/outlierFilter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,UAAU,cAAc,CAAC,MAAgB,EAAE,aAAqB,GAAG;IACvE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,0DAA0D;QAC1D,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,WAAW,CAAC;IAE/C,MAAM,MAAM,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACtD,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAE5C,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3B,MAAM,GAAG,GAAG,EAAE,GAAG,EAAE,CAAC;IAEpB,MAAM,UAAU,GAAG,EAAE,GAAG,UAAU,GAAG,GAAG,CAAC;IACzC,MAAM,UAAU,GAAG,EAAE,GAAG,UAAU,GAAG,GAAG,CAAC;IAEzC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,UAAU,IAAI,KAAK,IAAI,UAAU,CAAC,CAAC;IAEpF,sDAAsD;IACtD,OAAO,QAAQ,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,MAAgB,EAAE,aAAqB,GAAG;IACjF,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACpD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC;AACnD,CAAC"} \ No newline at end of file diff --git a/dist/routes/history.d.ts b/dist/routes/history.d.ts deleted file mode 100644 index 51da6dda..00000000 --- a/dist/routes/history.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare const router: import("express-serve-static-core").Router; -export default router; -//# sourceMappingURL=history.d.ts.map \ No newline at end of file diff --git a/dist/routes/history.d.ts.map b/dist/routes/history.d.ts.map deleted file mode 100644 index 5e136420..00000000 --- a/dist/routes/history.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/routes/history.ts"],"names":[],"mappings":"AAGA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA6DxB,eAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/dist/routes/history.js b/dist/routes/history.js deleted file mode 100644 index 938aa2c8..00000000 --- a/dist/routes/history.js +++ /dev/null @@ -1,58 +0,0 @@ -import { Router } from "express"; -import prisma from "../lib/prisma"; -const router = Router(); -const RANGE_MAP = { - "1d": 1, - "7d": 7, - "30d": 30, - "90d": 90, -}; -// GET /api/history/:asset?range=7d -router.get("/:asset", async (req, res) => { - const asset = req.params.asset.toUpperCase(); - const rangeParam = req.query.range ?? "7d"; - const days = RANGE_MAP[rangeParam]; - if (!days) { - res.status(400).json({ - success: false, - error: `Invalid range. Supported values: ${Object.keys(RANGE_MAP).join(", ")}`, - }); - return; - } - try { - const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000); - const rows = await prisma.priceHistory.findMany({ - where: { - currency: asset, - timestamp: { gte: since }, - }, - orderBy: { timestamp: "asc" }, - select: { timestamp: true, rate: true, source: true }, - }); - if (rows.length === 0) { - res.status(404).json({ - success: false, - error: `No history found for ${asset} in the last ${rangeParam}`, - }); - return; - } - res.json({ - success: true, - asset, - range: rangeParam, - data: rows.map((r) => ({ - timestamp: r.timestamp.toISOString(), - rate: Number(r.rate), - source: r.source, - })), - }); - } - catch (error) { - res.status(500).json({ - success: false, - error: error instanceof Error ? error.message : "Internal server error", - }); - } -}); -export default router; -//# sourceMappingURL=history.js.map \ No newline at end of file diff --git a/dist/routes/history.js.map b/dist/routes/history.js.map deleted file mode 100644 index 3b256df1..00000000 --- a/dist/routes/history.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/routes/history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,MAAM,MAAM,eAAe,CAAC;AAEnC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;AAExB,MAAM,SAAS,GAA2B;IACxC,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,EAAE;IACT,KAAK,EAAE,EAAE;CACV,CAAC;AAEF,mCAAmC;AACnC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;IACvC,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IAC7C,MAAM,UAAU,GAAI,GAAG,CAAC,KAAK,CAAC,KAAgB,IAAI,IAAI,CAAC;IACvD,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;IAEnC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,oCAAoC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SAC/E,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAEhE,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC;YAC9C,KAAK,EAAE;gBACL,QAAQ,EAAE,KAAK;gBACf,SAAS,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;aAC1B;YACD,OAAO,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE;YAC7B,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;SACtD,CAAC,CAAC;QAEH,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;gBACnB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,wBAAwB,KAAK,gBAAgB,UAAU,EAAE;aACjE,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,GAAG,CAAC,IAAI,CAAC;YACP,OAAO,EAAE,IAAI;YACb,KAAK;YACL,KAAK,EAAE,UAAU;YACjB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAqD,EAAE,EAAE,CAAC,CAAC;gBACzE,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE;gBACpC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;gBACpB,MAAM,EAAE,CAAC,CAAC,MAAM;aACjB,CAAC,CAAC;SACJ,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB;SACxE,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/dist/routes/marketRates.d.ts b/dist/routes/marketRates.d.ts deleted file mode 100644 index b13ae8da..00000000 --- a/dist/routes/marketRates.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare const router: import("express-serve-static-core").Router; -export default router; -//# sourceMappingURL=marketRates.d.ts.map \ No newline at end of file diff --git a/dist/routes/marketRates.d.ts.map b/dist/routes/marketRates.d.ts.map deleted file mode 100644 index 173dfc72..00000000 --- a/dist/routes/marketRates.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"marketRates.d.ts","sourceRoot":"","sources":["../../src/routes/marketRates.ts"],"names":[],"mappings":"AAOA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAkMxB,eAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/dist/routes/marketRates.js b/dist/routes/marketRates.js deleted file mode 100644 index e0cdeaa3..00000000 --- a/dist/routes/marketRates.js +++ /dev/null @@ -1,173 +0,0 @@ -import { Router } from "express"; -import { getRate, getAllRates } from "../controllers/marketRatesController"; -import { MarketRateService } from "../services/marketRate"; -const marketRateService = new MarketRateService(); -const router = Router(); -// Get rate for specific currency -router.get("/rate/:currency", getRate); -// Get all available rates -router.get("/rates", getAllRates); -// GET /api/market-rates/latest -router.get("/latest", async (req, res) => { - try { - const result = await marketRateService.getLatestPrices(); - if (result.success) { - res.json({ - success: true, - data: result.data, - ...(result.errors && { errors: result.errors }), - }); - } - else { - res.status(500).json({ - success: false, - error: result.error, - }); - } - } - catch (error) { - console.error("Error fetching latest prices:", error); - res.status(500).json({ - success: false, - error: error instanceof Error - ? error.message - : "Failed to fetch latest prices", - }); - } -}); -router.get("/reviews/pending", async (req, res) => { - try { - const reviews = await marketRateService.getPendingReviews(); - res.json({ - success: true, - data: reviews, - }); - } - catch (error) { - res.status(500).json({ - success: false, - error: error instanceof Error - ? error.message - : "Failed to fetch pending price reviews", - }); - } -}); -router.post("/reviews/:id/approve", async (req, res) => { - try { - const reviewId = Number.parseInt(req.params.id, 10); - if (!Number.isFinite(reviewId)) { - res.status(400).json({ - success: false, - error: "Review ID must be a valid number", - }); - return; - } - const { reviewedBy, note } = req.body ?? {}; - const review = await marketRateService.approvePendingReview(reviewId, reviewedBy, note); - res.json({ - success: true, - data: review, - }); - } - catch (error) { - res.status(500).json({ - success: false, - error: error instanceof Error - ? error.message - : "Failed to approve price review", - }); - } -}); -router.post("/reviews/:id/reject", async (req, res) => { - try { - const reviewId = Number.parseInt(req.params.id, 10); - if (!Number.isFinite(reviewId)) { - res.status(400).json({ - success: false, - error: "Review ID must be a valid number", - }); - return; - } - const { reviewedBy, note } = req.body ?? {}; - const review = await marketRateService.rejectPendingReview(reviewId, reviewedBy, note); - res.json({ - success: true, - data: review, - }); - } - catch (error) { - res.status(500).json({ - success: false, - error: error instanceof Error - ? error.message - : "Failed to reject price review", - }); - } -}); -// Health check for all fetchers -router.get("/health", async (req, res) => { - try { - const health = await marketRateService.healthCheck(); - res.json({ - success: true, - data: health, - overallHealthy: Object.values(health).every((status) => status), - }); - } - catch (error) { - res.status(500).json({ - success: false, - error: error instanceof Error ? error.message : "Internal server error", - }); - } -}); -// Get supported currencies -router.get("/currencies", (req, res) => { - try { - const currencies = marketRateService.getSupportedCurrencies(); - res.json({ - success: true, - data: currencies, - }); - } - catch (error) { - res.status(500).json({ - success: false, - error: error instanceof Error ? error.message : "Internal server error", - }); - } -}); -// Get cache status -router.get("/cache", (req, res) => { - try { - const cacheStatus = marketRateService.getCacheStatus(); - res.json({ - success: true, - data: cacheStatus, - }); - } - catch (error) { - res.status(500).json({ - success: false, - error: error instanceof Error ? error.message : "Internal server error", - }); - } -}); -// Clear cache -router.post("/cache/clear", (req, res) => { - try { - marketRateService.clearCache(); - res.json({ - success: true, - message: "Cache cleared successfully", - }); - } - catch (error) { - res.status(500).json({ - success: false, - error: error instanceof Error ? error.message : "Internal server error", - }); - } -}); -export default router; -//# sourceMappingURL=marketRates.js.map \ No newline at end of file diff --git a/dist/routes/marketRates.js.map b/dist/routes/marketRates.js.map deleted file mode 100644 index 8ad148d2..00000000 --- a/dist/routes/marketRates.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"marketRates.js","sourceRoot":"","sources":["../../src/routes/marketRates.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/routes/priceUpdates.d.ts b/dist/routes/priceUpdates.d.ts deleted file mode 100644 index 77ddb3d7..00000000 --- a/dist/routes/priceUpdates.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare const router: import("express-serve-static-core").Router; -export default router; -//# sourceMappingURL=priceUpdates.d.ts.map \ No newline at end of file diff --git a/dist/routes/priceUpdates.d.ts.map b/dist/routes/priceUpdates.d.ts.map deleted file mode 100644 index ec5a468f..00000000 --- a/dist/routes/priceUpdates.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"priceUpdates.d.ts","sourceRoot":"","sources":["../../src/routes/priceUpdates.ts"],"names":[],"mappings":"AAGA,QAAA,MAAM,MAAM,4CAAmB,CAAC;AA+UhC,eAAe,MAAM,CAAC"} \ No newline at end of file diff --git a/dist/routes/priceUpdates.js b/dist/routes/priceUpdates.js deleted file mode 100644 index 57321de6..00000000 --- a/dist/routes/priceUpdates.js +++ /dev/null @@ -1,290 +0,0 @@ -import express from "express"; -import { multiSigService } from "../services/multiSigService"; -const router = express.Router(); -/** - * POST /api/price-updates/multi-sig/request - * Creates a multi-sig price update request. - * Called by the initializing server to start the approval process. - */ -router.post("/multi-sig/request", async (req, res) => { - try { - const { priceReviewId, currency, rate, source, memoId } = req.body; - if (!priceReviewId || !currency || rate === undefined || !source || !memoId) { - return res.status(400).json({ - success: false, - error: "Missing required fields: priceReviewId, currency, rate, source, memoId", - }); - } - const signatureRequest = await multiSigService.createMultiSigRequest(priceReviewId, currency, rate, source, memoId); - res.json({ - success: true, - data: signatureRequest, - }); - } - catch (error) { - console.error("[API] Multi-sig request creation failed:", error); - res.status(500).json({ - success: false, - error: String(error), - }); - } -}); -/** - * POST /api/price-updates/sign - * Endpoint for remote servers to request a signature. - * This is called by peer servers in the multi-sig setup. - * - * Requires: - * - Authorization header with token (if MULTI_SIG_AUTH_TOKEN is set) - * - Signature payload in body - */ -router.post("/sign", async (req, res) => { - try { - // Validate authorization if token is configured - const authToken = process.env.MULTI_SIG_AUTH_TOKEN; - if (authToken) { - const authHeader = req.headers.authorization || ""; - const token = authHeader.startsWith("Bearer ") - ? authHeader.slice(7) - : authHeader; - if (token !== authToken) { - return res.status(403).json({ - success: false, - error: "Unauthorized - invalid token", - }); - } - } - const { multiSigPriceId } = req.body; - if (!multiSigPriceId) { - return res.status(400).json({ - success: false, - error: "Missing multiSigPriceId", - }); - } - // Sign the price update locally - const { signature, signerPublicKey } = await multiSigService.signMultiSigPrice(multiSigPriceId); - const signerInfo = multiSigService.getLocalSignerInfo(); - res.json({ - success: true, - data: { - multiSigPriceId, - signature, - signerPublicKey, - signerName: signerInfo.name, - }, - }); - } - catch (error) { - console.error("[API] Signature creation failed:", error); - res.status(400).json({ - success: false, - error: String(error), - }); - } -}); -/** - * POST /api/price-updates/multi-sig/:multiSigPriceId/request-signature - * Request a signature from a remote server. - * The body should contain the remote server URL. - */ -router.post("/multi-sig/:multiSigPriceId/request-signature", async (req, res) => { - try { - const multiSigPriceId = req.params.multiSigPriceId; - const { remoteServerUrl } = req.body; - if (!multiSigPriceId || typeof multiSigPriceId !== "string" || !remoteServerUrl) { - return res.status(400).json({ - success: false, - error: "Missing multiSigPriceId (in URL) or remoteServerUrl (in body)", - }); - } - const result = await multiSigService.requestRemoteSignature(parseInt(multiSigPriceId, 10), remoteServerUrl); - if (!result.success) { - return res.status(400).json({ - success: false, - error: result.error, - }); - } - res.json({ success: true }); - } - catch (error) { - console.error("[API] Remote signature request failed:", error); - res.status(500).json({ - success: false, - error: String(error), - }); - } -}); -/** - * GET /api/price-updates/multi-sig/:multiSigPriceId/status - * Get the status of a multi-sig price update. - */ -router.get("/multi-sig/:multiSigPriceId/status", async (req, res) => { - try { - const multiSigPriceId = req.params.multiSigPriceId; - if (!multiSigPriceId || typeof multiSigPriceId !== "string") { - return res.status(400).json({ - success: false, - error: "Missing multiSigPriceId in URL", - }); - } - const multiSigPrice = await multiSigService.getMultiSigPrice(parseInt(multiSigPriceId, 10)); - if (!multiSigPrice) { - return res.status(404).json({ - success: false, - error: `MultiSigPrice ${multiSigPriceId} not found`, - }); - } - res.json({ - success: true, - data: { - id: multiSigPrice.id, - currency: multiSigPrice.currency, - rate: multiSigPrice.rate, - status: multiSigPrice.status, - collectedSignatures: multiSigPrice.collectedSignatures, - requiredSignatures: multiSigPrice.requiredSignatures, - expiresAt: multiSigPrice.expiresAt, - signers: multiSigPrice.multiSigSignatures?.map((sig) => ({ - publicKey: sig.signerPublicKey, - name: sig.signerName, - signedAt: sig.signedAt, - })), - }, - }); - } - catch (error) { - console.error("[API] Multi-sig status fetch failed:", error); - res.status(500).json({ - success: false, - error: String(error), - }); - } -}); -/** - * GET /api/price-updates/multi-sig/pending - * Get all pending multi-sig price updates. - * Useful for monitoring and coordination between servers. - */ -router.get("/multi-sig/pending", async (req, res) => { - try { - const pendingPrices = await multiSigService.getPendingMultiSigPrices(); - res.json({ - success: true, - data: pendingPrices.map((price) => ({ - id: price.id, - currency: price.currency, - rate: price.rate, - status: price.status, - collectedSignatures: price.collectedSignatures, - requiredSignatures: price.requiredSignatures, - expiresAt: price.expiresAt, - signerCount: price.multiSigSignatures?.length || 0, - })), - }); - } - catch (error) { - console.error("[API] Pending multi-sig fetch failed:", error); - res.status(500).json({ - success: false, - error: String(error), - }); - } -}); -/** - * GET /api/price-updates/multi-sig/:multiSigPriceId/signatures - * Get all signatures for a multi-sig price update. - * Only returns once all signatures are collected and approved. - */ -router.get("/multi-sig/:multiSigPriceId/signatures", async (req, res) => { - try { - const multiSigPriceId = req.params.multiSigPriceId; - if (!multiSigPriceId || typeof multiSigPriceId !== "string") { - return res.status(400).json({ - success: false, - error: "Missing multiSigPriceId in URL", - }); - } - const multiSigPrice = await multiSigService.getMultiSigPrice(parseInt(multiSigPriceId, 10)); - if (!multiSigPrice) { - return res.status(404).json({ - success: false, - error: `MultiSigPrice ${multiSigPriceId} not found`, - }); - } - if (multiSigPrice.status !== "APPROVED") { - return res.status(400).json({ - success: false, - error: `MultiSigPrice ${multiSigPriceId} is not approved yet (status: ${multiSigPrice.status})`, - }); - } - const signatures = await multiSigService.getSignatures(parseInt(multiSigPriceId, 10)); - res.json({ - success: true, - data: { - multiSigPriceId: multiSigPrice.id, - currency: multiSigPrice.currency, - rate: multiSigPrice.rate, - signatures: signatures.map((sig) => ({ - signerPublicKey: sig.signerPublicKey, - signerName: sig.signerName, - signature: sig.signature, - })), - }, - }); - } - catch (error) { - console.error("[API] Signature fetch failed:", error); - res.status(500).json({ - success: false, - error: String(error), - }); - } -}); -/** - * POST /api/price-updates/multi-sig/:multiSigPriceId/record-submission - * Record that a multi-sig price has been submitted to Stellar. - */ -router.post("/multi-sig/:multiSigPriceId/record-submission", async (req, res) => { - try { - const multiSigPriceId = req.params.multiSigPriceId; - const { memoId, stellarTxHash } = req.body; - if (!multiSigPriceId || typeof multiSigPriceId !== "string" || !memoId || !stellarTxHash) { - return res.status(400).json({ - success: false, - error: "Missing required fields: multiSigPriceId (in URL), memoId, stellarTxHash (in body)", - }); - } - await multiSigService.recordSubmission(parseInt(multiSigPriceId, 10), memoId, stellarTxHash); - res.json({ success: true }); - } - catch (error) { - console.error("[API] Submission recording failed:", error); - res.status(500).json({ - success: false, - error: String(error), - }); - } -}); -/** - * GET /api/price-updates/multi-sig/signer-info - * Get this server's signer information. - * Useful for remote servers to identify who is signing. - */ -router.get("/multi-sig/signer-info", async (req, res) => { - try { - const signerInfo = multiSigService.getLocalSignerInfo(); - res.json({ - success: true, - data: signerInfo, - }); - } - catch (error) { - console.error("[API] Signer info fetch failed:", error); - res.status(500).json({ - success: false, - error: String(error), - }); - } -}); -export default router; -//# sourceMappingURL=priceUpdates.js.map \ No newline at end of file diff --git a/dist/routes/priceUpdates.js.map b/dist/routes/priceUpdates.js.map deleted file mode 100644 index 8f5b9f21..00000000 --- a/dist/routes/priceUpdates.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"priceUpdates.js","sourceRoot":"","sources":["../../src/routes/priceUpdates.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/services/errorTracker.d.ts b/dist/services/errorTracker.d.ts deleted file mode 100644 index 8a15d403..00000000 --- a/dist/services/errorTracker.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -export declare class ErrorTracker { - private failureCounters; - private readonly threshold; - trackFailure(serviceKey: string, errorDetails: unknown): boolean; - trackSuccess(serviceKey: string): void; - reset(serviceKey: string): void; -} -export declare const errorTracker: ErrorTracker; -export declare const errorTracker: ErrorTracker; -//# sourceMappingURL=errorTracker.d.ts.map \ No newline at end of file diff --git a/dist/services/errorTracker.d.ts.map b/dist/services/errorTracker.d.ts.map deleted file mode 100644 index c7689883..00000000 --- a/dist/services/errorTracker.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"errorTracker.d.ts","sourceRoot":"","sources":["../../src/services/errorTracker.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAY;IACvB,OAAO,CAAC,eAAe,CACX;IACZ,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAK;IAE/B,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,OAAO;IAahE,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAItC,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;CAGhC;AAED,eAAO,MAAM,YAAY,cAAqB,CAAC;AAC/C,eAAO,MAAM,YAAY,cAAqB,CAAC"} \ No newline at end of file diff --git a/dist/services/errorTracker.js b/dist/services/errorTracker.js deleted file mode 100644 index ee2976c4..00000000 --- a/dist/services/errorTracker.js +++ /dev/null @@ -1,24 +0,0 @@ -export class ErrorTracker { - failureCounters = new Map(); - threshold = 3; - trackFailure(serviceKey, errorDetails) { - const existing = this.failureCounters.get(serviceKey); - if (existing) { - existing.count += 1; - existing.errors.push(errorDetails); - this.failureCounters.set(serviceKey, existing); - return existing.count >= this.threshold; - } - this.failureCounters.set(serviceKey, { count: 1, errors: [errorDetails] }); - return false; - } - trackSuccess(serviceKey) { - this.failureCounters.delete(serviceKey); - } - reset(serviceKey) { - this.failureCounters.delete(serviceKey); - } -} -export const errorTracker = new ErrorTracker(); -export const errorTracker = new ErrorTracker(); -//# sourceMappingURL=errorTracker.js.map \ No newline at end of file diff --git a/dist/services/errorTracker.js.map b/dist/services/errorTracker.js.map deleted file mode 100644 index 38e11f99..00000000 --- a/dist/services/errorTracker.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"errorTracker.js","sourceRoot":"","sources":["../../src/services/errorTracker.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,YAAY;IACf,eAAe,GACrB,IAAI,GAAG,EAAE,CAAC;IACK,SAAS,GAAG,CAAC,CAAC;IAE/B,YAAY,CAAC,UAAkB,EAAE,YAAqB;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC;YACpB,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACnC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC/C,OAAO,QAAQ,CAAC,KAAK,IAAI,IAAI,CAAC,SAAS,CAAC;QAC1C,CAAC;QAED,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QAC3E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,YAAY,CAAC,UAAkB;QAC7B,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,UAAkB;QACtB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC1C,CAAC;CACF;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC;AAC/C,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/services/marketRate/coingeckoFetcher.d.ts b/dist/services/marketRate/coingeckoFetcher.d.ts deleted file mode 100644 index 8365377b..00000000 --- a/dist/services/marketRate/coingeckoFetcher.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -export declare class CoinGeckoFetcher { - private static readonly API_URL; - /** - * Fetches the current XLM/USD price from CoinGecko. - * @returns The price as a number (e.g., 0.12 for 1 XLM = $0.12) - * @throws Error if the fetch fails or the response is invalid - */ - static fetchXlmUsdPrice(): Promise; -} -//# sourceMappingURL=coingeckoFetcher.d.ts.map \ No newline at end of file diff --git a/dist/services/marketRate/coingeckoFetcher.d.ts.map b/dist/services/marketRate/coingeckoFetcher.d.ts.map deleted file mode 100644 index 4b7d3b05..00000000 --- a/dist/services/marketRate/coingeckoFetcher.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"coingeckoFetcher.d.ts","sourceRoot":"","sources":["../../../src/services/marketRate/coingeckoFetcher.ts"],"names":[],"mappings":"AAEA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAiF;IAEhH;;;;OAIG;WACU,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;CAWjD"} \ No newline at end of file diff --git a/dist/services/marketRate/coingeckoFetcher.js b/dist/services/marketRate/coingeckoFetcher.js deleted file mode 100644 index d56f7906..00000000 --- a/dist/services/marketRate/coingeckoFetcher.js +++ /dev/null @@ -1,19 +0,0 @@ -import axios from "axios"; -export class CoinGeckoFetcher { - static API_URL = "https://api.coingecko.com/api/v3/simple/price?ids=stellar&vs_currencies=usd"; - /** - * Fetches the current XLM/USD price from CoinGecko. - * @returns The price as a number (e.g., 0.12 for 1 XLM = $0.12) - * @throws Error if the fetch fails or the response is invalid - */ - static async fetchXlmUsdPrice() { - const response = await axios.get(CoinGeckoFetcher.API_URL); - if (response.data && - response.data.stellar && - typeof response.data.stellar.usd === "number") { - return response.data.stellar.usd; - } - throw new Error("Invalid response from CoinGecko API"); - } -} -//# sourceMappingURL=coingeckoFetcher.js.map \ No newline at end of file diff --git a/dist/services/marketRate/coingeckoFetcher.js.map b/dist/services/marketRate/coingeckoFetcher.js.map deleted file mode 100644 index 5314518b..00000000 --- a/dist/services/marketRate/coingeckoFetcher.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"coingeckoFetcher.js","sourceRoot":"","sources":["../../../src/services/marketRate/coingeckoFetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,OAAO,gBAAgB;IACnB,MAAM,CAAU,OAAO,GAAG,6EAA6E,CAAC;IAEhH;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,gBAAgB;QAC3B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC3D,IACE,QAAQ,CAAC,IAAI;YACb,QAAQ,CAAC,IAAI,CAAC,OAAO;YACrB,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,KAAK,QAAQ,EAC7C,CAAC;YACD,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;QACnC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC"} \ No newline at end of file diff --git a/dist/services/marketRate/ghsFetcher.d.ts b/dist/services/marketRate/ghsFetcher.d.ts deleted file mode 100644 index 21cf3380..00000000 --- a/dist/services/marketRate/ghsFetcher.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { MarketRateFetcher, MarketRate } from "./types"; -export declare class GHSRateFetcher implements MarketRateFetcher { - private readonly coinGeckoUrl; - private readonly usdToGhsUrl; - getCurrency(): string; - fetchRate(): Promise; - isHealthy(): Promise; -} -//# sourceMappingURL=ghsFetcher.d.ts.map \ No newline at end of file diff --git a/dist/services/marketRate/ghsFetcher.d.ts.map b/dist/services/marketRate/ghsFetcher.d.ts.map deleted file mode 100644 index b62352b6..00000000 --- a/dist/services/marketRate/ghsFetcher.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ghsFetcher.d.ts","sourceRoot":"","sources":["../../../src/services/marketRate/ghsFetcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAmC,MAAM,SAAS,CAAC;AAoBzF,qBAAa,cAAe,YAAW,iBAAiB;IACtD,OAAO,CAAC,QAAQ,CAAC,YAAY,CACoF;IAEjH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA2C;IAEvE,WAAW,IAAI,MAAM;IAIf,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC;IA2LhC,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;CAQpC"} \ No newline at end of file diff --git a/dist/services/marketRate/ghsFetcher.js b/dist/services/marketRate/ghsFetcher.js deleted file mode 100644 index 849cd9b4..00000000 --- a/dist/services/marketRate/ghsFetcher.js +++ /dev/null @@ -1,162 +0,0 @@ -import axios from "axios"; -import { calculateMedian, filterOutliers } from "./types"; -import { errorTracker } from "../errorTracker"; -import { webhookService } from "../webhook"; -export class GHSRateFetcher { - coinGeckoUrl = "https://api.coingecko.com/api/v3/simple/price?ids=stellar&vs_currencies=ghs,usd&include_last_updated_at=true"; - usdToGhsUrl = "https://open.er-api.com/v6/latest/USD"; - getCurrency() { - return "GHS"; - } - async fetchRate() { - const prices = []; - // Strategy 1: Try CoinGecko direct GHS price - try { - const coinGeckoResponse = await axios.get(this.coinGeckoUrl, { - timeout: 10000, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - }, - }); - const stellarPrice = coinGeckoResponse.data.stellar; - if (stellarPrice && - typeof stellarPrice.ghs === "number" && - stellarPrice.ghs > 0) { - const lastUpdatedAt = stellarPrice.last_updated_at - ? new Date(stellarPrice.last_updated_at * 1000) - : new Date(); - prices.push({ - rate: stellarPrice.ghs, - timestamp: lastUpdatedAt, - source: "CoinGecko (direct)", - trustLevel: "standard", - }); - // Success - reset error tracker - errorTracker.trackSuccess("GHS-price-fetch"); - } - } - catch (error) { - console.debug("CoinGecko direct GHS price failed"); - } - // Strategy 2: CoinGecko XLM/USD + ExchangeRate API - try { - const coinGeckoResponse = await axios.get(this.coinGeckoUrl, { - timeout: 10000, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - }, - }); - const stellarPrice = coinGeckoResponse.data.stellar; - if (stellarPrice && - typeof stellarPrice.usd === "number" && - stellarPrice.usd > 0) { - const exchangeRateResponse = await axios.get(this.usdToGhsUrl, { - timeout: 10000, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - }, - }); - const usdToGhsRate = exchangeRateResponse.data.rates?.GHS; - if (exchangeRateResponse.data.result === "success" && - typeof usdToGhsRate === "number" && - usdToGhsRate > 0) { - const fxTimestamp = exchangeRateResponse.data.time_last_update_unix - ? new Date(exchangeRateResponse.data.time_last_update_unix * 1000) - : new Date(); - const lastUpdatedAt = stellarPrice.last_updated_at - ? new Date(stellarPrice.last_updated_at * 1000) - : new Date(); - prices.push({ - rate: stellarPrice.usd * usdToGhsRate, - timestamp: fxTimestamp > lastUpdatedAt ? fxTimestamp : lastUpdatedAt, - source: "CoinGecko + ExchangeRate API", - trustLevel: "trusted", - }); - // Success - reset error tracker - errorTracker.trackSuccess("GHS-price-fetch"); - } - } - } - catch (error) { - console.debug("CoinGecko + ExchangeRate API failed"); - } - // Strategy 3: Try alternative XLM pricing source - try { - const alternativeUrl = "https://api.coingecko.com/api/v3/simple/price?ids=stellar&vs_currencies=usd"; - const altResponse = await axios.get(alternativeUrl, { - timeout: 10000, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - }, - }); - if (altResponse.data?.stellar?.usd) { - const xlmUsd = parseFloat(altResponse.data.stellar.usd); - if (!isNaN(xlmUsd) && xlmUsd > 0) { - const ghsResponse = await axios.get(this.usdToGhsUrl, { - timeout: 10000, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - }, - }); - const ghsRate = ghsResponse.data.rates?.GHS; - if (ghsResponse.data.result === "success" && - typeof ghsRate === "number" && - ghsRate > 0) { - prices.push({ - rate: xlmUsd * ghsRate, - timestamp: new Date(), - source: "Alternative XLM pricing", - trustLevel: "new", - }); - // Success - reset error tracker - errorTracker.trackSuccess("GHS-price-fetch"); - } - } - } - } - catch (error) { - console.debug("Alternative XLM pricing source failed"); - } - // If we have prices, calculate median - if (prices.length > 0) { - let rateValues = prices.map((p) => p.rate).filter(p => p > 0); - rateValues = filterOutliers(rateValues); - const medianRate = calculateMedian(rateValues); - const mostRecentTimestamp = prices.reduce((latest, p) => (p.timestamp > latest ? p.timestamp : latest), prices[0]?.timestamp ?? new Date()); - return { - currency: "GHS", - rate: weightedRate, - timestamp: mostRecentTimestamp, - source: `Median of ${prices.length} sources (outliers filtered)`, - }; - } - // All strategies failed - track failure and send notification if 3 consecutive failures - const error = new Error("All GHS rate sources failed"); - const thresholdReached = errorTracker.trackFailure("GHS-price-fetch", { - errorMessage: error.message, - timestamp: new Date(), - service: "GHSRateFetcher", - }); - if (thresholdReached) { - await webhookService.sendErrorNotification({ - errorType: "PRICE_FETCH_FAILED_CONSECUTIVE", - errorMessage: error.message, - attempts: 3, - service: "GHSRateFetcher", - pricePair: "XLM/GHS", - timestamp: new Date(), - }); - } - throw error; - } - async isHealthy() { - try { - const rate = await this.fetchRate(); - return rate.rate > 0; - } - catch { - return false; - } - } -} -//# sourceMappingURL=ghsFetcher.js.map \ No newline at end of file diff --git a/dist/services/marketRate/ghsFetcher.js.map b/dist/services/marketRate/ghsFetcher.js.map deleted file mode 100644 index 0e940c58..00000000 --- a/dist/services/marketRate/ghsFetcher.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ghsFetcher.js","sourceRoot":"","sources":["../../../src/services/marketRate/ghsFetcher.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/services/marketRate/index.d.ts b/dist/services/marketRate/index.d.ts deleted file mode 100644 index 8a4e3ec0..00000000 --- a/dist/services/marketRate/index.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './types'; -export * from './kesFetcher'; -export * from './ghsFetcher'; -export * from './ngnFetcher'; -export * from './marketRateService'; -//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/services/marketRate/index.d.ts.map b/dist/services/marketRate/index.d.ts.map deleted file mode 100644 index 13e0f4ad..00000000 --- a/dist/services/marketRate/index.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/marketRate/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC"} \ No newline at end of file diff --git a/dist/services/marketRate/index.js b/dist/services/marketRate/index.js deleted file mode 100644 index 5e562131..00000000 --- a/dist/services/marketRate/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export * from './types'; -export * from './kesFetcher'; -export * from './ghsFetcher'; -export * from './ngnFetcher'; -export * from './marketRateService'; -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/services/marketRate/index.js.map b/dist/services/marketRate/index.js.map deleted file mode 100644 index 049bcefd..00000000 --- a/dist/services/marketRate/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/marketRate/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC"} \ No newline at end of file diff --git a/dist/services/marketRate/kesFetcher.d.ts b/dist/services/marketRate/kesFetcher.d.ts deleted file mode 100644 index d08f5521..00000000 --- a/dist/services/marketRate/kesFetcher.d.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { MarketRateFetcher, MarketRate } from "./types"; -/** - * Circuit Breaker States - */ -declare enum CircuitState { - CLOSED = "CLOSED",// Normal operation, requests pass through - OPEN = "OPEN",// Failing, reject requests immediately - HALF_OPEN = "HALF_OPEN" -} -/** - * KES/XLM Rate Fetcher using Binance Public API - * Implements multiple strategies to fetch KES rates: - * 1. Direct Binance Spot API (XLMKES pair) - * 2. Binance P2P API for KES - * 3. Binance Spot API (XLMUSDT) × USD/KES calculation - * 4. Fallback to Central Bank of Kenya - */ -export declare class KESRateFetcher implements MarketRateFetcher { - private readonly circuitBreaker; - private readonly retryConfig; - constructor(); - /** - * Get the currency code this fetcher handles - */ - getCurrency(): string; - /** - * Fetch the KES/XLM rate with comprehensive error handling - * Tries multiple strategies in order of reliability - */ - fetchRate(): Promise; - /** - * Fetch KES/XLM rate from Binance API - * Tries multiple strategies: - * 1. Direct XLMKES pair - * 2. Binance P2P API - * 3. XLMUSDT × KES/USD calculation - * Returns all successful rates to calculate median - */ - private fetchFromBinance; - /** - * Fetch a specific trading pair price from Binance Spot API - */ - private fetchBinanceSpotPrice; - /** - * Fetch KES rates from Binance P2P API - * Note: Binance P2P API may require authentication or have CORS restrictions - */ - private fetchBinanceP2PRate; - /** - * Fetch KES/USD rate from Central Bank of Kenya - */ - private fetchFromCBK; - /** - * Fetch rate from alternative sources - */ - private fetchFromSource; - /** - * Handle API errors with detailed logging - */ - private handleApiError; - /** - * Build comprehensive error message from all failures - */ - private buildErrorMessage; - /** - * Health check for the fetcher - * Tests Binance API availability specifically - */ - isHealthy(): Promise; - /** - * Get circuit breaker status for diagnostics - */ - getCircuitBreakerStatus(): { - state: CircuitState; - failureCount: number; - }; - /** - * Reset circuit breaker (for manual intervention) - */ - resetCircuitBreaker(): void; -} -export {}; -//# sourceMappingURL=kesFetcher.d.ts.map \ No newline at end of file diff --git a/dist/services/marketRate/kesFetcher.d.ts.map b/dist/services/marketRate/kesFetcher.d.ts.map deleted file mode 100644 index 5849fb58..00000000 --- a/dist/services/marketRate/kesFetcher.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"kesFetcher.d.ts","sourceRoot":"","sources":["../../../src/services/marketRate/kesFetcher.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EACjB,UAAU,EAKX,MAAM,SAAS,CAAC;AA2CjB;;GAEG;AACH,aAAK,YAAY;IACf,MAAM,WAAW,CAAE,0CAA0C;IAC7D,IAAI,SAAS,CAAE,uCAAuC;IACtD,SAAS,cAAc;CACxB;AAgLD;;;;;;;GAOG;AACH,qBAAa,cAAe,YAAW,iBAAiB;IACtD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;;IAiB1C;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC;IA8EtC;;;;;;;OAOG;YACW,gBAAgB;IA8E9B;;OAEG;YACW,qBAAqB;IAiCnC;;;OAGG;YACW,mBAAmB;IAgDjC;;OAEG;YACW,YAAY;IAmC1B;;OAEG;YACW,eAAe;IA0B7B;;OAEG;IACH,OAAO,CAAC,cAAc;IAgCtB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IASzB;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAsBnC;;OAEG;IACH,uBAAuB,IAAI;QAAE,KAAK,EAAE,YAAY,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;IAOxE;;OAEG;IACH,mBAAmB,IAAI,IAAI;CAI5B"} \ No newline at end of file diff --git a/dist/services/marketRate/kesFetcher.js b/dist/services/marketRate/kesFetcher.js deleted file mode 100644 index 70d71ca7..00000000 --- a/dist/services/marketRate/kesFetcher.js +++ /dev/null @@ -1,519 +0,0 @@ -import axios from "axios"; -import { calculateMedian, filterOutliers, } from "./types"; -/** - * Circuit Breaker States - */ -var CircuitState; -(function (CircuitState) { - CircuitState["CLOSED"] = "CLOSED"; - CircuitState["OPEN"] = "OPEN"; - CircuitState["HALF_OPEN"] = "HALF_OPEN"; -})(CircuitState || (CircuitState = {})); -/** - * Circuit Breaker Implementation - */ -class CircuitBreaker { - config; - state = CircuitState.CLOSED; - failureCount = 0; - lastFailureTime = null; - halfOpenAttempts = 0; - constructor(config) { - this.config = config; - } - async execute(operation) { - if (this.state === CircuitState.OPEN) { - if (this.shouldAttemptRecovery()) { - this.state = CircuitState.HALF_OPEN; - this.halfOpenAttempts = 0; - } - else { - throw new Error("Circuit breaker is OPEN - service temporarily unavailable"); - } - } - if (this.state === CircuitState.HALF_OPEN) { - this.halfOpenAttempts++; - if (this.halfOpenAttempts > this.config.halfOpenMaxAttempts) { - throw new Error("Circuit breaker half-open test limit exceeded"); - } - } - try { - const result = await operation(); - this.onSuccess(); - return result; - } - catch (error) { - this.onFailure(); - throw error; - } - } - onSuccess() { - this.failureCount = 0; - if (this.state === CircuitState.HALF_OPEN) { - this.state = CircuitState.CLOSED; - } - } - onFailure() { - this.failureCount++; - this.lastFailureTime = new Date(); - if (this.state === CircuitState.HALF_OPEN) { - this.state = CircuitState.OPEN; - } - else if (this.failureCount >= this.config.failureThreshold) { - this.state = CircuitState.OPEN; - } - } - shouldAttemptRecovery() { - if (!this.lastFailureTime) - return true; - const elapsed = Date.now() - this.lastFailureTime.getTime(); - return elapsed >= this.config.recoveryTimeoutMs; - } - getState() { - return this.state; - } - reset() { - this.state = CircuitState.CLOSED; - this.failureCount = 0; - this.lastFailureTime = null; - this.halfOpenAttempts = 0; - } -} -/** - * Retry with exponential backoff - */ -async function withRetry(operation, config, operationName) { - let lastError = null; - for (let attempt = 1; attempt <= config.maxAttempts; attempt++) { - try { - return await operation(); - } - catch (error) { - lastError = error instanceof Error ? error : new Error(String(error)); - if (attempt < config.maxAttempts) { - const delay = Math.min(config.baseDelayMs * Math.pow(config.backoffMultiplier, attempt - 1), config.maxDelayMs); - console.debug(`Retry attempt ${attempt}/${config.maxAttempts} for ${operationName} ` + - `after ${delay}ms delay. Error: ${lastError.message}`); - await new Promise((resolve) => setTimeout(resolve, delay)); - } - } - } - throw (lastError || - new Error(`${operationName} failed after ${config.maxAttempts} attempts`)); -} -/** - * Rate Source Configuration - */ -const RATE_SOURCES = [ - { - name: "Binance Spot API", - url: "https://api.binance.com/api/v3/ticker/price", - }, - { - name: "Binance Unified Trading (24h)", - url: "https://api.binance.com/api/v3/ticker/24hr", - }, - { - name: "Central Bank of Kenya", - url: "https://www.centralbank.go.ke/wp-json/fx-rate/v1/rates", - }, - { - name: "XE.com", - url: "https://www.xe.com/currencytables/?from=USD&to=KES", - }, -]; -/** - * API Configuration - */ -const BINANCE_SPOT_URL = "https://api.binance.com/api/v3/ticker/price"; -const BINANCE_24H_URL = "https://api.binance.com/api/v3/ticker/24hr"; -const BINANCE_P2P_URL = "https://p2p-api.binance.com/bapi/c2c/v2/public/c2c/adv/search"; -/** - * Default timeout for API requests (ms) - */ -const DEFAULT_TIMEOUT_MS = 8000; -/** - * Approximate KES/USD rate for calculation fallback - * Note: In production, this should be fetched from a reliable source - */ -const APPROXIMATE_KES_USD_RATE = 130.5; -/** - * KES/XLM Rate Fetcher using Binance Public API - * Implements multiple strategies to fetch KES rates: - * 1. Direct Binance Spot API (XLMKES pair) - * 2. Binance P2P API for KES - * 3. Binance Spot API (XLMUSDT) × USD/KES calculation - * 4. Fallback to Central Bank of Kenya - */ -export class KESRateFetcher { - circuitBreaker; - retryConfig; - constructor() { - this.circuitBreaker = new CircuitBreaker({ - failureThreshold: 5, - recoveryTimeoutMs: 30000, - halfOpenMaxAttempts: 3, - }); - this.retryConfig = { - maxAttempts: 3, - baseDelayMs: 500, - maxDelayMs: 5000, - backoffMultiplier: 2, - }; - } - /** - * Get the currency code this fetcher handles - */ - getCurrency() { - return "KES"; - } - /** - * Fetch the KES/XLM rate with comprehensive error handling - * Tries multiple strategies in order of reliability - */ - async fetchRate() { - const errors = []; - // Strategy 1: Try Binance API (with circuit breaker and retry) - try { - const binanceRate = await this.circuitBreaker.execute(() => withRetry(() => this.fetchFromBinance(), this.retryConfig, "Binance API")); - if (binanceRate) { - console.info(`✅ KES rate fetched from Binance: ${binanceRate.rate}`); - return binanceRate; - } - } - catch (error) { - const errorMsg = error instanceof Error ? error.message : "Unknown Binance error"; - console.warn(`⚠️ Binance API failed: ${errorMsg}`); - errors.push({ - source: "Binance API", - message: errorMsg, - timestamp: new Date(), - }); - } - // Strategy 2: Try Central Bank of Kenya - try { - const cbkRate = await this.fetchFromCBK(); - if (cbkRate) { - console.info(`✅ KES rate fetched from CBK: ${cbkRate.rate}`); - return cbkRate; - } - } - catch (error) { - const errorMsg = error instanceof Error ? error.message : "Unknown CBK error"; - console.warn(`⚠️ Central Bank of Kenya API failed: ${errorMsg}`); - errors.push({ - source: "Central Bank of Kenya", - message: errorMsg, - timestamp: new Date(), - }); - } - // Strategy 3: Try alternative sources - for (const source of RATE_SOURCES.slice(2)) { - try { - const rate = await withRetry(() => this.fetchFromSource(source), this.retryConfig, source.name); - if (rate) { - console.info(`✅ KES rate fetched from ${source.name}: ${rate.rate}`); - return rate; - } - } - catch (error) { - const errorMsg = error instanceof Error - ? error.message - : `Unknown ${source.name} error`; - console.warn(`⚠️ ${source.name} failed: ${errorMsg}`); - errors.push({ - source: source.name, - message: errorMsg, - timestamp: new Date(), - }); - } - } - // All sources failed - throw comprehensive error - const errorMessage = this.buildErrorMessage(errors); - console.error(`❌ All KES rate sources failed: ${errorMessage}`); - throw new Error(errorMessage); - } - /** - * Fetch KES/XLM rate from Binance API - * Tries multiple strategies: - * 1. Direct XLMKES pair - * 2. Binance P2P API - * 3. XLMUSDT × KES/USD calculation - * Returns all successful rates to calculate median - */ - async fetchFromBinance() { - const prices = []; - // Strategy 1: Direct XLMKES pair - try { - const directRate = await this.fetchBinanceSpotPrice("XLMKES"); - if (directRate) { - prices.push({ - rate: directRate.rate, - timestamp: directRate.timestamp, - source: "Binance Spot (XLMKES)", - trustLevel: "standard", - }); - } - } - catch (error) { - console.debug("Direct XLMKES pair not available"); - } - // Strategy 2: Try Binance P2P API - try { - const p2pRate = await this.fetchBinanceP2PRate(); - if (p2pRate) { - prices.push({ - rate: p2pRate.rate, - timestamp: p2pRate.timestamp, - source: p2pRate.source, - trustLevel: "new", - }); - } - } - catch (error) { - console.debug("Binance P2P API not available"); - } - // Strategy 3: XLMUSDT × KES/USD calculation - try { - const xlmUsdRate = await this.fetchBinanceSpotPrice("XLMUSDT"); - if (xlmUsdRate) { - prices.push({ - rate: xlmUsdRate.rate * APPROXIMATE_KES_USD_RATE, - timestamp: xlmUsdRate.timestamp, - source: "Binance Spot (XLMUSDT × KES/USD)", - trustLevel: "new", - }); - } - } - catch (error) { - console.debug("XLMUSDT pair not available"); - } - // If no prices were collected, return null - if (prices.length === 0) { - return null; - } - // Calculate median rate from all sources (with outlier filtering) - let rateValues = prices.map((p) => p.rate).filter(p => p > 0); - rateValues = filterOutliers(rateValues); - const medianRate = calculateMedian(rateValues); - // Return the median with the most recent timestamp - const firstTimestamp = prices[0]?.timestamp ?? new Date(); - const mostRecentTimestamp = prices.reduce((latest, p) => (p.timestamp > latest ? p.timestamp : latest), firstTimestamp); - return { - currency: "KES", - rate: weightedRate, - timestamp: mostRecentTimestamp, - source: `Binance (Median of ${prices.length} sources, outliers filtered)`, - }; - } - /** - * Fetch a specific trading pair price from Binance Spot API - */ - async fetchBinanceSpotPrice(symbol) { - try { - const response = await axios.get(BINANCE_SPOT_URL, { - params: { symbol }, - timeout: DEFAULT_TIMEOUT_MS, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - Accept: "application/json", - }, - }); - if (response.data && response.data.lastPrice) { - const rate = parseFloat(response.data.lastPrice); - if (!isNaN(rate) && rate > 0) { - return { - rate, - timestamp: new Date(), - }; - } - } - return null; - } - catch (error) { - this.handleApiError(error, `Binance Spot (${symbol})`); - return null; - } - } - /** - * Fetch KES rates from Binance P2P API - * Note: Binance P2P API may require authentication or have CORS restrictions - */ - async fetchBinanceP2PRate() { - try { - const response = await axios.post(BINANCE_P2P_URL, { - fiat: "KES", - asset: "XLM", - merchantCheck: false, - rows: 5, - page: 1, - tradeType: "BUY", - }, { - timeout: DEFAULT_TIMEOUT_MS, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - "Content-Type": "application/json", - Accept: "application/json", - }, - }); - if (response.data?.data && response.data.data.length > 0) { - // Calculate average price from available offers - const prices = response.data.data - .map((item) => item.adv?.price) - .filter((price) => !!price) - .map((price) => parseFloat(price)) - .filter((price) => !isNaN(price) && price > 0); - if (prices.length > 0) { - const avgPrice = prices.reduce((a, b) => a + b, 0) / prices.length; - return { - currency: "KES", - rate: avgPrice, - timestamp: new Date(), - source: "Binance P2P API", - }; - } - } - return null; - } - catch (error) { - this.handleApiError(error, "Binance P2P API"); - return null; - } - } - /** - * Fetch KES/USD rate from Central Bank of Kenya - */ - async fetchFromCBK() { - const cbkSource = RATE_SOURCES[2]; - if (!cbkSource) { - console.warn("Central Bank of Kenya source not configured"); - return null; - } - try { - const response = await axios.get(cbkSource.url, { - timeout: 10000, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - Accept: "application/json", - }, - }); - // CBK API returns rates in KES per USD - const rates = response.data; - if (rates && rates.length > 0) { - const latestRate = rates[0]; - return { - currency: "KES", - rate: parseFloat(latestRate.rate), - timestamp: new Date(latestRate.date), - source: cbkSource.name, - }; - } - return null; - } - catch (error) { - this.handleApiError(error, cbkSource.name); - return null; - } - } - /** - * Fetch rate from alternative sources - */ - async fetchFromSource(source) { - try { - const response = await axios.get(source.url, { - timeout: 10000, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - Accept: "application/json", - }, - }); - // Placeholder - in production, parse actual response - // For now, return approximate rate - return { - currency: "KES", - rate: APPROXIMATE_KES_USD_RATE, - timestamp: new Date(), - source: source.name, - }; - } - catch (error) { - this.handleApiError(error, source.name); - return null; - } - } - /** - * Handle API errors with detailed logging - */ - handleApiError(error, source) { - if (axios.isAxiosError(error)) { - const axiosError = error; - if (axiosError.response) { - // Server responded with error status - console.warn(`${source} returned status ${axiosError.response.status}: ` + - `${axiosError.response.statusText}`); - } - else if (axiosError.code === "ECONNABORTED" || - axiosError.code === "ETIMEDOUT") { - // Request timeout - console.warn(`${source} request timed out`); - } - else if (axiosError.code === "ERR_NETWORK") { - // Network error - console.warn(`${source} network error - service may be down`); - } - else if (axiosError.message.includes("Network Error")) { - // CORS or network issue - console.warn(`${source} network error - check connectivity or CORS settings`); - } - else { - console.warn(`${source} error: ${axiosError.message}`); - } - } - else { - console.warn(`${source} unexpected error:`, error); - } - } - /** - * Build comprehensive error message from all failures - */ - buildErrorMessage(errors) { - if (errors.length === 0) { - return "Failed to fetch KES rate: All sources returned no data"; - } - const messages = errors.map((e) => `${e.source}: ${e.message}`).join("; "); - return `Failed to fetch KES rate from all sources. Errors: ${messages}`; - } - /** - * Health check for the fetcher - * Tests Binance API availability specifically - */ - async isHealthy() { - try { - const testRate = await withRetry(() => this.fetchFromBinance(), { ...this.retryConfig, maxAttempts: 1 }, "Health check"); - const healthy = testRate !== null && testRate.rate > 0; - console.debug(`Health check result: ${healthy ? "HEALTHY" : "UNHEALTHY"}`); - return healthy; - } - catch (error) { - console.warn("Health check failed:", error instanceof Error ? error.message : "Unknown error"); - return false; - } - } - /** - * Get circuit breaker status for diagnostics - */ - getCircuitBreakerStatus() { - return { - state: this.circuitBreaker.getState(), - failureCount: 0, // Internal state not exposed - }; - } - /** - * Reset circuit breaker (for manual intervention) - */ - resetCircuitBreaker() { - this.circuitBreaker.reset(); - console.info("Circuit breaker reset"); - } -} -//# sourceMappingURL=kesFetcher.js.map \ No newline at end of file diff --git a/dist/services/marketRate/kesFetcher.js.map b/dist/services/marketRate/kesFetcher.js.map deleted file mode 100644 index cfb1f096..00000000 --- a/dist/services/marketRate/kesFetcher.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"kesFetcher.js","sourceRoot":"","sources":["../../../src/services/marketRate/kesFetcher.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/services/marketRate/marketRateService.d.ts b/dist/services/marketRate/marketRateService.d.ts deleted file mode 100644 index e898d685..00000000 --- a/dist/services/marketRate/marketRateService.d.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { FetcherResponse, AggregatedFetcherResponse } from "./types"; -export declare class MarketRateService { - private fetchers; - private cache; - private stellarService; - private readonly CACHE_DURATION_MS; - private multiSigEnabled; - private remoteOracleServers; - constructor(); - private initializeFetchers; - getRate(currency: string): Promise; - getAllRates(): Promise; - healthCheck(): Promise>; - getSupportedCurrencies(): string[]; - getLatestPrices(): Promise; - clearCache(): void; - getPendingReviews(): Promise; - approvePendingReview(reviewId: number, reviewedBy?: string, reviewNotes?: string): Promise; - rejectPendingReview(reviewId: number, reviewedBy?: string, reviewNotes?: string): Promise; - getCacheStatus(): Record; - /** - * Asynchronously request signatures from remote oracle servers. - * This is non-blocking and doesn't wait for completion. - * Errors are logged but don't fail the price fetch operation. - */ - private requestRemoteSignaturesAsync; -} -//# sourceMappingURL=marketRateService.d.ts.map \ No newline at end of file diff --git a/dist/services/marketRate/marketRateService.d.ts.map b/dist/services/marketRate/marketRateService.d.ts.map deleted file mode 100644 index 9635afb6..00000000 --- a/dist/services/marketRate/marketRateService.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"marketRateService.d.ts","sourceRoot":"","sources":["../../../src/services/marketRate/marketRateService.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,eAAe,EACf,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AAejB,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAA6C;IAC7D,OAAO,CAAC,KAAK,CAA8D;IAC3E,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,eAAe,CAAU;IACjC,OAAO,CAAC,mBAAmB,CAAgB;;IA0B3C,OAAO,CAAC,kBAAkB;IAUpB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA6KnD,WAAW,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAOzC,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAcrD,sBAAsB,IAAI,MAAM,EAAE;IAI5B,eAAe,IAAI,OAAO,CAAC,yBAAyB,CAAC;IAuB3D,UAAU,IAAI,IAAI;IAIZ,iBAAiB;IAIjB,oBAAoB,CACxB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM;IAoChB,mBAAmB,CACvB,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM;IAsBtB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,IAAI,CAAA;KAAE,CAAC;IAoBpE;;;;OAIG;YACW,4BAA4B;CAmC3C"} \ No newline at end of file diff --git a/dist/services/marketRate/marketRateService.js b/dist/services/marketRate/marketRateService.js deleted file mode 100644 index b26116d2..00000000 --- a/dist/services/marketRate/marketRateService.js +++ /dev/null @@ -1,306 +0,0 @@ -import { KESRateFetcher } from "./kesFetcher"; -import { GHSRateFetcher } from "./ghsFetcher"; -import { NGNRateFetcher } from "./ngnFetcher"; -import { StellarService } from "../stellarService"; -import { multiSigService } from "../multiSigService"; -import { getIO } from "../../lib/socket"; -import prisma from "../../lib/prisma"; -import dotenv from "dotenv"; -dotenv.config(); -// Global import for priceReviewService -import { priceReviewService } from "../priceReviewService"; -export class MarketRateService { - fetchers = new Map(); - cache = new Map(); - stellarService; - CACHE_DURATION_MS = 30000; // 30 seconds - multiSigEnabled; - remoteOracleServers = []; - constructor() { - this.stellarService = new StellarService(); - // Check if multi-sig is enabled - this.multiSigEnabled = process.env.MULTI_SIG_ENABLED === "true"; - // Parse remote oracle server URLs - const remoteServersEnv = process.env.REMOTE_ORACLE_SERVERS || ""; - if (remoteServersEnv) { - this.remoteOracleServers = remoteServersEnv - .split(",") - .map((url) => url.trim()) - .filter((url) => url.length > 0); - } - if (this.multiSigEnabled) { - console.info(`[MarketRateService] Multi-Sig mode ENABLED with ${this.remoteOracleServers.length} remote servers`); - } - this.initializeFetchers(); - } - initializeFetchers() { - const kesFetcher = new KESRateFetcher(); - const ghsFetcher = new GHSRateFetcher(); - const ngnFetcher = new NGNRateFetcher(); - this.fetchers.set("KES", kesFetcher); - this.fetchers.set("GHS", ghsFetcher); - this.fetchers.set("NGN", ngnFetcher); - } - async getRate(currency) { - try { - const normalizedCurrency = currency.toUpperCase(); - const fetcher = this.fetchers.get(normalizedCurrency); - if (!fetcher) { - return { - success: false, - error: `No fetcher available for currency: ${currency}`, - }; - } - const cached = this.cache.get(normalizedCurrency); - if (cached && cached.expiry > new Date()) { - return { - success: true, - data: cached.rate, - }; - } - const rate = await fetcher.fetchRate(); - const reviewAssessment = await priceReviewService.assessRate(rate); - const enrichedRate = { - ...rate, - manualReviewRequired: reviewAssessment.manualReviewRequired, - reviewId: reviewAssessment.reviewRecordId, - contractSubmissionSkipped: reviewAssessment.manualReviewRequired, - ...(reviewAssessment.reason !== undefined && { - reviewReason: reviewAssessment.reason, - }), - ...(reviewAssessment.changePercent !== undefined && { - reviewChangePercent: reviewAssessment.changePercent, - }), - ...(reviewAssessment.comparisonRate !== undefined && { - comparisonRate: reviewAssessment.comparisonRate, - }), - ...(reviewAssessment.comparisonTimestamp !== undefined && { - comparisonTimestamp: reviewAssessment.comparisonTimestamp, - }), - }; - if (!reviewAssessment.manualReviewRequired) { - try { - const memoId = this.stellarService.generateMemoId(normalizedCurrency); - if (this.multiSigEnabled) { - // Multi-sig workflow: create request and collect signatures - console.info(`[MarketRateService] Starting multi-sig workflow for ${normalizedCurrency} rate ${rate.rate}`); - const signatureRequest = await multiSigService.createMultiSigRequest(reviewAssessment.reviewRecordId, normalizedCurrency, rate.rate, rate.source, memoId); - // Sign locally first - try { - await multiSigService.signMultiSigPrice(signatureRequest.multiSigPriceId); - console.info(`[MarketRateService] Local signature added for multi-sig request ${signatureRequest.multiSigPriceId}`); - } - catch (error) { - console.error(`[MarketRateService] Failed to sign locally:`, error); - } - // Request signatures from remote servers asynchronously - // (non-blocking - don't wait for completion) - this.requestRemoteSignaturesAsync(signatureRequest.multiSigPriceId, memoId).catch((err) => { - console.error(`[MarketRateService] Error requesting remote signatures:`, err); - }); - // Mark as multi-sig pending (don't submit to Stellar yet) - // The submission will happen via a background job once all signatures are collected - enrichedRate.contractSubmissionSkipped = false; - enrichedRate.pendingMultiSig = true; - enrichedRate.multiSigPriceId = signatureRequest.multiSigPriceId; - } - else { - // Single-sig workflow: submit directly to Stellar - const txHash = await this.stellarService.submitPriceUpdate(normalizedCurrency, rate.rate, memoId); - await priceReviewService.markContractSubmitted(reviewAssessment.reviewRecordId, memoId, txHash); - console.info(`[MarketRateService] Single-sig price update submitted for ${normalizedCurrency}`); - } - } - catch (stellarError) { - console.error("Failed to submit price update to Stellar network:", stellarError); - } - } - else { - console.warn(`Manual review required for ${normalizedCurrency} rate ${rate.rate}. Skipping contract submission.`); - } - this.cache.set(normalizedCurrency, { - rate: enrichedRate, - expiry: new Date(Date.now() + this.CACHE_DURATION_MS), - }); - // Persist to price history for sparkline charts - try { - await prisma.priceHistory.upsert({ - where: { - currency_source_timestamp: { - currency: currency.toUpperCase(), - source: rate.source, - timestamp: rate.timestamp, - }, - }, - update: {}, - create: { - currency: currency.toUpperCase(), - rate: rate.rate, - source: rate.source, - timestamp: rate.timestamp, - }, - }); - } - catch (dbError) { - console.error("Failed to persist price history:", dbError); - } - // Broadcast fresh price to all connected dashboard clients - try { - getIO().emit("price:update", { - currency: normalizedCurrency, - rate: enrichedRate, - }); - if (reviewAssessment.manualReviewRequired) { - getIO().emit("price:review_required", { - currency: normalizedCurrency, - rate: enrichedRate, - }); - } - } - catch { - // Socket not initialized yet (e.g. during tests) - skip silently - } - return { - success: true, - data: enrichedRate, - }; - } - catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : "Unknown error occurred", - }; - } - } - async getAllRates() { - const currencies = Array.from(this.fetchers.keys()); - const promises = currencies.map((currency) => this.getRate(currency)); - return Promise.all(promises); - } - async healthCheck() { - const results = {}; - for (const [currency, fetcher] of this.fetchers) { - try { - results[currency] = await fetcher.isHealthy(); - } - catch { - results[currency] = false; - } - } - return results; - } - getSupportedCurrencies() { - return Array.from(this.fetchers.keys()); - } - async getLatestPrices() { - const results = await this.getAllRates(); - const successfulRates = results - .filter((result) => result.success && result.data) - .map((result) => result.data); - const errorMessages = results - .filter((result) => !result.success) - .map((result) => result.error) - .filter((error) => !!error); - const allSuccessful = successfulRates.length > 0 && errorMessages.length === 0; - return { - success: allSuccessful, - data: successfulRates, - ...(errorMessages.length > 0 && { error: errorMessages[0] }), - ...(errorMessages.length > 0 && { errors: errorMessages }), - }; - } - clearCache() { - this.cache.clear(); - } - async getPendingReviews() { - return priceReviewService.getPendingReviews(); - } - async approvePendingReview(reviewId, reviewedBy, reviewNotes) { - const pendingReview = await priceReviewService.getPendingReviewById(reviewId); - if (!pendingReview) { - throw new Error(`Pending review ${reviewId} was not found`); - } - const memoId = this.stellarService.generateMemoId(pendingReview.currency); - const txHash = await this.stellarService.submitPriceUpdate(pendingReview.currency, pendingReview.rate, memoId); - const approvedReview = await priceReviewService.approveReview({ - reviewId, - memoId, - stellarTxHash: txHash, - ...(reviewedBy !== undefined && { reviewedBy }), - ...(reviewNotes !== undefined && { reviewNotes }), - }); - this.cache.delete(pendingReview.currency.toUpperCase()); - try { - getIO().emit("price:review_resolved", { - action: "approved", - review: approvedReview, - }); - } - catch { - // Socket not initialized yet (e.g. during tests) - skip silently - } - return approvedReview; - } - async rejectPendingReview(reviewId, reviewedBy, reviewNotes) { - const rejectedReview = await priceReviewService.rejectReview({ - reviewId, - ...(reviewedBy !== undefined && { reviewedBy }), - ...(reviewNotes !== undefined && { reviewNotes }), - }); - this.cache.delete(rejectedReview.currency.toUpperCase()); - try { - getIO().emit("price:review_resolved", { - action: "rejected", - review: rejectedReview, - }); - } - catch { - // Socket not initialized yet (e.g. during tests) - skip silently - } - return rejectedReview; - } - getCacheStatus() { - const status = {}; - for (const currency of this.fetchers.keys()) { - const cached = this.cache.get(currency); - if (cached && cached.expiry > new Date()) { - status[currency] = { - cached: true, - expiry: cached.expiry, - }; - } - else { - status[currency] = { - cached: false, - }; - } - } - return status; - } - /** - * Asynchronously request signatures from remote oracle servers. - * This is non-blocking and doesn't wait for completion. - * Errors are logged but don't fail the price fetch operation. - */ - async requestRemoteSignaturesAsync(multiSigPriceId, memoId) { - console.info(`[MarketRateService] Requesting signatures from ${this.remoteOracleServers.length} remote servers for multi-sig ${multiSigPriceId}`); - // Request signatures from all remote servers in parallel - const signatureRequests = this.remoteOracleServers.map((serverUrl) => multiSigService.requestRemoteSignature(multiSigPriceId, serverUrl)); - const results = await Promise.allSettled(signatureRequests); - // Log results for monitoring - results.forEach((result, index) => { - if (result.status === "fulfilled") { - if (result.value.success) { - console.info(`[MarketRateService] ✅ Signature request sent to ${this.remoteOracleServers[index]}`); - } - else { - console.warn(`[MarketRateService] ⚠️ Signature request failed for ${this.remoteOracleServers[index]}: ${result.value.error}`); - } - } - else { - console.error(`[MarketRateService] ❌ Error requesting signature from ${this.remoteOracleServers[index]}:`, result.reason); - } - }); - } -} -//# sourceMappingURL=marketRateService.js.map \ No newline at end of file diff --git a/dist/services/marketRate/marketRateService.js.map b/dist/services/marketRate/marketRateService.js.map deleted file mode 100644 index 3b29fb36..00000000 --- a/dist/services/marketRate/marketRateService.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"marketRateService.js","sourceRoot":"","sources":["../../../src/services/marketRate/marketRateService.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/services/marketRate/ngnFetcher.d.ts b/dist/services/marketRate/ngnFetcher.d.ts deleted file mode 100644 index af1b9474..00000000 --- a/dist/services/marketRate/ngnFetcher.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { MarketRateFetcher, MarketRate } from "./types"; -/** - * NGN/XLM rate fetcher. - * - * Primary path uses VTpass {@link https://www.vtpass.com/documentation/variation-codes/ service-variations} - * to read a configured variation's `variation_amount` as the Naira price for one unit of the underlying - * SKU (configure a 1 USD/BUSD reference variation so `variation_amount` ≈ NGN per USD). That value is - * multiplied by CoinGecko XLM/USD for NGN per XLM. - * - * Falls back to CoinGecko XLM/NGN directly, then XLM/USD × USD→NGN (open.er-api), matching other fetchers. - */ -export declare class NGNRateFetcher implements MarketRateFetcher { - private readonly coinGeckoUrl; - private readonly usdToNgnUrl; - private vtpassBase; - private vtpassHeaders; - getCurrency(): string; - private fetchNgnPerUsdFromVtpass; - fetchRate(): Promise; - isHealthy(): Promise; -} -//# sourceMappingURL=ngnFetcher.d.ts.map \ No newline at end of file diff --git a/dist/services/marketRate/ngnFetcher.d.ts.map b/dist/services/marketRate/ngnFetcher.d.ts.map deleted file mode 100644 index 26da90d8..00000000 --- a/dist/services/marketRate/ngnFetcher.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ngnFetcher.d.ts","sourceRoot":"","sources":["../../../src/services/marketRate/ngnFetcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAmC,MAAM,SAAS,CAAC;AAwCzF;;;;;;;;;GASG;AACH,qBAAa,cAAe,YAAW,iBAAiB;IACtD,OAAO,CAAC,QAAQ,CAAC,YAAY,CACoF;IAEjH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA2C;IAEvE,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,aAAa;IAYrB,WAAW,IAAI,MAAM;YAIP,wBAAwB;IAyChC,SAAS,IAAI,OAAO,CAAC,UAAU,CAAC;IAsJhC,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;CAQpC"} \ No newline at end of file diff --git a/dist/services/marketRate/ngnFetcher.js b/dist/services/marketRate/ngnFetcher.js deleted file mode 100644 index 28151db3..00000000 --- a/dist/services/marketRate/ngnFetcher.js +++ /dev/null @@ -1,191 +0,0 @@ -import axios from "axios"; -import { calculateMedian, filterOutliers } from "./types"; -function parseAmount(value) { - if (value == null) - return null; - const n = Number.parseFloat(String(value).replace(/,/g, "")); - if (!Number.isFinite(n) || n <= 0) - return null; - return n; -} -/** - * NGN/XLM rate fetcher. - * - * Primary path uses VTpass {@link https://www.vtpass.com/documentation/variation-codes/ service-variations} - * to read a configured variation's `variation_amount` as the Naira price for one unit of the underlying - * SKU (configure a 1 USD/BUSD reference variation so `variation_amount` ≈ NGN per USD). That value is - * multiplied by CoinGecko XLM/USD for NGN per XLM. - * - * Falls back to CoinGecko XLM/NGN directly, then XLM/USD × USD→NGN (open.er-api), matching other fetchers. - */ -export class NGNRateFetcher { - coinGeckoUrl = "https://api.coingecko.com/api/v3/simple/price?ids=stellar&vs_currencies=ngn,usd&include_last_updated_at=true"; - usdToNgnUrl = "https://open.er-api.com/v6/latest/USD"; - vtpassBase() { - return (process.env.VTPASS_API_BASE_URL ?? "https://vtpass.com/api").replace(/\/$/, ""); - } - vtpassHeaders() { - const apiKey = process.env.VTPASS_API_KEY; - const publicKey = process.env.VTPASS_PUBLIC_KEY; - if (apiKey && publicKey) { - return { - "api-key": apiKey, - "public-key": publicKey, - }; - } - return undefined; - } - getCurrency() { - return "NGN"; - } - async fetchNgnPerUsdFromVtpass() { - const serviceId = process.env.VTPASS_NGN_SERVICE_ID?.trim(); - const variationCode = process.env.VTPASS_NGN_VARIATION_CODE?.trim(); - if (!serviceId || !variationCode) - return null; - const headers = this.vtpassHeaders(); - if (!headers) - return null; - const response = await axios.get(`${this.vtpassBase()}/service-variations`, { - params: { serviceID: serviceId }, - timeout: 15000, - headers: { - ...headers, - "User-Agent": "StellarFlow-Oracle/1.0", - }, - }); - if (response.data.response_description !== "000") { - return null; - } - const variations = response.data.content?.variations ?? []; - const match = variations.find((v) => v.variation_code === variationCode); - if (!match) - return null; - const rateFromField = parseAmount(match.variation_rate); - const amount = parseAmount(match.variation_amount); - const ngnPerUsd = rateFromField ?? amount; - if (ngnPerUsd == null) - return null; - return { ngnPerUsd, timestamp: new Date() }; - } - async fetchRate() { - const prices = []; - // Strategy 1: VTpass NGN-per-USD (variation) × CoinGecko XLM/USD - try { - const vt = await this.fetchNgnPerUsdFromVtpass(); - if (vt) { - const coinGeckoResponse = await axios.get(this.coinGeckoUrl, { - timeout: 10000, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - }, - }); - const usd = coinGeckoResponse.data.stellar?.usd; - if (typeof usd === "number" && usd > 0) { - const lastUpdatedAt = coinGeckoResponse.data.stellar?.last_updated_at - ? new Date(coinGeckoResponse.data.stellar.last_updated_at * 1000) - : new Date(); - const ts = vt.timestamp > lastUpdatedAt ? vt.timestamp : lastUpdatedAt; - prices.push({ - rate: usd * vt.ngnPerUsd, - timestamp: ts, - source: "VTpass variation + CoinGecko (XLM/USD)", - trustLevel: "new", - }); - } - } - } - catch { - console.debug("VTpass + CoinGecko XLM/USD failed"); - } - // Strategy 2: CoinGecko direct XLM/NGN - try { - const coinGeckoResponse = await axios.get(this.coinGeckoUrl, { - timeout: 10000, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - }, - }); - const stellarPrice = coinGeckoResponse.data.stellar; - if (stellarPrice && - typeof stellarPrice.ngn === "number" && - stellarPrice.ngn > 0) { - const lastUpdatedAt = stellarPrice.last_updated_at - ? new Date(stellarPrice.last_updated_at * 1000) - : new Date(); - prices.push({ - rate: stellarPrice.ngn, - timestamp: lastUpdatedAt, - source: "CoinGecko (direct NGN)", - trustLevel: "standard", - }); - } - } - catch { - console.debug("CoinGecko direct NGN failed"); - } - // Strategy 3: CoinGecko XLM/USD × USD/NGN (open.er-api) - try { - const coinGeckoResponse = await axios.get(this.coinGeckoUrl, { - timeout: 10000, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - }, - }); - const stellarPrice = coinGeckoResponse.data.stellar; - if (stellarPrice && - typeof stellarPrice.usd === "number" && - stellarPrice.usd > 0) { - const fxResponse = await axios.get(this.usdToNgnUrl, { - timeout: 10000, - headers: { - "User-Agent": "StellarFlow-Oracle/1.0", - }, - }); - const usdToNgn = fxResponse.data.rates?.NGN; - if (fxResponse.data.result === "success" && - typeof usdToNgn === "number" && - usdToNgn > 0) { - const fxTimestamp = fxResponse.data.time_last_update_unix - ? new Date(fxResponse.data.time_last_update_unix * 1000) - : new Date(); - const lastUpdatedAt = stellarPrice.last_updated_at - ? new Date(stellarPrice.last_updated_at * 1000) - : new Date(); - prices.push({ - rate: stellarPrice.usd * usdToNgn, - timestamp: fxTimestamp > lastUpdatedAt ? fxTimestamp : lastUpdatedAt, - source: "CoinGecko + ExchangeRate API (USD→NGN)", - trustLevel: "trusted", - }); - } - } - } - catch { - console.debug("CoinGecko + ExchangeRate API (NGN) failed"); - } - if (prices.length > 0) { - let rateValues = prices.map((p) => p.rate).filter(p => p > 0); - rateValues = filterOutliers(rateValues); - const medianRate = calculateMedian(rateValues); - const mostRecentTimestamp = prices.reduce((latest, p) => (p.timestamp > latest ? p.timestamp : latest), prices[0]?.timestamp ?? new Date()); - return { - currency: "NGN", - rate: weightedRate, - timestamp: mostRecentTimestamp, - source: `Median of ${prices.length} sources (outliers filtered)`, - }; - } - throw new Error("All NGN rate sources failed"); - } - async isHealthy() { - try { - const rate = await this.fetchRate(); - return rate.rate > 0; - } - catch { - return false; - } - } -} -//# sourceMappingURL=ngnFetcher.js.map \ No newline at end of file diff --git a/dist/services/marketRate/ngnFetcher.js.map b/dist/services/marketRate/ngnFetcher.js.map deleted file mode 100644 index ff763170..00000000 --- a/dist/services/marketRate/ngnFetcher.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"ngnFetcher.js","sourceRoot":"","sources":["../../../src/services/marketRate/ngnFetcher.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/services/marketRate/types.d.ts b/dist/services/marketRate/types.d.ts deleted file mode 100644 index df83de66..00000000 --- a/dist/services/marketRate/types.d.ts +++ /dev/null @@ -1,137 +0,0 @@ -/** - * Market Rate Interface - * Represents the fetched exchange rate data - */ -export interface MarketRate { - currency: string; - rate: number; - timestamp: Date; - source: string; - manualReviewRequired?: boolean; - reviewId?: number; - reviewReason?: string; - reviewChangePercent?: number; - comparisonRate?: number; - comparisonTimestamp?: Date; - contractSubmissionSkipped?: boolean; - pendingMultiSig?: boolean; - multiSigPriceId?: number; -} -/** - * Market Rate Fetcher Interface - * Contract for all currency rate fetcher implementations - */ -export interface MarketRateFetcher { - /** - * Get the currency code this fetcher handles - */ - getCurrency(): string; - /** - * Fetch the current exchange rate - * @throws Error if all rate sources fail - */ - fetchRate(): Promise; - /** - * Check if the fetcher is healthy and can reach its sources - */ - isHealthy(): Promise; -} -/** - * Rate Source Configuration - * Represents an external API source for exchange rates - */ -export interface RateSource { - name: string; - url: string; - apiKey?: string; -} -/** - * Fetcher Response Wrapper - * Standardized response format for rate fetcher operations - */ -export interface FetcherResponse { - success: boolean; - data?: MarketRate; - error?: string; -} -/** - * Aggregated Response for multiple fetchers - * Used when fetching rates from multiple currency sources - */ -export interface AggregatedFetcherResponse { - success: boolean; - data?: MarketRate[]; - error?: string; - errors?: string[]; -} -/** - * Rate Fetch Error - * Detailed error information for failed rate fetches - */ -export interface RateFetchError { - source: string; - message: string; - timestamp: Date; - retryable?: boolean; -} -/** - * Circuit Breaker State - * Represents the state of a circuit breaker - */ -export declare enum CircuitBreakerState { - CLOSED = "CLOSED", - OPEN = "OPEN", - HALF_OPEN = "HALF_OPEN" -} -/** - * Health Check Response - * Standardized health check response - */ -export interface HealthCheckResponse { - healthy: boolean; - lastChecked: Date; - latencyMs?: number; - error?: string; -} -/** - * Source trust tier used when weighting multi-source rates. - */ -export type SourceTrustLevel = "trusted" | "standard" | "new"; -/** - * Calculate the median of an array of numbers - * This helps prevent a single bad API from ruining the data - * @param values - Array of price numbers from different sources - * @returns The median value - */ -export declare function calculateMedian(values: number[]): number; -/** - * Calculate the simple average (arithmetic mean) of an array of numbers. - * Used to produce one final price from multiple source prices (e.g. NGN). - * @param prices - Array of price numbers from different sources - * @returns The arithmetic mean, or 0 for an empty array - */ -export declare function calculateAverage(prices: number[]): number; -export interface WeightedPriceInput { - value: number; - trustLevel?: SourceTrustLevel; - weight?: number; -} -/** - * Calculate weighted average from source values. - * Use explicit `weight` when provided, otherwise derive by trust level. - */ -export declare function calculateWeightedAverage(values: WeightedPriceInput[]): number; -/** - * Rate Fetch Statistics - * Performance and reliability metrics - */ -export { filterOutliers, isOutlier, percentDeviation } from '../../logic/outlierFilter'; -export interface RateFetchStats { - totalRequests: number; - successfulRequests: number; - failedRequests: number; - averageLatencyMs: number; - lastSuccessfulFetch?: Date; - lastFailedFetch?: Date; -} -//# sourceMappingURL=types.d.ts.map \ No newline at end of file diff --git a/dist/services/marketRate/types.d.ts.map b/dist/services/marketRate/types.d.ts.map deleted file mode 100644 index 2f0bcebe..00000000 --- a/dist/services/marketRate/types.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/marketRate/types.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/services/marketRate/types.js b/dist/services/marketRate/types.js deleted file mode 100644 index 004146c3..00000000 --- a/dist/services/marketRate/types.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Circuit Breaker State - * Represents the state of a circuit breaker - */ -export var CircuitBreakerState; -(function (CircuitBreakerState) { - CircuitBreakerState["CLOSED"] = "CLOSED"; - CircuitBreakerState["OPEN"] = "OPEN"; - CircuitBreakerState["HALF_OPEN"] = "HALF_OPEN"; -})(CircuitBreakerState || (CircuitBreakerState = {})); -/** - * Calculate the median of an array of numbers - * This helps prevent a single bad API from ruining the data - * @param values - Array of price numbers from different sources - * @returns The median value - */ -export function calculateMedian(values) { - if (values.length === 0) - return 0; - const sorted = [...values].sort((a, b) => a - b); - const middle = Math.floor(sorted.length / 2); - if (sorted.length % 2 === 0) { - const mid1 = sorted[middle - 1]; - const mid2 = sorted[middle]; - if (mid1 !== undefined && mid2 !== undefined) { - return (mid1 + mid2) / 2; - } - return mid2 ?? mid1 ?? 0; - } - return sorted[middle] ?? 0; -} -/** - * Calculate the simple average (arithmetic mean) of an array of numbers. - * Used to produce one final price from multiple source prices (e.g. NGN). - * @param prices - Array of price numbers from different sources - * @returns The arithmetic mean, or 0 for an empty array - */ -export function calculateAverage(prices) { - if (prices.length === 0) - return 0; - const sum = prices.reduce((acc, price) => acc + price, 0); - return sum / prices.length; -} -const SOURCE_TRUST_WEIGHTS = { - trusted: 3, - standard: 2, - new: 1, -}; -/** - * Calculate weighted average from source values. - * Use explicit `weight` when provided, otherwise derive by trust level. - */ -export function calculateWeightedAverage(values) { - if (values.length === 0) - return 0; - let weightedSum = 0; - let totalWeight = 0; - for (const value of values) { - const trustWeight = SOURCE_TRUST_WEIGHTS[value.trustLevel ?? "standard"]; - const weight = typeof value.weight === "number" && Number.isFinite(value.weight) && value.weight > 0 - ? value.weight - : trustWeight; - weightedSum += value.value * weight; - totalWeight += weight; - } - if (totalWeight === 0) - return 0; - return weightedSum / totalWeight; -} -/** - * Rate Fetch Statistics - * Performance and reliability metrics - */ -export { filterOutliers, isOutlier, percentDeviation } from '../../logic/outlierFilter'; -//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/dist/services/marketRate/types.js.map b/dist/services/marketRate/types.js.map deleted file mode 100644 index bfb4f627..00000000 --- a/dist/services/marketRate/types.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/marketRate/types.ts"],"names":[],"mappings":"AAqFA;;;GAGG;AACH,MAAM,CAAN,IAAY,mBAIX;AAJD,WAAY,mBAAmB;IAC7B,wCAAiB,CAAA;IACjB,oCAAa,CAAA;IACb,8CAAuB,CAAA;AACzB,CAAC,EAJW,mBAAmB,KAAnB,mBAAmB,QAI9B;AAkBD;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,MAAgB;IAC9C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAElC,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE7C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAC7C,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAgB;IAC/C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAElC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;IAC1D,OAAO,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;AAC7B,CAAC;AAQD,MAAM,oBAAoB,GAAqC;IAC7D,OAAO,EAAE,CAAC;IACV,QAAQ,EAAE,CAAC;IACX,GAAG,EAAE,CAAC;CACP,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAA4B;IACnE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAElC,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,WAAW,GAAG,oBAAoB,CAAC,KAAK,CAAC,UAAU,IAAI,UAAU,CAAC,CAAC;QACzE,MAAM,MAAM,GACV,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YACnF,CAAC,CAAC,KAAK,CAAC,MAAM;YACd,CAAC,CAAC,WAAW,CAAC;QAElB,WAAW,IAAI,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC;QACpC,WAAW,IAAI,MAAM,CAAC;IACxB,CAAC;IAED,IAAI,WAAW,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAChC,OAAO,WAAW,GAAG,WAAW,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC"} \ No newline at end of file diff --git a/dist/services/multiSigService.d.ts b/dist/services/multiSigService.d.ts deleted file mode 100644 index a1be54b9..00000000 --- a/dist/services/multiSigService.d.ts +++ /dev/null @@ -1,89 +0,0 @@ -export interface SignatureRequest { - multiSigPriceId: number; - currency: string; - rate: number; - source: string; - memoId: string; - requiredSignatures: number; -} -export interface SignaturePayload { - multiSigPriceId: number; - currency: string; - rate: number; - source: string; - memoId: string; - signerPublicKey: string; -} -export declare class MultiSigService { - private localSignerPublicKey; - private localSignerSecret; - private signerName; - private readonly SIGNATURE_EXPIRY_MS; - private readonly REQUIRED_SIGNATURES; - constructor(); - /** - * Create a multi-sig price update request. - * This initiates the process where the price needs to be signed by multiple servers. - */ - createMultiSigRequest(priceReviewId: number, currency: string, rate: number, source: string, memoId: string): Promise; - /** - * Sign a multi-sig price update locally. - * This creates a signature from the current server instance and records it. - */ - signMultiSigPrice(multiSigPriceId: number): Promise<{ - signature: string; - signerPublicKey: string; - }>; - /** - * Request a signature from a remote server. - * Sends an HTTP request to a peer server to sign the price update. - */ - requestRemoteSignature(multiSigPriceId: number, remoteServerUrl: string): Promise<{ - success: boolean; - error?: string; - }>; - /** - * Get a pending multi-sig price by ID. - * Returns the price details and current signature status. - */ - getMultiSigPrice(multiSigPriceId: number): Promise; - /** - * Get all pending multi-sig prices. - * Useful for monitoring and checking expiration. - */ - getPendingMultiSigPrices(): Promise; - /** - * Clean up expired multi-sig prices. - * Should be called periodically by a background job. - */ - cleanupExpiredRequests(): Promise; - /** - * Mark a multi-sig price as approved (all signatures collected). - * This happens automatically when all required signatures are collected. - */ - private approveMultiSigPrice; - /** - * Get all signatures for a multi-sig price. - * Returns the signatures needed for submitting to Stellar. - */ - getSignatures(multiSigPriceId: number): Promise; - /** - * Mark a multi-sig price as submitted to Stellar. - * Records the transaction hash and memo ID. - */ - recordSubmission(multiSigPriceId: number, memoId: string, stellarTxHash: string): Promise; - /** - * Create a deterministic message for signing. - * Must be consistent across all servers to ensure valid multi-sig. - */ - private createSignatureMessage; - /** - * Get this server's signer identity. - */ - getLocalSignerInfo(): { - publicKey: string; - name: string; - }; -} -export declare const multiSigService: MultiSigService; -//# sourceMappingURL=multiSigService.d.ts.map \ No newline at end of file diff --git a/dist/services/multiSigService.d.ts.map b/dist/services/multiSigService.d.ts.map deleted file mode 100644 index 9b176f51..00000000 --- a/dist/services/multiSigService.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"multiSigService.d.ts","sourceRoot":"","sources":["../../src/services/multiSigService.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAW;IAC/C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAK;;IAuBzC;;;OAGG;IACG,qBAAqB,CACzB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,gBAAgB,CAAC;IA8B5B;;;OAGG;IACG,iBAAiB,CACrB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IAwE1D;;;OAGG;IACG,sBAAsB,CAC1B,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAmFhD;;;OAGG;IACG,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAkB7D;;;OAGG;IACG,wBAAwB,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAgBhD;;;OAGG;IACG,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC;IAqB/C;;;OAGG;YACW,oBAAoB;IAalC;;;OAGG;IACG,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAQ5D;;;OAGG;IACG,gBAAgB,CACpB,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;IAehB;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;OAEG;IACH,kBAAkB,IAAI;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;KACd;CAMF;AAGD,eAAO,MAAM,eAAe,iBAAwB,CAAC"} \ No newline at end of file diff --git a/dist/services/multiSigService.js b/dist/services/multiSigService.js deleted file mode 100644 index 45955858..00000000 --- a/dist/services/multiSigService.js +++ /dev/null @@ -1,302 +0,0 @@ -import prisma from "../lib/prisma"; -import { Keypair } from "@stellar/stellar-sdk"; -import dotenv from "dotenv"; -dotenv.config(); -export class MultiSigService { - localSignerPublicKey; - localSignerSecret; - signerName; - SIGNATURE_EXPIRY_MS = 3600000; // 1 hour - REQUIRED_SIGNATURES = 2; // Default: 2 signatures needed - constructor() { - const secret = process.env.ORACLE_SECRET_KEY || process.env.SOROBAN_ADMIN_SECRET; - if (!secret) { - throw new Error("ORACLE_SECRET_KEY or SOROBAN_ADMIN_SECRET not found in environment variables"); - } - this.localSignerSecret = secret; - this.localSignerPublicKey = Keypair.fromSecret(secret).publicKey(); - this.signerName = process.env.ORACLE_SIGNER_NAME || "oracle-server"; - const requiredSigs = process.env.MULTI_SIG_REQUIRED_COUNT; - if (requiredSigs) { - const parsed = parseInt(requiredSigs, 10); - if (!isNaN(parsed) && parsed > 0) { - this.REQUIRED_SIGNATURES = parsed; - } - } - } - /** - * Create a multi-sig price update request. - * This initiates the process where the price needs to be signed by multiple servers. - */ - async createMultiSigRequest(priceReviewId, currency, rate, source, memoId) { - const expiresAt = new Date(Date.now() + this.SIGNATURE_EXPIRY_MS); - const created = await prisma.multiSigPrice.create({ - data: { - priceReviewId, - currency, - rate, - source, - status: "PENDING", - requiredSignatures: this.REQUIRED_SIGNATURES, - collectedSignatures: 0, - expiresAt, - }, - }); - console.info(`[MultiSig] Created signature request ${created.id} for ${currency} rate ${rate}`); - return { - multiSigPriceId: created.id, - currency, - rate, - source, - memoId, - requiredSignatures: this.REQUIRED_SIGNATURES, - }; - } - /** - * Sign a multi-sig price update locally. - * This creates a signature from the current server instance and records it. - */ - async signMultiSigPrice(multiSigPriceId) { - // Fetch the multi-sig price record - const multiSigPrice = await prisma.multiSigPrice.findUnique({ - where: { id: multiSigPriceId }, - }); - if (!multiSigPrice) { - throw new Error(`MultiSigPrice ${multiSigPriceId} not found`); - } - if (multiSigPrice.status !== "PENDING") { - throw new Error(`Cannot sign MultiSigPrice ${multiSigPriceId} - status is ${multiSigPrice.status}`); - } - if (new Date() > multiSigPrice.expiresAt) { - // Mark as expired - await prisma.multiSigPrice.update({ - where: { id: multiSigPriceId }, - data: { status: "EXPIRED" }, - }); - throw new Error(`MultiSigPrice ${multiSigPriceId} has expired`); - } - // Create a deterministic signature message based on the price data - const signatureMessage = this.createSignatureMessage(multiSigPrice.currency, multiSigPrice.rate.toString(), multiSigPrice.source); - // Sign the message - const keypair = Keypair.fromSecret(this.localSignerSecret); - // Convert message to buffer and sign - const messageBuffer = Buffer.from(signatureMessage, "utf-8"); - const signatureBuffer = keypair.sign(messageBuffer); - const signature = signatureBuffer.toString("hex"); - // Record the signature - await prisma.multiSigSignature.create({ - data: { - multiSigPriceId, - signerPublicKey: this.localSignerPublicKey, - signerName: this.signerName, - signature, - }, - }); - // Increment the collected signatures count - const updated = await prisma.multiSigPrice.update({ - where: { id: multiSigPriceId }, - data: { - collectedSignatures: { - increment: 1, - }, - }, - }); - console.info(`[MultiSig] Added signature ${updated.collectedSignatures}/${updated.requiredSignatures} for MultiSigPrice ${multiSigPriceId}`); - // If we have all required signatures, mark as approved - if (updated.collectedSignatures >= updated.requiredSignatures) { - await this.approveMultiSigPrice(multiSigPriceId); - } - return { signature, signerPublicKey: this.localSignerPublicKey }; - } - /** - * Request a signature from a remote server. - * Sends an HTTP request to a peer server to sign the price update. - */ - async requestRemoteSignature(multiSigPriceId, remoteServerUrl) { - try { - const multiSigPrice = await prisma.multiSigPrice.findUnique({ - where: { id: multiSigPriceId }, - }); - if (!multiSigPrice) { - return { - success: false, - error: `MultiSigPrice ${multiSigPriceId} not found`, - }; - } - const payload = { - multiSigPriceId, - currency: multiSigPrice.currency, - rate: multiSigPrice.rate.toNumber(), - source: multiSigPrice.source, - memoId: multiSigPrice.memoId || "", - signerPublicKey: this.localSignerPublicKey, - }; - // Make HTTP request to remote server - const response = await fetch(`${remoteServerUrl}/api/price-updates/sign`, { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${process.env.MULTI_SIG_AUTH_TOKEN || ""}`, - }, - body: JSON.stringify(payload), - }); - if (!response.ok) { - const error = await response.text().catch(() => response.statusText); - return { success: false, error: `Remote server error: ${error}` }; - } - const result = await response.json(); - if (result.signature && result.signerPublicKey) { - // Record the remote signature - await prisma.multiSigSignature.create({ - data: { - multiSigPriceId, - signerPublicKey: result.signerPublicKey, - signerName: result.signerName || "remote-signer", - signature: result.signature, - }, - }).catch((err) => { - // Ignore duplicate signers - if (err.code !== "P2002") - throw err; - }); - // Increment collected signatures - const updated = await prisma.multiSigPrice.update({ - where: { id: multiSigPriceId }, - data: { - collectedSignatures: { - increment: 1, - }, - }, - }); - console.info(`[MultiSig] Added remote signature ${updated.collectedSignatures}/${updated.requiredSignatures} for MultiSigPrice ${multiSigPriceId}`); - // Check if all signatures are collected - if (updated.collectedSignatures >= updated.requiredSignatures) { - await this.approveMultiSigPrice(multiSigPriceId); - } - } - return { success: true }; - } - catch (error) { - console.error(`[MultiSig] Failed to request signature from ${remoteServerUrl}:`, error); - return { success: false, error: String(error) }; - } - } - /** - * Get a pending multi-sig price by ID. - * Returns the price details and current signature status. - */ - async getMultiSigPrice(multiSigPriceId) { - const multiSigPrice = await prisma.multiSigPrice.findUnique({ - where: { id: multiSigPriceId }, - include: { - multiSigSignatures: { - select: { - signerPublicKey: true, - signerName: true, - signature: true, - signedAt: true, - }, - }, - }, - }); - return multiSigPrice; - } - /** - * Get all pending multi-sig prices. - * Useful for monitoring and checking expiration. - */ - async getPendingMultiSigPrices() { - return await prisma.multiSigPrice.findMany({ - where: { status: "PENDING" }, - include: { - multiSigSignatures: { - select: { - signerPublicKey: true, - signerName: true, - signedAt: true, - }, - }, - }, - orderBy: { requestedAt: "desc" }, - }); - } - /** - * Clean up expired multi-sig prices. - * Should be called periodically by a background job. - */ - async cleanupExpiredRequests() { - const now = new Date(); - const result = await prisma.multiSigPrice.updateMany({ - where: { - status: "PENDING", - expiresAt: { lt: now }, - }, - data: { - status: "EXPIRED", - }, - }); - if (result.count > 0) { - console.warn(`[MultiSig] Expired ${result.count} multi-sig price requests`); - } - return result.count; - } - /** - * Mark a multi-sig price as approved (all signatures collected). - * This happens automatically when all required signatures are collected. - */ - async approveMultiSigPrice(multiSigPriceId) { - await prisma.multiSigPrice.update({ - where: { id: multiSigPriceId }, - data: { - status: "APPROVED", - }, - }); - console.info(`[MultiSig] MultiSigPrice ${multiSigPriceId} is now APPROVED (all signatures collected)`); - } - /** - * Get all signatures for a multi-sig price. - * Returns the signatures needed for submitting to Stellar. - */ - async getSignatures(multiSigPriceId) { - const signatures = await prisma.multiSigSignature.findMany({ - where: { multiSigPriceId }, - }); - return signatures; - } - /** - * Mark a multi-sig price as submitted to Stellar. - * Records the transaction hash and memo ID. - */ - async recordSubmission(multiSigPriceId, memoId, stellarTxHash) { - await prisma.multiSigPrice.update({ - where: { id: multiSigPriceId }, - data: { - memoId, - stellarTxHash, - submittedAt: new Date(), - }, - }); - console.info(`[MultiSig] MultiSigPrice ${multiSigPriceId} submitted to Stellar - TxHash: ${stellarTxHash}`); - } - /** - * Create a deterministic message for signing. - * Must be consistent across all servers to ensure valid multi-sig. - */ - createSignatureMessage(currency, rate, source) { - // Create a deterministic message format - // Format: "SF-PRICE---" - return `SF-PRICE-${currency}-${rate}-${source}`; - } - /** - * Get this server's signer identity. - */ - getLocalSignerInfo() { - return { - publicKey: this.localSignerPublicKey, - name: this.signerName, - }; - } -} -// Export singleton instance -export const multiSigService = new MultiSigService(); -//# sourceMappingURL=multiSigService.js.map \ No newline at end of file diff --git a/dist/services/multiSigService.js.map b/dist/services/multiSigService.js.map deleted file mode 100644 index c79ea70b..00000000 --- a/dist/services/multiSigService.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"multiSigService.js","sourceRoot":"","sources":["../../src/services/multiSigService.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/services/multiSigSubmissionService.d.ts b/dist/services/multiSigSubmissionService.d.ts deleted file mode 100644 index d8c232c2..00000000 --- a/dist/services/multiSigSubmissionService.d.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * MultiSigSubmissionService - * Handles the automatic submission of approved multi-sig prices to Stellar. - * Runs as a background job/scheduler. - */ -export declare class MultiSigSubmissionService { - private stellarService; - private pollIntervalMs; - private isRunning; - private pollTimer; - constructor(pollIntervalMs?: number); - /** - * Start the background submission service. - * This will periodically check for approved multi-sig prices and submit them to Stellar. - */ - start(): Promise; - /** - * Stop the background submission service. - */ - stop(): void; - /** - * Check for approved multi-sig prices and submit them to Stellar. - * This is the main polling function. - */ - private checkAndSubmitApprovedPrices; - /** - * Submit a single approved multi-sig price to Stellar. - */ - private submitApprovedPrice; - /** - * Cleanup expired multi-sig requests. - * Can be called manually or as part of a scheduled maintenance task. - */ - cleanupExpired(): Promise; - /** - * Get status of the background service. - */ - getStatus(): { - isRunning: boolean; - pollIntervalMs: number; - }; -} -export declare const multiSigSubmissionService: MultiSigSubmissionService; -//# sourceMappingURL=multiSigSubmissionService.d.ts.map \ No newline at end of file diff --git a/dist/services/multiSigSubmissionService.d.ts.map b/dist/services/multiSigSubmissionService.d.ts.map deleted file mode 100644 index c1925285..00000000 --- a/dist/services/multiSigSubmissionService.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"multiSigSubmissionService.d.ts","sourceRoot":"","sources":["../../src/services/multiSigSubmissionService.ts"],"names":[],"mappings":"AAQA;;;;GAIG;AACH,qBAAa,yBAAyB;IACpC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,SAAS,CAA+C;gBAEpD,cAAc,GAAE,MAAc;IAK1C;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA2B5B;;OAEG;IACH,IAAI,IAAI,IAAI;IASZ;;;OAGG;YACW,4BAA4B;IA8C1C;;OAEG;YACW,mBAAmB;IAsDjC;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAkBvC;;OAEG;IACH,SAAS,IAAI;QACX,SAAS,EAAE,OAAO,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;KACxB;CAMF;AAGD,eAAO,MAAM,yBAAyB,2BAAkC,CAAC"} \ No newline at end of file diff --git a/dist/services/multiSigSubmissionService.js b/dist/services/multiSigSubmissionService.js deleted file mode 100644 index bf4b79fe..00000000 --- a/dist/services/multiSigSubmissionService.js +++ /dev/null @@ -1,150 +0,0 @@ -import { multiSigService } from "./multiSigService"; -import { StellarService } from "./stellarService"; -import { priceReviewService } from "./priceReviewService"; -import prisma from "../lib/prisma"; -import dotenv from "dotenv"; -dotenv.config(); -/** - * MultiSigSubmissionService - * Handles the automatic submission of approved multi-sig prices to Stellar. - * Runs as a background job/scheduler. - */ -export class MultiSigSubmissionService { - stellarService; - pollIntervalMs; - isRunning = false; - pollTimer = null; - constructor(pollIntervalMs = 30000) { - this.stellarService = new StellarService(); - this.pollIntervalMs = pollIntervalMs; - } - /** - * Start the background submission service. - * This will periodically check for approved multi-sig prices and submit them to Stellar. - */ - async start() { - if (this.isRunning) { - console.warn("[MultiSigSubmissionService] Service is already running"); - return; - } - this.isRunning = true; - console.info(`[MultiSigSubmissionService] Started with ${this.pollIntervalMs}ms poll interval`); - // Initial check - await this.checkAndSubmitApprovedPrices(); - // Start periodic polling - this.pollTimer = setInterval(() => { - this.checkAndSubmitApprovedPrices().catch((err) => { - console.error("[MultiSigSubmissionService] Polling error:", err); - }); - }, this.pollIntervalMs); - } - /** - * Stop the background submission service. - */ - stop() { - if (this.pollTimer) { - clearInterval(this.pollTimer); - this.pollTimer = null; - } - this.isRunning = false; - console.info("[MultiSigSubmissionService] Stopped"); - } - /** - * Check for approved multi-sig prices and submit them to Stellar. - * This is the main polling function. - */ - async checkAndSubmitApprovedPrices() { - try { - // Find all approved multi-sig prices that haven't been submitted yet - const approvedPrices = await prisma.multiSigPrice.findMany({ - where: { - status: "APPROVED", - submittedAt: null, // Not yet submitted to Stellar - }, - include: { - multiSigSignatures: { - select: { - signature: true, - signerPublicKey: true, - }, - }, - }, - }); - if (approvedPrices.length === 0) { - return; // Nothing to do - } - console.info(`[MultiSigSubmissionService] Found ${approvedPrices.length} approved prices to submit`); - // Process each approved price - for (const multiSigPrice of approvedPrices) { - try { - await this.submitApprovedPrice(multiSigPrice); - } - catch (error) { - console.error(`[MultiSigSubmissionService] Failed to submit multi-sig price ${multiSigPrice.id}:`, error); - // Continue with next price, don't let one failure block others - } - } - } - catch (error) { - console.error("[MultiSigSubmissionService] Error checking approved prices:", error); - } - } - /** - * Submit a single approved multi-sig price to Stellar. - */ - async submitApprovedPrice(multiSigPrice) { - try { - // Prepare signatures for submission - const signatures = multiSigPrice.multiSigSignatures.map((sig) => ({ - signerPublicKey: sig.signerPublicKey, - signature: sig.signature, - })); - if (signatures.length === 0) { - console.warn(`[MultiSigSubmissionService] No signatures found for multi-sig price ${multiSigPrice.id}`); - return; - } - console.info(`[MultiSigSubmissionService] Submitting multi-sig price ${multiSigPrice.id} (${multiSigPrice.currency} @ ${multiSigPrice.rate}) with ${signatures.length} signatures`); - // Submit to Stellar with multiple signatures - const memoId = multiSigPrice.memoId || `MS-${multiSigPrice.id}`; - const txHash = await this.stellarService.submitMultiSignedPriceUpdate(multiSigPrice.currency, multiSigPrice.rate.toNumber(), memoId, signatures); - // Record the submission - await multiSigService.recordSubmission(multiSigPrice.id, memoId, txHash); - // Mark the associated price review as submitted - await priceReviewService.markContractSubmitted(multiSigPrice.priceReviewId, memoId, txHash); - console.info(`[MultiSigSubmissionService] ✅ Successfully submitted multi-sig price ${multiSigPrice.id} - TxHash: ${txHash}`); - } - catch (error) { - console.error(`[MultiSigSubmissionService] Error submitting multi-sig price ${multiSigPrice.id}:`, error); - throw error; - } - } - /** - * Cleanup expired multi-sig requests. - * Can be called manually or as part of a scheduled maintenance task. - */ - async cleanupExpired() { - try { - const count = await multiSigService.cleanupExpiredRequests(); - if (count > 0) { - console.info(`[MultiSigSubmissionService] Cleaned up ${count} expired multi-sig requests`); - } - return count; - } - catch (error) { - console.error("[MultiSigSubmissionService] Error during cleanup:", error); - return 0; - } - } - /** - * Get status of the background service. - */ - getStatus() { - return { - isRunning: this.isRunning, - pollIntervalMs: this.pollIntervalMs, - }; - } -} -// Export singleton instance -export const multiSigSubmissionService = new MultiSigSubmissionService(); -//# sourceMappingURL=multiSigSubmissionService.js.map \ No newline at end of file diff --git a/dist/services/multiSigSubmissionService.js.map b/dist/services/multiSigSubmissionService.js.map deleted file mode 100644 index 5f158b77..00000000 --- a/dist/services/multiSigSubmissionService.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"multiSigSubmissionService.js","sourceRoot":"","sources":["../../src/services/multiSigSubmissionService.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/services/priceProtection.d.ts b/dist/services/priceProtection.d.ts deleted file mode 100644 index 0662d4c4..00000000 --- a/dist/services/priceProtection.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -export declare const PRICE_REVIEW_WINDOW_MS: number; -export declare const PRICE_CHANGE_THRESHOLD = 0.15; -export interface PriceMovementEvaluation { - isAnomalous: boolean; - changePercent: number; - reason?: string | undefined; -} -export declare function evaluatePriceMovement(params: { - currentRate: number; - baselineRate: number; - currency: string; - threshold?: number; -}): PriceMovementEvaluation; -//# sourceMappingURL=priceProtection.d.ts.map \ No newline at end of file diff --git a/dist/services/priceProtection.d.ts.map b/dist/services/priceProtection.d.ts.map deleted file mode 100644 index 6310d6e1..00000000 --- a/dist/services/priceProtection.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"priceProtection.d.ts","sourceRoot":"","sources":["../../src/services/priceProtection.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,QAAgB,CAAC;AACpD,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAE3C,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,uBAAuB,CAyB1B"} \ No newline at end of file diff --git a/dist/services/priceProtection.js b/dist/services/priceProtection.js deleted file mode 100644 index d006efb0..00000000 --- a/dist/services/priceProtection.js +++ /dev/null @@ -1,25 +0,0 @@ -export const PRICE_REVIEW_WINDOW_MS = 5 * 60 * 1000; -export const PRICE_CHANGE_THRESHOLD = 0.15; -export function evaluatePriceMovement(params) { - const threshold = params.threshold ?? PRICE_CHANGE_THRESHOLD; - if (params.baselineRate <= 0 || params.currentRate <= 0) { - return { - isAnomalous: false, - changePercent: 0, - }; - } - const changePercent = (Math.abs(params.currentRate - params.baselineRate) / params.baselineRate) * - 100; - const isAnomalous = changePercent > threshold * 100; - return isAnomalous - ? { - isAnomalous, - changePercent, - reason: `${params.currency} moved ${changePercent.toFixed(2)}% within 5 minutes, exceeding the 15% manual review threshold.`, - } - : { - isAnomalous, - changePercent, - }; -} -//# sourceMappingURL=priceProtection.js.map \ No newline at end of file diff --git a/dist/services/priceProtection.js.map b/dist/services/priceProtection.js.map deleted file mode 100644 index 9278459d..00000000 --- a/dist/services/priceProtection.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"priceProtection.js","sourceRoot":"","sources":["../../src/services/priceProtection.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AACpD,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAQ3C,MAAM,UAAU,qBAAqB,CAAC,MAKrC;IACC,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,sBAAsB,CAAC;IAE7D,IAAI,MAAM,CAAC,YAAY,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,IAAI,CAAC,EAAE,CAAC;QACxD,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,aAAa,EAAE,CAAC;SACjB,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GACjB,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC;QAC1E,GAAG,CAAC;IACN,MAAM,WAAW,GAAG,aAAa,GAAG,SAAS,GAAG,GAAG,CAAC;IAEpD,OAAO,WAAW;QAChB,CAAC,CAAC;YACE,WAAW;YACX,aAAa;YACb,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,UAAU,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,gEAAgE;SAC7H;QACH,CAAC,CAAC;YACE,WAAW;YACX,aAAa;SACd,CAAC;AACR,CAAC"} \ No newline at end of file diff --git a/dist/services/priceReviewService.d.ts b/dist/services/priceReviewService.d.ts deleted file mode 100644 index 55f12acd..00000000 --- a/dist/services/priceReviewService.d.ts +++ /dev/null @@ -1,56 +0,0 @@ -import type { MarketRate } from "./marketRate/types"; -export declare const REVIEWABLE_CURRENCIES: Set; -type ReviewStatus = "AUTO_APPROVED" | "PENDING" | "APPROVED" | "REJECTED"; -type ContractStatus = "NOT_SUBMITTED" | "SUBMITTED" | "SKIPPED"; -export interface PendingPriceReview { - id: number; - currency: string; - rate: number; - source: string; - fetchedAt: Date; - reviewStatus: ReviewStatus; - contractStatus: ContractStatus; - reason: string | null; - notes: string | null; - baselineRate: number | null; - baselineTimestamp: Date | null; - changePercent: number | null; - memoId: string | null; - stellarTxHash: string | null; - reviewedAt: Date | null; - reviewedBy: string | null; - createdAt: Date; - updatedAt: Date; -} -export interface PriceAssessment { - reviewRecordId: number; - manualReviewRequired: boolean; - reason?: string | undefined; - changePercent?: number | undefined; - comparisonRate?: number | undefined; - comparisonTimestamp?: Date | undefined; -} -export declare class PriceReviewService { - private schemaReadyPromise; - private ensureSchema; - assessRate(rate: MarketRate): Promise; - markContractSubmitted(reviewRecordId: number, memoId: string, stellarTxHash: string): Promise; - getPendingReviews(): Promise; - getPendingReviewById(reviewId: number): Promise; - approveReview(params: { - reviewId: number; - reviewedBy?: string; - reviewNotes?: string; - memoId: string; - stellarTxHash: string; - }): Promise; - rejectReview(params: { - reviewId: number; - reviewedBy?: string; - reviewNotes?: string; - }): Promise; - private getLatestSubmittedBaseline; -} -export declare const priceReviewService: PriceReviewService; -export {}; -//# sourceMappingURL=priceReviewService.d.ts.map \ No newline at end of file diff --git a/dist/services/priceReviewService.d.ts.map b/dist/services/priceReviewService.d.ts.map deleted file mode 100644 index 7288decd..00000000 --- a/dist/services/priceReviewService.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"priceReviewService.d.ts","sourceRoot":"","sources":["../../src/services/priceReviewService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAOrD,eAAO,MAAM,qBAAqB,aAAiC,CAAC;AAEpE,KAAK,YAAY,GAAG,eAAe,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAC1E,KAAK,cAAc,GAAG,eAAe,GAAG,WAAW,GAAG,SAAS,CAAC;AAuBhE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,iBAAiB,EAAE,IAAI,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,mBAAmB,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;CACxC;AAsCD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,kBAAkB,CAA8B;IAExD,OAAO,CAAC,YAAY;IAwCd,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,CAAC;IA8FtD,qBAAqB,CACzB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;IAcV,iBAAiB,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAalD,oBAAoB,CACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAc/B,aAAa,CAAC,MAAM,EAAE;QAC1B,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,aAAa,EAAE,MAAM,CAAC;KACvB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA0BzB,YAAY,CAAC,MAAM,EAAE;QACzB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,kBAAkB,CAAC;YAwBjB,0BAA0B;CA+BzC;AAED,eAAO,MAAM,kBAAkB,oBAA2B,CAAC"} \ No newline at end of file diff --git a/dist/services/priceReviewService.js b/dist/services/priceReviewService.js deleted file mode 100644 index c7494a11..00000000 --- a/dist/services/priceReviewService.js +++ /dev/null @@ -1,263 +0,0 @@ -import prisma from "../lib/prisma"; -import { evaluatePriceMovement, PRICE_REVIEW_WINDOW_MS, } from "./priceProtection"; -import { webhookService } from "./webhook"; -export const REVIEWABLE_CURRENCIES = new Set(["NGN", "KES", "GHS"]); -function toNumber(value) { - if (value === null || value === undefined) - return null; - if (typeof value === "number") { - return Number.isFinite(value) ? value : null; - } - const parsed = Number.parseFloat(value); - return Number.isFinite(parsed) ? parsed : null; -} -function mapReviewRow(row) { - return { - id: row.id, - currency: row.currency, - rate: toNumber(row.rate) ?? 0, - source: row.source, - fetchedAt: new Date(row.fetched_at), - reviewStatus: row.review_status, - contractStatus: row.contract_status, - reason: row.review_reason, - notes: row.review_notes, - baselineRate: toNumber(row.baseline_rate), - baselineTimestamp: row.baseline_timestamp - ? new Date(row.baseline_timestamp) - : null, - changePercent: toNumber(row.change_percent), - memoId: row.memo_id, - stellarTxHash: row.stellar_tx_hash, - reviewedAt: row.reviewed_at ? new Date(row.reviewed_at) : null, - reviewedBy: row.reviewed_by, - createdAt: new Date(row.created_at), - updatedAt: new Date(row.updated_at), - }; -} -export class PriceReviewService { - schemaReadyPromise = null; - ensureSchema() { - if (!this.schemaReadyPromise) { - this.schemaReadyPromise = prisma - .$executeRawUnsafe(` - CREATE TABLE IF NOT EXISTS price_review_records ( - id SERIAL PRIMARY KEY, - currency VARCHAR(10) NOT NULL, - rate NUMERIC(20, 10) NOT NULL, - source VARCHAR(100) NOT NULL, - fetched_at TIMESTAMP(3) NOT NULL, - review_status VARCHAR(20) NOT NULL DEFAULT 'AUTO_APPROVED', - contract_status VARCHAR(20) NOT NULL DEFAULT 'NOT_SUBMITTED', - review_reason TEXT NULL, - review_notes TEXT NULL, - baseline_rate NUMERIC(20, 10) NULL, - baseline_timestamp TIMESTAMP(3) NULL, - change_percent NUMERIC(10, 4) NULL, - memo_id VARCHAR(28) NULL, - stellar_tx_hash VARCHAR(128) NULL, - reviewed_at TIMESTAMP(3) NULL, - reviewed_by VARCHAR(100) NULL, - created_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP - ); - - CREATE INDEX IF NOT EXISTS idx_price_review_currency_time - ON price_review_records (currency, fetched_at DESC); - - CREATE INDEX IF NOT EXISTS idx_price_review_pending - ON price_review_records (review_status, created_at DESC); - - CREATE INDEX IF NOT EXISTS idx_price_review_contract_status - ON price_review_records (currency, contract_status, fetched_at DESC); - `) - .then(() => undefined); - } - return this.schemaReadyPromise; - } - async assessRate(rate) { - await this.ensureSchema(); - const currency = rate.currency.toUpperCase(); - const reviewable = REVIEWABLE_CURRENCIES.has(currency); - const baseline = reviewable - ? await this.getLatestSubmittedBaseline(currency, rate.timestamp) - : null; - let reviewStatus = "AUTO_APPROVED"; - let contractStatus = "NOT_SUBMITTED"; - let reason; - let changePercent; - let comparisonRate; - let comparisonTimestamp; - if (reviewable && baseline) { - const evaluation = evaluatePriceMovement({ - currentRate: rate.rate, - baselineRate: baseline.rate, - currency, - }); - if (evaluation.isAnomalous) { - reviewStatus = "PENDING"; - contractStatus = "SKIPPED"; - reason = evaluation.reason; - changePercent = evaluation.changePercent; - comparisonRate = baseline.rate; - comparisonTimestamp = baseline.fetchedAt; - } - } - const insertedRows = await prisma.$queryRaw ` - INSERT INTO price_review_records ( - currency, - rate, - source, - fetched_at, - review_status, - contract_status, - review_reason, - baseline_rate, - baseline_timestamp, - change_percent - ) - VALUES ( - ${currency}, - ${rate.rate}, - ${rate.source}, - ${rate.timestamp}, - ${reviewStatus}, - ${contractStatus}, - ${reason ?? null}, - ${comparisonRate ?? null}, - ${comparisonTimestamp ?? null}, - ${changePercent ?? null} - ) - RETURNING * - `; - const inserted = insertedRows[0]; - if (!inserted) { - throw new Error(`Failed to create price review record for ${currency}`); - } - if (reviewStatus === "PENDING" && - reason && - changePercent !== undefined && - comparisonRate !== undefined) { - await webhookService.sendManualReviewNotification({ - reviewId: inserted.id, - currency, - rate: rate.rate, - previousRate: comparisonRate, - changePercent, - source: rate.source, - timestamp: rate.timestamp, - reason, - }); - } - return { - reviewRecordId: inserted.id, - manualReviewRequired: reviewStatus === "PENDING", - ...(reason !== undefined && { reason }), - ...(changePercent !== undefined && { changePercent }), - ...(comparisonRate !== undefined && { comparisonRate }), - ...(comparisonTimestamp !== undefined && { comparisonTimestamp }), - }; - } - async markContractSubmitted(reviewRecordId, memoId, stellarTxHash) { - await this.ensureSchema(); - await prisma.$executeRaw ` - UPDATE price_review_records - SET - contract_status = 'SUBMITTED', - memo_id = ${memoId}, - stellar_tx_hash = ${stellarTxHash}, - updated_at = CURRENT_TIMESTAMP - WHERE id = ${reviewRecordId} - `; - } - async getPendingReviews() { - await this.ensureSchema(); - const rows = await prisma.$queryRaw ` - SELECT * - FROM price_review_records - WHERE review_status = 'PENDING' - ORDER BY created_at DESC - `; - return rows.map(mapReviewRow); - } - async getPendingReviewById(reviewId) { - await this.ensureSchema(); - const rows = await prisma.$queryRaw ` - SELECT * - FROM price_review_records - WHERE id = ${reviewId} - AND review_status = 'PENDING' - LIMIT 1 - `; - return rows[0] ? mapReviewRow(rows[0]) : null; - } - async approveReview(params) { - await this.ensureSchema(); - const rows = await prisma.$queryRaw ` - UPDATE price_review_records - SET - review_status = 'APPROVED', - contract_status = 'SUBMITTED', - review_notes = ${params.reviewNotes ?? null}, - reviewed_by = ${params.reviewedBy ?? "manual-review"}, - reviewed_at = CURRENT_TIMESTAMP, - memo_id = ${params.memoId}, - stellar_tx_hash = ${params.stellarTxHash}, - updated_at = CURRENT_TIMESTAMP - WHERE id = ${params.reviewId} - AND review_status = 'PENDING' - RETURNING * - `; - if (!rows[0]) { - throw new Error(`Pending review ${params.reviewId} was not found`); - } - return mapReviewRow(rows[0]); - } - async rejectReview(params) { - await this.ensureSchema(); - const rows = await prisma.$queryRaw ` - UPDATE price_review_records - SET - review_status = 'REJECTED', - contract_status = 'SKIPPED', - review_notes = ${params.reviewNotes ?? null}, - reviewed_by = ${params.reviewedBy ?? "manual-review"}, - reviewed_at = CURRENT_TIMESTAMP, - updated_at = CURRENT_TIMESTAMP - WHERE id = ${params.reviewId} - AND review_status = 'PENDING' - RETURNING * - `; - if (!rows[0]) { - throw new Error(`Pending review ${params.reviewId} was not found`); - } - return mapReviewRow(rows[0]); - } - async getLatestSubmittedBaseline(currency, timestamp) { - const windowStart = new Date(timestamp.getTime() - PRICE_REVIEW_WINDOW_MS); - const rows = await prisma.$queryRaw ` - SELECT * - FROM price_review_records - WHERE currency = ${currency} - AND contract_status = 'SUBMITTED' - AND fetched_at >= ${windowStart} - AND fetched_at < ${timestamp} - ORDER BY fetched_at DESC - LIMIT 1 - `; - const row = rows[0]; - if (!row) { - return null; - } - const rate = toNumber(row.rate); - if (rate === null || rate <= 0) { - return null; - } - return { - rate, - fetchedAt: new Date(row.fetched_at), - }; - } -} -export const priceReviewService = new PriceReviewService(); -//# sourceMappingURL=priceReviewService.js.map \ No newline at end of file diff --git a/dist/services/priceReviewService.js.map b/dist/services/priceReviewService.js.map deleted file mode 100644 index f0f89686..00000000 --- a/dist/services/priceReviewService.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"priceReviewService.js","sourceRoot":"","sources":["../../src/services/priceReviewService.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/services/reputation.service.d.ts b/dist/services/reputation.service.d.ts deleted file mode 100644 index 7de62d89..00000000 --- a/dist/services/reputation.service.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export declare class ReputationService { - recordSuccess(providerName: string, endpoint: string | null, latencyMs?: number): Promise; - recordFailure(providerName: string, endpoint: string | null, errorType: 'offline' | 'incorrect'): Promise; - getReputation(providerName: string, endpoint?: string): Promise; - getLowReliabilityProviders(threshold?: number): Promise; - resetConsecutiveFailures(providerName: string, endpoint?: string): Promise; -} -export declare const reputationService: ReputationService; -//# sourceMappingURL=reputation.service.d.ts.map \ No newline at end of file diff --git a/dist/services/reputation.service.d.ts.map b/dist/services/reputation.service.d.ts.map deleted file mode 100644 index 964c0ee9..00000000 --- a/dist/services/reputation.service.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"reputation.service.d.ts","sourceRoot":"","sources":["../../src/services/reputation.service.ts"],"names":[],"mappings":"AAIA,qBAAa,iBAAiB;IACtB,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyD/F,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAsE/G,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAWpE,0BAA0B,CAAC,SAAS,GAAE,MAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAUlE,wBAAwB,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAevF;AAED,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"} \ No newline at end of file diff --git a/dist/services/reputation.service.js b/dist/services/reputation.service.js deleted file mode 100644 index 0738a9aa..00000000 --- a/dist/services/reputation.service.js +++ /dev/null @@ -1,158 +0,0 @@ -import { PrismaClient } from '@prisma/client'; -const prisma = new PrismaClient(); -export class ReputationService { - async recordSuccess(providerName, endpoint, latencyMs) { - const existing = await prisma.providerReputation.findUnique({ - where: { - providerName_endpoint: { - providerName, - endpoint: endpoint || '', - }, - }, - }); - const newTotalRequests = (existing?.totalRequests || 0) + 1; - const newSuccessfulRequests = (existing?.successfulRequests || 0) + 1; - const newConsecutiveFailures = 0; - const newConsecutiveIncorrect = 0; - // Calculate new average latency - let newAvgLatency = existing?.averageLatency || null; - if (latencyMs && existing?.averageLatency) { - newAvgLatency = (existing.averageLatency * existing.successfulRequests + latencyMs) / newSuccessfulRequests; - } - else if (latencyMs) { - newAvgLatency = latencyMs; - } - // Calculate reliability score - const reliabilityScore = (newSuccessfulRequests / newTotalRequests) * 100; - await prisma.providerReputation.upsert({ - where: { - providerName_endpoint: { - providerName, - endpoint: endpoint || '', - }, - }, - update: { - totalRequests: newTotalRequests, - successfulRequests: newSuccessfulRequests, - averageLatency: newAvgLatency, - lastSuccess: new Date(), - consecutiveFailures: newConsecutiveFailures, - consecutiveIncorrect: newConsecutiveIncorrect, - status: 'online', - reliabilityScore, - lastUpdated: new Date(), - }, - create: { - providerName, - endpoint: endpoint || '', - status: 'online', - totalRequests: 1, - successfulRequests: 1, - averageLatency: latencyMs || null, - lastSuccess: new Date(), - reliabilityScore: 100, - }, - }); - } - async recordFailure(providerName, endpoint, errorType) { - const existing = await prisma.providerReputation.findUnique({ - where: { - providerName_endpoint: { - providerName, - endpoint: endpoint || '', - }, - }, - }); - const newTotalRequests = (existing?.totalRequests || 0) + 1; - const newFailedRequests = (existing?.failedRequests || 0) + 1; - let newConsecutiveFailures = (existing?.consecutiveFailures || 0) + 1; - let newConsecutiveIncorrect = existing?.consecutiveIncorrect || 0; - if (errorType === 'incorrect') { - newConsecutiveIncorrect = (existing?.consecutiveIncorrect || 0) + 1; - } - // Determine status based on consecutive failures - let status = 'online'; - if (newConsecutiveFailures >= 5) { - status = 'offline'; - } - else if (newConsecutiveFailures >= 2) { - status = 'degraded'; - } - // Calculate reliability score - const successfulRequests = existing?.successfulRequests || 0; - const reliabilityScore = (successfulRequests / newTotalRequests) * 100; - await prisma.providerReputation.upsert({ - where: { - providerName_endpoint: { - providerName, - endpoint: endpoint || '', - }, - }, - update: { - totalRequests: newTotalRequests, - failedRequests: newFailedRequests, - lastFailure: new Date(), - consecutiveFailures: newConsecutiveFailures, - ...(errorType === 'incorrect' && { - incorrectResponses: (existing?.incorrectResponses || 0) + 1, - lastIncorrect: new Date(), - consecutiveIncorrect: newConsecutiveIncorrect, - }), - status, - reliabilityScore, - lastUpdated: new Date(), - }, - create: { - providerName, - endpoint: endpoint || '', - status: 'degraded', - totalRequests: 1, - failedRequests: 1, - lastFailure: new Date(), - consecutiveFailures: 1, - ...(errorType === 'incorrect' && { - incorrectResponses: 1, - lastIncorrect: new Date(), - consecutiveIncorrect: 1, - }), - reliabilityScore: 0, - }, - }); - } - async getReputation(providerName, endpoint) { - return prisma.providerReputation.findUnique({ - where: { - providerName_endpoint: { - providerName, - endpoint: endpoint || '', - }, - }, - }); - } - async getLowReliabilityProviders(threshold = 80) { - return prisma.providerReputation.findMany({ - where: { - reliabilityScore: { lt: threshold }, - totalRequests: { gt: 10 }, - }, - orderBy: { reliabilityScore: 'asc' }, - }); - } - async resetConsecutiveFailures(providerName, endpoint) { - await prisma.providerReputation.update({ - where: { - providerName_endpoint: { - providerName, - endpoint: endpoint || '', - }, - }, - data: { - consecutiveFailures: 0, - consecutiveIncorrect: 0, - status: 'online', - }, - }); - } -} -export const reputationService = new ReputationService(); -//# sourceMappingURL=reputation.service.js.map \ No newline at end of file diff --git a/dist/services/reputation.service.js.map b/dist/services/reputation.service.js.map deleted file mode 100644 index 8ed13c94..00000000 --- a/dist/services/reputation.service.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"reputation.service.js","sourceRoot":"","sources":["../../src/services/reputation.service.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/services/sorobanEventListener.d.ts b/dist/services/sorobanEventListener.d.ts deleted file mode 100644 index a46b9e31..00000000 --- a/dist/services/sorobanEventListener.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -export interface ConfirmedPrice { - currency: string; - rate: number; - txHash: string; - memoId: string | null; - ledgerSeq: number; - confirmedAt: Date; -} -export declare class SorobanEventListener { - private server; - private oraclePublicKey; - private isRunning; - private pollIntervalMs; - private lastProcessedLedger; - private pollTimer; - constructor(pollIntervalMs?: number); - start(): Promise; - stop(): void; - private pollTransactions; - private extractMemoId; - private parseOperations; - private saveConfirmedPrices; - private emitPriceUpdates; - getLatestConfirmedPrice(currency: string): Promise; - getConfirmedPriceHistory(currency: string, limit?: number): Promise; - isActive(): boolean; - getOraclePublicKey(): string; -} -//# sourceMappingURL=sorobanEventListener.d.ts.map \ No newline at end of file diff --git a/dist/services/sorobanEventListener.d.ts.map b/dist/services/sorobanEventListener.d.ts.map deleted file mode 100644 index 156b191d..00000000 --- a/dist/services/sorobanEventListener.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"sorobanEventListener.d.ts","sourceRoot":"","sources":["../../src/services/sorobanEventListener.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,IAAI,CAAC;CACnB;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,mBAAmB,CAAa;IACxC,OAAO,CAAC,SAAS,CAA+C;gBAEpD,cAAc,GAAE,MAAc;IAqBpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC5B,IAAI,IAAI,IAAI;YASE,gBAAgB;IAqD9B,OAAO,CAAC,aAAa;YASP,eAAe;YA2Df,mBAAmB;IAgCjC,OAAO,CAAC,gBAAgB;IAiBlB,uBAAuB,CAC3B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAoB3B,wBAAwB,CAC5B,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAAY,GAClB,OAAO,CAAC,cAAc,EAAE,CAAC;IAiB5B,QAAQ,IAAI,OAAO;IAInB,kBAAkB,IAAI,MAAM;CAG7B"} \ No newline at end of file diff --git a/dist/services/sorobanEventListener.js b/dist/services/sorobanEventListener.js deleted file mode 100644 index 578d6dd3..00000000 --- a/dist/services/sorobanEventListener.js +++ /dev/null @@ -1,232 +0,0 @@ -import { Horizon, Keypair } from "@stellar/stellar-sdk"; -import prisma from "../lib/prisma"; -import { getIO } from "../lib/socket"; -import dotenv from "dotenv"; -dotenv.config(); -export class SorobanEventListener { - server; - oraclePublicKey; - isRunning = false; - pollIntervalMs; - lastProcessedLedger = 0; - pollTimer = null; - constructor(pollIntervalMs = 15000) { - const secret = process.env.ORACLE_SECRET_KEY || process.env.SOROBAN_ADMIN_SECRET; - if (!secret) { - throw new Error("ORACLE_SECRET_KEY or SOROBAN_ADMIN_SECRET not found in environment variables"); - } - this.oraclePublicKey = Keypair.fromSecret(secret).publicKey(); - this.pollIntervalMs = pollIntervalMs; - const network = process.env.STELLAR_NETWORK || "TESTNET"; - const horizonUrl = network === "PUBLIC" - ? "https://horizon.stellar.org" - : "https://horizon-testnet.stellar.org"; - this.server = new Horizon.Server(horizonUrl); - } - async start() { - if (this.isRunning) { - console.warn("SorobanEventListener is already running"); - return; - } - this.isRunning = true; - console.log(`[EventListener] Starting listener for account ${this.oraclePublicKey}`); - // Initialize last processed ledger from the most recent on-chain record - const lastRecord = await prisma.onChainPrice.findFirst({ - orderBy: { ledgerSeq: "desc" }, - }); - if (lastRecord) { - this.lastProcessedLedger = lastRecord.ledgerSeq; - console.log(`[EventListener] Resuming from ledger ${this.lastProcessedLedger}`); - } - // Initial poll - await this.pollTransactions(); - // Start periodic polling - this.pollTimer = setInterval(() => { - this.pollTransactions().catch((err) => { - console.error("[EventListener] Poll error:", err); - }); - }, this.pollIntervalMs); - } - stop() { - if (this.pollTimer) { - clearInterval(this.pollTimer); - this.pollTimer = null; - } - this.isRunning = false; - console.log("[EventListener] Stopped"); - } - async pollTransactions() { - try { - const transactions = await this.server - .transactions() - .forAccount(this.oraclePublicKey) - .order("desc") - .limit(50) - .call(); - const confirmedPrices = []; - for (const tx of transactions.records) { - const ledgerSeq = tx.ledger_attr; - // Skip already processed transactions - if (ledgerSeq <= this.lastProcessedLedger) { - continue; - } - // Only process transactions with our memo prefix - const memoId = this.extractMemoId(tx); - if (!memoId || !memoId.startsWith("SF-")) { - continue; - } - // Parse price updates from operations - const prices = await this.parseOperations(tx, memoId); - confirmedPrices.push(...prices); - } - if (confirmedPrices.length > 0) { - await this.saveConfirmedPrices(confirmedPrices); - this.emitPriceUpdates(confirmedPrices); - // Update last processed ledger - const maxLedger = Math.max(...confirmedPrices.map((p) => p.ledgerSeq)); - if (maxLedger > this.lastProcessedLedger) { - this.lastProcessedLedger = maxLedger; - } - } - } - catch (error) { - // Account not found is expected for new accounts with no transactions - if (error instanceof Error && - error.message.includes("status code 404")) { - console.log("[EventListener] No transactions found for oracle account"); - return; - } - throw error; - } - } - extractMemoId(tx) { - if (tx.memo_type === "text" && tx.memo) { - return tx.memo; - } - return null; - } - async parseOperations(tx, memoId) { - const confirmedPrices = []; - try { - const operations = await tx.operations(); - for (const op of operations.records) { - if (op.type !== "manage_data") { - continue; - } - const manageDataOp = op; - const name = manageDataOp.name; - // Parse operation name format: _PRICE - if (!name.endsWith("_PRICE")) { - continue; - } - const currency = name.replace("_PRICE", ""); - const valueBase64 = manageDataOp.value; - if (!valueBase64) { - continue; - } - // Decode base64 value to string then parse as number - const valueStr = atob(String(valueBase64)); - const rate = parseFloat(valueStr); - if (isNaN(rate)) { - console.warn(`[EventListener] Invalid rate value for ${currency}: ${valueStr}`); - continue; - } - confirmedPrices.push({ - currency, - rate, - txHash: tx.hash, - memoId, - ledgerSeq: tx.ledger_attr, - confirmedAt: new Date(tx.created_at), - }); - } - } - catch (error) { - console.error(`[EventListener] Error parsing operations for tx ${tx.hash}:`, error); - } - return confirmedPrices; - } - async saveConfirmedPrices(prices) { - for (const price of prices) { - try { - await prisma.onChainPrice.upsert({ - where: { - txHash_currency: { - txHash: price.txHash, - currency: price.currency, - }, - }, - update: {}, - create: { - currency: price.currency, - rate: price.rate, - txHash: price.txHash, - memoId: price.memoId, - ledgerSeq: price.ledgerSeq, - confirmedAt: price.confirmedAt, - }, - }); - console.log(`[EventListener] Saved confirmed price: ${price.currency} = ${price.rate} (tx: ${price.txHash.substring(0, 8)}...)`); - } - catch (error) { - console.error(`[EventListener] Error saving price for ${price.currency}:`, error); - } - } - } - emitPriceUpdates(prices) { - try { - const io = getIO(); - for (const price of prices) { - io.emit("price:confirmed", { - currency: price.currency, - rate: price.rate, - txHash: price.txHash, - ledgerSeq: price.ledgerSeq, - confirmedAt: price.confirmedAt.toISOString(), - }); - } - } - catch { - // Socket not initialized (e.g., during tests) - } - } - async getLatestConfirmedPrice(currency) { - const record = await prisma.onChainPrice.findFirst({ - where: { currency: currency.toUpperCase() }, - orderBy: { confirmedAt: "desc" }, - }); - if (!record) { - return null; - } - return { - currency: record.currency, - rate: Number(record.rate), - txHash: record.txHash, - memoId: record.memoId, - ledgerSeq: record.ledgerSeq, - confirmedAt: record.confirmedAt, - }; - } - async getConfirmedPriceHistory(currency, limit = 100) { - const records = await prisma.onChainPrice.findMany({ - where: { currency: currency.toUpperCase() }, - orderBy: { confirmedAt: "desc" }, - take: limit, - }); - return records.map((record) => ({ - currency: record.currency, - rate: Number(record.rate), - txHash: record.txHash, - memoId: record.memoId, - ledgerSeq: record.ledgerSeq, - confirmedAt: record.confirmedAt, - })); - } - isActive() { - return this.isRunning; - } - getOraclePublicKey() { - return this.oraclePublicKey; - } -} -//# sourceMappingURL=sorobanEventListener.js.map \ No newline at end of file diff --git a/dist/services/sorobanEventListener.js.map b/dist/services/sorobanEventListener.js.map deleted file mode 100644 index 3e533820..00000000 --- a/dist/services/sorobanEventListener.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"sorobanEventListener.js","sourceRoot":"","sources":["../../src/services/sorobanEventListener.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/services/stellarService.d.ts b/dist/services/stellarService.d.ts deleted file mode 100644 index 39f69532..00000000 --- a/dist/services/stellarService.d.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Transaction, Horizon } from "@stellar/stellar-sdk"; -export declare class StellarService { - private server; - private keypair; - private network; - private readonly MAX_RETRIES; - private readonly FEE_INCREMENT_PERCENTAGE; - private readonly RETRY_DELAY_MS; - constructor(); - /** - * Fetches the recommended transaction fee from Horizon fee_stats. - * Uses p50 (median) of recent fees to avoid overpaying while ensuring inclusion. - * @returns Recommended fee in stroops as a string (required by TransactionBuilder) - */ - getRecommendedFee(): Promise; - /** - * Submit a price update to the Stellar network with a unique memo ID. - * Leverages submitTransactionWithRetries for automatic fee bumping if stuck. - * @param currency - The currency code (e.g., "NGN", "KES") - * @param price - The current price/rate - * @param memoId - Unique ID for auditing - */ - submitPriceUpdate(currency: string, price: number, memoId: string): Promise; - /** - * Submit a multi-signed price update to the Stellar network. - * Accepts signatures from multiple oracle servers. - * @param currency - The currency code (e.g., "NGN", "KES") - * @param price - The current price/rate - * @param memoId - Unique ID for auditing - * @param signatures - Array of signatures from different signers - */ - submitMultiSignedPriceUpdate(currency: string, price: number, memoId: string, signatures: Array<{ - signerPublicKey: string; - signature: string; - }>): Promise; - /** - * Generic method to submit a transaction with retries and automatic fee bumping. - * Optimizes interaction with the network (including Soroban contracts) by handling congestion. - * @param builderFn - Function that builds a new transaction for each attempt - * @param maxRetries - Max number of retries - * @param baseFee - The starting fee in stroops - */ - submitTransactionWithRetries(builderFn: (sourceAccount: Horizon.AccountResponse, currentFee: number) => Transaction, maxRetries: number | undefined, baseFee: number): Promise; - /** - * Submit a multi-signed transaction to the Stellar network. - * Adds multiple signatures to the transaction before submission. - * @param builderFn - Function that builds the transaction - * @param signatures - Array of signatures with signer public keys - * @param maxRetries - Max number of retries - * @param baseFee - The starting fee in stroops - */ - private submitMultiSignedTransaction; - /** - * Get the network passphrase for the current network. - * Ensures proper network identification for multi-sig operations. - */ - private getNetworkPassphrase; - /** - * Determines if a transaction error indicates it is "stuck" or needs a fee bump. - */ - private isStuckError; - /** - * Generate a unique ID for the transaction memo - * Format: SF-- - */ - generateMemoId(currency: string): string; -} -//# sourceMappingURL=stellarService.d.ts.map \ No newline at end of file diff --git a/dist/services/stellarService.d.ts.map b/dist/services/stellarService.d.ts.map deleted file mode 100644 index 70f5e1c8..00000000 --- a/dist/services/stellarService.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"stellarService.d.ts","sourceRoot":"","sources":["../../src/services/stellarService.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,WAAW,EAIX,OAAO,EACR,MAAM,sBAAsB,CAAC;AAK9B,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAK;IACjC,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAO;IAChD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;;IAkBvC;;;;OAIG;IACG,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAO1C;;;;;;OAMG;IACG,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA2BzF;;;;;;;OAOG;IACG,4BAA4B,CAChC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,KAAK,CAAC;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,GAChE,OAAO,CAAC,MAAM,CAAC;IA4BlB;;;;;;OAMG;IACG,4BAA4B,CAChC,SAAS,EAAE,CAAC,aAAa,EAAE,OAAO,CAAC,eAAe,EAAE,UAAU,EAAE,MAAM,KAAK,WAAW,EACtF,UAAU,oBAAmB,EAC7B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,GAAG,CAAC;IA8Bf;;;;;;;OAOG;YACW,4BAA4B;IA0E1C;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;OAEG;IACH,OAAO,CAAC,YAAY;IAgBpB;;;OAGG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAOzC"} \ No newline at end of file diff --git a/dist/services/stellarService.js b/dist/services/stellarService.js deleted file mode 100644 index 59a3f4cc..00000000 --- a/dist/services/stellarService.js +++ /dev/null @@ -1,208 +0,0 @@ -import { Keypair, TransactionBuilder, Operation, Networks, Memo, Horizon, } from "@stellar/stellar-sdk"; -import dotenv from "dotenv"; -dotenv.config(); -export class StellarService { - server; - keypair; - network; - MAX_RETRIES = 3; - FEE_INCREMENT_PERCENTAGE = 0.5; // 50% increase each retry - RETRY_DELAY_MS = 2000; // 2 seconds delay between retries - constructor() { - const secret = process.env.ORACLE_SECRET_KEY || process.env.SOROBAN_ADMIN_SECRET; - if (!secret) { - throw new Error("Stellar secret key not found in environment variables"); - } - this.keypair = Keypair.fromSecret(secret); - this.network = process.env.STELLAR_NETWORK || "TESTNET"; - const horizonUrl = this.network === "PUBLIC" - ? "https://horizon.stellar.org" - : "https://horizon-testnet.stellar.org"; - this.server = new Horizon.Server(horizonUrl); - } - /** - * Fetches the recommended transaction fee from Horizon fee_stats. - * Uses p50 (median) of recent fees to avoid overpaying while ensuring inclusion. - * @returns Recommended fee in stroops as a string (required by TransactionBuilder) - */ - async getRecommendedFee() { - const feeStats = await this.server.feeStats(); - // p50 = median fee paid in recent ledgers — safe and cost-efficient - const fee = parseInt(feeStats.fee_charged.p50, 10); - return Math.max(fee, 100).toString(); // floor at Stellar's base fee (100 stroops) - } - /** - * Submit a price update to the Stellar network with a unique memo ID. - * Leverages submitTransactionWithRetries for automatic fee bumping if stuck. - * @param currency - The currency code (e.g., "NGN", "KES") - * @param price - The current price/rate - * @param memoId - Unique ID for auditing - */ - async submitPriceUpdate(currency, price, memoId) { - const baseFee = parseInt(await this.getRecommendedFee(), 10); - const result = await this.submitTransactionWithRetries((sourceAccount, currentFee) => { - return new TransactionBuilder(sourceAccount, { - fee: currentFee.toString(), - networkPassphrase: this.network === "PUBLIC" ? Networks.PUBLIC : Networks.TESTNET, - }) - .addOperation(Operation.manageData({ - name: `${currency}_PRICE`, - value: price.toString(), - })) - .addMemo(Memo.text(memoId)) - .setTimeout(60) - .build(); - }, this.MAX_RETRIES, baseFee); - console.info(`✅ Price update for ${currency} confirmed. Hash: ${result.hash}`); - return result.hash; - } - /** - * Submit a multi-signed price update to the Stellar network. - * Accepts signatures from multiple oracle servers. - * @param currency - The currency code (e.g., "NGN", "KES") - * @param price - The current price/rate - * @param memoId - Unique ID for auditing - * @param signatures - Array of signatures from different signers - */ - async submitMultiSignedPriceUpdate(currency, price, memoId, signatures) { - const baseFee = parseInt(await this.getRecommendedFee(), 10); - const result = await this.submitMultiSignedTransaction((sourceAccount, currentFee) => { - return new TransactionBuilder(sourceAccount, { - fee: currentFee.toString(), - networkPassphrase: this.network === "PUBLIC" ? Networks.PUBLIC : Networks.TESTNET, - }) - .addOperation(Operation.manageData({ - name: `${currency}_PRICE`, - value: price.toString(), - })) - .addMemo(Memo.text(memoId)) - .setTimeout(60) - .build(); - }, signatures, this.MAX_RETRIES, baseFee); - console.info(`✅ Multi-signed price update for ${currency} confirmed. Hash: ${result.hash}`); - return result.hash; - } - /** - * Generic method to submit a transaction with retries and automatic fee bumping. - * Optimizes interaction with the network (including Soroban contracts) by handling congestion. - * @param builderFn - Function that builds a new transaction for each attempt - * @param maxRetries - Max number of retries - * @param baseFee - The starting fee in stroops - */ - async submitTransactionWithRetries(builderFn, maxRetries = this.MAX_RETRIES, baseFee) { - let attempt = 0; - while (attempt <= maxRetries) { - try { - const sourceAccount = await this.server.loadAccount(this.keypair.publicKey()); - const currentFee = Math.floor(baseFee * (1 + (this.FEE_INCREMENT_PERCENTAGE * attempt))); - const transaction = builderFn(sourceAccount, currentFee); - transaction.sign(this.keypair); - return await this.server.submitTransaction(transaction); - } - catch (error) { - attempt++; - const isStuck = this.isStuckError(error); - if (isStuck && attempt <= maxRetries) { - console.warn(`⚠️ Transaction stuck or fee too low (Attempt ${attempt}). Bumping fee and retrying in ${this.RETRY_DELAY_MS}ms...`); - await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS)); - continue; - } - throw error; - } - } - throw new Error(`Failed to submit transaction after ${maxRetries + 1} attempts`); - } - /** - * Submit a multi-signed transaction to the Stellar network. - * Adds multiple signatures to the transaction before submission. - * @param builderFn - Function that builds the transaction - * @param signatures - Array of signatures with signer public keys - * @param maxRetries - Max number of retries - * @param baseFee - The starting fee in stroops - */ - async submitMultiSignedTransaction(builderFn, signatures, maxRetries = this.MAX_RETRIES, baseFee) { - let attempt = 0; - while (attempt <= maxRetries) { - try { - const sourceAccount = await this.server.loadAccount(this.keypair.publicKey()); - const currentFee = Math.floor(baseFee * (1 + (this.FEE_INCREMENT_PERCENTAGE * attempt))); - const transaction = builderFn(sourceAccount, currentFee); - // Sign with the local keypair first - transaction.sign(this.keypair); - // Add signatures from other signers - for (const sig of signatures) { - // Skip if this is the local signer's public key (already signed) - if (sig.signerPublicKey === this.keypair.publicKey()) { - continue; - } - // Add the remote signature to the transaction - try { - // Convert hex signature to buffer - const signatureBuffer = Buffer.from(sig.signature, "hex"); - // Create a keypair from the signer's public key to get the hint - const signerKeypair = Keypair.fromPublicKey(sig.signerPublicKey); - // Get the signature hint - const hint = signerKeypair.signatureHint(); - // Get the current envelope - const envelope = transaction.toEnvelope(); - // Add the signature to the envelope - envelope.signature().push(signatureBuffer); - // Add the hint to the hints (Stellar tracks which keys signed) - // Note: This is a simplified approach; in production, - // you might want to use a library that properly handles multi-sig - } - catch (error) { - console.error(`[StellarService] Failed to add signature for ${sig.signerPublicKey}:`, error); - // Continue without this signature (may cause failure on Stellar side) - } - } - return await this.server.submitTransaction(transaction); - } - catch (error) { - attempt++; - const isStuck = this.isStuckError(error); - if (isStuck && attempt <= maxRetries) { - console.warn(`⚠️ Multi-sig transaction stuck or fee too low (Attempt ${attempt}). Bumping fee and retrying in ${this.RETRY_DELAY_MS}ms...`); - await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS)); - continue; - } - throw error; - } - } - throw new Error(`Failed to submit multi-signed transaction after ${maxRetries + 1} attempts`); - } - /** - * Get the network passphrase for the current network. - * Ensures proper network identification for multi-sig operations. - */ - getNetworkPassphrase() { - return this.network === "PUBLIC" ? Networks.PUBLIC : Networks.TESTNET; - } - /** - * Determines if a transaction error indicates it is "stuck" or needs a fee bump. - */ - isStuckError(error) { - const resultCode = error.response?.data?.extras?.result_codes?.transaction; - // tx_too_late: Transaction timebounds expired before inclusion - // tx_insufficient_fee: Mandatory fee not met - // tx_bad_seq: Sequence number mismatch (often due to race conditions/congestion) - // timeout: Network/SDK timeout during submission - return (resultCode === 'tx_too_late' || - resultCode === 'tx_insufficient_fee' || - resultCode === 'tx_bad_seq' || - error.message?.includes('timeout') || - error.code === 'ECONNABORTED'); - } - /** - * Generate a unique ID for the transaction memo - * Format: SF-- - */ - generateMemoId(currency) { - const timestamp = Math.floor(Date.now() / 1000); - const random = Math.floor(Math.random() * 1000).toString().padStart(3, '0'); - // Stellar MemoText limit is 28 bytes - const id = `SF-${currency}-${timestamp}-${random}`; - return id.substring(0, 28); - } -} -//# sourceMappingURL=stellarService.js.map \ No newline at end of file diff --git a/dist/services/stellarService.js.map b/dist/services/stellarService.js.map deleted file mode 100644 index 550340b3..00000000 --- a/dist/services/stellarService.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"stellarService.js","sourceRoot":"","sources":["../../src/services/stellarService.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,kBAAkB,EAElB,SAAS,EACT,QAAQ,EACR,IAAI,EACJ,OAAO,GACR,MAAM,sBAAsB,CAAC;AAC9B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAM,OAAO,cAAc;IACjB,MAAM,CAAiB;IACvB,OAAO,CAAU;IACjB,OAAO,CAAS;IACP,WAAW,GAAG,CAAC,CAAC;IAChB,wBAAwB,GAAG,GAAG,CAAC,CAAC,0BAA0B;IAC1D,cAAc,GAAG,IAAI,CAAC,CAAC,kCAAkC;IAE1E;QACE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;QACjF,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC3E,CAAC;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,SAAS,CAAC;QAExD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,KAAK,QAAQ;YAC1C,CAAC,CAAC,6BAA6B;YAC/B,CAAC,CAAC,qCAAqC,CAAC;QAE1C,IAAI,CAAC,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,iBAAiB;QACrB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC9C,oEAAoE;QACpE,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,4CAA4C;IACpF,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,KAAa,EAAE,MAAc;QACrE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,iBAAiB,EAAE,EAAE,EAAE,CAAC,CAAC;QAE7D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,4BAA4B,CACpD,CAAC,aAAa,EAAE,UAAU,EAAE,EAAE;YAC5B,OAAO,IAAI,kBAAkB,CAAC,aAAa,EAAE;gBAC3C,GAAG,EAAE,UAAU,CAAC,QAAQ,EAAE;gBAC1B,iBAAiB,EAAE,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO;aAClF,CAAC;iBACC,YAAY,CACX,SAAS,CAAC,UAAU,CAAC;gBACnB,IAAI,EAAE,GAAG,QAAQ,QAAQ;gBACzB,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE;aACxB,CAAC,CACH;iBACA,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;iBAC1B,UAAU,CAAC,EAAE,CAAC;iBACd,KAAK,EAAE,CAAC;QACb,CAAC,EACD,IAAI,CAAC,WAAW,EAChB,OAAO,CACR,CAAC;QAEF,OAAO,CAAC,IAAI,CAAC,sBAAsB,QAAQ,qBAAqB,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/E,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,4BAA4B,CAChC,QAAgB,EAChB,KAAa,EACb,MAAc,EACd,UAAiE;QAEjE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,iBAAiB,EAAE,EAAE,EAAE,CAAC,CAAC;QAE7D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,4BAA4B,CACpD,CAAC,aAAa,EAAE,UAAU,EAAE,EAAE;YAC5B,OAAO,IAAI,kBAAkB,CAAC,aAAa,EAAE;gBAC3C,GAAG,EAAE,UAAU,CAAC,QAAQ,EAAE;gBAC1B,iBAAiB,EAAE,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO;aAClF,CAAC;iBACC,YAAY,CACX,SAAS,CAAC,UAAU,CAAC;gBACnB,IAAI,EAAE,GAAG,QAAQ,QAAQ;gBACzB,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE;aACxB,CAAC,CACH;iBACA,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;iBAC1B,UAAU,CAAC,EAAE,CAAC;iBACd,KAAK,EAAE,CAAC;QACb,CAAC,EACD,UAAU,EACV,IAAI,CAAC,WAAW,EAChB,OAAO,CACR,CAAC;QAEF,OAAO,CAAC,IAAI,CAAC,mCAAmC,QAAQ,qBAAqB,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5F,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,4BAA4B,CAChC,SAAsF,EACtF,UAAU,GAAG,IAAI,CAAC,WAAW,EAC7B,OAAe;QAEf,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,OAAO,OAAO,IAAI,UAAU,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;gBAC9E,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,wBAAwB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBAEzF,MAAM,WAAW,GAAG,SAAS,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;gBACzD,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAE/B,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YAC1D,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,OAAO,EAAE,CAAC;gBAEV,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;gBAEzC,IAAI,OAAO,IAAI,OAAO,IAAI,UAAU,EAAE,CAAC;oBACrC,OAAO,CAAC,IAAI,CAAC,gDAAgD,OAAO,kCAAkC,IAAI,CAAC,cAAc,OAAO,CAAC,CAAC;oBAClI,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;oBACvE,SAAS;gBACX,CAAC;gBAED,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,sCAAsC,UAAU,GAAG,CAAC,WAAW,CAAC,CAAC;IACnF,CAAC;IAED;;;;;;;OAOG;IACK,KAAK,CAAC,4BAA4B,CACxC,SAAsF,EACtF,UAAiE,EACjE,UAAU,GAAG,IAAI,CAAC,WAAW,EAC7B,OAAe;QAEf,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,OAAO,OAAO,IAAI,UAAU,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;gBAC9E,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,wBAAwB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBAEzF,MAAM,WAAW,GAAG,SAAS,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;gBAEzD,oCAAoC;gBACpC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAE/B,oCAAoC;gBACpC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;oBAC7B,iEAAiE;oBACjE,IAAI,GAAG,CAAC,eAAe,KAAK,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;wBACrD,SAAS;oBACX,CAAC;oBAED,8CAA8C;oBAC9C,IAAI,CAAC;wBACH,kCAAkC;wBAClC,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;wBAE1D,gEAAgE;wBAChE,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;wBAEjE,yBAAyB;wBACzB,MAAM,IAAI,GAAG,aAAa,CAAC,aAAa,EAAE,CAAC;wBAE3C,2BAA2B;wBAC3B,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,EAAE,CAAC;wBAE1C,oCAAoC;wBACpC,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;wBAE3C,+DAA+D;wBAC/D,sDAAsD;wBACtD,kEAAkE;oBAEpE,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,OAAO,CAAC,KAAK,CACX,gDAAgD,GAAG,CAAC,eAAe,GAAG,EACtE,KAAK,CACN,CAAC;wBACF,sEAAsE;oBACxE,CAAC;gBACH,CAAC;gBAED,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YAC1D,CAAC;YAAC,OAAO,KAAU,EAAE,CAAC;gBACpB,OAAO,EAAE,CAAC;gBAEV,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;gBAEzC,IAAI,OAAO,IAAI,OAAO,IAAI,UAAU,EAAE,CAAC;oBACrC,OAAO,CAAC,IAAI,CAAC,0DAA0D,OAAO,kCAAkC,IAAI,CAAC,cAAc,OAAO,CAAC,CAAC;oBAC5I,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;oBACvE,SAAS;gBACX,CAAC;gBAED,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,mDAAmD,UAAU,GAAG,CAAC,WAAW,CAAC,CAAC;IAChG,CAAC;IAED;;;OAGG;IACK,oBAAoB;QAC1B,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;IACxE,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,KAAU;QAC7B,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,CAAC;QAE3E,+DAA+D;QAC/D,6CAA6C;QAC7C,iFAAiF;QACjF,iDAAiD;QACjD,OAAO,CACL,UAAU,KAAK,aAAa;YAC5B,UAAU,KAAK,qBAAqB;YACpC,UAAU,KAAK,YAAY;YAC3B,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC;YAClC,KAAK,CAAC,IAAI,KAAK,cAAc,CAC9B,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,QAAgB;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAC5E,qCAAqC;QACrC,MAAM,EAAE,GAAG,MAAM,QAAQ,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;QACnD,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7B,CAAC;CACF"} \ No newline at end of file diff --git a/dist/services/webhook.d.ts b/dist/services/webhook.d.ts deleted file mode 100644 index 7620c9d5..00000000 --- a/dist/services/webhook.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -export declare class WebhookService { - private webhookUrl; - private platform; - constructor(); - sendErrorNotification(errorDetails: { - errorType: string; - errorMessage: string; - attempts: number; - service: string; - pricePair: string; - timestamp: Date; - }): Promise; - sendManualReviewNotification(reviewDetails: { - reviewId: number; - currency: string; - rate: number; - previousRate: number; - changePercent: number; - source: string; - timestamp: Date; - reason: string; - }): Promise; - private postMessage; - private formatErrorMessage; - private formatReviewMessage; -} -export declare const webhookService: WebhookService; -export declare const webhookService: WebhookService; -//# sourceMappingURL=webhook.d.ts.map \ No newline at end of file diff --git a/dist/services/webhook.d.ts.map b/dist/services/webhook.d.ts.map deleted file mode 100644 index 68b26653..00000000 --- a/dist/services/webhook.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/services/webhook.ts"],"names":[],"mappings":"AAGA,qBAAa,cAAc;IACzB,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,QAAQ,CAAS;;IAQnB,qBAAqB,CAAC,YAAY,EAAE;QACxC,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,IAAI,CAAC;KACjB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOX,4BAA4B,CAAC,aAAa,EAAE;QAChD,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,IAAI,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,IAAI,CAAC;YAOH,WAAW;IAWzB,OAAO,CAAC,kBAAkB;IA8D1B,OAAO,CAAC,mBAAmB;CA4F5B;AAED,eAAO,MAAM,cAAc,gBAAuB,CAAC;AACnD,eAAO,MAAM,cAAc,gBAAuB,CAAC"} \ No newline at end of file diff --git a/dist/services/webhook.js b/dist/services/webhook.js deleted file mode 100644 index 5605d315..00000000 --- a/dist/services/webhook.js +++ /dev/null @@ -1,159 +0,0 @@ -import axios from "axios"; -export class WebhookService { - webhookUrl; - platform; - constructor() { - this.webhookUrl = - process.env.SLACK_WEBHOOK_URL || process.env.DISCORD_WEBHOOK_URL; - this.platform = process.env.NOTIFICATION_PLATFORM || "slack"; - } - async sendErrorNotification(errorDetails) { - if (!this.webhookUrl) - return; - const message = this.formatErrorMessage(errorDetails); - await this.postMessage(message); - } - async sendManualReviewNotification(reviewDetails) { - if (!this.webhookUrl) - return; - const message = this.formatReviewMessage(reviewDetails); - await this.postMessage(message); - } - async postMessage(message) { - try { - await axios.post(this.webhookUrl, message, { - headers: { "Content-Type": "application/json" }, - timeout: 5000, - }); - } - catch (error) { - console.error("Failed to send webhook notification:", error); - } - } - formatErrorMessage(errorDetails) { - const { errorMessage, attempts, service, pricePair, timestamp } = errorDetails; - if (this.platform === "discord") { - return { - embeds: [ - { - title: "Price Fetch Error", - color: 0xff0000, - fields: [ - { name: "Service", value: service, inline: true }, - { name: "Price Pair", value: pricePair, inline: true }, - { - name: "Failed Attempts", - value: attempts.toString(), - inline: true, - }, - { name: "Error", value: errorMessage.substring(0, 500) }, - { name: "Time", value: new Date(timestamp).toISOString() }, - ], - }, - ], - }; - } - return { - blocks: [ - { - type: "header", - text: { type: "plain_text", text: "Price Fetch Error" }, - }, - { - type: "section", - fields: [ - { type: "mrkdwn", text: `*Service:*\n${service}` }, - { type: "mrkdwn", text: `*Price Pair:*\n${pricePair}` }, - { type: "mrkdwn", text: `*Failed Attempts:*\n${attempts}/3` }, - { - type: "mrkdwn", - text: `*Time:*\n${new Date(timestamp).toISOString()}`, - }, - ], - }, - { - type: "section", - text: { - type: "mrkdwn", - text: `*Error:*\n\`\`\`${errorMessage.substring(0, 500)}\`\`\``, - }, - }, - ], - }; - } - formatReviewMessage(reviewDetails) { - const { reviewId, currency, rate, previousRate, changePercent, source, timestamp, reason, } = reviewDetails; - if (this.platform === "discord") { - return { - embeds: [ - { - title: "Manual Price Review Required", - color: 0xffa500, - fields: [ - { name: "Review ID", value: reviewId.toString(), inline: true }, - { name: "Currency", value: currency, inline: true }, - { name: "Source", value: source, inline: true }, - { name: "Current Rate", value: rate.toString(), inline: true }, - { - name: "Previous Safe Rate", - value: previousRate.toString(), - inline: true, - }, - { - name: "Change", - value: `${changePercent.toFixed(2)}%`, - inline: true, - }, - { name: "Reason", value: reason.substring(0, 500) }, - { name: "Time", value: timestamp.toISOString() }, - ], - }, - ], - }; - } - return { - blocks: [ - { - type: "header", - text: { type: "plain_text", text: "Manual Price Review Required" }, - }, - { - type: "section", - fields: [ - { type: "mrkdwn", text: `*Review ID:*\n${reviewId}` }, - { type: "mrkdwn", text: `*Currency:*\n${currency}` }, - { type: "mrkdwn", text: `*Source:*\n${source}` }, - { type: "mrkdwn", text: `*Current Rate:*\n${rate}` }, - { - type: "mrkdwn", - text: `*Previous Safe Rate:*\n${previousRate}`, - }, - { - type: "mrkdwn", - text: `*Change:*\n${changePercent.toFixed(2)}%`, - }, - ], - }, - { - type: "section", - text: { - type: "mrkdwn", - text: `*Reason:*\n${reason}`, - }, - }, - { - type: "context", - elements: [ - { - type: "mrkdwn", - text: `Detected at ${timestamp.toISOString()}`, - }, - ], - }, - ], - }; - } -} -export const webhookService = new WebhookService(); -export const webhookService = new WebhookService(); -//# sourceMappingURL=webhook.js.map \ No newline at end of file diff --git a/dist/services/webhook.js.map b/dist/services/webhook.js.map deleted file mode 100644 index 69839efb..00000000 --- a/dist/services/webhook.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/services/webhook.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/stroops.d.ts b/dist/utils/stroops.d.ts deleted file mode 100644 index 28d578bb..00000000 --- a/dist/utils/stroops.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export declare function toStroops(price: number | string): number; -//# sourceMappingURL=stroops.d.ts.map \ No newline at end of file diff --git a/dist/utils/stroops.d.ts.map b/dist/utils/stroops.d.ts.map deleted file mode 100644 index ae8b9723..00000000 --- a/dist/utils/stroops.d.ts.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"stroops.d.ts","sourceRoot":"","sources":["../../src/utils/stroops.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAGxD"} \ No newline at end of file diff --git a/dist/utils/stroops.js b/dist/utils/stroops.js deleted file mode 100644 index e0ef6e97..00000000 --- a/dist/utils/stroops.js +++ /dev/null @@ -1,6 +0,0 @@ -const STROOPS_PER_UNIT = 10_000_000; -export function toStroops(price) { - const value = typeof price === "string" ? parseFloat(price) : price; - return Math.round(value * STROOPS_PER_UNIT); -} -//# sourceMappingURL=stroops.js.map \ No newline at end of file diff --git a/dist/utils/stroops.js.map b/dist/utils/stroops.js.map deleted file mode 100644 index b9a89e6c..00000000 --- a/dist/utils/stroops.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"stroops.js","sourceRoot":"","sources":["../../src/utils/stroops.ts"],"names":[],"mappings":"AAAA,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAEpC,MAAM,UAAU,SAAS,CAAC,KAAsB;IAC9C,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACpE,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,gBAAgB,CAAC,CAAC;AAC9C,CAAC"} \ No newline at end of file diff --git a/node_modules/.bin/acorn b/node_modules/.bin/acorn index cf767603..679bd163 120000 --- a/node_modules/.bin/acorn +++ b/node_modules/.bin/acorn @@ -1 +1,16 @@ -../acorn/bin/acorn \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../acorn/bin/acorn" "$@" +else + exec node "$basedir/../acorn/bin/acorn" "$@" +fi diff --git a/node_modules/.bin/esbuild b/node_modules/.bin/esbuild index c83ac070..63bb6d40 120000 --- a/node_modules/.bin/esbuild +++ b/node_modules/.bin/esbuild @@ -1 +1,16 @@ -../esbuild/bin/esbuild \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../esbuild/bin/esbuild" "$@" +else + exec node "$basedir/../esbuild/bin/esbuild" "$@" +fi diff --git a/node_modules/.bin/prisma b/node_modules/.bin/prisma index af8b4c8c..d770cd32 120000 --- a/node_modules/.bin/prisma +++ b/node_modules/.bin/prisma @@ -1 +1,16 @@ -../prisma/build/index.js \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../prisma/build/index.js" "$@" +else + exec node "$basedir/../prisma/build/index.js" "$@" +fi diff --git a/node_modules/.bin/sha.js b/node_modules/.bin/sha.js index 3c761051..9215bc22 120000 --- a/node_modules/.bin/sha.js +++ b/node_modules/.bin/sha.js @@ -1 +1,16 @@ -../sha.js/bin.js \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../sha.js/bin.js" "$@" +else + exec node "$basedir/../sha.js/bin.js" "$@" +fi diff --git a/node_modules/.bin/stellar-js b/node_modules/.bin/stellar-js index 6dd7e36d..19973a83 120000 --- a/node_modules/.bin/stellar-js +++ b/node_modules/.bin/stellar-js @@ -1 +1,16 @@ -../@stellar/stellar-sdk/bin/stellar-js \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../@stellar/stellar-sdk/bin/stellar-js" "$@" +else + exec node "$basedir/../@stellar/stellar-sdk/bin/stellar-js" "$@" +fi diff --git a/node_modules/.bin/ts-node b/node_modules/.bin/ts-node index b3ff94bc..f3d4faba 120000 --- a/node_modules/.bin/ts-node +++ b/node_modules/.bin/ts-node @@ -1 +1,16 @@ -../ts-node/dist/bin.js \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../ts-node/dist/bin.js" "$@" +else + exec node "$basedir/../ts-node/dist/bin.js" "$@" +fi diff --git a/node_modules/.bin/ts-node-cwd b/node_modules/.bin/ts-node-cwd index 54984a43..ae68e858 120000 --- a/node_modules/.bin/ts-node-cwd +++ b/node_modules/.bin/ts-node-cwd @@ -1 +1,16 @@ -../ts-node/dist/bin-cwd.js \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../ts-node/dist/bin-cwd.js" "$@" +else + exec node "$basedir/../ts-node/dist/bin-cwd.js" "$@" +fi diff --git a/node_modules/.bin/ts-node-esm b/node_modules/.bin/ts-node-esm index a19d9ed1..19ea759f 120000 --- a/node_modules/.bin/ts-node-esm +++ b/node_modules/.bin/ts-node-esm @@ -1 +1,16 @@ -../ts-node/dist/bin-esm.js \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../ts-node/dist/bin-esm.js" "$@" +else + exec node "$basedir/../ts-node/dist/bin-esm.js" "$@" +fi diff --git a/node_modules/.bin/ts-node-script b/node_modules/.bin/ts-node-script index edc40b30..14c2f67c 120000 --- a/node_modules/.bin/ts-node-script +++ b/node_modules/.bin/ts-node-script @@ -1 +1,16 @@ -../ts-node/dist/bin-script.js \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../ts-node/dist/bin-script.js" "$@" +else + exec node "$basedir/../ts-node/dist/bin-script.js" "$@" +fi diff --git a/node_modules/.bin/ts-node-transpile-only b/node_modules/.bin/ts-node-transpile-only index 173710d0..d3d4c0c9 120000 --- a/node_modules/.bin/ts-node-transpile-only +++ b/node_modules/.bin/ts-node-transpile-only @@ -1 +1,16 @@ -../ts-node/dist/bin-transpile.js \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../ts-node/dist/bin-transpile.js" "$@" +else + exec node "$basedir/../ts-node/dist/bin-transpile.js" "$@" +fi diff --git a/node_modules/.bin/ts-script b/node_modules/.bin/ts-script index 7382912f..8f65f364 120000 --- a/node_modules/.bin/ts-script +++ b/node_modules/.bin/ts-script @@ -1 +1,16 @@ -../ts-node/dist/bin-script-deprecated.js \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../ts-node/dist/bin-script-deprecated.js" "$@" +else + exec node "$basedir/../ts-node/dist/bin-script-deprecated.js" "$@" +fi diff --git a/node_modules/.bin/tsc b/node_modules/.bin/tsc index 0863208a..c4864b9a 120000 --- a/node_modules/.bin/tsc +++ b/node_modules/.bin/tsc @@ -1 +1,16 @@ -../typescript/bin/tsc \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@" +else + exec node "$basedir/../typescript/bin/tsc" "$@" +fi diff --git a/node_modules/.bin/tsserver b/node_modules/.bin/tsserver index f8f8f1a0..6c19ce3d 120000 --- a/node_modules/.bin/tsserver +++ b/node_modules/.bin/tsserver @@ -1 +1,16 @@ -../typescript/bin/tsserver \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@" +else + exec node "$basedir/../typescript/bin/tsserver" "$@" +fi diff --git a/node_modules/.bin/tsx b/node_modules/.bin/tsx index f7282dd8..590318c3 120000 --- a/node_modules/.bin/tsx +++ b/node_modules/.bin/tsx @@ -1 +1,16 @@ -../tsx/dist/cli.mjs \ No newline at end of file +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) + if command -v cygpath > /dev/null 2>&1; then + basedir=`cygpath -w "$basedir"` + fi + ;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../tsx/dist/cli.mjs" "$@" +else + exec node "$basedir/../tsx/dist/cli.mjs" "$@" +fi diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index a00fa1b7..51340650 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -4,10 +4,55 @@ "lockfileVersion": 3, "requires": true, "packages": { + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", + "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "license": "MIT" + }, + "node_modules/@apidevtools/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^9.0.6", + "@apidevtools/openapi-schemas": "^2.0.4", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "z-schema": "^5.0.1" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, "node_modules/@chevrotain/cst-dts-gen": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz", "integrity": "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==", + "license": "Apache-2.0", "dependencies": { "@chevrotain/gast": "10.5.0", "@chevrotain/types": "10.5.0", @@ -18,6 +63,7 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz", "integrity": "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==", + "license": "Apache-2.0", "dependencies": { "@chevrotain/types": "10.5.0", "lodash": "4.17.21" @@ -26,12 +72,23 @@ "node_modules/@chevrotain/types": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz", - "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==" + "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==", + "license": "Apache-2.0" }, "node_modules/@chevrotain/utils": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz", - "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==" + "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==", + "license": "Apache-2.0" + }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", @@ -45,15 +102,28 @@ "node": ">=12" } }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.8.tgz", + "integrity": "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==", + "license": "MIT", + "dependencies": { + "@so-ric/colorspace": "^1.1.6", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "node_modules/@electric-sql/pglite": { "version": "0.3.15", "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.15.tgz", - "integrity": "sha512-Cj++n1Mekf9ETfdc16TlDi+cDDQF0W7EcbyRHYOAeZdsAe8M/FJg18itDTSwyHfar2WIezawM9o0EKaRGVKygQ==" + "integrity": "sha512-Cj++n1Mekf9ETfdc16TlDi+cDDQF0W7EcbyRHYOAeZdsAe8M/FJg18itDTSwyHfar2WIezawM9o0EKaRGVKygQ==", + "license": "Apache-2.0" }, "node_modules/@electric-sql/pglite-socket": { "version": "0.0.20", "resolved": "https://registry.npmjs.org/@electric-sql/pglite-socket/-/pglite-socket-0.0.20.tgz", "integrity": "sha512-J5nLGsicnD9wJHnno9r+DGxfcZWh+YJMCe0q/aCgtG6XOm9Z7fKeite8IZSNXgZeGltSigM9U/vAWZQWdgcSFg==", + "license": "Apache-2.0", "bin": { "pglite-server": "dist/scripts/server.js" }, @@ -65,14 +135,33 @@ "version": "0.2.20", "resolved": "https://registry.npmjs.org/@electric-sql/pglite-tools/-/pglite-tools-0.2.20.tgz", "integrity": "sha512-BK50ZnYa3IG7ztXhtgYf0Q7zijV32Iw1cYS8C+ThdQlwx12V5VZ9KRJ42y82Hyb4PkTxZQklVQA9JHyUlex33A==", + "license": "Apache-2.0", "peerDependencies": { "@electric-sql/pglite": "0.3.15" } }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz", + "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@hono/node-server": { "version": "1.19.9", "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==", + "license": "MIT", "engines": { "node": ">=18.14.1" }, @@ -105,10 +194,17 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "license": "MIT" + }, "node_modules/@mrleebo/prisma-ast": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/@mrleebo/prisma-ast/-/prisma-ast-0.13.1.tgz", "integrity": "sha512-XyroGQXcHrZdvmrGJvsA9KNeOOgGMg1Vg9OlheUsBOSKznLMDl+YChxbkboRHvtFYJEMRYmlV3uoo/njCw05iw==", + "license": "MIT", "dependencies": { "chevrotain": "^10.5.0", "lilconfig": "^2.1.0" @@ -219,6 +315,7 @@ "version": "7.5.0", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-7.5.0.tgz", "integrity": "sha512-h4hF9ctp+kSRs7ENHGsFQmHAgHcfkOCxbYt6Ti9Xi8x7D+kP4tTi9x51UKmiTH/OqdyJAO+8V+r+JA5AWdav7w==", + "license": "Apache-2.0", "dependencies": { "@prisma/client-runtime-utils": "7.5.0" }, @@ -241,12 +338,14 @@ "node_modules/@prisma/client-runtime-utils": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@prisma/client-runtime-utils/-/client-runtime-utils-7.5.0.tgz", - "integrity": "sha512-KnJ2b4Si/pcWEtK68uM+h0h1oh80CZt2suhLTVuLaSKg4n58Q9jBF/A42Kw6Ma+aThy1yAhfDeTC0JvEmeZnFQ==" + "integrity": "sha512-KnJ2b4Si/pcWEtK68uM+h0h1oh80CZt2suhLTVuLaSKg4n58Q9jBF/A42Kw6Ma+aThy1yAhfDeTC0JvEmeZnFQ==", + "license": "Apache-2.0" }, "node_modules/@prisma/config": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@prisma/config/-/config-7.5.0.tgz", "integrity": "sha512-1J/9YEX7A889xM46PYg9e8VAuSL1IUmXJW3tEhMv7XQHDWlfC9YSkIw9sTYRaq5GswGlxZ+GnnyiNsUZ9JJhSQ==", + "license": "Apache-2.0", "dependencies": { "c12": "3.1.0", "deepmerge-ts": "7.1.5", @@ -264,6 +363,7 @@ "version": "0.20.0", "resolved": "https://registry.npmjs.org/@prisma/dev/-/dev-0.20.0.tgz", "integrity": "sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ==", + "license": "ISC", "dependencies": { "@electric-sql/pglite": "0.3.15", "@electric-sql/pglite-socket": "0.0.20", @@ -308,12 +408,14 @@ "node_modules/@prisma/engines-version": { "version": "7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e", "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e.tgz", - "integrity": "sha512-E+iRV/vbJLl8iGjVr6g/TEWokA+gjkV/doZkaQN1i/ULVdDwGnPJDfLUIFGS3BVwlG/m6L8T4x1x5isl8hGMxA==" + "integrity": "sha512-E+iRV/vbJLl8iGjVr6g/TEWokA+gjkV/doZkaQN1i/ULVdDwGnPJDfLUIFGS3BVwlG/m6L8T4x1x5isl8hGMxA==", + "license": "Apache-2.0" }, "node_modules/@prisma/engines/node_modules/@prisma/get-platform": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.5.0.tgz", "integrity": "sha512-7I+2y1nu/gkEKSiHHbcZ1HPe/euGdEqJZxEEMT0246q4De1+hla0ZzlTgvaT9dHcVCgLSuCG8v39db5qUUWNgw==", + "license": "Apache-2.0", "dependencies": { "@prisma/debug": "7.5.0" } @@ -322,6 +424,7 @@ "version": "7.5.0", "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-7.5.0.tgz", "integrity": "sha512-kZCl2FV54qnyrVdnII8MI6qvt7HfU6Cbiz8dZ8PXz4f4lbSw45jEB9/gEMK2SGdiNhBKyk/Wv95uthoLhGMLYA==", + "license": "Apache-2.0", "dependencies": { "@prisma/debug": "7.5.0", "@prisma/engines-version": "7.5.0-15.280c870be64f457428992c43c1f6d557fab6e29e", @@ -332,6 +435,7 @@ "version": "7.5.0", "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.5.0.tgz", "integrity": "sha512-7I+2y1nu/gkEKSiHHbcZ1HPe/euGdEqJZxEEMT0246q4De1+hla0ZzlTgvaT9dHcVCgLSuCG8v39db5qUUWNgw==", + "license": "Apache-2.0", "dependencies": { "@prisma/debug": "7.5.0" } @@ -340,6 +444,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-7.2.0.tgz", "integrity": "sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==", + "license": "Apache-2.0", "dependencies": { "@prisma/debug": "7.2.0" } @@ -347,17 +452,20 @@ "node_modules/@prisma/get-platform/node_modules/@prisma/debug": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-7.2.0.tgz", - "integrity": "sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw==" + "integrity": "sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw==", + "license": "Apache-2.0" }, "node_modules/@prisma/query-plan-executor": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@prisma/query-plan-executor/-/query-plan-executor-7.2.0.tgz", - "integrity": "sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==" + "integrity": "sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==", + "license": "Apache-2.0" }, "node_modules/@prisma/studio-core": { "version": "0.21.1", "resolved": "https://registry.npmjs.org/@prisma/studio-core/-/studio-core-0.21.1.tgz", "integrity": "sha512-bOGqG/eMQtKC0XVvcVLRmhWWzm/I+0QUWqAEhEBtetpuS3k3V4IWqKGUONkAIT223DNXJMxMtZp36b1FmcdPeg==", + "license": "Apache-2.0", "engines": { "node": "^20.19 || ^22.12 || ^24.0", "pnpm": "8" @@ -368,6 +476,23 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "hasInstallScript": true, + "license": "Apache-2.0" + }, + "node_modules/@so-ric/colorspace": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@so-ric/colorspace/-/colorspace-1.1.6.tgz", + "integrity": "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==", + "license": "MIT", + "dependencies": { + "color": "^5.0.2", + "text-hex": "1.0.x" + } + }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", @@ -377,7 +502,8 @@ "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==" + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" }, "node_modules/@stellar/js-xdr": { "version": "3.1.2", @@ -511,6 +637,22 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/morgan": { + "version": "1.9.10", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.10.tgz", + "integrity": "sha512-sS4A1zheMvsADRVfT0lYbJ4S9lmsey8Zo2F7cnbYjWHP67Q0AwMYuuzLlkIM2N8gAbb9cubhIVFwcIN2XyYCkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "22.19.15", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.15.tgz", @@ -549,6 +691,7 @@ "version": "19.2.14", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "license": "MIT", "peer": true, "dependencies": { "csstype": "^3.2.2" @@ -575,6 +718,30 @@ "@types/node": "*" } }, + "node_modules/@types/swagger-jsdoc": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/swagger-jsdoc/-/swagger-jsdoc-6.0.4.tgz", + "integrity": "sha512-W+Xw5epcOZrF/AooUM/PccNMSAFOKWZA5dasNyMujTwsBkU74njSJBpvCCJhHAJ95XRMzQrrW844Btu0uoetwQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/swagger-ui-express": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.8.tgz", + "integrity": "sha512-AhZV8/EIreHFmBV5wAs0gzJUNq9JbbSXgJLQubCC0jtIo6prnI9MIRRxnU4MZX9RB9yXxF1V4R7jtLl/Wcj31g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "license": "MIT" + }, "node_modules/@types/ws": { "version": "8.18.1", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", @@ -627,6 +794,18 @@ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "license": "MIT" }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -652,6 +831,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "license": "MIT", "engines": { "node": ">= 6.0.0" } @@ -667,6 +847,12 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, "node_modules/base32.js": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", @@ -705,6 +891,24 @@ "node": "^4.5.0 || >= 5.9" } }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, "node_modules/bignumber.js": { "version": "9.3.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", @@ -738,6 +942,16 @@ "url": "https://opencollective.com/express" } }, + "node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -775,6 +989,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/c12/-/c12-3.1.0.tgz", "integrity": "sha512-uWoS8OU1MEIsOv8p/5a82c3H31LsWVR5qiyXVfBNOzfffjUWtPnhAb4BYI2uG2HfGmZmFjCtui5XNWaps+iFuw==", + "license": "MIT", "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.2.2", @@ -802,6 +1017,7 @@ "version": "16.6.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, @@ -856,10 +1072,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "license": "MIT" + }, "node_modules/chevrotain": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz", "integrity": "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==", + "license": "Apache-2.0", "dependencies": { "@chevrotain/cst-dts-gen": "10.5.0", "@chevrotain/gast": "10.5.0", @@ -873,6 +1096,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", "dependencies": { "readdirp": "^4.0.1" }, @@ -887,10 +1111,57 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "license": "MIT", "dependencies": { "consola": "^3.2.3" } }, + "node_modules/color": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", + "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", + "license": "MIT", + "dependencies": { + "color-convert": "^3.1.3", + "color-string": "^2.1.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/color-convert": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", + "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=14.6" + } + }, + "node_modules/color-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/color-string": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", + "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -912,15 +1183,23 @@ "node": ">=20" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, "node_modules/confbox": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", - "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==" + "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", + "license": "MIT" }, "node_modules/consola": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "license": "MIT", "engines": { "node": "^14.18.0 || >=16.10.0" } @@ -992,6 +1271,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1005,6 +1285,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT", "peer": true }, "node_modules/debug": { @@ -1028,6 +1309,7 @@ "version": "7.1.5", "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz", "integrity": "sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==", + "license": "BSD-3-Clause", "engines": { "node": ">=16.0.0" } @@ -1052,7 +1334,8 @@ "node_modules/defu": { "version": "6.1.4", "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==" + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "license": "MIT" }, "node_modules/delayed-stream": { "version": "1.0.0", @@ -1067,6 +1350,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", "engines": { "node": ">=0.10" } @@ -1083,7 +1367,8 @@ "node_modules/destr": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", - "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==" + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "license": "MIT" }, "node_modules/diff": { "version": "4.0.4", @@ -1094,6 +1379,18 @@ "node": ">=0.3.1" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dotenv": { "version": "17.3.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", @@ -1130,6 +1427,7 @@ "version": "3.18.4", "resolved": "https://registry.npmjs.org/effect/-/effect-3.18.4.tgz", "integrity": "sha512-b1LXQJLe9D11wfnOKAk3PKxuqYshQ0Heez+y5pnkd3jLj1yx9QhM72zZ9uUrOQyNvrs2GZZd/3maL0ZV18YuDA==", + "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", "fast-check": "^3.23.1" @@ -1139,10 +1437,17 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz", "integrity": "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==", + "license": "MIT", "engines": { "node": ">=14" } }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "license": "MIT" + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -1318,6 +1623,15 @@ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "license": "MIT" }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -1382,7 +1696,8 @@ "node_modules/exsolve": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", - "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==" + "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", + "license": "MIT" }, "node_modules/fast-check": { "version": "3.23.2", @@ -1398,6 +1713,7 @@ "url": "https://opencollective.com/fast-check" } ], + "license": "MIT", "dependencies": { "pure-rand": "^6.1.0" }, @@ -1414,6 +1730,12 @@ "is-retry-allowed": "^3.0.0" } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "license": "MIT" + }, "node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", @@ -1435,6 +1757,12 @@ "url": "https://opencollective.com/express" } }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", + "license": "MIT" + }, "node_modules/follow-redirects": { "version": "1.15.11", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", @@ -1474,6 +1802,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" @@ -1540,6 +1869,12 @@ "node": ">= 0.8" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -1553,6 +1888,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "license": "MIT", "dependencies": { "is-property": "^1.0.2" } @@ -1584,7 +1920,8 @@ "node_modules/get-port-please": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.2.0.tgz", - "integrity": "sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==" + "integrity": "sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==", + "license": "MIT" }, "node_modules/get-proto": { "version": "1.0.1", @@ -1616,6 +1953,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "license": "MIT", "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", @@ -1628,6 +1966,27 @@ "giget": "dist/cli.mjs" } }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -1643,17 +2002,20 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" }, "node_modules/grammex": { "version": "3.1.12", "resolved": "https://registry.npmjs.org/grammex/-/grammex-3.1.12.tgz", - "integrity": "sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ==" + "integrity": "sha512-6ufJOsSA7LcQehIJNCO7HIBykfM7DXQual0Ny780/DEcJIpBlHRvcqEBWGPYd7hrXL2GJ3oJI1MIhaXjWmLQOQ==", + "license": "MIT" }, "node_modules/graphmatch": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/graphmatch/-/graphmatch-1.1.1.tgz", - "integrity": "sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==" + "integrity": "sha512-5ykVn/EXM1hF0XCaWh05VbYvEiOL2lY1kBxZtaYsyvjp7cmWOU1XsAdfQBwClraEofXDT197lFbXOEVMHpvQOg==", + "license": "MIT" }, "node_modules/has-property-descriptors": { "version": "1.0.2", @@ -1710,6 +2072,7 @@ "version": "4.11.4", "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.4.tgz", "integrity": "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==", + "license": "MIT", "engines": { "node": ">=16.9.0" } @@ -1737,7 +2100,8 @@ "node_modules/http-status-codes": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/http-status-codes/-/http-status-codes-2.3.0.tgz", - "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==" + "integrity": "sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==", + "license": "MIT" }, "node_modules/iconv-lite": { "version": "0.7.2", @@ -1775,6 +2139,17 @@ ], "license": "BSD-3-Clause" }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -1811,7 +2186,8 @@ "node_modules/is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "license": "MIT" }, "node_modules/is-retry-allowed": { "version": "3.0.0", @@ -1825,6 +2201,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-typed-array": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", @@ -1849,20 +2237,41 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "license": "MIT" + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "license": "MIT", "engines": { "node": ">=10" } @@ -1870,17 +2279,57 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "license": "MIT" + }, + "node_modules/logform": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", + "license": "MIT", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } }, "node_modules/long": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==" + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" }, "node_modules/lru.min": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.4.tgz", "integrity": "sha512-DqC6n3QQ77zdFpCMASA1a3Jlb64Hv2N2DciFGkO/4L9+q/IpIAuRlKOvCXabtRW6cQf8usbmM6BE/TOPysCdIA==", + "license": "MIT", "engines": { "bun": ">=1.0.0", "deno": ">=1.30.0", @@ -1952,6 +2401,61 @@ "url": "https://opencollective.com/express" } }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/morgan": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz", + "integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==", + "license": "MIT", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.1.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -1962,6 +2466,7 @@ "version": "3.15.3", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.15.3.tgz", "integrity": "sha512-FBrGau0IXmuqg4haEZRBfHNWB5mUARw6hNwPDXXGg0XzVJ50mr/9hb267lvpVMnhZ1FON3qNd4Xfcez1rbFwSg==", + "license": "MIT", "dependencies": { "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", @@ -1981,6 +2486,7 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz", "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==", + "license": "MIT", "dependencies": { "lru.min": "^1.1.0" }, @@ -2000,12 +2506,14 @@ "node_modules/node-fetch-native": { "version": "1.6.7", "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", - "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==" + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "license": "MIT" }, "node_modules/nypm": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.5.tgz", "integrity": "sha512-K6AJy1GMVyfyMXRVB88700BJqNUkByijGJM8kEHpLdcAt+vSQAVfkWWHYzuRXHSY6xA2sNc5RjTj0p9rE2izVQ==", + "license": "MIT", "dependencies": { "citty": "^0.2.0", "pathe": "^2.0.3", @@ -2021,7 +2529,8 @@ "node_modules/nypm/node_modules/citty": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.1.tgz", - "integrity": "sha512-kEV95lFBhQgtogAPlQfJJ0WGVSokvLr/UEoFPiKKOXF7pl98HfUVUD0ejsuTCld/9xH9vogSywZ5KqHzXrZpqg==" + "integrity": "sha512-kEV95lFBhQgtogAPlQfJJ0WGVSokvLr/UEoFPiKKOXF7pl98HfUVUD0ejsuTCld/9xH9vogSywZ5KqHzXrZpqg==", + "license": "MIT" }, "node_modules/object-assign": { "version": "4.1.1", @@ -2053,7 +2562,8 @@ "node_modules/ohash": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==" + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "license": "MIT" }, "node_modules/on-finished": { "version": "2.4.1", @@ -2067,6 +2577,15 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2076,6 +2595,22 @@ "wrappy": "1" } }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "license": "MIT", + "dependencies": { + "fn.name": "1.x.x" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "license": "MIT", + "peer": true + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -2085,10 +2620,20 @@ "node": ">= 0.8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", "engines": { "node": ">=8" } @@ -2106,12 +2651,14 @@ "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==" + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" }, "node_modules/perfect-debounce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", - "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==" + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" }, "node_modules/pg": { "version": "8.20.0", @@ -2224,6 +2771,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "license": "MIT", "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", @@ -2243,6 +2791,7 @@ "version": "3.4.7", "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.7.tgz", "integrity": "sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==", + "license": "Unlicense", "engines": { "node": ">=12" }, @@ -2332,6 +2881,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", @@ -2341,7 +2891,8 @@ "node_modules/proper-lockfile/node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -2375,7 +2926,8 @@ "type": "opencollective", "url": "https://opencollective.com/fast-check" } - ] + ], + "license": "MIT" }, "node_modules/qs": { "version": "6.15.0", @@ -2429,6 +2981,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "license": "MIT", "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" @@ -2438,6 +2991,7 @@ "version": "19.2.4", "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -2447,6 +3001,7 @@ "version": "19.2.4", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", "peer": true, "dependencies": { "scheduler": "^0.27.0" @@ -2455,10 +3010,25 @@ "react": "^19.2.4" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "license": "MIT", "engines": { "node": ">= 14.18.0" }, @@ -2470,12 +3040,14 @@ "node_modules/regexp-to-ast": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", - "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==", + "license": "MIT" }, "node_modules/remeda": { "version": "2.33.4", "resolved": "https://registry.npmjs.org/remeda/-/remeda-2.33.4.tgz", "integrity": "sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/remeda" } @@ -2494,6 +3066,7 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", "engines": { "node": ">= 4" } @@ -2534,6 +3107,15 @@ ], "license": "MIT" }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -2544,6 +3126,7 @@ "version": "0.27.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT", "peer": true }, "node_modules/send": { @@ -2643,6 +3226,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -2654,6 +3238,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", "engines": { "node": ">=8" } @@ -2734,6 +3319,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", "engines": { "node": ">=14" }, @@ -2838,10 +3424,20 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -2854,12 +3450,94 @@ "node_modules/std-env": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==" + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/swagger-jsdoc": { + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", + "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", + "license": "MIT", + "dependencies": { + "commander": "6.2.0", + "doctrine": "3.0.0", + "glob": "7.1.6", + "lodash.mergewith": "^4.6.2", + "swagger-parser": "^10.0.3", + "yaml": "2.0.0-1" + }, + "bin": { + "swagger-jsdoc": "bin/swagger-jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/swagger-jsdoc/node_modules/commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", + "license": "MIT", + "dependencies": { + "@apidevtools/swagger-parser": "10.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.32.1", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.32.1.tgz", + "integrity": "sha512-6HQoo7+j8PA2QqP5kgAb9dl1uxUjvR0SAoL/WUp1sTEvm0F6D5npgU2OGCLwl++bIInqGlEUQ2mpuZRZYtyCzQ==", + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "=1.4.0" + } + }, + "node_modules/swagger-ui-express": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz", + "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==", + "license": "MIT", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "license": "MIT" }, "node_modules/tinyexec": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "license": "MIT", "engines": { "node": ">=18" } @@ -2893,6 +3571,15 @@ "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", "license": "MIT" }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -3018,6 +3705,12 @@ "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", "license": "MIT" }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -3028,6 +3721,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/valibot/-/valibot-1.2.0.tgz", "integrity": "sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==", + "license": "MIT", "peerDependencies": { "typescript": ">=5" }, @@ -3037,6 +3731,15 @@ } } }, + "node_modules/validator": { + "version": "13.15.26", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz", + "integrity": "sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -3050,6 +3753,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -3081,6 +3785,42 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/winston": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz", + "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==", + "license": "MIT", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.8", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.7.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.9.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", + "license": "MIT", + "dependencies": { + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -3117,6 +3857,15 @@ "node": ">=0.4" } }, + "node_modules/yaml": { + "version": "2.0.0-1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", + "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -3126,10 +3875,41 @@ "node": ">=6" } }, + "node_modules/z-schema": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", + "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", + "license": "MIT", + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "commander": "^9.4.1" + } + }, + "node_modules/z-schema/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/zeptomatch": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/zeptomatch/-/zeptomatch-2.1.0.tgz", "integrity": "sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA==", + "license": "MIT", "dependencies": { "grammex": "^3.1.11", "graphmatch": "^1.1.0" diff --git a/node_modules/esbuild/bin/esbuild b/node_modules/esbuild/bin/esbuild index 21e1bda0..0ee0ef1e 100755 Binary files a/node_modules/esbuild/bin/esbuild and b/node_modules/esbuild/bin/esbuild differ diff --git a/package-lock.json b/package-lock.json index 73036d7a..8ab62d60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,8 @@ "swagger-jsdoc": "^6.2.8", "swagger-ui-express": "^5.0.1", "ts-node": "^10.9.2", - "typescript": "^5.9.3" + "typescript": "^5.9.3", + "winston": "^3.17.0" }, "devDependencies": { "@types/cors": "^2.8.19", @@ -113,6 +114,15 @@ "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==", "license": "Apache-2.0" }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -125,6 +135,17 @@ "node": ">=12" } }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.8.tgz", + "integrity": "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==", + "license": "MIT", + "dependencies": { + "@so-ric/colorspace": "^1.1.6", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "node_modules/@electric-sql/pglite": { "version": "0.3.15", "resolved": "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.15.tgz", @@ -920,6 +941,16 @@ "hasInstallScript": true, "license": "Apache-2.0" }, + "node_modules/@so-ric/colorspace": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@so-ric/colorspace/-/colorspace-1.1.6.tgz", + "integrity": "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==", + "license": "MIT", + "dependencies": { + "color": "^5.0.2", + "text-hex": "1.0.x" + } + }, "node_modules/@socket.io/component-emitter": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", @@ -1163,6 +1194,12 @@ "@types/serve-static": "*" } }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "license": "MIT" + }, "node_modules/@types/ws": { "version": "8.18.1", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", @@ -1221,6 +1258,12 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "license": "Python-2.0" }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1531,6 +1574,52 @@ "consola": "^3.2.3" } }, + "node_modules/color": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", + "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", + "license": "MIT", + "dependencies": { + "color-convert": "^3.1.3", + "color-string": "^2.1.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/color-convert": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", + "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=14.6" + } + }, + "node_modules/color-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/color-string": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", + "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1811,6 +1900,12 @@ "node": ">=14" } }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "license": "MIT" + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -2093,6 +2188,12 @@ "is-retry-allowed": "^3.0.0" } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "license": "MIT" + }, "node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", @@ -2114,6 +2215,12 @@ "url": "https://opencollective.com/express" } }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", + "license": "MIT" + }, "node_modules/follow-redirects": { "version": "1.15.11", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", @@ -2567,6 +2674,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-typed-array": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", @@ -2615,6 +2734,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "license": "MIT" + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -2650,6 +2775,23 @@ "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", "license": "MIT" }, + "node_modules/logform": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", + "license": "MIT", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/long": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", @@ -2926,6 +3068,15 @@ "wrappy": "1" } }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "license": "MIT", + "dependencies": { + "fn.name": "1.x.x" + } + }, "node_modules/openapi-types": { "version": "12.1.3", "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", @@ -3332,6 +3483,20 @@ "react": "^19.2.4" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -3415,6 +3580,15 @@ ], "license": "MIT" }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -3728,6 +3902,15 @@ "node": ">= 0.6" } }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -3743,6 +3926,15 @@ "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "license": "MIT" }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/swagger-jsdoc": { "version": "6.2.8", "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", @@ -3808,6 +4000,12 @@ "express": ">=4.0.0 || >=5.0.0-beta" } }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "license": "MIT" + }, "node_modules/tinyexec": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", @@ -3846,6 +4044,15 @@ "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", "license": "MIT" }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -3971,6 +4178,12 @@ "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==", "license": "MIT" }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -4045,6 +4258,42 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/winston": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz", + "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==", + "license": "MIT", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.8", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.7.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.9.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", + "license": "MIT", + "dependencies": { + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/prisma/seed.ts b/prisma/seed.ts index eada5956..f0d150df 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -4,6 +4,7 @@ */ import { PrismaClient } from "@prisma/client"; +import { logger } from "../src/lib/logger"; const prisma = new PrismaClient(); @@ -53,7 +54,7 @@ const currencies = [ ]; async function main() { - console.log("Seeding database..."); + logger.info("Seeding database..."); for (const currency of currencies) { const existing = await prisma.currency.findUnique({ @@ -64,18 +65,18 @@ async function main() { await prisma.currency.create({ data: currency, }); - console.log(`Created currency: ${currency.code}`); + logger.info(`Created currency: ${currency.code}`); } else { - console.log(`Currency already exists: ${currency.code}`); + logger.info(`Currency already exists: ${currency.code}`); } } - console.log("Seeding completed!"); + logger.info("Seeding completed!"); } main() .catch((e) => { - console.error(e); + logger.error(e); process.exit(1); }) .finally(async () => { diff --git a/prisma_output.txt b/prisma_output.txt new file mode 100644 index 00000000..a1492515 Binary files /dev/null and b/prisma_output.txt differ diff --git a/scripts/check-gas-balance.ts b/scripts/check-gas-balance.ts index 7dd2b04f..98314ee8 100644 --- a/scripts/check-gas-balance.ts +++ b/scripts/check-gas-balance.ts @@ -2,6 +2,7 @@ import dotenv from "dotenv"; import { Horizon, Keypair } from "@stellar/stellar-sdk"; +import { logger } from "../src/lib/logger"; dotenv.config(); @@ -61,19 +62,19 @@ async function checkGasAccountBalance(): Promise { const now = new Date().toISOString(); if (xlmBalance < threshold) { - console.error( + logger.error( `ALERT ${now}: Gas Account balance is low (${xlmBalance.toFixed(7)} XLM). Threshold: ${threshold.toFixed(2)} XLM. Account: ${publicKey}`, ); process.exitCode = 2; return; } - console.log( + logger.info( `OK ${now}: Gas Account balance is healthy (${xlmBalance.toFixed(7)} XLM). Threshold: ${threshold.toFixed(2)} XLM.`, ); } checkGasAccountBalance().catch((error) => { - console.error("Failed to check Gas Account balance:", error); + logger.error("Failed to check Gas Account balance:", error); process.exit(1); }); \ No newline at end of file diff --git a/scripts/download-ngn-rates.ts b/scripts/download-ngn-rates.ts index 8d09feea..4e0a62d2 100644 --- a/scripts/download-ngn-rates.ts +++ b/scripts/download-ngn-rates.ts @@ -3,6 +3,7 @@ import { writeFileSync } from "fs"; import { Prisma, PriceHistory } from "@prisma/client"; import { prisma } from "../src/lib/prisma.js"; +import { logger } from "../src/lib/logger.js"; async function downloadNGNRates() { try { @@ -10,7 +11,7 @@ async function downloadNGNRates() { const thirtyDaysAgo = new Date(); thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30); - console.log(`Fetching NGN rates from ${thirtyDaysAgo.toISOString()} to now...`); + logger.info(`Fetching NGN rates from ${thirtyDaysAgo.toISOString()} to now...`); // Query PriceHistory for NGN rates in the last 30 days const rates: PriceHistory[] = await prisma.priceHistory.findMany({ @@ -26,11 +27,11 @@ async function downloadNGNRates() { }); if (rates.length === 0) { - console.log("No NGN rates found in the last 30 days."); + logger.info("No NGN rates found in the last 30 days."); return; } - console.log(`Found ${rates.length} NGN rate records.`); + logger.info(`Found ${rates.length} NGN rate records.`); // Convert to CSV format const csvHeader = "timestamp,rate,source\n"; @@ -43,8 +44,8 @@ async function downloadNGNRates() { const filename = `ngn-rates-last-30-days-${new Date().toISOString().split('T')[0]}.csv`; writeFileSync(filename, csvContent); - console.log(`NGN rates exported to ${filename}`); - console.log(`Total records: ${rates.length}`); + logger.info(`NGN rates exported to ${filename}`); + logger.info(`Total records: ${rates.length}`); // Show some stats const ratesValues = rates.map((r: PriceHistory) => parseFloat(r.rate.toString())); @@ -52,11 +53,11 @@ async function downloadNGNRates() { const maxRate = Math.max(...ratesValues); const avgRate = ratesValues.reduce((sum: number, rate: number) => sum + rate, 0) / ratesValues.length; - console.log(`Rate range: ${minRate.toFixed(2)} - ${maxRate.toFixed(2)} NGN/XLM`); - console.log(`Average rate: ${avgRate.toFixed(2)} NGN/XLM`); + logger.info(`Rate range: ${minRate.toFixed(2)} - ${maxRate.toFixed(2)} NGN/XLM`); + logger.info(`Average rate: ${avgRate.toFixed(2)} NGN/XLM`); } catch (error) { - console.error("Error downloading NGN rates:", error); + logger.error("Error downloading NGN rates:", error); process.exit(1); } finally { await prisma.$disconnect(); diff --git a/src/index.ts b/src/index.ts index c345de75..20a193cd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ import express from "express"; +// Standardized logging system initialization. import { createServer } from "http"; import cors from "cors"; import dotenv from "dotenv"; @@ -17,6 +18,7 @@ import { SorobanEventListener } from "./services/sorobanEventListener"; import { specs } from "./lib/swagger"; import { multiSigSubmissionService } from "./services/multiSigSubmissionService"; import { apiKeyMiddleware } from "./middleware/apiKeyMiddleware"; +import { logger, morganStream } from "./lib/logger"; // Load environment variables dotenv.config(); @@ -32,9 +34,9 @@ for (const envVar of requiredEnvVars) { } if (missingEnvVars.length > 0) { - console.error("❌ Missing required environment variables:"); - missingEnvVars.forEach((varName) => console.error(` - ${varName}`)); - console.error( + logger.error("❌ Missing required environment variables:"); + missingEnvVars.forEach((varName) => logger.error(` - ${varName}`)); + logger.error( "\nPlease set these variables in your .env file and restart the server.", ); process.exit(1); @@ -44,7 +46,7 @@ const dashboardUrl = process.env.DASHBOARD_URL || process.env.FRONTEND_URL || "http://localhost:3000"; if (!dashboardUrl) { - console.error("❌ Missing required environment variable: DASHBOARD_URL"); + logger.error("❌ Missing required environment variable: DASHBOARD_URL"); process.exit(1); } @@ -60,7 +62,12 @@ const horizonUrl = const horizonServer = new Horizon.Server(horizonUrl); // Middleware -app.use(morgan("dev")); +app.use( + morgan(process.env.NODE_ENV === "production" ? "combined" : "dev", { + stream: morganStream, + skip: (req) => req.url === "/health" || req.url === "/", + }), +); app.use( cors({ origin: (origin, callback) => { @@ -242,7 +249,7 @@ app.use( res: express.Response, next: express.NextFunction, ) => { - console.error("Unhandled error:", err); + logger.error("Unhandled error:", err); res.status(500).json({ success: false, error: "Internal server error", @@ -263,25 +270,25 @@ const httpServer = createServer(app); initSocket(httpServer); httpServer.listen(PORT, () => { - console.log(`🌊 StellarFlow Backend running on port ${PORT}`); - console.log( + logger.info(`🌊 StellarFlow Backend running on port ${PORT}`); + logger.info( `📊 Market Rates API available at http://localhost:${PORT}/api/market-rates`, ); - console.log( + logger.info( `📚 API Documentation available at http://localhost:${PORT}/api/docs`, ); - console.log(`🏥 Health check at http://localhost:${PORT}/health`); - console.log(`🔌 Socket.io ready for dashboard connections`); + logger.info(`🏥 Health check at http://localhost:${PORT}/health`); + logger.info(`🔌 Socket.io ready for dashboard connections`); // Start Soroban event listener to track confirmed on-chain prices try { const eventListener = new SorobanEventListener(); eventListener.start().catch((err) => { - console.error("Failed to start event listener:", err); + logger.error("Failed to start event listener:", err); }); - console.log(`👂 Soroban event listener started`); + logger.info(`👂 Soroban event listener started`); } catch (err) { - console.warn( + logger.warn( "Event listener not started:", err instanceof Error ? err.message : err, ); @@ -291,11 +298,11 @@ httpServer.listen(PORT, () => { if (process.env.MULTI_SIG_ENABLED === "true") { try { multiSigSubmissionService.start().catch((err: Error) => { - console.error("Failed to start multi-sig submission service:", err); + logger.error("Failed to start multi-sig submission service:", err); }); - console.log(`🔐 Multi-Sig submission service started`); + logger.info(`🔐 Multi-Sig submission service started`); } catch (err) { - console.warn( + logger.warn( "Multi-sig submission service not started:", err instanceof Error ? err.message : err ); diff --git a/src/lib/logger.ts b/src/lib/logger.ts new file mode 100644 index 00000000..7eaf4a56 --- /dev/null +++ b/src/lib/logger.ts @@ -0,0 +1,63 @@ +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import winston from "winston"; + +const { combine, timestamp, errors, json, colorize, printf } = winston.format; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const logsDirectory = path.resolve(__dirname, "../../logs"); + +if (!fs.existsSync(logsDirectory)) { + fs.mkdirSync(logsDirectory, { recursive: true }); +} + +const consoleFormat = combine( + colorize(), + timestamp(), + errors({ stack: true }), + printf(({ timestamp: time, level, message, stack, ...meta }) => { + const metadata = + Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : ""; + + if (stack) { + return `${time} ${level}: ${message}\n${stack}${metadata}`; + } + + return `${time} ${level}: ${message}${metadata}`; + }), +); + +const transports: winston.transport[] = [ + new winston.transports.File({ + filename: path.join(logsDirectory, "error.log"), + level: "error", + maxsize: 5 * 1024 * 1024, + maxFiles: 5, + tailable: true, + }), + new winston.transports.File({ + filename: path.join(logsDirectory, "combined.log"), + maxsize: 10 * 1024 * 1024, + maxFiles: 5, + tailable: true, + }), + new winston.transports.Console({ + format: consoleFormat, + }), +]; + +export const logger = winston.createLogger({ + level: process.env.NODE_ENV === "production" ? "info" : "debug", + format: combine(timestamp(), errors({ stack: true }), json()), + defaultMeta: { service: "stellarflow-backend" }, + transports, + exitOnError: false, +}); + +export const morganStream = { + write: (message: string): void => { + logger.http(message.trim()); + }, +}; diff --git a/src/lib/socket.ts b/src/lib/socket.ts index a15edec8..aa3bde37 100644 --- a/src/lib/socket.ts +++ b/src/lib/socket.ts @@ -1,4 +1,5 @@ import { Server } from "socket.io"; +import { logger } from "./logger"; let io: Server | null = null; @@ -8,9 +9,9 @@ export function initSocket(server: import("http").Server): Server { }); io.on("connection", (socket) => { - console.log(`🔌 Client connected: ${socket.id}`); + logger.info(`🔌 Client connected: ${socket.id}`); socket.on("disconnect", () => - console.log(`🔌 Client disconnected: ${socket.id}`) + logger.info(`🔌 Client disconnected: ${socket.id}`) ); }); diff --git a/src/middleware/apiKeyMiddleware.ts b/src/middleware/apiKeyMiddleware.ts index 883961c6..ec621d7f 100644 --- a/src/middleware/apiKeyMiddleware.ts +++ b/src/middleware/apiKeyMiddleware.ts @@ -1,11 +1,12 @@ import { Request, Response, NextFunction } from "express"; +import { logger } from "../lib/logger"; export const apiKeyMiddleware = (req: Request, res: Response, next: NextFunction) => { const apiKey = req.headers["x-api-key"]; const expectedKey = process.env.API_KEY; if (!expectedKey) { - console.error("Critical: API_KEY not set in environment"); + logger.error("Critical: API_KEY not set in environment"); return res.status(500).json({ success: false, error: "Authentication configuration error", diff --git a/src/routes/marketRates.ts b/src/routes/marketRates.ts index e153f6be..53231832 100644 --- a/src/routes/marketRates.ts +++ b/src/routes/marketRates.ts @@ -2,6 +2,7 @@ import { Router } from "express"; import { getRate, getAllRates } from "../controllers/marketRatesController"; import { MarketRateService } from "../services/marketRate"; +import { logger } from "../lib/logger"; const marketRateService = new MarketRateService(); @@ -109,7 +110,7 @@ router.get("/latest", async (req, res) => { }); } } catch (error) { - console.error("Error fetching latest prices:", error); + logger.error("Error fetching latest prices:", error); res.status(500).json({ success: false, diff --git a/src/routes/priceUpdates.ts b/src/routes/priceUpdates.ts index c97f5c49..d0f7b824 100644 --- a/src/routes/priceUpdates.ts +++ b/src/routes/priceUpdates.ts @@ -1,5 +1,6 @@ import express, { Request, Response } from "express"; import { multiSigService, SignaturePayload } from "../services/multiSigService"; +import { logger } from "../lib/logger"; const router = express.Router(); @@ -32,7 +33,7 @@ router.post("/multi-sig/request", async (req: Request, res: Response) => { data: signatureRequest, }); } catch (error) { - console.error("[API] Multi-sig request creation failed:", error); + logger.error("[API] Multi-sig request creation failed:", error); res.status(500).json({ success: false, error: String(error), @@ -46,7 +47,7 @@ router.post("/multi-sig/request", async (req: Request, res: Response) => { * This is called by peer servers in the multi-sig setup. * * Requires: - * - Authorization header with token (if MULTI_SIG_AUTH_TOKEN is set) + * - Authorization header with token ( if MULTI_SIG_AUTH_TOKEN is set) * - Signature payload in body */ router.post("/sign", async (req: Request, res: Response) => { @@ -93,7 +94,7 @@ router.post("/sign", async (req: Request, res: Response) => { }, }); } catch (error) { - console.error("[API] Signature creation failed:", error); + logger.error("[API] Signature creation failed:", error); res.status(400).json({ success: false, error: String(error), @@ -132,7 +133,7 @@ router.post("/multi-sig/:multiSigPriceId/request-signature", async (req: Request res.json({ success: true }); } catch (error) { - console.error("[API] Remote signature request failed:", error); + logger.error("[API] Remote signature request failed:", error); res.status(500).json({ success: false, error: String(error), @@ -184,7 +185,7 @@ router.get("/multi-sig/:multiSigPriceId/status", async (req: Request, res: Respo }, }); } catch (error) { - console.error("[API] Multi-sig status fetch failed:", error); + logger.error("[API] Multi-sig status fetch failed:", error); res.status(500).json({ success: false, error: String(error), @@ -215,7 +216,7 @@ router.get("/multi-sig/pending", async (req: Request, res: Response) => { })), }); } catch (error) { - console.error("[API] Pending multi-sig fetch failed:", error); + logger.error("[API] Pending multi-sig fetch failed:", error); res.status(500).json({ success: false, error: String(error), @@ -275,7 +276,7 @@ router.get("/multi-sig/:multiSigPriceId/signatures", async (req: Request, res: R }, }); } catch (error) { - console.error("[API] Signature fetch failed:", error); + logger.error("[API] Signature fetch failed:", error); res.status(500).json({ success: false, error: String(error), @@ -307,7 +308,7 @@ router.post("/multi-sig/:multiSigPriceId/record-submission", async (req: Request res.json({ success: true }); } catch (error) { - console.error("[API] Submission recording failed:", error); + logger.error("[API] Submission recording failed:", error); res.status(500).json({ success: false, error: String(error), @@ -328,7 +329,7 @@ router.get("/multi-sig/signer-info", async (req: Request, res: Response) => { data: signerInfo, }); } catch (error) { - console.error("[API] Signer info fetch failed:", error); + logger.error("[API] Signer info fetch failed:", error); res.status(500).json({ success: false, error: String(error), diff --git a/src/routes/stats.ts b/src/routes/stats.ts index 8e30acec..a827df38 100644 --- a/src/routes/stats.ts +++ b/src/routes/stats.ts @@ -1,5 +1,6 @@ import { Router } from "express"; import prisma from "../lib/prisma"; +import { logger } from "../lib/logger"; const router = Router(); @@ -128,7 +129,7 @@ router.get("/volume", async (req, res) => { data: volumeStats, }); } catch (error) { - console.error("Error fetching volume stats:", error); + logger.error("Error fetching volume stats:", error); res.status(500).json({ success: false, error: error instanceof Error ? error.message : "Internal server error", diff --git a/src/services/intelligenceService.ts b/src/services/intelligenceService.ts index 1d8b352c..bb3351c5 100644 --- a/src/services/intelligenceService.ts +++ b/src/services/intelligenceService.ts @@ -1,4 +1,5 @@ import prisma from "../lib/prisma"; +import { logger } from "../lib/logger"; export class IntelligenceService { /** @@ -59,7 +60,7 @@ export class IntelligenceService { return `${sign}${changePercent.toFixed(1)}%`; } catch (error) { - console.error(`Error calculating 24h change for ${asset}:`, error); + logger.error(`Error calculating 24h change for ${asset}:`, error); return "0.0%"; } } @@ -99,7 +100,7 @@ export class IntelligenceService { return staleCurrencies; } catch (error) { - console.error("Error detecting stale currencies:", error); + logger.error("Error detecting stale currencies:", error); return []; } } diff --git a/src/services/marketRate/ghsFetcher.ts b/src/services/marketRate/ghsFetcher.ts index 74f0d910..3b853e5f 100644 --- a/src/services/marketRate/ghsFetcher.ts +++ b/src/services/marketRate/ghsFetcher.ts @@ -1,4 +1,5 @@ import axios from "axios"; +import { logger } from "../../lib/logger"; import { MarketRateFetcher, MarketRate, calculateMedian, filterOutliers, SourceTrustLevel, calculateWeightedAverage } from "./types"; import { errorTracker } from "../errorTracker"; import { webhookService } from "../webhook"; @@ -70,7 +71,7 @@ export class GHSRateFetcher implements MarketRateFetcher { errorTracker.trackSuccess("GHS-price-fetch"); } } catch (error) { - console.debug("CoinGecko direct GHS price failed"); + logger.debug("CoinGecko direct GHS price failed"); } // Strategy 2: CoinGecko XLM/USD + ExchangeRate API @@ -127,7 +128,7 @@ export class GHSRateFetcher implements MarketRateFetcher { } } } catch (error) { - console.debug("CoinGecko + ExchangeRate API failed"); + logger.debug("CoinGecko + ExchangeRate API failed"); } // Strategy 3: Try alternative XLM pricing source @@ -173,7 +174,7 @@ export class GHSRateFetcher implements MarketRateFetcher { } } } catch (error) { - console.debug("Alternative XLM pricing source failed"); + logger.debug("Alternative XLM pricing source failed"); } // If we have prices, calculate median diff --git a/src/services/marketRate/kesFetcher.ts b/src/services/marketRate/kesFetcher.ts index 3512ad2c..40baa919 100644 --- a/src/services/marketRate/kesFetcher.ts +++ b/src/services/marketRate/kesFetcher.ts @@ -1,4 +1,5 @@ import axios, { AxiosError } from "axios"; +import { logger } from "../../lib/logger"; import { MarketRateFetcher, MarketRate, @@ -177,7 +178,7 @@ async function withRetry( config.maxDelayMs, ); - console.debug( + logger.debug( `Retry attempt ${attempt}/${config.maxAttempts} for ${operationName} ` + `after ${delay}ms delay. Error: ${lastError.message}`, ); @@ -286,13 +287,13 @@ export class KESRateFetcher implements MarketRateFetcher { ); if (binanceRate) { - console.info(`✅ KES rate fetched from Binance: ${binanceRate.rate}`); + logger.info(`✅ KES rate fetched from Binance: ${binanceRate.rate}`); return binanceRate; } } catch (error) { const errorMsg = error instanceof Error ? error.message : "Unknown Binance error"; - console.warn(`⚠️ Binance API failed: ${errorMsg}`); + logger.warn(`⚠️ Binance API failed: ${errorMsg}`); errors.push({ source: "Binance API", message: errorMsg, @@ -304,13 +305,13 @@ export class KESRateFetcher implements MarketRateFetcher { try { const cbkRate = await this.fetchFromCBK(); if (cbkRate) { - console.info(`✅ KES rate fetched from CBK: ${cbkRate.rate}`); + logger.info(`✅ KES rate fetched from CBK: ${cbkRate.rate}`); return cbkRate; } } catch (error) { const errorMsg = error instanceof Error ? error.message : "Unknown CBK error"; - console.warn(`⚠️ Central Bank of Kenya API failed: ${errorMsg}`); + logger.warn(`⚠️ Central Bank of Kenya API failed: ${errorMsg}`); errors.push({ source: "Central Bank of Kenya", message: errorMsg, @@ -327,7 +328,7 @@ export class KESRateFetcher implements MarketRateFetcher { source.name, ); if (rate) { - console.info(`✅ KES rate fetched from ${source.name}: ${rate.rate}`); + logger.info(`✅ KES rate fetched from ${source.name}: ${rate.rate}`); return rate; } } catch (error) { @@ -335,7 +336,7 @@ export class KESRateFetcher implements MarketRateFetcher { error instanceof Error ? error.message : `Unknown ${source.name} error`; - console.warn(`⚠️ ${source.name} failed: ${errorMsg}`); + logger.warn(`⚠️ ${source.name} failed: ${errorMsg}`); errors.push({ source: source.name, message: errorMsg, @@ -346,7 +347,7 @@ export class KESRateFetcher implements MarketRateFetcher { // All sources failed - throw comprehensive error const errorMessage = this.buildErrorMessage(errors); - console.error(`❌ All KES rate sources failed: ${errorMessage}`); + logger.error(`❌ All KES rate sources failed: ${errorMessage}`); throw new Error(errorMessage); } @@ -378,7 +379,7 @@ export class KESRateFetcher implements MarketRateFetcher { }); } } catch (error) { - console.debug("Direct XLMKES pair not available"); + logger.debug("Direct XLMKES pair not available"); } // Strategy 2: Try Binance P2P API @@ -393,7 +394,7 @@ export class KESRateFetcher implements MarketRateFetcher { }); } } catch (error) { - console.debug("Binance P2P API not available"); + logger.debug("Binance P2P API not available"); } // Strategy 3: XLMUSDT × KES/USD calculation @@ -408,7 +409,7 @@ export class KESRateFetcher implements MarketRateFetcher { }); } } catch (error) { - console.debug("XLMUSDT pair not available"); + logger.debug("XLMUSDT pair not available"); } // If no prices were collected, return null @@ -536,7 +537,7 @@ export class KESRateFetcher implements MarketRateFetcher { private async fetchFromCBK(): Promise { const cbkSource = RATE_SOURCES[2]; if (!cbkSource) { - console.warn("Central Bank of Kenya source not configured"); + logger.warn("Central Bank of Kenya source not configured"); return null; } @@ -606,7 +607,7 @@ export class KESRateFetcher implements MarketRateFetcher { if (axiosError.response) { // Server responded with error status - console.warn( + logger.warn( `${source} returned status ${axiosError.response.status}: ` + `${axiosError.response.statusText}`, ); @@ -615,20 +616,20 @@ export class KESRateFetcher implements MarketRateFetcher { axiosError.code === "ETIMEDOUT" ) { // Request timeout - console.warn(`${source} request timed out`); + logger.warn(`${source} request timed out`); } else if (axiosError.code === "ERR_NETWORK") { // Network error - console.warn(`${source} network error - service may be down`); + logger.warn(`${source} network error - service may be down`); } else if (axiosError.message.includes("Network Error")) { // CORS or network issue - console.warn( + logger.warn( `${source} network error - check connectivity or CORS settings`, ); } else { - console.warn(`${source} error: ${axiosError.message}`); + logger.warn(`${source} error: ${axiosError.message}`); } } else { - console.warn(`${source} unexpected error:`, error); + logger.warn(`${source} unexpected error:`, error); } } @@ -657,12 +658,12 @@ export class KESRateFetcher implements MarketRateFetcher { ); const healthy = testRate !== null && testRate.rate > 0; - console.debug( + logger.debug( `Health check result: ${healthy ? "HEALTHY" : "UNHEALTHY"}`, ); return healthy; } catch (error) { - console.warn( + logger.warn( "Health check failed:", error instanceof Error ? error.message : "Unknown error", ); @@ -685,6 +686,6 @@ export class KESRateFetcher implements MarketRateFetcher { */ resetCircuitBreaker(): void { this.circuitBreaker.reset(); - console.info("Circuit breaker reset"); + logger.info("Circuit breaker reset"); } } diff --git a/src/services/marketRate/marketRateService.ts b/src/services/marketRate/marketRateService.ts index b94f4eb9..c2dabf4a 100644 --- a/src/services/marketRate/marketRateService.ts +++ b/src/services/marketRate/marketRateService.ts @@ -12,6 +12,7 @@ import { multiSigService } from "../multiSigService"; import { getIO } from "../../lib/socket"; import prisma from "../../lib/prisma"; import dotenv from "dotenv"; +import { logger } from "../../lib/logger"; dotenv.config(); @@ -42,7 +43,7 @@ export class MarketRateService { } if (this.multiSigEnabled) { - console.info( + logger.info( `[MarketRateService] Multi-Sig mode ENABLED with ${this.remoteOracleServers.length} remote servers` ); } @@ -144,7 +145,7 @@ export class MarketRateService { if (this.multiSigEnabled) { // Multi-sig workflow: create request and collect signatures - console.info( + logger.info( `[MarketRateService] Starting multi-sig workflow for ${normalizedCurrency} rate ${rate.rate}` ); @@ -159,11 +160,11 @@ export class MarketRateService { // Sign locally first try { await multiSigService.signMultiSigPrice(signatureRequest.multiSigPriceId); - console.info( + logger.info( `[MarketRateService] Local signature added for multi-sig request ${signatureRequest.multiSigPriceId}` ); } catch (error) { - console.error( + logger.error( `[MarketRateService] Failed to sign locally:`, error ); @@ -175,7 +176,7 @@ export class MarketRateService { signatureRequest.multiSigPriceId, memoId ).catch((err) => { - console.error( + logger.error( `[MarketRateService] Error requesting remote signatures:`, err ); @@ -198,18 +199,18 @@ export class MarketRateService { memoId, txHash ); - console.info( + logger.info( `[MarketRateService] Single-sig price update submitted for ${normalizedCurrency}` ); } } catch (stellarError) { - console.error( + logger.error( "Failed to submit price update to Stellar network:", stellarError ); } } else { - console.warn( + logger.warn( `Manual review required for ${normalizedCurrency} rate ${rate.rate}. Skipping contract submission.` ); } @@ -238,7 +239,7 @@ export class MarketRateService { }, }); } catch (dbError) { - console.error("Failed to persist price history:", dbError); + logger.error("Failed to persist price history:", dbError); } // Broadcast fresh price to all connected dashboard clients @@ -420,7 +421,7 @@ export class MarketRateService { multiSigPriceId: number, memoId: string ): Promise { - console.info( + logger.info( `[MarketRateService] Requesting signatures from ${this.remoteOracleServers.length} remote servers for multi-sig ${multiSigPriceId}` ); @@ -435,16 +436,16 @@ export class MarketRateService { results.forEach((result, index) => { if (result.status === "fulfilled") { if (result.value.success) { - console.info( + logger.info( `[MarketRateService] ✅ Signature request sent to ${this.remoteOracleServers[index]}` ); } else { - console.warn( + logger.warn( `[MarketRateService] ⚠️ Signature request failed for ${this.remoteOracleServers[index]}: ${result.value.error}` ); } } else { - console.error( + logger.error( `[MarketRateService] ❌ Error requesting signature from ${this.remoteOracleServers[index]}:`, result.reason ); diff --git a/src/services/marketRate/ngnFetcher.ts b/src/services/marketRate/ngnFetcher.ts index 6958d2c0..5788f78a 100644 --- a/src/services/marketRate/ngnFetcher.ts +++ b/src/services/marketRate/ngnFetcher.ts @@ -1,4 +1,5 @@ import axios from "axios"; +import { logger } from "../../lib/logger"; import { MarketRateFetcher, MarketRate, calculateMedian, filterOutliers, SourceTrustLevel, calculateWeightedAverage } from "./types"; type CoinGeckoPriceResponse = { @@ -158,7 +159,7 @@ export class NGNRateFetcher implements MarketRateFetcher { } } } catch { - console.debug("VTpass + CoinGecko XLM/USD failed"); + logger.debug("VTpass + CoinGecko XLM/USD failed"); } // Strategy 2: CoinGecko direct XLM/NGN @@ -191,7 +192,7 @@ export class NGNRateFetcher implements MarketRateFetcher { }); } } catch { - console.debug("CoinGecko direct NGN failed"); + logger.debug("CoinGecko direct NGN failed"); } // Strategy 3: CoinGecko XLM/USD × USD/NGN (open.er-api) @@ -245,7 +246,7 @@ export class NGNRateFetcher implements MarketRateFetcher { } } } catch { - console.debug("CoinGecko + ExchangeRate API (NGN) failed"); + logger.debug("CoinGecko + ExchangeRate API (NGN) failed"); } if (prices.length > 0) { diff --git a/src/services/multiSigService.ts b/src/services/multiSigService.ts index 93d989a5..646fe6f5 100644 --- a/src/services/multiSigService.ts +++ b/src/services/multiSigService.ts @@ -1,6 +1,7 @@ import prisma from "../lib/prisma"; import { Keypair } from "@stellar/stellar-sdk"; import dotenv from "dotenv"; +import { logger } from "../lib/logger"; dotenv.config(); @@ -76,7 +77,7 @@ export class MultiSigService { }, }); - console.info( + logger.info( `[MultiSig] Created signature request ${created.id} for ${currency} rate ${rate}` ); @@ -156,7 +157,7 @@ export class MultiSigService { }, }); - console.info( + logger.info( `[MultiSig] Added signature ${updated.collectedSignatures}/${updated.requiredSignatures} for MultiSigPrice ${multiSigPriceId}` ); @@ -238,7 +239,7 @@ export class MultiSigService { }, }); - console.info( + logger.info( `[MultiSig] Added remote signature ${updated.collectedSignatures}/${updated.requiredSignatures} for MultiSigPrice ${multiSigPriceId}` ); @@ -250,7 +251,7 @@ export class MultiSigService { return { success: true }; } catch (error) { - console.error( + logger.error( `[MultiSig] Failed to request signature from ${remoteServerUrl}:`, error ); @@ -317,7 +318,7 @@ export class MultiSigService { }); if (result.count > 0) { - console.warn( + logger.warn( `[MultiSig] Expired ${result.count} multi-sig price requests` ); } @@ -337,7 +338,7 @@ export class MultiSigService { }, }); - console.info( + logger.info( `[MultiSig] MultiSigPrice ${multiSigPriceId} is now APPROVED (all signatures collected)` ); } @@ -372,7 +373,7 @@ export class MultiSigService { }, }); - console.info( + logger.info( `[MultiSig] MultiSigPrice ${multiSigPriceId} submitted to Stellar - TxHash: ${stellarTxHash}` ); } diff --git a/src/services/multiSigSubmissionService.ts b/src/services/multiSigSubmissionService.ts index cb4d2676..cae67f7d 100644 --- a/src/services/multiSigSubmissionService.ts +++ b/src/services/multiSigSubmissionService.ts @@ -3,6 +3,7 @@ import { StellarService } from "./stellarService"; import { priceReviewService } from "./priceReviewService"; import prisma from "../lib/prisma"; import dotenv from "dotenv"; +import { logger } from "../lib/logger"; dotenv.config(); @@ -28,14 +29,12 @@ export class MultiSigSubmissionService { */ async start(): Promise { if (this.isRunning) { - console.warn( - "[MultiSigSubmissionService] Service is already running" - ); + logger.warn("[MultiSigSubmissionService] Service is already running"); return; } this.isRunning = true; - console.info( + logger.info( `[MultiSigSubmissionService] Started with ${this.pollIntervalMs}ms poll interval` ); @@ -45,7 +44,7 @@ export class MultiSigSubmissionService { // Start periodic polling this.pollTimer = setInterval(() => { this.checkAndSubmitApprovedPrices().catch((err) => { - console.error( + logger.error( "[MultiSigSubmissionService] Polling error:", err ); @@ -62,7 +61,7 @@ export class MultiSigSubmissionService { this.pollTimer = null; } this.isRunning = false; - console.info("[MultiSigSubmissionService] Stopped"); + logger.info("[MultiSigSubmissionService] Stopped"); } /** @@ -91,7 +90,7 @@ export class MultiSigSubmissionService { return; // Nothing to do } - console.info( + logger.info( `[MultiSigSubmissionService] Found ${approvedPrices.length} approved prices to submit` ); @@ -100,7 +99,7 @@ export class MultiSigSubmissionService { try { await this.submitApprovedPrice(multiSigPrice); } catch (error) { - console.error( + logger.error( `[MultiSigSubmissionService] Failed to submit multi-sig price ${multiSigPrice.id}:`, error ); @@ -108,7 +107,7 @@ export class MultiSigSubmissionService { } } } catch (error) { - console.error( + logger.error( "[MultiSigSubmissionService] Error checking approved prices:", error ); @@ -127,13 +126,13 @@ export class MultiSigSubmissionService { })); if (signatures.length === 0) { - console.warn( + logger.warn( `[MultiSigSubmissionService] No signatures found for multi-sig price ${multiSigPrice.id}` ); return; } - console.info( + logger.info( `[MultiSigSubmissionService] Submitting multi-sig price ${multiSigPrice.id} (${multiSigPrice.currency} @ ${multiSigPrice.rate}) with ${signatures.length} signatures` ); @@ -160,11 +159,11 @@ export class MultiSigSubmissionService { txHash ); - console.info( + logger.info( `[MultiSigSubmissionService] ✅ Successfully submitted multi-sig price ${multiSigPrice.id} - TxHash: ${txHash}` ); } catch (error) { - console.error( + logger.error( `[MultiSigSubmissionService] Error submitting multi-sig price ${multiSigPrice.id}:`, error ); @@ -180,13 +179,13 @@ export class MultiSigSubmissionService { try { const count = await multiSigService.cleanupExpiredRequests(); if (count > 0) { - console.info( + logger.info( `[MultiSigSubmissionService] Cleaned up ${count} expired multi-sig requests` ); } return count; } catch (error) { - console.error( + logger.error( "[MultiSigSubmissionService] Error during cleanup:", error ); diff --git a/src/services/sorobanEventListener.ts b/src/services/sorobanEventListener.ts index d4ed65d5..d14ef059 100644 --- a/src/services/sorobanEventListener.ts +++ b/src/services/sorobanEventListener.ts @@ -4,6 +4,7 @@ import type { OnChainPrice } from "@prisma/client"; import prisma from "../lib/prisma"; import { getIO } from "../lib/socket"; import dotenv from "dotenv"; +import { logger } from "../lib/logger"; dotenv.config(); @@ -47,12 +48,12 @@ export class SorobanEventListener { async start(): Promise { if (this.isRunning) { - console.warn("SorobanEventListener is already running"); + logger.warn("SorobanEventListener is already running"); return; } this.isRunning = true; - console.log( + logger.info( `[EventListener] Starting listener for account ${this.oraclePublicKey}` ); @@ -62,7 +63,7 @@ export class SorobanEventListener { }); if (lastRecord) { this.lastProcessedLedger = lastRecord.ledgerSeq; - console.log( + logger.info( `[EventListener] Resuming from ledger ${this.lastProcessedLedger}` ); } @@ -73,7 +74,7 @@ export class SorobanEventListener { // Start periodic polling this.pollTimer = setInterval(() => { this.pollTransactions().catch((err) => { - console.error("[EventListener] Poll error:", err); + logger.error("[EventListener] Poll error:", err); }); }, this.pollIntervalMs); } @@ -84,7 +85,7 @@ export class SorobanEventListener { this.pollTimer = null; } this.isRunning = false; - console.log("[EventListener] Stopped"); + logger.info("[EventListener] Stopped"); } private async pollTransactions(): Promise { @@ -133,7 +134,7 @@ export class SorobanEventListener { error instanceof Error && error.message.includes("status code 404") ) { - console.log("[EventListener] No transactions found for oracle account"); + logger.info("[EventListener] No transactions found for oracle account"); return; } throw error; @@ -183,7 +184,7 @@ export class SorobanEventListener { const rate = parseFloat(valueStr); if (isNaN(rate)) { - console.warn( + logger.warn( `[EventListener] Invalid rate value for ${currency}: ${valueStr}` ); continue; @@ -199,7 +200,7 @@ export class SorobanEventListener { }); } } catch (error) { - console.error( + logger.error( `[EventListener] Error parsing operations for tx ${tx.hash}:`, error ); @@ -228,11 +229,11 @@ export class SorobanEventListener { confirmedAt: price.confirmedAt, }, }); - console.log( + logger.info( `[EventListener] Saved confirmed price: ${price.currency} = ${price.rate} (tx: ${price.txHash.substring(0, 8)}...)` ); } catch (error) { - console.error( + logger.error( `[EventListener] Error saving price for ${price.currency}:`, error ); diff --git a/src/services/stellarService.ts b/src/services/stellarService.ts index 1d3c273a..1ce2e7b2 100644 --- a/src/services/stellarService.ts +++ b/src/services/stellarService.ts @@ -9,6 +9,7 @@ import { xdr, } from "@stellar/stellar-sdk"; import dotenv from "dotenv"; +import { logger } from "../lib/logger"; dotenv.config(); @@ -78,7 +79,7 @@ export class StellarService { baseFee ); - console.info(`✅ Price update for ${currency} confirmed. Hash: ${result.hash}`); + logger.info(`✅ Price update for ${currency} confirmed. Hash: ${result.hash}`); return result.hash; } @@ -119,7 +120,7 @@ export class StellarService { baseFee ); - console.info(`✅ Multi-signed price update for ${currency} confirmed. Hash: ${result.hash}`); + logger.info(`✅ Multi-signed price update for ${currency} confirmed. Hash: ${result.hash}`); return result.hash; } @@ -152,7 +153,7 @@ export class StellarService { const isStuck = this.isStuckError(error); if (isStuck && attempt <= maxRetries) { - console.warn(`⚠️ Transaction stuck or fee too low (Attempt ${attempt}). Bumping fee and retrying in ${this.RETRY_DELAY_MS}ms...`); + logger.warn(`⚠️ Transaction stuck or fee too low (Attempt ${attempt}). Bumping fee and retrying in ${this.RETRY_DELAY_MS}ms...`); await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS)); continue; } @@ -217,7 +218,7 @@ export class StellarService { transaction.signatures.push(decoratedSignature); } catch (error) { - console.error( + logger.error( `[StellarService] Failed to add signature for ${sig.signerPublicKey}:`, error ); @@ -232,7 +233,7 @@ export class StellarService { const isStuck = this.isStuckError(error); if (isStuck && attempt <= maxRetries) { - console.warn(`⚠️ Multi-sig transaction stuck or fee too low (Attempt ${attempt}). Bumping fee and retrying in ${this.RETRY_DELAY_MS}ms...`); + logger.warn(`⚠️ Multi-sig transaction stuck or fee too low (Attempt ${attempt}). Bumping fee and retrying in ${this.RETRY_DELAY_MS}ms...`); await new Promise(resolve => setTimeout(resolve, this.RETRY_DELAY_MS)); continue; } diff --git a/src/services/webhook.ts b/src/services/webhook.ts index f31b8ba1..2e689fc3 100644 --- a/src/services/webhook.ts +++ b/src/services/webhook.ts @@ -1,4 +1,5 @@ import axios from "axios"; +import { logger } from "../lib/logger"; export class WebhookService { private webhookUrl: string | undefined; @@ -47,7 +48,7 @@ export class WebhookService { timeout: 5000, }); } catch (error) { - console.error("Failed to send webhook notification:", error); + logger.error("Failed to send webhook notification:", error); } } diff --git a/test_output.txt b/test_output.txt new file mode 100644 index 00000000..153902c0 Binary files /dev/null and b/test_output.txt differ diff --git a/tsc_output.txt b/tsc_output.txt new file mode 100644 index 00000000..7eddfe28 Binary files /dev/null and b/tsc_output.txt differ