import { config as loadEnv } from "dotenv";
import express from "express";
import { paymentMiddleware } from "x402-express";
import { facilitator } from "@coinbase/x402";
import { readFileSync } from "fs";
import { load } from "js-yaml";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
loadEnv();
// Load configuration
const __dirname = dirname(fileURLToPath(import.meta.url));
const config = load(readFileSync(join(__dirname, "../config.yaml"), "utf8")) as any;
// Build payment route config - create specific routes for each riddle, sharing one payment config
const paymentConfig = Object.fromEntries(
config.riddles.map((_: any, i: number) => [
`GET /riddle/${i + 1}/answer`,
config.payment
])
);
const app = express();
app.use(express.json());
// Store paid but unconsumed orders: payid -> riddleId
const paidOrders = new Map<string, number>();
// Use paymentMiddleware (legacy interface: payToAddress, routes, facilitator)
app.use(paymentMiddleware(config.payToAddress, paymentConfig, facilitator));
// Internal verification endpoint - MCP calls this to verify payment
app.post("/verify-payment", (req: any, res: any) => {
const { payid } = req.body;
if (!payid) {
return res.status(400).send({ error: "Missing payid" });
}
if (paidOrders.has(payid)) {
const riddleId = paidOrders.get(payid);
paidOrders.delete(payid); // Consume this payid
return res.send({ verified: true, riddleId });
}
return res.send({ verified: false });
});
// Riddle answer endpoint (payment required) - Record payid after successful payment
app.get("/riddle/:id/answer", (req: any, res: any) => {
const id = parseInt(req.params.id);
const payid = req.query.payid as string;
const riddle = config.riddles[id - 1];
if (!riddle) {
return res.status(404).send({ error: "Riddle not found" });
}
if (payid) {
paidOrders.set(payid, id);
console.log(`✅ Payment verified for riddle ${id}, payid: ${payid}`);
}
res.send({
status: "success",
message: "Payment successful. You can now use the get_answer tool with your payid to retrieve the answer."
});
});
app.listen(config.x402Server.port, config.x402Server.host, () => {
console.log(`🚀 x402 Server: http://${config.x402Server.host}:${config.x402Server.port}`);
console.log(`💰 ${config.payment.price} on ${config.payment.network} - ${config.riddles.length} riddles`);
});