Add ECDSA signature verification and enhance ComboHandler functionality
- Integrated ECDSA for signature verification in ComboHandler. - Updated event emissions to include additional parameters for better tracking. - Improved gas tracking during execution of combo plans. - Enhanced database interactions for storing and retrieving plans, including conflict resolution and status updates. - Added new dependencies for security and database management in orchestrator.
This commit is contained in:
49
orchestrator/src/api/execution.ts
Normal file
49
orchestrator/src/api/execution.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { Request, Response } from "express";
|
||||
import { executionCoordinator } from "../services/execution";
|
||||
import { asyncHandler } from "../services/errorHandler";
|
||||
import { auditLog } from "../middleware";
|
||||
|
||||
/**
|
||||
* POST /api/plans/:planId/execute
|
||||
* Execute a plan
|
||||
*/
|
||||
export const executePlan = asyncHandler(async (req: Request, res: Response) => {
|
||||
const { planId } = req.params;
|
||||
|
||||
const result = await executionCoordinator.executePlan(planId);
|
||||
|
||||
res.json(result);
|
||||
});
|
||||
|
||||
/**
|
||||
* GET /api/plans/:planId/status
|
||||
* Get execution status
|
||||
*/
|
||||
export const getExecutionStatus = asyncHandler(async (req: Request, res: Response) => {
|
||||
const { planId } = req.params;
|
||||
const executionId = req.query.executionId as string;
|
||||
|
||||
if (executionId) {
|
||||
const status = await executionCoordinator.getExecutionStatus(executionId);
|
||||
return res.json(status);
|
||||
}
|
||||
|
||||
// Get latest execution for plan
|
||||
res.json({ status: "pending" });
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/plans/:planId/abort
|
||||
* Abort execution
|
||||
*/
|
||||
export const abortExecution = asyncHandler(async (req: Request, res: Response) => {
|
||||
const { planId } = req.params;
|
||||
const executionId = req.query.executionId as string;
|
||||
|
||||
if (executionId) {
|
||||
await executionCoordinator.abortExecution(executionId, planId, "User aborted");
|
||||
}
|
||||
|
||||
res.json({ success: true });
|
||||
});
|
||||
|
||||
38
orchestrator/src/api/swagger.ts
Normal file
38
orchestrator/src/api/swagger.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Router } from "express";
|
||||
import swaggerUi from "swagger-ui-express";
|
||||
import swaggerJsdoc from "swagger-jsdoc";
|
||||
|
||||
const options: swaggerJsdoc.Options = {
|
||||
definition: {
|
||||
openapi: "3.0.0",
|
||||
info: {
|
||||
title: "ISO-20022 Combo Flow Orchestrator API",
|
||||
version: "1.0.0",
|
||||
description: "API for managing and executing financial workflow plans",
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
url: "http://localhost:8080",
|
||||
description: "Development server",
|
||||
},
|
||||
],
|
||||
components: {
|
||||
securitySchemes: {
|
||||
ApiKeyAuth: {
|
||||
type: "apiKey",
|
||||
in: "header",
|
||||
name: "X-API-Key",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
apis: ["./src/api/**/*.ts"],
|
||||
};
|
||||
|
||||
const specs = swaggerJsdoc(options);
|
||||
|
||||
export function setupSwagger(router: Router) {
|
||||
router.use("/api-docs", swaggerUi.serve);
|
||||
router.get("/api-docs", swaggerUi.setup(specs));
|
||||
}
|
||||
|
||||
22
orchestrator/src/api/version.ts
Normal file
22
orchestrator/src/api/version.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Router } from "express";
|
||||
|
||||
/**
|
||||
* API versioning middleware
|
||||
*/
|
||||
export function apiVersion(version: string) {
|
||||
return (req: any, res: any, next: any) => {
|
||||
req.apiVersion = version;
|
||||
res.setHeader("API-Version", version);
|
||||
next();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create versioned router
|
||||
*/
|
||||
export function createVersionedRouter(version: string) {
|
||||
const router = Router();
|
||||
router.use(apiVersion(version));
|
||||
return router;
|
||||
}
|
||||
|
||||
78
orchestrator/src/api/webhooks.ts
Normal file
78
orchestrator/src/api/webhooks.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { Request, Response } from "express";
|
||||
import { executionCoordinator } from "../services/execution";
|
||||
import { logger } from "../logging/logger";
|
||||
|
||||
interface WebhookConfig {
|
||||
url: string;
|
||||
secret: string;
|
||||
events: string[];
|
||||
}
|
||||
|
||||
const webhooks: Map<string, WebhookConfig> = new Map();
|
||||
|
||||
/**
|
||||
* POST /api/webhooks
|
||||
* Register a webhook
|
||||
*/
|
||||
export async function registerWebhook(req: Request, res: Response) {
|
||||
try {
|
||||
const { url, secret, events } = req.body;
|
||||
|
||||
if (!url || !secret || !events || !Array.isArray(events)) {
|
||||
return res.status(400).json({
|
||||
error: "Invalid webhook configuration",
|
||||
});
|
||||
}
|
||||
|
||||
const webhookId = `webhook-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
webhooks.set(webhookId, { url, secret, events });
|
||||
|
||||
res.json({ webhookId, url, events });
|
||||
} catch (error: any) {
|
||||
logger.error({ error }, "Failed to register webhook");
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send webhook notification
|
||||
*/
|
||||
export async function sendWebhook(event: string, payload: any) {
|
||||
for (const [webhookId, config] of webhooks.entries()) {
|
||||
if (config.events.includes(event) || config.events.includes("*")) {
|
||||
try {
|
||||
const signature = createWebhookSignature(JSON.stringify(payload), config.secret);
|
||||
|
||||
await fetch(config.url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Webhook-Event": event,
|
||||
"X-Webhook-Signature": signature,
|
||||
"X-Webhook-Id": webhookId,
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error({ error, webhookId, event }, "Failed to send webhook");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create webhook signature
|
||||
*/
|
||||
function createWebhookSignature(payload: string, secret: string): string {
|
||||
const crypto = require("crypto");
|
||||
return crypto.createHmac("sha256", secret).update(payload).digest("hex");
|
||||
}
|
||||
|
||||
// Listen to execution events
|
||||
executionCoordinator.onStatus((executionId, event) => {
|
||||
sendWebhook("plan.status", {
|
||||
executionId,
|
||||
...event,
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user