Repository Public
1// Routes of the collateral path — all under /api/v1/derivatives/live/accounts/:id/collateral/… (the read-only2// GET …/collateral of live-routes.ts is unchanged). Authentication and CSRF are the global hook of server.ts. Nothing here3// holds a key or judges a passkey: assertions go to the isolated signer untouched. Shapes: docs/v4/API-LIVE-NOTES.md.4import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';5import { z } from 'zod';6import { AmountBodySchema, collateral, CollateralAssertionSchema, type CollateralService } from './collateral.ts';7import { venueFailure } from './data.ts';89const P = '/api/v1/derivatives/live/accounts/:id/collateral';1011export function collateralRoutes(app: FastifyInstance, given?: CollateralService): void {12 const svc = async (): Promise<CollateralService> => given ?? collateral();13 const id = (req: FastifyRequest): string => z.uuid().parse((req.params as { id: string }).id);14 const op = (req: FastifyRequest): string => z.uuid().parse((req.params as { opId: string }).opId);15 const run = <T>(fn: (s: CollateralService, req: FastifyRequest, reply: FastifyReply) => Promise<T>) => async (req: FastifyRequest, reply: FastifyReply): Promise<T> => { try { return await fn(await svc(), req, reply); } catch (e) { throw venueFailure(e); } };1617 // venue balance, route facts (bridge, minimum, time), wallet side (USDC and gas on the deposit network, USDC elsewhere, limits), operations18 app.get(`${P}/status`, run(async (s, req) => s.status(id(req))));19 app.get(`${P}/operations/:opId`, run(async (s, req) => s.operation(id(req), op(req))));20 // deposit: prepare (guards, liveness, intent with the venueDeposit section, WebAuthn request over the intent hash) → approve (assertion)21 app.post(`${P}/deposit/prepare`, run(async (s, req) => s.prepareDeposit(id(req), AmountBodySchema.parse(req.body))));22 app.post(`${P}/deposit/:opId/approve`, run(async (s, req) => s.approveDeposit(id(req), op(req), CollateralAssertionSchema.parse(req.body).assertion)));23 // withdrawal: prepare (canonical withdrawal, WebAuthn request over its hash) → approve (assertion) → the venue24 app.post(`${P}/withdraw/prepare`, run(async (s, req) => s.prepareWithdraw(id(req), AmountBodySchema.parse(req.body))));25 app.post(`${P}/withdraw/:opId/approve`, run(async (s, req) => s.approveWithdraw(id(req), op(req), CollateralAssertionSchema.parse(req.body).assertion)));26 // before the passkey only27 app.post(`${P}/operations/:opId/cancel`, run(async (s, req) => s.cancel(id(req), op(req))));28}29