Files
xo-sync-server-hono/src/utils/invitation-parser.ts
2026-06-08 13:28:20 +00:00

68 lines
2.2 KiB
TypeScript

import Z, { z } from 'zod';
/**
* Zod schemas for invitation validation.
*
* IMPORTANT: We use .passthrough() on all object schemas to preserve fields
* that aren't explicitly defined. This is critical because:
* 1. Invitations are signed based on stringify(commit.data)
* 2. If we strip fields, the signature verification will fail
* 3. The actual XOInvitation types have many more fields than we validate here
*/
const variableSchema = z.object({
variableIdentifier: z.string(),
roleIdentifier: z.string().optional(),
value: z.number().or(z.string()).or(z.boolean()).or(z.bigint()),
}).passthrough();
const mergesWithSchema = z.object({
commitIdentifier: z.string(),
index: z.number(),
}).passthrough();
const inputSchema = z.object({
inputIdentifier: z.string().optional(),
transactionIndex: z.number().optional(),
roleIdentifier: z.string().optional(),
mergesWith: mergesWithSchema.optional(),
// Additional fields preserved via passthrough:
// outpointTransactionHash, outpointIndex, sequenceNumber, unlockingBytecode, etc.
}).passthrough();
const outputSchema = z.object({
outputIdentifier: z.string().optional(),
roleIdentifier: z.string().optional(),
secretIdentifier: z.string().optional(),
transactionIndex: z.number().optional(),
mergesWith: mergesWithSchema.optional(),
// Additional fields preserved via passthrough:
// valueSatoshis, lockingBytecode, token, etc.
}).passthrough();
const dataSchema = z.object({
transactionVersion: z.number().optional(),
transactionLocktime: z.number().optional(),
variables: z.array(variableSchema).optional(),
inputs: z.array(inputSchema).optional(),
outputs: z.array(outputSchema).optional(),
}).passthrough();
const commitSchema = z.object({
commitIdentifier: z.string(),
previousCommitIdentifier: z.string().or(z.undefined()),
entityIdentifier: z.string(),
data: dataSchema,
signature: z.string(),
expiresAtTimestamp: z.number(),
}).passthrough();
export const parseInvitation = z.object({
invitationIdentifier: z.string(),
commits: z.array(commitSchema),
createdAtTimestamp: z.number(),
templateIdentifier: z.string(),
actionIdentifier: z.string(),
}).passthrough();
export type InvitationSchema = Z.infer<typeof parseInvitation>;