896 lines
32 KiB
TypeScript
896 lines
32 KiB
TypeScript
/* eslint-disable @stylistic/newline-per-chained-call */
|
|
import { z } from 'zod';
|
|
|
|
// ============================================================
|
|
// Enums
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for a BCH VM version identifier. Defines the set of known BCH VM versions
|
|
* that XO templates declare support for.
|
|
*
|
|
* Zod's `z.enum` requires the exact values to be defined inline because it needs to know each
|
|
* specific value at compile time to validate against them. Defining the versions here directly
|
|
* satisfies that requirement and allows `z.array(bchVmVersionSchema)` to be used elsewhere
|
|
*
|
|
* ```
|
|
* {
|
|
* "supported": [ "BCH_2025_05" ] ← each value
|
|
* }
|
|
* ```
|
|
*/
|
|
export const bchVmVersionSchema = z.enum([ 'BCH_2020_05', 'BCH_2021_05', 'BCH_2022_05', 'BCH_2023_05', 'BCH_2024_05', 'BCH_2025_05', 'BCH_2026_05' ]);
|
|
|
|
/**
|
|
* Validation schema for the capability of a non-fungible token. Defines the three capability
|
|
* types supported on BCH: minting tokens can create new NFTs, mutable tokens can update their
|
|
* commitment, and none tokens cannot be changed after creation.
|
|
*
|
|
* ```
|
|
* {
|
|
* "inputs|outputs": {
|
|
* "[id]": {
|
|
* "token": {
|
|
* "nft": {
|
|
* "capability": "minting" ← this schema
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateNftCapabilitySchema = z.enum([ 'minting', 'mutable', 'none' ]);
|
|
|
|
/**
|
|
* Validation schema for a BCH locking script type. Defines the standard locking script types
|
|
* supported on BCH.
|
|
*
|
|
* ```
|
|
* {
|
|
* "lockingScripts": {
|
|
* "[id]": {
|
|
* "lockingType": "p2pkh" ← this schema
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateLockingTypeSchema = z.enum([ 'p2s', 'p2pkh', 'p2sh' ]);
|
|
|
|
/**
|
|
* Validation schema for a primitive type identifier. Defines the set of primitive types
|
|
* that can be declared in an XO template. Used by constants, variables, and data fields.
|
|
*/
|
|
export const xoTemplatePrimitiveTypeSchema = z.enum([ 'boolean', 'bytes', 'integer', 'bigint', 'string', 'private_key', 'public_key' ]);
|
|
|
|
// ============================================================
|
|
// Primitives
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for byte array fields i.e. Uint8Array instance.
|
|
*/
|
|
export const uint8ArraySchema = z.instanceof(Uint8Array).describe('A sequence of unsigned 8-bit integers expressed as a Uint8Array.');
|
|
|
|
/**
|
|
* Validation schema for the Satoshis type i.e. bigint.
|
|
*/
|
|
export const satoshisSchema = z.bigint().describe('A satoshi amount expressed as a bigint.');
|
|
|
|
// ============================================================
|
|
// Shared
|
|
// ============================================================
|
|
|
|
/** Maximum character length for name fields on view properties. */
|
|
export const VIEW_PROPERTIES_NAME_MAX_LENGTH = 200;
|
|
|
|
/** Maximum character length for description fields on view properties. */
|
|
export const VIEW_PROPERTIES_DESCRIPTION_MAX_LENGTH = 5000;
|
|
|
|
/** Maximum character length for icon fields on view properties. */
|
|
export const VIEW_PROPERTIES_ICON_MAX_LENGTH = 50;
|
|
|
|
/**
|
|
* Validation schema for view properties shared across many template elements i.e. name, description, icon.
|
|
* Extended by most other schemas in this file.
|
|
*/
|
|
export const xoTemplateViewPropertiesSchema = z
|
|
.object({
|
|
name: z.string().max(VIEW_PROPERTIES_NAME_MAX_LENGTH).describe('A short human-readable label for this element.'),
|
|
description: z
|
|
.string()
|
|
.max(VIEW_PROPERTIES_DESCRIPTION_MAX_LENGTH)
|
|
.describe('A human-readable explanation of what this element does and when it is relevant.'),
|
|
icon: z.string().max(VIEW_PROPERTIES_ICON_MAX_LENGTH).optional().describe('An optional icon identifier or URL for this element.'),
|
|
})
|
|
.strict();
|
|
|
|
// ============================================================
|
|
// Intents
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for the base intent structure. Describes the common data parameters shared
|
|
* by all intent types regardless of what they target.
|
|
*
|
|
* An optional templateIdentifier allows the intent to reference a target defined in a different
|
|
* template, enabling cross-template interaction.
|
|
*
|
|
* Extended by: xoTemplateActionIntentSchema, xoTemplateOutputIntentSchema,
|
|
* xoTemplateLockingScriptIntentSchema.
|
|
*/
|
|
export const xoTemplateIntentSchema = z
|
|
.object({
|
|
templateIdentifier: z
|
|
.string()
|
|
.optional()
|
|
.describe('Optional identifier for the template used in this intent. If not provided, uses the current template.'),
|
|
role: z.string().optional().describe('Optional identifier for the role used in this intent.'),
|
|
generate: z.array(z.string()).optional().describe('Identifiers for items to generate when this intent is resolved, e.g. keys or secrets.'),
|
|
variables: z.array(z.record(z.string(), z.unknown())).optional().describe('Variable values to apply when this intent is resolved.'),
|
|
constants: z.array(z.record(z.string(), z.unknown())).optional().describe('Constant values to apply when this intent is resolved.'),
|
|
secrets: z.array(z.record(z.string(), z.unknown())).optional().describe('Secret values to apply when this intent is resolved.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for an action intent. Extends the base intent structure with an action
|
|
* identifier. Used in locking script action lists and in the template's start array.
|
|
*
|
|
* ```
|
|
* {
|
|
* "start": [
|
|
* { "action": "..." } ← this schema
|
|
* ],
|
|
* "lockingScripts": {
|
|
* "[id]": {
|
|
* "actions": [
|
|
* { "action": "..." } ← this schema
|
|
* ],
|
|
* "roles": {
|
|
* "[roleId]": {
|
|
* "actions": [
|
|
* { "action": "..." } ← this schema
|
|
* ]
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateActionIntentSchema = xoTemplateIntentSchema
|
|
.extend({
|
|
action: z.string().describe('The identifier for the intended action.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for an output intent. Extends the base intent structure with an output
|
|
* identifier. Used in the template's defaults block.
|
|
*
|
|
* ```
|
|
* {
|
|
* "defaults": {
|
|
* "change": { "output": "..." } ← this schema
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateOutputIntentSchema = xoTemplateIntentSchema
|
|
.extend({
|
|
output: z.string().describe('The identifier for the intended output.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for a locking script intent. Extends the base intent structure with
|
|
* a locking script identifier.
|
|
*
|
|
* @todo The location of this schema in the template JSON is not yet determined.
|
|
*/
|
|
export const xoTemplateLockingScriptIntentSchema = xoTemplateIntentSchema
|
|
.extend({
|
|
lockingScript: z.string().describe('The identifier for the intended locking script.'),
|
|
})
|
|
.strict();
|
|
|
|
// ============================================================
|
|
// Actions
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for the slot count configuration on a role requirement. Declares how many
|
|
* participants of a given role are needed. min sets the lower bound and max sets the upper bound.
|
|
* When max is absent, there is no upper limit.
|
|
*
|
|
* ```
|
|
* {
|
|
* "actions": {
|
|
* "[id]": {
|
|
* "requirements": {
|
|
* "participants": [
|
|
* { "slots": { "min": 1, "max": 1 } } ← this schema
|
|
* ]
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateRoleSlotsRequirementsSchema = z
|
|
.object({
|
|
min: z.number().describe('Minimum number of participants required for this role.'),
|
|
max: z.number().optional().describe('Maximum number of participants allowed for this role. Undefined means unlimited.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for the capability requirements declared on a role within an action.
|
|
* Describes what data, secrets, or state the role is responsible for providing when participating in an action.
|
|
*
|
|
* ```
|
|
* {
|
|
* "actions": {
|
|
* "[id]": {
|
|
* "roles": {
|
|
* "[roleId]": {
|
|
* "requirements": { "variables": [], "secrets": [] } ← this schema
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateActionRoleRequirementsSchema = z
|
|
.object({
|
|
variables: z.array(z.string()).optional().describe('List of variable identifiers required for this role.'),
|
|
secrets: z.array(z.string()).optional().describe('List of secret identifiers required for this role.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for a role-specific definition within an action.
|
|
* All view properties are optional.
|
|
*
|
|
* ```
|
|
* {
|
|
* "actions": {
|
|
* "[id]": {
|
|
* "roles": {
|
|
* "[roleId]": { } ← this schema
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateActionRoleSchema = xoTemplateViewPropertiesSchema
|
|
.partial()
|
|
.extend({
|
|
generate: z
|
|
.array(z.string())
|
|
.optional()
|
|
.describe('Identifiers for data items that should be generated for this role when participating in the action.'),
|
|
|
|
// Describes under what conditions this role can proceed with the action. All values listed
|
|
// under requirements must be populated for the action to work. This is a developer and
|
|
// author concern. It is not present on intents because intents are used to populate the
|
|
// action rather than to define it, and their fields are flattened accordingly.
|
|
requirements: xoTemplateActionRoleRequirementsSchema.optional().describe('The requirements for this role within this action.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for a role participation requirement in an action's requirements block.
|
|
*
|
|
* ```
|
|
* {
|
|
* "actions": {
|
|
* "[id]": {
|
|
* "requirements": {
|
|
* "participants": [
|
|
* { "role": "...", "slots": { } } ← this schema
|
|
* ]
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateRoleSlotSchema = z
|
|
.object({
|
|
role: z.string().describe('The role identifier that this requirement applies to.'),
|
|
slots: xoTemplateRoleSlotsRequirementsSchema.describe('Slot configuration specifying how many participants of this role are required.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for the requirements of an action.
|
|
*
|
|
* ```
|
|
* {
|
|
* "actions": {
|
|
* "[id]": {
|
|
* "requirements": { "participants": [], "secrets": [] } ← this schema
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateActionRequirementsSchema = z
|
|
.object({
|
|
participants: z.array(xoTemplateRoleSlotSchema).optional().describe('The participants required for this action.'),
|
|
secrets: z.array(z.string()).optional().describe('The secrets required for this action.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for an action definition.
|
|
*
|
|
* ```
|
|
* {
|
|
* "actions": {
|
|
* "[id]": { } ← this schema
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateActionSchema = xoTemplateViewPropertiesSchema
|
|
.extend({
|
|
roles: z.record(z.string(), xoTemplateActionRoleSchema).optional().describe('Specific context for each role participating in this action.'),
|
|
requirements: xoTemplateActionRequirementsSchema.optional().describe('The requirements for this action.'),
|
|
|
|
// This is a list of conditions that can influence how the action behaves.
|
|
// This needs more work to be done.
|
|
conditions: z.array(z.string()).optional().describe('Conditions that must be met for this action to be available.'),
|
|
|
|
// A single transaction produced by the action.
|
|
// In future this might be moved to a results block that can have multiple transactions.
|
|
transaction: z
|
|
.string()
|
|
.optional()
|
|
.describe("The identifier of the transaction this action produces, referencing an entry in the template's transactions."),
|
|
|
|
// The data that is produced by the action.
|
|
// In future this might be moved to a results block that can have multiple data fields.
|
|
data: z.string().optional().describe("The identifier of the data field this action produces, referencing an entry in the template's data."),
|
|
})
|
|
.strict();
|
|
|
|
// ============================================================
|
|
// Tokens & Amounts
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for the non-fungible token configuration within a token field.
|
|
*
|
|
* ```
|
|
* {
|
|
* "inputs|outputs": {
|
|
* "[id]": {
|
|
* "token": {
|
|
* "nft": { } ← this schema
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateNonFungibleTokenDetailsSchema = z
|
|
.object({
|
|
capability: z
|
|
.union([ xoTemplateNftCapabilitySchema, z.string() ])
|
|
.optional()
|
|
.describe('The capability of the NFT. May be a known capability value or a CashASM expression resolving to a capability.'),
|
|
commitment: z.string().optional().describe('The commitment data for the NFT, as a string or CashASM expression resolving to a commitment.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for the token configuration on inputs and outputs.
|
|
*
|
|
* ```
|
|
* {
|
|
* "inputs|outputs": {
|
|
* "[id]": {
|
|
* "token": { } ← this schema
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateTokenSchema = z
|
|
.object({
|
|
category: z.string().optional().describe('The category of the token, as a string or CashASM expression resolving to a category.'),
|
|
amount: z
|
|
.union([ z.bigint(), z.string(), z.null() ])
|
|
.optional()
|
|
.describe('The amount of fungible tokens as a bigint, a CashASM expression resolving to a bigint, or null indicating no FT is present.'),
|
|
nft: xoTemplateNonFungibleTokenDetailsSchema
|
|
.nullable()
|
|
.optional()
|
|
.describe('Non-fungible token configuration. Null indicates no NFT is present.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for the asset amounts configuration. Used by omitChangeAmounts on inputs
|
|
* and by balance on locking scripts, outputs, and their roles.
|
|
*/
|
|
export const xoTemplateAssetAmountsSchema = z
|
|
.object({
|
|
|
|
/**
|
|
* The satoshi amount.
|
|
* - `Satoshis`: A specific bigint amount.
|
|
* - `string`: A CashASM expression that resolves to the amount.
|
|
* - `true`: all, i.e. the entire amount
|
|
*/
|
|
satoshis: z
|
|
.union([ satoshisSchema, z.string(), z.literal(true) ])
|
|
.optional()
|
|
.describe('The satoshi amount. Accepts a bigint for a specific value, a CashASM expression, or true for the entire amount.'),
|
|
|
|
/**
|
|
* The fungible token amount.
|
|
* - `FungibleTokenAmount`: A specific bigint amount.
|
|
* - `string`: A CashASM expression that resolves to the amount.
|
|
* - `true`: all, i.e. the entire amount
|
|
*/
|
|
fungibleTokens: z
|
|
.union([ z.bigint(), z.string(), z.literal(true) ])
|
|
.optional()
|
|
.describe('The fungible token amount. Accepts a bigint for a specific value, a CashASM expression, or true for the entire amount.'),
|
|
|
|
/**
|
|
* Whether a non-fungible token is present (0 for absent, 1 for present),
|
|
* or a CashASM expression that evaluates to 0 or 1.
|
|
* - `true`: resolves to 1 if an NFT is present, or 0 if none is present. Use this when
|
|
* the NFT is optional, to express that the NFT is estimated to be part of the balance
|
|
* if present, or absent from it if not.
|
|
* - `0`: None, i.e. nothing is expected to be included
|
|
* - `1`: present and complete, as value > 1 does not make sense for non-fungible tokens
|
|
* - `string`: A CashASM expression that evaluates to 0 or 1.
|
|
*/
|
|
nonfungibleTokens: z
|
|
.union([ z.literal(0), z.literal(1), z.string(), z.literal(true) ])
|
|
.optional()
|
|
.describe('Whether an NFT is present: 0 for absent, 1 for present, a CashASM expression evaluating to 0 or 1, or true to estimate the NFT as part of the balance if present, or absent from it if not.'),
|
|
})
|
|
.strict();
|
|
|
|
// ============================================================
|
|
// Locking Scripts
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for the state configuration shared by a locking script and its individual roles.
|
|
* Declares which variables and secrets are tracked in the on-chain state for a given participant.
|
|
*
|
|
* ```
|
|
* {
|
|
* "lockingScripts": {
|
|
* "[id]": {
|
|
* "state": { "variables": [], "secrets": [] } ← this schema
|
|
* "roles": {
|
|
* "[roleId]": {
|
|
* "state": { "variables": [], "secrets": [] } ← this schema
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateStateSchema = z
|
|
.object({
|
|
variables: z.array(z.string()).optional().describe('List of variable identifiers to track in state.'),
|
|
secrets: z.array(z.string()).optional().describe('List of secret identifiers to track in state.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for a role definition for a locking script.
|
|
*
|
|
* ```
|
|
* {
|
|
* "lockingScripts": {
|
|
* "[id]": {
|
|
* "roles": {
|
|
* "[roleId]": { } ← this schema
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateLockingScriptRoleSchema = xoTemplateViewPropertiesSchema
|
|
.partial()
|
|
.extend({
|
|
state: xoTemplateStateSchema.optional().describe('List of items to track as state for this role.'),
|
|
actions: z.array(xoTemplateActionIntentSchema).optional().describe('List of action references available to this role.'),
|
|
balance: xoTemplateAssetAmountsSchema.partial().optional().describe('Estimated ownership in the optional set of asset amounts specified.'),
|
|
selectable: z.boolean().optional().describe('Whether outputs locked to this script should be available for coin selection.'),
|
|
privacy: z
|
|
.union([ z.number(), z.string() ])
|
|
.optional()
|
|
.describe('Privacy level for outputs locked to this script. A numeric level or a CashASM expression that evaluates to a privacy level.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for a locking script definition.
|
|
*
|
|
* ```
|
|
* {
|
|
* "lockingScripts": {
|
|
* "[id]": { } ← this schema
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateLockingScriptSchema = xoTemplateViewPropertiesSchema
|
|
.extend({
|
|
lockingType: xoTemplateLockingTypeSchema.optional().describe('The type of locking mechanism. Defaults to p2s if not specified.'),
|
|
lockingBytecode: z.string().describe('The locking script bytecode.'),
|
|
unlockingBytecode: z.string().optional().describe('Optional default unlocking bytecode when used in automatic coin selection.'),
|
|
actions: z.array(xoTemplateActionIntentSchema).optional().describe('The actions available for this locking script.'),
|
|
state: xoTemplateStateSchema.optional().describe('List of items to track as state for all participants.'),
|
|
balance: xoTemplateAssetAmountsSchema.partial().optional().describe('Estimated ownership in the optional set of asset amounts specified.'),
|
|
selectable: z.boolean().optional().describe('Whether outputs locked to this script should be available for coin selection.'),
|
|
// Might be levels or tags
|
|
privacy: z
|
|
.union([ z.number(), z.string() ])
|
|
.optional()
|
|
.describe('Privacy level for outputs locked to this script. A numeric level or a CashASM expression that evaluates to a privacy level.'),
|
|
roles: z
|
|
.record(z.string(), xoTemplateLockingScriptRoleSchema)
|
|
.optional()
|
|
.describe('Specific context for each role participating in this locking script.'),
|
|
})
|
|
.strict();
|
|
|
|
// ============================================================
|
|
// Inputs
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for an input definition in the template. Extends view properties with optional
|
|
* satoshi value, token configuration, and other transaction level fields.
|
|
*
|
|
* ```
|
|
* {
|
|
* "inputs": {
|
|
* "[id]": { } ← this schema
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateInputSchema = xoTemplateViewPropertiesSchema
|
|
.extend({
|
|
valueSatoshis: z
|
|
.union([ satoshisSchema, z.string() ])
|
|
.optional()
|
|
.describe('The amount of satoshis for this input as a bigint or a CashASM expression resolving to the amount.'),
|
|
token: xoTemplateTokenSchema.nullable().optional().describe('Token configuration for this input.'),
|
|
sequenceNumber: z
|
|
.union([ z.number(), z.string() ])
|
|
.optional()
|
|
.describe('The sequence number of this input as a specific number or a CashASM expression.'),
|
|
unlockingScript: z.string().optional().describe('Identifier of the unlocking script to use for the UTXO provided for this input.'),
|
|
omitChangeAmounts: xoTemplateAssetAmountsSchema
|
|
.optional()
|
|
.describe('Amount of change that should be omitted from the automatic change handling. WARNING: Setting this can result in loss of funds!'),
|
|
})
|
|
.strict();
|
|
|
|
// ============================================================
|
|
// Outputs
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for an output definition. Extends the locking script schema so that
|
|
* every output inherits the same locking script fields and adds output-specific fields.
|
|
*
|
|
* ```
|
|
* {
|
|
* "outputs": {
|
|
* "[id]": { } ← this schema
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateOutputSchema = xoTemplateLockingScriptSchema
|
|
.omit({ lockingType: true, lockingBytecode: true, unlockingBytecode: true })
|
|
.extend({
|
|
lockingScript: z.string().describe('Identifier of the locking script to use for this output.'),
|
|
valueSatoshis: z
|
|
.union([ satoshisSchema, z.string() ])
|
|
.optional()
|
|
.describe('The amount of satoshis for this output as a bigint or a CashASM expression resolving to the amount.'),
|
|
token: xoTemplateTokenSchema.nullable().optional().describe('Token configuration for this output.'),
|
|
})
|
|
.strict();
|
|
|
|
// ============================================================
|
|
// Transactions
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for a transaction input reference for a transaction definition.
|
|
*
|
|
* ```
|
|
* {
|
|
* "transactions": {
|
|
* "[id]": {
|
|
* "inputs": [
|
|
* { "input": "..." } ← this schema
|
|
* ]
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateTransactionInputSchema = z
|
|
.object({
|
|
input: z.string().describe('The input definition identifier.'),
|
|
inputIndex: z.number().optional().describe('Optional index of this input in the transaction.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for a transaction output reference for a transaction definition.
|
|
*
|
|
* ```
|
|
* {
|
|
* "transactions": {
|
|
* "[id]": {
|
|
* "outputs": [
|
|
* { "output": "..." } ← this schema
|
|
* ]
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateTransactionOutputSchema = z
|
|
.object({
|
|
output: z.string().describe('The output definition identifier.'),
|
|
outputIndex: z.number().optional().describe('Optional index of this output in the transaction.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for role-specific data for a transaction definition.
|
|
*
|
|
* ```
|
|
* {
|
|
* "transactions": {
|
|
* "[id]": {
|
|
* "roles": {
|
|
* "[roleId]": { } ← this schema
|
|
* }
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateTransactionRoleDataSchema = xoTemplateViewPropertiesSchema
|
|
.partial()
|
|
.extend({
|
|
inputs: z.array(xoTemplateTransactionInputSchema).optional().describe('The inputs required for this role.'),
|
|
outputs: z.array(xoTemplateTransactionOutputSchema).optional().describe('The outputs required for this role.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for a transaction template definition.
|
|
*
|
|
* ```
|
|
* {
|
|
* "transactions": {
|
|
* "[id]": { } ← this schema
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateTransactionSchema = xoTemplateViewPropertiesSchema
|
|
.extend({
|
|
version: z.number().optional().describe('The version of the transaction.'),
|
|
locktime: z.number().optional().describe('The locktime for this transaction.'),
|
|
inputs: z.array(xoTemplateTransactionInputSchema).describe('The inputs for this transaction.'),
|
|
outputs: z.array(xoTemplateTransactionOutputSchema).describe('The outputs for this transaction.'),
|
|
roles: z
|
|
.record(z.string(), xoTemplateTransactionRoleDataSchema)
|
|
.optional()
|
|
.describe('Specific context for each role participating in this transaction.'),
|
|
composable: z.boolean().optional().describe('Whether this transaction can be composed with other transactions.'),
|
|
})
|
|
.strict();
|
|
|
|
// ============================================================
|
|
// Template Data
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for a constant value definition.
|
|
*
|
|
* ```
|
|
* {
|
|
* "constants": {
|
|
* "[id]": { } ← this schema
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateConstantSchema = xoTemplateViewPropertiesSchema
|
|
.extend({
|
|
type: xoTemplatePrimitiveTypeSchema.describe('The data type of this constant.'),
|
|
value: z.unknown().describe('The value of this constant.'),
|
|
hint: z.string().optional().describe('An optional hint to help apps and users understand what this constant represents.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for a data field definition.
|
|
*
|
|
* ```
|
|
* {
|
|
* "data": {
|
|
* "[id]": { } ← this schema
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateDataSchema = z
|
|
.object({
|
|
type: xoTemplatePrimitiveTypeSchema.describe('The data type of this data field.'),
|
|
value: z.unknown().describe('The value for this data field.'),
|
|
hint: z.string().optional().describe('An optional hint to help apps and users understand this data field.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for an import default value intent. Extends the base intent with optional
|
|
* view properties that the engine evaluates at runtime to produce human-readable output.
|
|
*
|
|
* ```
|
|
* {
|
|
* "variables": {
|
|
* "[id]": {
|
|
* "importDefaultValue": { } ← this schema
|
|
* }
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateImportDefaultValueSchema = xoTemplateIntentSchema
|
|
// .shape unwraps the ZodObject to the raw field map { name, description, icon } with each field made optional
|
|
.extend(xoTemplateViewPropertiesSchema.partial().shape)
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for a variable definition.
|
|
*
|
|
* ```
|
|
* {
|
|
* "variables": {
|
|
* "[id]": { } ← this schema
|
|
* }
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateVariableSchema = xoTemplateViewPropertiesSchema
|
|
.extend({
|
|
type: xoTemplatePrimitiveTypeSchema.optional().describe('The data type of this variable.'),
|
|
hint: z.string().optional().describe('A hint to help users understand what value to provide.'),
|
|
|
|
// A neutral intent that the engine uses to populate the default value for this variable.
|
|
// View properties (name, description, icon) may contain CashASM expressions that the
|
|
// engine evaluates at runtime to produce human-readable output. The engine overrides
|
|
// whatever values are set here when resolving the variable for a participant.
|
|
importDefaultValue: xoTemplateImportDefaultValueSchema
|
|
.optional()
|
|
.describe('A neutral intent that the engine uses to populate the default value for this variable.'),
|
|
})
|
|
.strict();
|
|
|
|
// ============================================================
|
|
// Template Resources
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for a resource reference attached to a template element. Extends view
|
|
* properties with a URL pointing to external documentation or tooling.
|
|
*
|
|
* ```
|
|
* {
|
|
* "resources": [
|
|
* { "name": "...", "description": "...", "url": "..." } ← this schema
|
|
* ]
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateResourceSchema = xoTemplateViewPropertiesSchema
|
|
.extend({
|
|
url: z.string().describe('The URL for this resource.'),
|
|
})
|
|
.strict();
|
|
|
|
/**
|
|
* Validation schema for an icon reference.
|
|
*
|
|
* ```
|
|
* {
|
|
* "icons": [
|
|
* { "name": "...", "hash": "..." } ← this schema
|
|
* ]
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateIconSchema = xoTemplateViewPropertiesSchema
|
|
.pick({ name: true })
|
|
.extend({
|
|
hash: z.string().describe('The identifier of the icon.'),
|
|
})
|
|
.strict();
|
|
|
|
// ============================================================
|
|
// Defaults
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for the defaults block of a template.
|
|
*
|
|
* ```
|
|
* {
|
|
* "defaults": { } ← this schema
|
|
* }
|
|
* ```
|
|
*/
|
|
export const xoTemplateDefaultsSchema = z
|
|
.object({
|
|
change: xoTemplateOutputIntentSchema.optional().describe('Instructions for how to construct automated change output.'),
|
|
})
|
|
.strict();
|
|
|
|
// ============================================================
|
|
// Template
|
|
// ============================================================
|
|
|
|
/**
|
|
* Validation schema for the full XOTemplate type.
|
|
*/
|
|
export const xoTemplateSchema = xoTemplateViewPropertiesSchema
|
|
.extend({
|
|
$schema: z
|
|
.string()
|
|
.describe('The URI that identifies the JSON Schema used by this template. This enables documentation, autocompletion, and validation in JSON documents.'),
|
|
version: z.string().optional().describe('A string identifying the version of this template.'),
|
|
supported: z.array(bchVmVersionSchema).min(1).describe('The BCH VM versions that this template supports. At least one version is required.'),
|
|
defaults: xoTemplateDefaultsSchema.optional().describe('Optional default settings used in this template.'),
|
|
roles: z.record(z.string(), xoTemplateViewPropertiesSchema).describe('The roles defined in this template.'),
|
|
start: z.array(xoTemplateActionIntentSchema).describe('A list of entry points defining which actions are available at the start.'),
|
|
actions: z.record(z.string(), xoTemplateActionSchema).describe('The actions defined in this template.'),
|
|
data: z.record(z.string(), xoTemplateDataSchema).optional().describe('The data fields defined in this template.'),
|
|
transactions: z.record(z.string(), xoTemplateTransactionSchema).optional().describe('The transaction templates defined in this template.'),
|
|
inputs: z.record(z.string(), xoTemplateInputSchema).describe('The inputs defined in this template.'),
|
|
outputs: z.record(z.string(), xoTemplateOutputSchema).describe('The outputs defined in this template.'),
|
|
lockingScripts: z.record(z.string(), xoTemplateLockingScriptSchema).describe('The locking script templates defined in this template.'),
|
|
scripts: z
|
|
.record(z.string(), z.string())
|
|
.describe('Scripts used in this template. Keys are script identifiers, values are bytecode or CashASM expressions.'),
|
|
constants: z.record(z.string(), xoTemplateConstantSchema).optional().describe('The constants defined in this template.'),
|
|
variables: z
|
|
.record(z.string(), xoTemplateVariableSchema)
|
|
.optional()
|
|
.describe("The variables that must be provided for use in the template's scripts."),
|
|
resources: z.array(xoTemplateResourceSchema).optional().describe('Resource references providing external documentation or tooling links.'),
|
|
icons: z.array(xoTemplateIconSchema).optional().describe('The icons available for use throughout the template.'),
|
|
scenarios: z.unknown().optional().describe('The scenarios defined in this template.'),
|
|
})
|
|
.strict();
|