CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-xyo-network--payload-model

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.

Overview
Eval results
Files

bundles-queries.mddocs/

Payload Bundles and Queries

System for grouping related payloads and structured querying capabilities for payload discovery and filtering within the XYO Protocol 2.0 ecosystem.

Capabilities

Payload Bundle System

Payload bundles group multiple related payloads together with a root hash reference, enabling efficient handling of collections of related data in the XYO network.

/**
 * Schema constant for payload bundles
 */
const PayloadBundleSchema: "network.xyo.payload.bundle";

/**
 * Type alias for the payload bundle schema
 */
type PayloadBundleSchema = typeof PayloadBundleSchema;

/**
 * Fields interface for payload bundle data
 */
interface PayloadBundleFields<T extends Payload = Payload> {
  /** Array of payloads contained in this bundle */
  payloads: T[];
  /** Root hash identifying the complete bundle */
  root: Hash;
}

/**
 * Complete payload bundle type combining fields with schema
 */
type PayloadBundle = Payload<PayloadBundleFields, PayloadBundleSchema>;

/**
 * Type guard for payload bundle validation
 */
function isPayloadBundle(value: unknown): value is PayloadBundle;

/**
 * Type assertion for payload bundle
 */
function asPayloadBundle(value: unknown): PayloadBundle;

/**
 * Optional type assertion for payload bundle
 */
function asOptionalPayloadBundle(value: unknown): PayloadBundle | undefined;

Usage Examples:

import { 
  PayloadBundle,
  PayloadBundleFields,
  PayloadBundleSchema,
  isPayloadBundle,
  asPayloadBundle,
  Payload
} from "@xyo-network/payload-model";

// Define custom payload types for bundling
interface UserPayload extends Payload {
  schema: "network.example.user";
  name: string;
  email: string;
}

interface ProductPayload extends Payload {
  schema: "network.example.product";
  name: string;
  price: number;
}

// Create individual payloads
const userPayload: UserPayload = {
  schema: "network.example.user",
  name: "Alice",
  email: "alice@example.com"
};

const productPayload: ProductPayload = {
  schema: "network.example.product",
  name: "Laptop",
  price: 999
};

// Create a payload bundle
const bundle: PayloadBundle = {
  schema: PayloadBundleSchema,
  payloads: [userPayload, productPayload],
  root: "0x1234567890abcdef..."
};

// Validate bundle
if (isPayloadBundle(bundle)) {
  console.log(`Bundle contains ${bundle.payloads.length} payloads`);
  console.log(`Root hash: ${bundle.root}`);
}

// Process bundles from unknown data
const unknownData: unknown = {
  schema: PayloadBundleSchema,
  payloads: [
    { schema: "network.example.user", name: "Bob", email: "bob@example.com" },
    { schema: "network.example.product", name: "Phone", price: 599 }
  ],
  root: "0xabcdef1234567890..."
};

try {
  const validBundle = asPayloadBundle(unknownData);
  validBundle.payloads.forEach((payload, index) => {
    console.log(`Payload ${index}: ${payload.schema}`);
  });
} catch (error) {
  console.error("Invalid bundle format");
}

// Create typed bundle for specific payload types
function createUserProductBundle(
  users: UserPayload[], 
  products: ProductPayload[], 
  rootHash: string
): PayloadBundle {
  return {
    schema: PayloadBundleSchema,
    payloads: [...users, ...products],
    root: rootHash as Hash
  };
}

Query System

Structured query interface for payload discovery and filtering with support for address targeting, budget constraints, and frequency limitations.

/**
 * Query fields interface defining query parameters
 */
interface QueryFields {
  /** The addresses of the intended handlers */
  address?: Address | Address[];
  
  /** The maximum XYO that can be spent executing the query */
  budget?: number;
  
  /** The frequency on which this query can be rerun */
  maxFrequency?: 'once' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year';
  
  /** The starting point for the bidding on the query */
  minBid?: number;
}

/**
 * Query payload type combining custom data with query fields
 */
type Query<T extends void | EmptyObject | WithSchema = void, S extends Schema | void = void> = Payload<
  T extends void ? QueryFields : T & QueryFields,
  S extends void
    ? T extends WithSchema ? T['schema']
      : T extends void ? Schema
        : void
    : S
>;

Usage Examples:

import { Query, QueryFields } from "@xyo-network/payload-model";

// Basic query with just query fields
type BasicQuery = Query;

const basicQuery: BasicQuery = {
  schema: "network.xyo.query",
  address: "0x742d35Cc6065C6EaABf23bA0aC21e0017E3BB26C",
  budget: 1000,
  maxFrequency: "hour",
  minBid: 10
};

// Query with custom data
interface UserSearchQuery {
  searchTerm: string;
  filters: {
    minAge?: number;
    maxAge?: number;
    location?: string;
  };
}

const UserSearchSchema = "network.example.query.user-search" as const;
type UserSearchQueryPayload = Query<UserSearchQuery, typeof UserSearchSchema>;

const userSearchQuery: UserSearchQueryPayload = {
  schema: UserSearchSchema,
  searchTerm: "alice",
  filters: {
    minAge: 18,
    location: "New York"
  },
  address: ["0x123...", "0x456..."],
  budget: 500,
  maxFrequency: "minute",
  minBid: 5
};

// Query with multiple addresses
const multiAddressQuery: Query = {
  schema: "network.xyo.multi-query",
  address: [
    "0x742d35Cc6065C6EaABf23bA0aC21e0017E3BB26C",
    "0x8ba1f109551bD432803012645Hac136c73ce2A",
    "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"
  ],
  budget: 2000,
  maxFrequency: "day"
};

// Query factory function
function createQuery<T>(
  data: T,
  schema: string,
  options: Partial<QueryFields> = {}
): Query<T & { data: T }, typeof schema> {
  return {
    schema: schema as any,
    data,
    address: options.address,
    budget: options.budget || 100,
    maxFrequency: options.maxFrequency || "hour",
    minBid: options.minBid || 1
  } as Query<T & { data: T }, typeof schema>;
}

// Use query factory
const productQuery = createQuery(
  { category: "electronics", priceRange: [100, 1000] },
  "network.example.query.product",
  {
    address: "0x742d35Cc6065C6EaABf23bA0aC21e0017E3BB26C",
    budget: 300,
    maxFrequency: "minute"
  }
);

Payload Collection Utilities

Additional utilities for working with collections of payloads and filtering operations.

/**
 * Filter interface for payload discovery operations
 */
interface PayloadFindFilter {
  /** Maximum number of results to return */
  limit?: number;
  
  /** Sort order for results */
  order?: 'desc' | 'asc';
  
  /** Schema filter - single schema or array of schemas */
  schema?: string | string[];
}

/**
 * Hash map interface for efficient payload lookup
 */
interface PayloadHashMap<TPayload extends Payload = Payload, TId extends string | number | symbol = Hash> {
  /** Data hash mappings - multiple root hashes may have same data hash */
  dataHash: Record<TId, TId>;
  
  /** Complete payload mappings by hash */
  hash: Record<TId, TPayload>;
}

Usage Examples:

import { 
  PayloadFindFilter, 
  PayloadHashMap,
  Payload 
} from "@xyo-network/payload-model";

// Create payload filter for search operations
const userFilter: PayloadFindFilter = {
  limit: 10,
  order: 'desc',
  schema: ["network.example.user", "network.example.profile"]
};

const productFilter: PayloadFindFilter = {
  limit: 50,
  order: 'asc',
  schema: "network.example.product"
};

// Simulate payload search function
function findPayloads(
  payloads: Payload[], 
  filter: PayloadFindFilter
): Payload[] {
  let filtered = payloads;
  
  // Filter by schema
  if (filter.schema) {
    const schemas = Array.isArray(filter.schema) ? filter.schema : [filter.schema];
    filtered = filtered.filter(p => schemas.includes(p.schema));
  }
  
  // Apply ordering (simplified example)
  if (filter.order === 'desc') {
    filtered = filtered.reverse();
  }
  
  // Apply limit
  if (filter.limit) {
    filtered = filtered.slice(0, filter.limit);
  }
  
  return filtered;
}

// Payload hash map for efficient lookups
interface UserPayload extends Payload {
  schema: "network.example.user";
  name: string;
  email: string;
}

const payloadHashMap: PayloadHashMap<UserPayload> = {
  dataHash: {
    "0x123...": "0x123...",
    "0x456...": "0x123...", // Same data hash
    "0x789...": "0x789..."
  },
  hash: {
    "0x123...": {
      schema: "network.example.user",
      name: "Alice",
      email: "alice@example.com"
    },
    "0x456...": {
      schema: "network.example.user", 
      name: "Alice",
      email: "alice@example.com"
    },
    "0x789...": {
      schema: "network.example.user",
      name: "Bob", 
      email: "bob@example.com"
    }
  }
};

// Use hash map for lookups
function getPayloadByHash(hashMap: PayloadHashMap, hash: string): Payload | undefined {
  return hashMap.hash[hash];
}

function getUniqueDataHashes(hashMap: PayloadHashMap): string[] {
  return Object.values(hashMap.dataHash);
}

// Bundle operations with queries
function createBundleQuery(
  bundleRoot: string,
  targetAddress: string,
  budget: number
): Query<{ bundleRoot: string }, "network.xyo.query.bundle"> {
  return {
    schema: "network.xyo.query.bundle",
    bundleRoot,
    address: targetAddress as Address,
    budget,
    maxFrequency: "hour",
    minBid: 1
  };
}

// Query for bundle contents
const bundleQuery = createBundleQuery(
  "0x1234567890abcdef...",
  "0x742d35Cc6065C6EaABf23bA0aC21e0017E3BB26C",
  500
);

PayloadSet System

System for defining collections of required and optional payloads with quantity specifications.

/**
 * Schema constant for payload sets
 */
const PayloadSetSchema: "network.xyo.payload.set";

/**
 * PayloadSet interface defining required and optional payload quantities
 */
interface PayloadSet {
  /** Optional payload requirements by schema with quantities */
  optional?: Record<string, number>;
  
  /** Required payload requirements by schema with quantities */
  required?: Record<string, number>;
}

/**
 * Complete PayloadSet payload type
 */
type PayloadSetPayload = Payload<PayloadSet, PayloadSetSchema>;

Usage Examples:

import { 
  PayloadSet, 
  PayloadSetPayload, 
  PayloadSetSchema 
} from "@xyo-network/payload-model";

// Define payload set requirements
const payloadSet: PayloadSetPayload = {
  schema: PayloadSetSchema,
  required: {
    "network.example.user": 1,
    "network.example.auth": 1
  },
  optional: {
    "network.example.preferences": 1,
    "network.example.metadata": 3
  }
};

// Validate payload collection against PayloadSet
function validatePayloadCollection(
  payloads: Payload[],
  requirements: PayloadSet
): { valid: boolean; missing: string[]; errors: string[] } {
  const payloadCounts = payloads.reduce((counts, payload) => {
    counts[payload.schema] = (counts[payload.schema] || 0) + 1;
    return counts;
  }, {} as Record<string, number>);

  const missing: string[] = [];
  const errors: string[] = [];

  // Check required payloads
  if (requirements.required) {
    for (const [schema, required] of Object.entries(requirements.required)) {
      const actual = payloadCounts[schema] || 0;
      if (actual < required) {
        missing.push(`${schema} (need ${required}, have ${actual})`);
      }
    }
  }

  // Check optional payloads don't exceed limits
  if (requirements.optional) {
    for (const [schema, max] of Object.entries(requirements.optional)) {
      const actual = payloadCounts[schema] || 0;
      if (actual > max) {
        errors.push(`${schema} exceeds maximum (max ${max}, have ${actual})`);
      }
    }
  }

  return {
    valid: missing.length === 0 && errors.length === 0,
    missing,
    errors
  };
}

// Use validation
const testPayloads: Payload[] = [
  { schema: "network.example.user", name: "Alice" },
  { schema: "network.example.auth", token: "abc123" },
  { schema: "network.example.preferences", theme: "dark" }
];

const validation = validatePayloadCollection(testPayloads, payloadSet);
console.log("Validation result:", validation);

Advanced Usage Patterns

Bundle Processing Pipeline

import { 
  PayloadBundle, 
  PayloadBundleSchema,
  isPayloadBundle,
  Query,
  PayloadFindFilter
} from "@xyo-network/payload-model";

// Bundle processing pipeline
class BundleProcessor {
  async processBundle(data: unknown): Promise<ProcessedBundle | null> {
    if (!isPayloadBundle(data)) {
      return null;
    }

    const processed = {
      root: data.root,
      payloadCount: data.payloads.length,
      schemas: [...new Set(data.payloads.map(p => p.schema))],
      payloads: data.payloads
    };

    return processed;
  }

  createBundleFromQuery(query: Query, results: Payload[]): PayloadBundle {
    return {
      schema: PayloadBundleSchema,
      payloads: results,
      root: this.calculateRootHash(results)
    };
  }

  private calculateRootHash(payloads: Payload[]): Hash {
    // Simplified hash calculation
    const combined = payloads.map(p => JSON.stringify(p)).join('');
    return `0x${combined.slice(0, 64)}` as Hash;
  }
}

interface ProcessedBundle {
  root: Hash;
  payloadCount: number;
  schemas: string[];
  payloads: Payload[];
}

Query Builder Pattern

import { Query, QueryFields, Address } from "@xyo-network/payload-model";

// Query builder for complex query construction
class QueryBuilder<T = {}> {
  private data: T = {} as T;
  private fields: Partial<QueryFields> = {};
  private schemaValue: string = "network.xyo.query";

  schema(schema: string): QueryBuilder<T> {
    this.schemaValue = schema;
    return this;
  }

  withData<U>(data: U): QueryBuilder<T & U> {
    const builder = new QueryBuilder<T & U>();
    builder.data = { ...this.data, ...data };
    builder.fields = { ...this.fields };
    builder.schemaValue = this.schemaValue;
    return builder;
  }

  address(address: Address | Address[]): QueryBuilder<T> {
    this.fields.address = address;
    return this;
  }

  budget(budget: number): QueryBuilder<T> {
    this.fields.budget = budget;
    return this;
  }

  frequency(freq: QueryFields['maxFrequency']): QueryBuilder<T> {
    this.fields.maxFrequency = freq;
    return this;
  }

  minBid(bid: number): QueryBuilder<T> {
    this.fields.minBid = bid;
    return this;
  }

  build(): Query<T, typeof this.schemaValue> {
    return {
      schema: this.schemaValue,
      ...this.data,
      ...this.fields
    } as Query<T, typeof this.schemaValue>;
  }
}

// Usage
const query = new QueryBuilder()
  .schema("network.example.user-search")
  .withData({ searchTerm: "alice", filters: { location: "NYC" } })
  .address("0x742d35Cc6065C6EaABf23bA0aC21e0017E3BB26C")
  .budget(1000)
  .frequency("minute")
  .minBid(10)
  .build();

Types Reference

Bundle Types

  • PayloadBundle: Complete payload bundle type
  • PayloadBundleFields<T>: Bundle data fields interface
  • PayloadBundleSchema: Bundle schema constant

Query Types

  • Query<T, S>: Query payload type with custom data
  • QueryFields: Query parameter fields interface

Utility Types

  • PayloadFindFilter: Filter interface for payload search
  • PayloadHashMap<TPayload, TId>: Hash map for efficient payload lookup
  • PayloadSet: Required/optional payload specifications
  • PayloadSetPayload: PayloadSet as payload type

Constants

  • PayloadBundleSchema: "network.xyo.payload.bundle"
  • PayloadSetSchema: "network.xyo.payload.set"

Functions

  • isPayloadBundle(value): Type guard for payload bundles
  • asPayloadBundle(value): Type assertion for payload bundles
  • asOptionalPayloadBundle(value): Optional type assertion for payload bundles

Install with Tessl CLI

npx tessl i tessl/npm-xyo-network--payload-model

docs

bundles-queries.md

core-payload-types.md

index.md

storage-metadata.md

type-guards.md

utility-types.md

validation-errors.md

tile.json