or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bundles-queries.mdcore-payload-types.mdindex.mdstorage-metadata.mdtype-guards.mdutility-types.mdvalidation-errors.md

bundles-queries.mddocs/

0

# Payload Bundles and Queries

1

2

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

3

4

## Capabilities

5

6

### Payload Bundle System

7

8

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

9

10

```typescript { .api }

11

/**

12

* Schema constant for payload bundles

13

*/

14

const PayloadBundleSchema: "network.xyo.payload.bundle";

15

16

/**

17

* Type alias for the payload bundle schema

18

*/

19

type PayloadBundleSchema = typeof PayloadBundleSchema;

20

21

/**

22

* Fields interface for payload bundle data

23

*/

24

interface PayloadBundleFields<T extends Payload = Payload> {

25

/** Array of payloads contained in this bundle */

26

payloads: T[];

27

/** Root hash identifying the complete bundle */

28

root: Hash;

29

}

30

31

/**

32

* Complete payload bundle type combining fields with schema

33

*/

34

type PayloadBundle = Payload<PayloadBundleFields, PayloadBundleSchema>;

35

36

/**

37

* Type guard for payload bundle validation

38

*/

39

function isPayloadBundle(value: unknown): value is PayloadBundle;

40

41

/**

42

* Type assertion for payload bundle

43

*/

44

function asPayloadBundle(value: unknown): PayloadBundle;

45

46

/**

47

* Optional type assertion for payload bundle

48

*/

49

function asOptionalPayloadBundle(value: unknown): PayloadBundle | undefined;

50

```

51

52

**Usage Examples:**

53

54

```typescript

55

import {

56

PayloadBundle,

57

PayloadBundleFields,

58

PayloadBundleSchema,

59

isPayloadBundle,

60

asPayloadBundle,

61

Payload

62

} from "@xyo-network/payload-model";

63

64

// Define custom payload types for bundling

65

interface UserPayload extends Payload {

66

schema: "network.example.user";

67

name: string;

68

email: string;

69

}

70

71

interface ProductPayload extends Payload {

72

schema: "network.example.product";

73

name: string;

74

price: number;

75

}

76

77

// Create individual payloads

78

const userPayload: UserPayload = {

79

schema: "network.example.user",

80

name: "Alice",

81

email: "alice@example.com"

82

};

83

84

const productPayload: ProductPayload = {

85

schema: "network.example.product",

86

name: "Laptop",

87

price: 999

88

};

89

90

// Create a payload bundle

91

const bundle: PayloadBundle = {

92

schema: PayloadBundleSchema,

93

payloads: [userPayload, productPayload],

94

root: "0x1234567890abcdef..."

95

};

96

97

// Validate bundle

98

if (isPayloadBundle(bundle)) {

99

console.log(`Bundle contains ${bundle.payloads.length} payloads`);

100

console.log(`Root hash: ${bundle.root}`);

101

}

102

103

// Process bundles from unknown data

104

const unknownData: unknown = {

105

schema: PayloadBundleSchema,

106

payloads: [

107

{ schema: "network.example.user", name: "Bob", email: "bob@example.com" },

108

{ schema: "network.example.product", name: "Phone", price: 599 }

109

],

110

root: "0xabcdef1234567890..."

111

};

112

113

try {

114

const validBundle = asPayloadBundle(unknownData);

115

validBundle.payloads.forEach((payload, index) => {

116

console.log(`Payload ${index}: ${payload.schema}`);

117

});

118

} catch (error) {

119

console.error("Invalid bundle format");

120

}

121

122

// Create typed bundle for specific payload types

123

function createUserProductBundle(

124

users: UserPayload[],

125

products: ProductPayload[],

126

rootHash: string

127

): PayloadBundle {

128

return {

129

schema: PayloadBundleSchema,

130

payloads: [...users, ...products],

131

root: rootHash as Hash

132

};

133

}

134

```

135

136

### Query System

137

138

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

139

140

```typescript { .api }

141

/**

142

* Query fields interface defining query parameters

143

*/

144

interface QueryFields {

145

/** The addresses of the intended handlers */

146

address?: Address | Address[];

147

148

/** The maximum XYO that can be spent executing the query */

149

budget?: number;

150

151

/** The frequency on which this query can be rerun */

152

maxFrequency?: 'once' | 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year';

153

154

/** The starting point for the bidding on the query */

155

minBid?: number;

156

}

157

158

/**

159

* Query payload type combining custom data with query fields

160

*/

161

type Query<T extends void | EmptyObject | WithSchema = void, S extends Schema | void = void> = Payload<

162

T extends void ? QueryFields : T & QueryFields,

163

S extends void

164

? T extends WithSchema ? T['schema']

165

: T extends void ? Schema

166

: void

167

: S

168

>;

169

```

170

171

**Usage Examples:**

172

173

```typescript

174

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

175

176

// Basic query with just query fields

177

type BasicQuery = Query;

178

179

const basicQuery: BasicQuery = {

180

schema: "network.xyo.query",

181

address: "0x742d35Cc6065C6EaABf23bA0aC21e0017E3BB26C",

182

budget: 1000,

183

maxFrequency: "hour",

184

minBid: 10

185

};

186

187

// Query with custom data

188

interface UserSearchQuery {

189

searchTerm: string;

190

filters: {

191

minAge?: number;

192

maxAge?: number;

193

location?: string;

194

};

195

}

196

197

const UserSearchSchema = "network.example.query.user-search" as const;

198

type UserSearchQueryPayload = Query<UserSearchQuery, typeof UserSearchSchema>;

199

200

const userSearchQuery: UserSearchQueryPayload = {

201

schema: UserSearchSchema,

202

searchTerm: "alice",

203

filters: {

204

minAge: 18,

205

location: "New York"

206

},

207

address: ["0x123...", "0x456..."],

208

budget: 500,

209

maxFrequency: "minute",

210

minBid: 5

211

};

212

213

// Query with multiple addresses

214

const multiAddressQuery: Query = {

215

schema: "network.xyo.multi-query",

216

address: [

217

"0x742d35Cc6065C6EaABf23bA0aC21e0017E3BB26C",

218

"0x8ba1f109551bD432803012645Hac136c73ce2A",

219

"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"

220

],

221

budget: 2000,

222

maxFrequency: "day"

223

};

224

225

// Query factory function

226

function createQuery<T>(

227

data: T,

228

schema: string,

229

options: Partial<QueryFields> = {}

230

): Query<T & { data: T }, typeof schema> {

231

return {

232

schema: schema as any,

233

data,

234

address: options.address,

235

budget: options.budget || 100,

236

maxFrequency: options.maxFrequency || "hour",

237

minBid: options.minBid || 1

238

} as Query<T & { data: T }, typeof schema>;

239

}

240

241

// Use query factory

242

const productQuery = createQuery(

243

{ category: "electronics", priceRange: [100, 1000] },

244

"network.example.query.product",

245

{

246

address: "0x742d35Cc6065C6EaABf23bA0aC21e0017E3BB26C",

247

budget: 300,

248

maxFrequency: "minute"

249

}

250

);

251

```

252

253

### Payload Collection Utilities

254

255

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

256

257

```typescript { .api }

258

/**

259

* Filter interface for payload discovery operations

260

*/

261

interface PayloadFindFilter {

262

/** Maximum number of results to return */

263

limit?: number;

264

265

/** Sort order for results */

266

order?: 'desc' | 'asc';

267

268

/** Schema filter - single schema or array of schemas */

269

schema?: string | string[];

270

}

271

272

/**

273

* Hash map interface for efficient payload lookup

274

*/

275

interface PayloadHashMap<TPayload extends Payload = Payload, TId extends string | number | symbol = Hash> {

276

/** Data hash mappings - multiple root hashes may have same data hash */

277

dataHash: Record<TId, TId>;

278

279

/** Complete payload mappings by hash */

280

hash: Record<TId, TPayload>;

281

}

282

```

283

284

**Usage Examples:**

285

286

```typescript

287

import {

288

PayloadFindFilter,

289

PayloadHashMap,

290

Payload

291

} from "@xyo-network/payload-model";

292

293

// Create payload filter for search operations

294

const userFilter: PayloadFindFilter = {

295

limit: 10,

296

order: 'desc',

297

schema: ["network.example.user", "network.example.profile"]

298

};

299

300

const productFilter: PayloadFindFilter = {

301

limit: 50,

302

order: 'asc',

303

schema: "network.example.product"

304

};

305

306

// Simulate payload search function

307

function findPayloads(

308

payloads: Payload[],

309

filter: PayloadFindFilter

310

): Payload[] {

311

let filtered = payloads;

312

313

// Filter by schema

314

if (filter.schema) {

315

const schemas = Array.isArray(filter.schema) ? filter.schema : [filter.schema];

316

filtered = filtered.filter(p => schemas.includes(p.schema));

317

}

318

319

// Apply ordering (simplified example)

320

if (filter.order === 'desc') {

321

filtered = filtered.reverse();

322

}

323

324

// Apply limit

325

if (filter.limit) {

326

filtered = filtered.slice(0, filter.limit);

327

}

328

329

return filtered;

330

}

331

332

// Payload hash map for efficient lookups

333

interface UserPayload extends Payload {

334

schema: "network.example.user";

335

name: string;

336

email: string;

337

}

338

339

const payloadHashMap: PayloadHashMap<UserPayload> = {

340

dataHash: {

341

"0x123...": "0x123...",

342

"0x456...": "0x123...", // Same data hash

343

"0x789...": "0x789..."

344

},

345

hash: {

346

"0x123...": {

347

schema: "network.example.user",

348

name: "Alice",

349

email: "alice@example.com"

350

},

351

"0x456...": {

352

schema: "network.example.user",

353

name: "Alice",

354

email: "alice@example.com"

355

},

356

"0x789...": {

357

schema: "network.example.user",

358

name: "Bob",

359

email: "bob@example.com"

360

}

361

}

362

};

363

364

// Use hash map for lookups

365

function getPayloadByHash(hashMap: PayloadHashMap, hash: string): Payload | undefined {

366

return hashMap.hash[hash];

367

}

368

369

function getUniqueDataHashes(hashMap: PayloadHashMap): string[] {

370

return Object.values(hashMap.dataHash);

371

}

372

373

// Bundle operations with queries

374

function createBundleQuery(

375

bundleRoot: string,

376

targetAddress: string,

377

budget: number

378

): Query<{ bundleRoot: string }, "network.xyo.query.bundle"> {

379

return {

380

schema: "network.xyo.query.bundle",

381

bundleRoot,

382

address: targetAddress as Address,

383

budget,

384

maxFrequency: "hour",

385

minBid: 1

386

};

387

}

388

389

// Query for bundle contents

390

const bundleQuery = createBundleQuery(

391

"0x1234567890abcdef...",

392

"0x742d35Cc6065C6EaABf23bA0aC21e0017E3BB26C",

393

500

394

);

395

```

396

397

### PayloadSet System

398

399

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

400

401

```typescript { .api }

402

/**

403

* Schema constant for payload sets

404

*/

405

const PayloadSetSchema: "network.xyo.payload.set";

406

407

/**

408

* PayloadSet interface defining required and optional payload quantities

409

*/

410

interface PayloadSet {

411

/** Optional payload requirements by schema with quantities */

412

optional?: Record<string, number>;

413

414

/** Required payload requirements by schema with quantities */

415

required?: Record<string, number>;

416

}

417

418

/**

419

* Complete PayloadSet payload type

420

*/

421

type PayloadSetPayload = Payload<PayloadSet, PayloadSetSchema>;

422

```

423

424

**Usage Examples:**

425

426

```typescript

427

import {

428

PayloadSet,

429

PayloadSetPayload,

430

PayloadSetSchema

431

} from "@xyo-network/payload-model";

432

433

// Define payload set requirements

434

const payloadSet: PayloadSetPayload = {

435

schema: PayloadSetSchema,

436

required: {

437

"network.example.user": 1,

438

"network.example.auth": 1

439

},

440

optional: {

441

"network.example.preferences": 1,

442

"network.example.metadata": 3

443

}

444

};

445

446

// Validate payload collection against PayloadSet

447

function validatePayloadCollection(

448

payloads: Payload[],

449

requirements: PayloadSet

450

): { valid: boolean; missing: string[]; errors: string[] } {

451

const payloadCounts = payloads.reduce((counts, payload) => {

452

counts[payload.schema] = (counts[payload.schema] || 0) + 1;

453

return counts;

454

}, {} as Record<string, number>);

455

456

const missing: string[] = [];

457

const errors: string[] = [];

458

459

// Check required payloads

460

if (requirements.required) {

461

for (const [schema, required] of Object.entries(requirements.required)) {

462

const actual = payloadCounts[schema] || 0;

463

if (actual < required) {

464

missing.push(`${schema} (need ${required}, have ${actual})`);

465

}

466

}

467

}

468

469

// Check optional payloads don't exceed limits

470

if (requirements.optional) {

471

for (const [schema, max] of Object.entries(requirements.optional)) {

472

const actual = payloadCounts[schema] || 0;

473

if (actual > max) {

474

errors.push(`${schema} exceeds maximum (max ${max}, have ${actual})`);

475

}

476

}

477

}

478

479

return {

480

valid: missing.length === 0 && errors.length === 0,

481

missing,

482

errors

483

};

484

}

485

486

// Use validation

487

const testPayloads: Payload[] = [

488

{ schema: "network.example.user", name: "Alice" },

489

{ schema: "network.example.auth", token: "abc123" },

490

{ schema: "network.example.preferences", theme: "dark" }

491

];

492

493

const validation = validatePayloadCollection(testPayloads, payloadSet);

494

console.log("Validation result:", validation);

495

```

496

497

## Advanced Usage Patterns

498

499

### Bundle Processing Pipeline

500

501

```typescript

502

import {

503

PayloadBundle,

504

PayloadBundleSchema,

505

isPayloadBundle,

506

Query,

507

PayloadFindFilter

508

} from "@xyo-network/payload-model";

509

510

// Bundle processing pipeline

511

class BundleProcessor {

512

async processBundle(data: unknown): Promise<ProcessedBundle | null> {

513

if (!isPayloadBundle(data)) {

514

return null;

515

}

516

517

const processed = {

518

root: data.root,

519

payloadCount: data.payloads.length,

520

schemas: [...new Set(data.payloads.map(p => p.schema))],

521

payloads: data.payloads

522

};

523

524

return processed;

525

}

526

527

createBundleFromQuery(query: Query, results: Payload[]): PayloadBundle {

528

return {

529

schema: PayloadBundleSchema,

530

payloads: results,

531

root: this.calculateRootHash(results)

532

};

533

}

534

535

private calculateRootHash(payloads: Payload[]): Hash {

536

// Simplified hash calculation

537

const combined = payloads.map(p => JSON.stringify(p)).join('');

538

return `0x${combined.slice(0, 64)}` as Hash;

539

}

540

}

541

542

interface ProcessedBundle {

543

root: Hash;

544

payloadCount: number;

545

schemas: string[];

546

payloads: Payload[];

547

}

548

```

549

550

### Query Builder Pattern

551

552

```typescript

553

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

554

555

// Query builder for complex query construction

556

class QueryBuilder<T = {}> {

557

private data: T = {} as T;

558

private fields: Partial<QueryFields> = {};

559

private schemaValue: string = "network.xyo.query";

560

561

schema(schema: string): QueryBuilder<T> {

562

this.schemaValue = schema;

563

return this;

564

}

565

566

withData<U>(data: U): QueryBuilder<T & U> {

567

const builder = new QueryBuilder<T & U>();

568

builder.data = { ...this.data, ...data };

569

builder.fields = { ...this.fields };

570

builder.schemaValue = this.schemaValue;

571

return builder;

572

}

573

574

address(address: Address | Address[]): QueryBuilder<T> {

575

this.fields.address = address;

576

return this;

577

}

578

579

budget(budget: number): QueryBuilder<T> {

580

this.fields.budget = budget;

581

return this;

582

}

583

584

frequency(freq: QueryFields['maxFrequency']): QueryBuilder<T> {

585

this.fields.maxFrequency = freq;

586

return this;

587

}

588

589

minBid(bid: number): QueryBuilder<T> {

590

this.fields.minBid = bid;

591

return this;

592

}

593

594

build(): Query<T, typeof this.schemaValue> {

595

return {

596

schema: this.schemaValue,

597

...this.data,

598

...this.fields

599

} as Query<T, typeof this.schemaValue>;

600

}

601

}

602

603

// Usage

604

const query = new QueryBuilder()

605

.schema("network.example.user-search")

606

.withData({ searchTerm: "alice", filters: { location: "NYC" } })

607

.address("0x742d35Cc6065C6EaABf23bA0aC21e0017E3BB26C")

608

.budget(1000)

609

.frequency("minute")

610

.minBid(10)

611

.build();

612

```

613

614

## Types Reference

615

616

### Bundle Types

617

618

- **`PayloadBundle`**: Complete payload bundle type

619

- **`PayloadBundleFields<T>`**: Bundle data fields interface

620

- **`PayloadBundleSchema`**: Bundle schema constant

621

622

### Query Types

623

624

- **`Query<T, S>`**: Query payload type with custom data

625

- **`QueryFields`**: Query parameter fields interface

626

627

### Utility Types

628

629

- **`PayloadFindFilter`**: Filter interface for payload search

630

- **`PayloadHashMap<TPayload, TId>`**: Hash map for efficient payload lookup

631

- **`PayloadSet`**: Required/optional payload specifications

632

- **`PayloadSetPayload`**: PayloadSet as payload type

633

634

### Constants

635

636

- **`PayloadBundleSchema`**: "network.xyo.payload.bundle"

637

- **`PayloadSetSchema`**: "network.xyo.payload.set"

638

639

### Functions

640

641

- **`isPayloadBundle(value)`**: Type guard for payload bundles

642

- **`asPayloadBundle(value)`**: Type assertion for payload bundles

643

- **`asOptionalPayloadBundle(value)`**: Optional type assertion for payload bundles