Core payload modeling capabilities for the XYO Protocol 2.0 ecosystem, offering TypeScript interfaces and types for defining, validating, and manipulating payloads within the XYO blockchain network.
Comprehensive validation framework with sync/async validation functions, structured error payload types, and Zod integration for runtime validation within the XYO Protocol 2.0 ecosystem.
Type definitions for synchronous and asynchronous payload validation functions with flexible validation patterns.
/**
* Synchronous payload validation function
* @param payload - Payload to validate
* @returns Boolean indicating validation result
*/
type SyncPayloadValidationFunction<T extends Payload = Payload> = (payload: T) => boolean;
/**
* Asynchronous payload validation function
* @param payload - Payload to validate
* @returns Promise resolving to boolean validation result
*/
type AsyncPayloadValidationFunction<T extends Payload = Payload> = (payload: T) => Promise<boolean>;
/**
* Union type for both sync and async validation functions
*/
type PayloadValidationFunction<T extends Payload = Payload> =
SyncPayloadValidationFunction<T> | AsyncPayloadValidationFunction<T>;Zod-based validation schemas for runtime payload validation and type checking with full TypeScript integration.
/**
* Import Zod for schema validation
*/
import * as z from 'zod';
/**
* Storage metadata Zod schema
*/
const StorageMetaZod: z.ZodObject<{
_hash: z.ZodType<Hash>;
_dataHash: z.ZodType<Hash>;
_sequence: z.ZodType<string>;
}>;
/**
* Base payload Zod schema
*/
const PayloadZod: z.ZodObject<{
schema: z.ZodType<Schema>;
}>;
/**
* Payload with storage metadata Zod schema
*/
const PayloadWithStorageMetaZod: z.ZodIntersection<
typeof PayloadZod,
typeof StorageMetaZod
>;
/**
* Any payload with flexible additional properties
*/
const AnyPayloadZod: z.ZodObject<{
schema: z.ZodType<Schema>;
}> & z.ZodCatchall<z.ZodAny>;
/**
* Any payload with storage metadata
*/
const AnyPayloadWithStorageMetaZod: z.ZodIntersection<
typeof AnyPayloadZod,
typeof StorageMetaZod
>;
/**
* Inferred types from Zod schemas
*/
type PayloadWithStorageMeta = z.infer<typeof PayloadWithStorageMetaZod>;
type AnyPayload = z.infer<typeof AnyPayloadZod>;
type AnyPayloadWithStorageMeta = z.infer<typeof AnyPayloadWithStorageMetaZod>;
/**
* Helper function to create payload schema with storage metadata
*/
function WithStorageMetaZod<T extends typeof PayloadZod>(valueZod: T): z.ZodIntersection<typeof StorageMetaZod, T>;Usage Examples:
import {
PayloadValidationFunction,
SyncPayloadValidationFunction,
AsyncPayloadValidationFunction,
Payload
} from "@xyo-network/payload-model";
// Define custom payload type
interface UserPayload extends Payload {
schema: "network.example.user";
name: string;
email: string;
age: number;
}
// Synchronous validation function
const validateUserSync: SyncPayloadValidationFunction<UserPayload> = (payload) => {
if (!payload.name || payload.name.length < 2) return false;
if (!payload.email || !payload.email.includes('@')) return false;
if (!payload.age || payload.age < 0 || payload.age > 150) return false;
return true;
};
// Asynchronous validation function
const validateUserAsync: AsyncPayloadValidationFunction<UserPayload> = async (payload) => {
// Simulate async validation (e.g., database check)
const emailExists = await checkEmailExists(payload.email);
if (emailExists) return false;
const nameValid = await validateNameFormat(payload.name);
return nameValid && payload.age >= 18;
};
// Generic validation function
const validateUser: PayloadValidationFunction<UserPayload> = validateUserSync;
// Use validation functions
const userPayload: UserPayload = {
schema: "network.example.user",
name: "Alice",
email: "alice@example.com",
age: 25
};
// Sync validation
if (validateUserSync(userPayload)) {
console.log("User payload is valid");
}
// Async validation
const isValid = await validateUserAsync(userPayload);
if (isValid) {
console.log("User payload passed async validation");
}
// Helper functions (examples)
async function checkEmailExists(email: string): Promise<boolean> {
// Simulate database check
return Promise.resolve(false);
}
async function validateNameFormat(name: string): Promise<boolean> {
// Simulate external validation service
return Promise.resolve(name.length >= 2 && /^[a-zA-Z\s]+$/.test(name));
}Structured error payload system for handling and communicating errors within XYO modules and operations.
/**
* Schema constant for module errors
*/
const ModuleErrorSchema: "network.xyo.error.module";
/**
* Type alias for module error schema
*/
type ModuleErrorSchema = typeof ModuleErrorSchema;
/**
* Import JsonValue type from @xylabs/object
*/
import type { JsonValue } from '@xylabs/object';
/**
* Module error payload type with comprehensive error information
*/
type ModuleError = Payload<{
/** Additional error details as JSON value */
details?: JsonValue;
/** Human-readable error message */
message?: string;
/** Error name or type identifier */
name?: string;
/** Query hash or schema that caused the error */
query?: Hash | Schema;
/** Module error schema */
schema: ModuleErrorSchema;
}>;
/**
* Type guard for module error validation
*/
function isModuleError(value: unknown): value is ModuleError;Usage Examples:
import {
ModuleError,
ModuleErrorSchema,
isModuleError,
Payload,
Hash,
Schema
} from "@xyo-network/payload-model";
// Create basic module error
const basicError: ModuleError = {
schema: ModuleErrorSchema,
message: "Validation failed",
name: "ValidationError"
};
// Create detailed module error
const detailedError: ModuleError = {
schema: ModuleErrorSchema,
message: "User payload validation failed",
name: "UserValidationError",
details: {
field: "email",
reason: "Invalid email format",
value: "invalid-email",
code: "EMAIL_INVALID"
},
query: "network.example.user" as Schema
};
// Create error with query hash
const queryError: ModuleError = {
schema: ModuleErrorSchema,
message: "Query execution failed",
name: "QueryExecutionError",
details: {
timeout: true,
duration: 30000,
retries: 3
},
query: "0x1234567890abcdef..." as Hash
};
// Error handling utility
function createModuleError(
message: string,
name: string,
details?: any,
query?: Hash | Schema
): ModuleError {
return {
schema: ModuleErrorSchema,
message,
name,
details,
query
};
}
// Validate and handle errors
function processPayload(payload: unknown): Payload | ModuleError {
if (!payload || typeof payload !== 'object') {
return createModuleError(
"Invalid payload format",
"PayloadFormatError",
{ received: typeof payload }
);
}
if (isModuleError(payload)) {
console.error("Module error detected:", payload.message);
return payload;
}
// Process valid payload
return payload as Payload;
}
// Error result handling
function handleResult(result: Payload | ModuleError) {
if (isModuleError(result)) {
console.error(`Error: ${result.name} - ${result.message}`);
if (result.details) {
console.error("Details:", result.details);
}
if (result.query) {
console.error("Related query:", result.query);
}
return null;
}
return result;
}
// Use in validation pipeline
async function validateAndProcess<T extends Payload>(
payload: T,
validator: PayloadValidationFunction<T>
): Promise<T | ModuleError> {
try {
const isValid = await Promise.resolve(validator(payload));
if (!isValid) {
return createModuleError(
"Payload validation failed",
"ValidationError",
{ schema: payload.schema },
payload.schema
);
}
return payload;
} catch (error) {
return createModuleError(
"Validation process failed",
"ValidationProcessError",
{
originalError: error instanceof Error ? error.message : String(error),
schema: payload.schema
},
payload.schema
);
}
}Runtime validation schemas using Zod for comprehensive payload structure validation and type safety.
/**
* Base Zod schema for payload validation
*/
const PayloadZod: ZodType<{ schema: Schema }>;
/**
* Zod schema for storage metadata validation
*/
const StorageMetaZod: ZodType<{
_hash: Hash;
_dataHash: Hash;
_sequence: Sequence;
}>;
/**
* Zod schema for payload with storage metadata
*/
const PayloadWithStorageMetaZod: ZodType<PayloadWithStorageMeta>;
/**
* Catch-all Zod schema for any payload with additional properties
*/
const AnyPayloadZod: ZodType<AnyPayload>;
/**
* Catch-all Zod schema for any payload with storage metadata
*/
const AnyPayloadWithStorageMetaZod: ZodType<AnyPayloadWithStorageMeta>;
/**
* Helper function to add storage metadata validation to existing schema
*/
function WithStorageMetaZod<T extends typeof PayloadZod>(
valueZod: T
): ZodType<StorageMeta & z.infer<T>>;
/**
* Inferred types from Zod schemas
*/
type PayloadWithStorageMeta = z.infer<typeof PayloadWithStorageMetaZod>;
type AnyPayload = z.infer<typeof AnyPayloadZod>;
type AnyPayloadWithStorageMeta = z.infer<typeof AnyPayloadWithStorageMetaZod>;Usage Examples:
import {
PayloadZod,
AnyPayloadZod,
StorageMetaZod,
PayloadWithStorageMetaZod,
WithStorageMetaZod
} from "@xyo-network/payload-model";
import * as z from "zod";
// Create custom payload schema
const UserPayloadZod = z.object({
schema: z.literal("network.example.user"),
name: z.string().min(2).max(50),
email: z.string().email(),
age: z.number().int().min(0).max(150),
preferences: z.object({
theme: z.enum(["light", "dark"]).optional(),
notifications: z.boolean().optional()
}).optional()
});
type UserPayload = z.infer<typeof UserPayloadZod>;
// Validate user payload
const userData = {
schema: "network.example.user",
name: "Alice",
email: "alice@example.com",
age: 25,
preferences: {
theme: "dark",
notifications: true
}
};
try {
const validUser = UserPayloadZod.parse(userData);
console.log("Valid user:", validUser.name);
} catch (error) {
if (error instanceof z.ZodError) {
console.error("Validation errors:", error.errors);
}
}
// Validate any payload
const unknownPayload = {
schema: "network.example.unknown",
data: "some data",
timestamp: Date.now()
};
const validPayload = AnyPayloadZod.parse(unknownPayload);
console.log("Valid payload schema:", validPayload.schema);
// Add storage metadata to custom schema
const UserWithStorageZod = WithStorageMetaZod(UserPayloadZod);
const userWithStorageData = {
schema: "network.example.user",
name: "Bob",
email: "bob@example.com",
age: 30,
_hash: "0x123...",
_dataHash: "0x456...",
_sequence: "1234567890abcdef"
};
const validUserWithStorage = UserWithStorageZod.parse(userWithStorageData);
console.log("User with storage:", validUserWithStorage.name);
console.log("Storage hash:", validUserWithStorage._hash);
// Validation with error handling
function validatePayloadSafely<T>(
schema: z.ZodType<T>,
data: unknown
): { success: true; data: T } | { success: false; errors: z.ZodError } {
try {
const validated = schema.parse(data);
return { success: true, data: validated };
} catch (error) {
if (error instanceof z.ZodError) {
return { success: false, errors: error };
}
throw error;
}
}
// Use safe validation
const result = validatePayloadSafely(UserPayloadZod, userData);
if (result.success) {
console.log("Validated user:", result.data.name);
} else {
console.error("Validation failed:", result.errors.errors);
}Complex validation scenarios and patterns for robust payload processing.
/**
* Schema validation with regex pattern
*/
const SchemaZod: ZodType<Schema>;
/**
* Schema validation functions
*/
function isSchema(value: unknown): value is Schema;
function asSchema(value: unknown): Schema;Usage Examples:
import {
PayloadValidationFunction,
ModuleError,
ModuleErrorSchema,
createModuleError,
SchemaZod,
AnyPayloadZod
} from "@xyo-network/payload-model";
import * as z from "zod";
// Complex validation pipeline
class PayloadValidator {
private validators: Map<string, PayloadValidationFunction> = new Map();
private schemas: Map<string, z.ZodType<any>> = new Map();
// Register schema validator
registerSchema<T extends Payload>(
schema: string,
zodSchema: z.ZodType<T>,
customValidator?: PayloadValidationFunction<T>
) {
this.schemas.set(schema, zodSchema);
if (customValidator) {
this.validators.set(schema, customValidator);
}
}
// Validate payload with comprehensive error reporting
async validatePayload(payload: unknown): Promise<{
valid: boolean;
payload?: Payload;
errors: ModuleError[];
}> {
const errors: ModuleError[] = [];
// Basic structure validation
try {
const basicPayload = AnyPayloadZod.parse(payload);
// Schema format validation
if (!SchemaZod.safeParse(basicPayload.schema).success) {
errors.push({
schema: ModuleErrorSchema,
message: "Invalid schema format",
name: "SchemaFormatError",
details: { schema: basicPayload.schema }
});
return { valid: false, errors };
}
// Schema-specific validation
const zodSchema = this.schemas.get(basicPayload.schema);
if (zodSchema) {
const zodResult = zodSchema.safeParse(payload);
if (!zodResult.success) {
errors.push({
schema: ModuleErrorSchema,
message: "Schema validation failed",
name: "ZodValidationError",
details: {
errors: zodResult.error.errors,
schema: basicPayload.schema
},
query: basicPayload.schema
});
}
}
// Custom validation
const customValidator = this.validators.get(basicPayload.schema);
if (customValidator) {
try {
const isValid = await Promise.resolve(customValidator(basicPayload));
if (!isValid) {
errors.push({
schema: ModuleErrorSchema,
message: "Custom validation failed",
name: "CustomValidationError",
details: { schema: basicPayload.schema },
query: basicPayload.schema
});
}
} catch (error) {
errors.push({
schema: ModuleErrorSchema,
message: "Custom validation error",
name: "CustomValidationException",
details: {
error: error instanceof Error ? error.message : String(error),
schema: basicPayload.schema
},
query: basicPayload.schema
});
}
}
return {
valid: errors.length === 0,
payload: errors.length === 0 ? basicPayload : undefined,
errors
};
} catch (error) {
errors.push({
schema: ModuleErrorSchema,
message: "Payload structure validation failed",
name: "StructureValidationError",
details: {
error: error instanceof Error ? error.message : String(error)
}
});
return { valid: false, errors };
}
}
// Batch validation
async validateBatch(payloads: unknown[]): Promise<{
valid: Payload[];
invalid: { payload: unknown; errors: ModuleError[] }[];
}> {
const valid: Payload[] = [];
const invalid: { payload: unknown; errors: ModuleError[] }[] = [];
for (const payload of payloads) {
const result = await this.validatePayload(payload);
if (result.valid && result.payload) {
valid.push(result.payload);
} else {
invalid.push({ payload, errors: result.errors });
}
}
return { valid, invalid };
}
}
// Usage example
const validator = new PayloadValidator();
// Register user schema
const UserSchema = z.object({
schema: z.literal("network.example.user"),
name: z.string().min(2),
email: z.string().email(),
age: z.number().int().min(0)
});
const userCustomValidator: PayloadValidationFunction = async (payload) => {
// Custom business logic validation
return payload.name !== "admin"; // Example: no admin users allowed
};
validator.registerSchema("network.example.user", UserSchema, userCustomValidator);
// Validate payloads
const testPayloads = [
{ schema: "network.example.user", name: "Alice", email: "alice@example.com", age: 25 },
{ schema: "network.example.user", name: "admin", email: "admin@example.com", age: 35 },
{ schema: "invalid.schema.format", data: "test" },
"invalid payload"
];
const batchResult = await validator.validateBatch(testPayloads);
console.log(`Valid: ${batchResult.valid.length}, Invalid: ${batchResult.invalid.length}`);
batchResult.invalid.forEach(({ payload, errors }) => {
console.error("Invalid payload:", errors.map(e => e.message));
});import { ModuleError, ModuleErrorSchema, Payload } from "@xyo-network/payload-model";
// Error recovery utilities
class ErrorRecovery {
// Attempt to recover from validation errors
static tryRecover(error: ModuleError, originalPayload: unknown): Payload | null {
if (error.name === "SchemaFormatError" && error.details?.schema) {
// Try to fix common schema format issues
const fixedSchema = this.fixSchemaFormat(error.details.schema);
if (fixedSchema && typeof originalPayload === 'object' && originalPayload) {
return { ...(originalPayload as object), schema: fixedSchema };
}
}
return null;
}
private static fixSchemaFormat(schema: string): string | null {
// Example: fix common schema format issues
if (schema.includes("_")) {
return schema.replace(/_/g, ".");
}
if (schema.toUpperCase() === schema) {
return schema.toLowerCase();
}
return null;
}
// Transform errors for external reporting
static transformError(error: ModuleError): {
code: string;
message: string;
details?: any;
} {
return {
code: error.name || "UNKNOWN_ERROR",
message: error.message || "An unknown error occurred",
details: error.details
};
}
}SyncPayloadValidationFunction<T>: Synchronous validation function typeAsyncPayloadValidationFunction<T>: Asynchronous validation function typePayloadValidationFunction<T>: Union of sync/async validation functionsModuleError: Structured error payload typeModuleErrorSchema: Module error schema constantPayloadWithStorageMeta: Payload with storage metadata (inferred from Zod)AnyPayload: Any payload type (inferred from Zod)AnyPayloadWithStorageMeta: Any payload with storage metadata (inferred from Zod)PayloadZod: Base payload Zod schemaStorageMetaZod: Storage metadata Zod schemaPayloadWithStorageMetaZod: Payload with storage metadata Zod schemaAnyPayloadZod: Catch-all payload Zod schemaAnyPayloadWithStorageMetaZod: Catch-all payload with storage metadata Zod schemaModuleErrorSchema: "network.xyo.error.module"isModuleError(value): Type guard for module errorsWithStorageMetaZod<T>(schema): Add storage metadata validation to Zod schemaInstall with Tessl CLI
npx tessl i tessl/npm-xyo-network--payload-model