@carrot-foundation/schemas 0.1.34 → 0.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -73,6 +73,34 @@ var NonEmptyStringSchema = z.string().min(1, "Cannot be empty").meta({
73
73
  description: "A string that contains at least one character",
74
74
  examples: ["Example text", "Sample value", "Test string"]
75
75
  });
76
+ var MunicipalitySchema = NonEmptyStringSchema.max(50).meta({
77
+ title: "Municipality",
78
+ description: "Municipality or city name",
79
+ examples: ["Macap\xE1", "S\xE3o Paulo", "New York", "Berlin", "Tokyo"]
80
+ });
81
+ var AdministrativeDivisionSchema = NonEmptyStringSchema.max(50).meta({
82
+ title: "Administrative Division",
83
+ description: "State, province, or administrative region name",
84
+ examples: ["Amap\xE1", "California", "Bavaria"]
85
+ });
86
+ var CountryNameSchema = NonEmptyStringSchema.max(50).meta({
87
+ title: "Country",
88
+ description: "Full country name in English",
89
+ examples: ["Brazil", "United States", "Germany", "Japan"]
90
+ });
91
+ var MethodologyNameSchema = NonEmptyStringSchema.max(100).meta({
92
+ title: "Methodology Name",
93
+ description: "Name of the methodology used for certification",
94
+ examples: ["BOLD Recycling", "BOLD Carbon (CH\u2084)"]
95
+ });
96
+ var StringifiedTokenIdSchema = NonEmptyStringSchema.regex(
97
+ /^#\d+$/,
98
+ "Must match pattern #<token_id>"
99
+ ).meta({
100
+ title: "Token ID",
101
+ description: "Token ID represented as #<token_id>",
102
+ example: "#123"
103
+ });
76
104
  var SlugSchema = NonEmptyStringSchema.regex(
77
105
  /^[a-z0-9-]+$/,
78
106
  "Must contain only lowercase letters, numbers, and hyphens"
@@ -140,6 +168,15 @@ var NonNegativeFloatSchema = z.number().min(0).meta({
140
168
  description: "Floating-point number that is zero or positive",
141
169
  examples: [0, 45.2, 72.5]
142
170
  });
171
+ var CreditTypeSchema = NonEmptyStringSchema.max(100).meta({
172
+ title: "Credit Type",
173
+ description: "Type of credit issued",
174
+ examples: ["Organic", "Carbon (CH\u2084)"]
175
+ });
176
+ var CreditAmountSchema = NonNegativeFloatSchema.meta({
177
+ title: "Credit Amount",
178
+ description: "Amount of credits issued"
179
+ });
143
180
  var HoursSchema = z.number().min(0).multipleOf(0.1).meta({
144
181
  title: "Hours",
145
182
  description: "Time duration in hours with 0.1 hour precision",
@@ -256,118 +293,6 @@ var RecordRelationshipTypeSchema = z.enum([
256
293
  description: "Type of relationship between different entities in the system",
257
294
  examples: ["mass-id", "audit", "collection"]
258
295
  });
259
- var SchemaInfoSchema = z.strictObject({
260
- hash: Keccak256HashSchema.meta({
261
- title: "Schema Hash",
262
- description: "Keccak256 hash of the JSON Schema this record was validated against"
263
- }),
264
- type: RecordSchemaTypeSchema.meta({
265
- title: "Schema Type",
266
- description: "Type/category of this schema"
267
- }),
268
- version: SemanticVersionSchema.meta({
269
- title: "Schema Version",
270
- description: "Version of the schema, using semantic versioning"
271
- })
272
- }).meta({
273
- title: "Schema Information"
274
- });
275
- var RecordCreatorSchema = z.strictObject({
276
- name: z.string().meta({
277
- title: "Creator Name",
278
- description: "Company or individual name that created this record",
279
- examples: ["Carrot Foundation"]
280
- }),
281
- id: UuidSchema.meta({
282
- title: "Creator ID",
283
- description: "Unique identifier for the creator"
284
- })
285
- }).meta({
286
- title: "Creator",
287
- description: "Entity that created this record"
288
- });
289
- var RecordRelationshipSchema = z.strictObject({
290
- target_uri: IpfsUriSchema.meta({
291
- title: "Target IPFS URI",
292
- description: "Target IPFS URI of the referenced record"
293
- }),
294
- type: RecordRelationshipTypeSchema.meta({
295
- title: "Relationship Type",
296
- description: "Type of relationship to the referenced record"
297
- }),
298
- description: z.string().optional().meta({
299
- title: "Relationship Description",
300
- description: "Human-readable description of the relationship",
301
- examples: [
302
- "This record supersedes the previous version",
303
- "Related carbon credit batch",
304
- "Source document for this verification",
305
- "Child record derived from this parent",
306
- "Updated version of original record"
307
- ]
308
- })
309
- }).meta({
310
- title: "Relationship",
311
- description: "Relationship to another IPFS record"
312
- });
313
- var RecordEnvironmentSchema = z.strictObject({
314
- blockchain_network: z.enum(["mainnet", "testnet"]).meta({
315
- title: "Blockchain Network",
316
- description: "Blockchain Network Environment"
317
- }),
318
- deployment: z.enum(["production", "development", "testing"]).meta({
319
- title: "Deployment Environment",
320
- description: "System environment where this record was generated"
321
- }),
322
- data_set_name: z.enum(["TEST", "PROD"]).meta({
323
- title: "Data Set Name",
324
- description: "Name of the data set for this record"
325
- })
326
- }).meta({
327
- title: "Environment",
328
- description: "Environment information"
329
- });
330
- var BaseIpfsSchema = z.strictObject({
331
- $schema: z.url("Must be a valid URI").meta({
332
- title: "JSON Schema URI",
333
- description: "URI of the JSON Schema used to validate this record",
334
- example: "https://raw.githubusercontent.com/carrot-foundation/schemas/refs/heads/main/schemas/ipfs/shared/base/base.schema.json"
335
- }),
336
- schema: SchemaInfoSchema,
337
- created_at: IsoTimestampSchema.meta({
338
- title: "Created At",
339
- description: "ISO 8601 creation timestamp for this record"
340
- }),
341
- external_id: ExternalIdSchema.meta({
342
- title: "External ID",
343
- description: "Off-chain reference ID (UUID from Carrot backend)"
344
- }),
345
- external_url: ExternalUrlSchema.meta({
346
- title: "External URL",
347
- description: "External URL of the content"
348
- }),
349
- original_content_hash: Sha256HashSchema.meta({
350
- title: "Original Content Hash",
351
- description: "SHA-256 hash of the original JSON content including private data before schema validation"
352
- }),
353
- content_hash: Sha256HashSchema.meta({
354
- title: "Content Hash",
355
- description: "SHA-256 hash of RFC 8785 canonicalized JSON after schema validation"
356
- }),
357
- creator: RecordCreatorSchema.optional(),
358
- relationships: z.array(RecordRelationshipSchema).optional().meta({
359
- title: "Relationships",
360
- description: "References to other IPFS records this record relates to"
361
- }),
362
- environment: RecordEnvironmentSchema.optional(),
363
- data: z.record(z.string(), z.unknown()).optional().meta({
364
- title: "Custom Data",
365
- description: "Custom data block that includes the record's data"
366
- })
367
- }).meta({
368
- title: "Base IPFS Record",
369
- description: "Base fields for all Carrot IPFS records, providing common structure for any JSON content stored in IPFS"
370
- });
371
296
  function uniqueArrayItems(schema, errorMessage = "Array items must be unique") {
372
297
  return z.array(schema).refine((items) => new Set(items).size === items.length, {
373
298
  message: errorMessage
@@ -385,760 +310,568 @@ function uniqueBy(schema, selector, errorMessage = "Items must be unique") {
385
310
  );
386
311
  }
387
312
 
388
- // src/shared/nft.schema.ts
389
- var NftSchemaTypeSchema = RecordSchemaTypeSchema.extract([
390
- "MassID",
391
- "RecycledID",
392
- "GasID",
393
- "PurchaseID"
394
- ]).meta({
395
- title: "NFT Schema Type",
396
- description: "Type of schema for NFT records"
397
- });
398
- var BlockchainReferenceSchema = z.strictObject({
399
- smart_contract_address: EthereumAddressSchema.meta({
400
- title: "Smart Contract Address"
401
- }),
402
- chain_id: BlockchainChainIdSchema.meta({
403
- title: "Chain ID",
404
- description: "Blockchain chain ID"
313
+ // src/shared/entities/participant.schema.ts
314
+ var ParticipantSchema = z.strictObject({
315
+ id_hash: Sha256HashSchema.meta({
316
+ title: "Participant ID Hash",
317
+ description: "Anonymized identifier for the participant"
405
318
  }),
406
- network_name: z.string().min(5).max(100).meta({
407
- title: "Network Name",
408
- description: "Name of the blockchain network"
319
+ name: ParticipantNameSchema.meta({
320
+ title: "Participant Name",
321
+ description: "Name of the participant"
409
322
  }),
410
- token_id: TokenIdSchema.meta({
411
- title: "Token ID",
412
- description: "NFT token ID"
323
+ roles: uniqueArrayItems(
324
+ ParticipantRoleSchema,
325
+ "Participant roles must be unique"
326
+ ).min(1).meta({
327
+ title: "Participant Roles",
328
+ description: "Roles of the participant in the waste management supply chain"
413
329
  })
414
330
  }).meta({
415
- title: "Blockchain Information",
416
- description: "Blockchain-specific information for the NFT"
331
+ title: "Participant",
332
+ description: "A participant in the waste management supply chain"
417
333
  });
418
- var ExternalLinkSchema = z.strictObject({
419
- label: z.string().min(1).max(50).meta({
420
- title: "Link Label",
421
- description: "Display name for the external link"
334
+ var PrecisionLevelSchema = z.enum(["exact", "neighborhood", "city", "region", "country"]).meta({
335
+ title: "Coordinate Precision Level",
336
+ description: "Level of coordinate precision",
337
+ examples: ["city", "exact", "neighborhood"]
338
+ });
339
+ var CoordinatesSchema = z.strictObject({
340
+ latitude: LatitudeSchema,
341
+ longitude: LongitudeSchema,
342
+ precision_level: PrecisionLevelSchema
343
+ }).meta({
344
+ title: "Coordinates",
345
+ description: "GPS coordinates of the location"
346
+ });
347
+ var LocationSchema = z.strictObject({
348
+ id_hash: Sha256HashSchema.meta({
349
+ title: "Location ID Hash",
350
+ description: "Anonymized identifier for the location"
422
351
  }),
423
- url: z.url("Must be a valid URI").meta({
424
- title: "Link URL",
425
- description: "Direct URI to the linked resource"
352
+ municipality: MunicipalitySchema,
353
+ administrative_division: AdministrativeDivisionSchema,
354
+ administrative_division_code: IsoAdministrativeDivisionCodeSchema.optional(),
355
+ country: CountryNameSchema,
356
+ country_code: IsoCountryCodeSchema,
357
+ responsible_participant_id_hash: Sha256HashSchema.meta({
358
+ title: "Responsible Participant ID Hash",
359
+ description: "Anonymized ID of the participant responsible for this location"
426
360
  }),
427
- description: z.string().min(10).max(100).optional().meta({
428
- title: "Link Description",
429
- description: "Optional context about what the link provides"
430
- })
361
+ coordinates: CoordinatesSchema,
362
+ facility_type: FacilityTypeSchema.optional()
431
363
  }).meta({
432
- title: "External Link",
433
- description: "External link with label and description"
364
+ title: "Location",
365
+ description: "Geographic location with address and coordinate information"
434
366
  });
435
- var NftAttributeSchema = z.strictObject({
436
- trait_type: z.string().max(50).meta({
437
- title: "Trait Type",
438
- description: "Name of the trait or attribute"
367
+ var MethodologyComplianceSchema = z.enum(["PASSED", "FAILED"]).meta({
368
+ title: "Methodology Compliance",
369
+ description: "Result of methodology compliance check",
370
+ examples: ["PASSED", "FAILED"]
371
+ });
372
+ var AuditReferenceSchema = z.strictObject({
373
+ date: IsoDateSchema.meta({
374
+ title: "Audit Date",
375
+ description: "Date when the audit was completed"
439
376
  }),
440
- value: z.union([z.string(), z.number(), z.boolean()]).meta({
441
- title: "Trait Value",
442
- description: "Value of the trait - can be string, number, or boolean"
377
+ external_id: ExternalIdSchema.meta({
378
+ title: "Audit External ID",
379
+ description: "Unique identifier for the audit"
443
380
  }),
444
- display_type: z.enum(["number", "date", "boost_number", "boost_percentage"]).optional().meta({
445
- title: "Display Type",
446
- description: "How the trait should be displayed in marketplace UIs"
381
+ external_url: ExternalUrlSchema.meta({
382
+ title: "Audit External URL",
383
+ description: "URL to view the audit on Carrot Explorer"
447
384
  }),
448
- max_value: NonNegativeFloatSchema.optional().meta({
449
- title: "Max Value",
450
- description: "Maximum possible value for numeric traits"
385
+ methodology_compliance: MethodologyComplianceSchema.meta({
386
+ title: "Methodology Compliance",
387
+ description: "Result of methodology compliance check"
388
+ }),
389
+ rules_executed: NonNegativeIntegerSchema.meta({
390
+ title: "Rules Executed",
391
+ description: "Number of rules executed during the audit"
392
+ }),
393
+ report: IpfsUriSchema.meta({
394
+ title: "Audit Report",
395
+ description: "IPFS URI of the audit report"
451
396
  })
452
397
  }).meta({
453
- title: "NFT Attribute",
454
- description: "NFT attribute or trait with type and value"
398
+ title: "Audit Reference",
399
+ description: "Reference to an audit record"
455
400
  });
456
- var NftIpfsSchema = BaseIpfsSchema.safeExtend({
457
- schema: BaseIpfsSchema.shape.schema.safeExtend({
458
- type: NftSchemaTypeSchema.meta({
459
- title: "NFT Schema Type",
460
- description: "Type/category of this NFT schema"
461
- })
462
- }),
463
- blockchain: BlockchainReferenceSchema,
464
- name: z.string().min(1).max(100).meta({
465
- title: "NFT Name",
466
- description: "Full display name for this NFT, including extra context",
467
- examples: [
468
- "MassID #123 \u2022 Organic \u2022 3.0t",
469
- "RecycledID #456 \u2022 Plastic \u2022 2.5t",
470
- "GasID #789 \u2022 Methane \u2022 1000 m\xB3"
471
- ]
401
+ var GasIDReferenceSchema = z.strictObject({
402
+ external_id: ExternalIdSchema.meta({
403
+ title: "GasID External ID",
404
+ description: "Unique identifier for the GasID"
472
405
  }),
473
- short_name: z.string().min(1).max(50).meta({
474
- title: "Short Name",
475
- description: "Compact name for UI summaries, tables, or tooltips",
476
- examples: ["MassID #123", "RecycledID #456", "GasID #789"]
406
+ token_id: TokenIdSchema.meta({
407
+ title: "GasID Token ID",
408
+ description: "NFT token ID of the GasID"
477
409
  }),
478
- description: z.string().min(10).max(500).meta({
479
- title: "Description",
480
- description: "Human-readable summary of the NFT's role and context. Ideally, maximum 300 characters.",
481
- examples: [
482
- "This MassID represents 3 metric tons of organic food waste from Enlatados Produ\xE7\xE3o, tracked through complete chain of custody from generation to composting.",
483
- "This RecycledID represents 2.5 metric tons of recycled plastic bottles processed by Green Solutions Ltd."
484
- ]
485
- }),
486
- image: IpfsUriSchema.meta({
487
- title: "Image URI",
488
- description: "IPFS URI pointing to the preview image"
410
+ external_url: ExternalUrlSchema.meta({
411
+ title: "GasID External URL",
412
+ description: "URL to view the GasID on Carrot Explorer"
489
413
  }),
490
- background_color: HexColorSchema.optional().meta({
491
- title: "Background Color",
492
- description: "Hex color code for marketplace background display"
414
+ uri: IpfsUriSchema.meta({
415
+ title: "GasID IPFS URI",
416
+ description: "IPFS URI of the GasID record"
417
+ })
418
+ }).meta({
419
+ title: "GasID Reference",
420
+ description: "Reference to a GasID record"
421
+ });
422
+ var MassIDReferenceSchema = z.strictObject({
423
+ external_id: ExternalIdSchema.meta({
424
+ title: "MassID External ID",
425
+ description: "Unique identifier for the MassID"
493
426
  }),
494
- animation_url: IpfsUriSchema.optional().meta({
495
- title: "Animation URL",
496
- description: "IPFS URI pointing to an animated or interactive media file",
497
- examples: [
498
- "ipfs://QmAnimation123/mass-id-animation.mp4",
499
- "ipfs://QmInteractive456/recycled-visualization.webm"
500
- ]
427
+ token_id: TokenIdSchema.meta({
428
+ title: "MassID Token ID",
429
+ description: "NFT token ID of the MassID"
501
430
  }),
502
- external_links: uniqueBy(
503
- ExternalLinkSchema,
504
- (link) => link.url,
505
- "External link URLs must be unique"
506
- ).max(10).optional().meta({
507
- title: "External Links",
508
- description: "Optional list of public resource links with labels",
509
- examples: [
510
- [
511
- {
512
- label: "Carrot Explorer",
513
- url: "https://explore.carrot.eco/document/ad44dd3f-f176-4b98-bf78-5ee6e77d0530",
514
- description: "Complete chain of custody and audit trail"
515
- },
516
- {
517
- label: "Carrot White Paper",
518
- url: "https://carrot.eco/whitepaper.pdf",
519
- description: "Carrot Foundation technical and impact white paper"
520
- }
521
- ]
522
- ]
431
+ external_url: ExternalUrlSchema.meta({
432
+ title: "MassID External URL",
433
+ description: "URL to view the MassID on Carrot Explorer"
523
434
  }),
524
- attributes: uniqueBy(
525
- NftAttributeSchema,
526
- (attr) => attr.trait_type,
527
- "Attribute trait_type values must be unique"
528
- ).meta({
529
- title: "NFT Attributes",
530
- description: "List of visual traits and filterable attributes compatible with NFT marketplaces",
531
- examples: [
532
- [
533
- {
534
- trait_type: "Waste Type",
535
- value: "Organic"
536
- },
537
- {
538
- trait_type: "Waste Subtype",
539
- value: "Food, Food Waste and Beverages"
540
- },
541
- {
542
- trait_type: "Weight (kg)",
543
- value: 3e3,
544
- display_type: "number"
545
- },
546
- {
547
- trait_type: "Origin Country",
548
- value: "Brazil"
549
- },
550
- {
551
- trait_type: "Pick-up Date",
552
- value: "2024-12-05",
553
- display_type: "date"
554
- }
555
- ]
556
- ]
435
+ uri: IpfsUriSchema.meta({
436
+ title: "MassID IPFS URI",
437
+ description: "IPFS URI of the MassID record"
557
438
  })
558
439
  }).meta({
559
- title: "NFT IPFS Record",
560
- description: "NFT-specific fields for Carrot IPFS records"
561
- });
562
-
563
- // src/mass-id/mass-id.attributes.ts
564
- var MassIDAttributeWasteTypeSchema = NftAttributeSchema.extend({
565
- trait_type: z.literal("Waste Type"),
566
- value: WasteTypeSchema
567
- }).meta({
568
- title: "Waste Type Attribute",
569
- description: "Waste type attribute"
570
- });
571
- var MassIDAttributeWasteSubtypeSchema = NftAttributeSchema.extend({
572
- trait_type: z.literal("Waste Subtype"),
573
- value: WasteSubtypeSchema
574
- }).meta({
575
- title: "Waste Subtype Attribute",
576
- description: "Waste subtype attribute"
577
- });
578
- var MassIDAttributeWeightSchema = NftAttributeSchema.extend({
579
- trait_type: z.literal("Weight (kg)"),
580
- value: WeightKgSchema,
581
- display_type: z.literal("number")
582
- }).meta({
583
- title: "Weight Attribute",
584
- description: "Weight attribute with numeric display"
440
+ title: "MassID Reference",
441
+ description: "Reference to a MassID record"
585
442
  });
586
- var MassIDAttributeOriginCountrySchema = NftAttributeSchema.extend({
587
- trait_type: z.literal("Origin Country"),
588
- value: NonEmptyStringSchema.max(100).meta({
589
- title: "Origin Country Value",
590
- description: "Country where the waste was generated",
591
- examples: ["Brazil", "United States", "Germany", "Japan"]
443
+ var MethodologyReferenceSchema = z.strictObject({
444
+ external_id: ExternalIdSchema.meta({
445
+ title: "Methodology External ID",
446
+ description: "Unique identifier for the methodology"
447
+ }),
448
+ name: NonEmptyStringSchema.min(5).max(150).meta({
449
+ title: "Methodology Name",
450
+ description: "Human-readable name of the methodology",
451
+ examples: ["BOLD Carbon (CH\u2084)", "BOLD Recycling"]
452
+ }),
453
+ version: SemanticVersionSchema.meta({
454
+ title: "Methodology Version",
455
+ description: "Version of the methodology"
456
+ }),
457
+ external_url: ExternalUrlSchema.meta({
458
+ title: "Methodology External URL",
459
+ description: "URL to view the methodology on Carrot Explorer"
460
+ }),
461
+ uri: IpfsUriSchema.optional().meta({
462
+ title: "Methodology IPFS URI",
463
+ description: "IPFS URI to the methodology record"
592
464
  })
593
465
  }).meta({
594
- title: "Origin Country Attribute",
595
- description: "Origin country attribute"
466
+ title: "Methodology Reference",
467
+ description: "Reference to a methodology record"
596
468
  });
597
- var MassIDAttributeOriginMunicipalitySchema = NftAttributeSchema.extend({
598
- trait_type: z.literal("Origin Municipality"),
599
- value: NonEmptyStringSchema.max(100).meta({
600
- title: "Origin Municipality Value",
601
- description: "Municipality where the waste was generated",
602
- examples: ["S\xE3o Paulo", "New York", "Berlin", "Tokyo"]
469
+ var WasteClassificationSchema = z.strictObject({
470
+ primary_type: WasteTypeSchema.meta({
471
+ title: "Source Waste Primary Type",
472
+ description: "Primary type of the source waste"
473
+ }),
474
+ subtype: WasteSubtypeSchema.meta({
475
+ title: "Source Waste Subtype",
476
+ description: "Subtype of the source waste"
477
+ }),
478
+ net_weight_kg: WeightKgSchema.meta({
479
+ title: "Source Waste Net Weight",
480
+ description: "Net weight of the source waste"
603
481
  })
604
482
  }).meta({
605
- title: "Origin Municipality Attribute",
606
- description: "Origin municipality attribute"
483
+ title: "Waste Classification",
484
+ description: "Classification of the source waste (MassID)"
607
485
  });
608
- var MassIDAttributeOriginDivisionSchema = NftAttributeSchema.extend({
609
- trait_type: z.literal("Origin Administrative Division"),
610
- value: NonEmptyStringSchema.max(100).meta({
611
- title: "Origin Division Value",
612
- description: "Administrative division (state/province) where the waste was generated",
613
- examples: ["S\xE3o Paulo", "California", "Bavaria"]
486
+ var AccreditedParticipantSchema = z.strictObject({
487
+ participant_id: UuidSchema.meta({
488
+ title: "Participant ID",
489
+ description: "Unique identifier for the participant"
490
+ }),
491
+ name: ParticipantNameSchema.meta({
492
+ title: "Participant Name",
493
+ description: "Name of the participant"
494
+ }),
495
+ role: ParticipantRoleSchema.meta({
496
+ title: "Participant Role",
497
+ description: "Role of the participant in the supply chain"
498
+ }),
499
+ accreditation_id: UuidSchema.meta({
500
+ title: "Accreditation ID",
501
+ description: "Unique identifier for the participant accreditation"
502
+ }),
503
+ external_url: ExternalUrlSchema.meta({
504
+ title: "Participant Accreditation External URL",
505
+ description: "URL to view the participant accreditation on Carrot Explorer"
614
506
  })
615
507
  }).meta({
616
- title: "Origin Administrative Division Attribute",
617
- description: "Origin administrative division attribute"
508
+ title: "Accredited Participant",
509
+ description: "Participant with valid accreditation in the supply chain"
618
510
  });
619
- var MassIDAttributeVehicleTypeSchema = NftAttributeSchema.extend({
620
- trait_type: z.literal("Vehicle Type"),
621
- value: NonEmptyStringSchema.max(100).meta({
622
- title: "Vehicle Type Value",
623
- description: "Type of vehicle used for waste transportation",
624
- examples: ["Garbage Truck", "Box Truck", "Flatbed Truck", "Roll-off Truck"]
511
+ var AccreditedParticipantsSchema = z.array(AccreditedParticipantSchema).min(1).meta({
512
+ title: "Accredited Participants",
513
+ description: "List of participants with valid accreditations"
514
+ });
515
+ var RewardAllocationSchema = z.strictObject({
516
+ participant_id: UuidSchema.meta({
517
+ title: "Participant ID",
518
+ description: "Unique identifier for the participant receiving the reward"
519
+ }),
520
+ participant_name: ParticipantNameSchema.meta({
521
+ title: "Participant Name",
522
+ description: "Name of the participant receiving the reward"
523
+ }),
524
+ role: ParticipantRoleSchema.meta({
525
+ title: "Participant Role",
526
+ description: "Role of the participant in the supply chain"
527
+ }),
528
+ reward_percentage: PercentageSchema.meta({
529
+ title: "Reward Percentage",
530
+ description: "Reward percentage allocated to the participant"
531
+ }),
532
+ large_business_discount_applied: z.boolean().optional().meta({
533
+ title: "Large Business Discount Applied",
534
+ description: "Whether the large business discount was applied"
535
+ }),
536
+ effective_percentage: PercentageSchema.meta({
537
+ title: "Effective Percentage",
538
+ description: "Effective percentage of the reward after discounts"
625
539
  })
626
540
  }).meta({
627
- title: "Vehicle Type Attribute",
628
- description: "Vehicle type attribute"
541
+ title: "Reward Allocation",
542
+ description: "Reward allocation for a specific participant"
629
543
  });
630
- var MassIDAttributeRecyclingMethodSchema = NftAttributeSchema.extend({
631
- trait_type: z.literal("Recycling Method"),
632
- value: NonEmptyStringSchema.max(100).meta({
633
- title: "Recycling Method Value",
634
- description: "Method used for recycling or processing the waste",
544
+ var DistributionNotesSchema = z.strictObject({
545
+ large_business_discount_applied: NonEmptyStringSchema.optional().meta({
546
+ title: "Large Business Discount Applied",
547
+ description: "Description of the large business discount applied",
635
548
  examples: [
636
- "Composting",
637
- "Mechanical Recycling",
638
- "Incineration with Energy Recovery"
549
+ "50% reduction applied to participants with >$4M annual revenue"
550
+ ]
551
+ }),
552
+ redirected_rewards: NonEmptyStringSchema.optional().meta({
553
+ title: "Redirected Rewards",
554
+ description: "Description of the redirected rewards",
555
+ examples: [
556
+ "Discounted rewards from large businesses redirected to accredited NGOs"
639
557
  ]
640
558
  })
641
559
  }).meta({
642
- title: "Recycling Method Attribute",
643
- description: "Recycling method attribute"
644
- });
645
- var MassIDAttributeProcessingTimeSchema = NftAttributeSchema.extend({
646
- trait_type: z.literal("Processing Time (hours)"),
647
- value: HoursSchema,
648
- trait_description: NonEmptyStringSchema.max(200).optional().meta({
649
- title: "Processing Time Description",
650
- description: "Custom description for the processing time"
651
- })
652
- }).meta({
653
- title: "Processing Time Attribute",
654
- description: "Processing time attribute with optional trait description"
560
+ title: "Distribution Notes",
561
+ description: "Additional notes about the reward distribution"
655
562
  });
656
- var MassIDAttributeLocalWasteClassificationIdSchema = NftAttributeSchema.extend({
657
- trait_type: z.literal("Local Waste Classification ID"),
658
- value: NonEmptyStringSchema.max(100).meta({
659
- title: "Local Waste Classification ID Value",
660
- description: "Local or regional waste classification identifier",
661
- examples: ["04 02 20", "IBAMA-A001", "EWC-150101"]
563
+ var ParticipantRewardsSchema = z.strictObject({
564
+ distribution_basis: NonEmptyStringSchema.max(200).meta({
565
+ title: "Distribution Basis",
566
+ description: "Basis for the rewards distribution"
567
+ }),
568
+ reward_allocations: z.array(RewardAllocationSchema).min(1).meta({
569
+ title: "Reward Allocations",
570
+ description: "Rewards percentage allocated to each participant"
571
+ }),
572
+ distribution_notes: DistributionNotesSchema.optional().meta({
573
+ title: "Distribution Notes",
574
+ description: "Additional notes about the reward distribution"
662
575
  })
663
576
  }).meta({
664
- title: "Local Waste Classification ID Attribute",
665
- description: "Local waste classification ID attribute"
577
+ title: "Participant Rewards",
578
+ description: "Rewards distribution to participants"
666
579
  });
667
- var MassIDAttributeRecyclingManifestCodeSchema = NftAttributeSchema.extend({
668
- trait_type: z.literal("Recycling Manifest Code"),
669
- value: NonEmptyStringSchema.max(100).meta({
670
- title: "Recycling Manifest Code Value",
671
- description: "Concatenated recycling manifest code (Document Type + Document Number)",
672
- examples: ["CDF-2353", "RC-12345", "REC-MANIFEST-789"]
673
- })
674
- }).meta({
675
- title: "Recycling Manifest Code Attribute",
676
- description: "Recycling manifest code attribute (optional)"
580
+ var SchemaHashSchema = z.union([
581
+ Keccak256HashSchema,
582
+ z.string().regex(
583
+ /^0x[a-fA-F0-9]{64}$/,
584
+ "Must be a Keccak256 hash as 0x-prefixed hex string"
585
+ )
586
+ ]).meta({
587
+ title: "Schema Hash",
588
+ description: "Keccak256 hash of the JSON Schema this record was validated against",
589
+ examples: [
590
+ "ac08c3cf2e175e55961d6affdb38bc24591b84ceef7f3707c69ae3d52c148b2f",
591
+ "0xac08c3cf2e175e55961d6affdb38bc24591b84ceef7f3707c69ae3d52c148b2f"
592
+ ]
677
593
  });
678
- var MassIDAttributeTransportManifestCodeSchema = NftAttributeSchema.extend({
679
- trait_type: z.literal("Transport Manifest Code"),
680
- value: NonEmptyStringSchema.max(100).meta({
681
- title: "Transport Manifest Code Value",
682
- description: "Concatenated transport manifest code (Document Type + Document Number)",
683
- examples: ["MTR-4126", "TRN-67890", "TRANS-MANIFEST-456"]
594
+ var SchemaInfoSchema = z.strictObject({
595
+ hash: SchemaHashSchema,
596
+ type: RecordSchemaTypeSchema.meta({
597
+ title: "Schema Type",
598
+ description: "Type/category of this schema"
599
+ }),
600
+ version: SemanticVersionSchema.meta({
601
+ title: "Schema Version",
602
+ description: "Version of the schema, using semantic versioning"
684
603
  })
685
604
  }).meta({
686
- title: "Transport Manifest Code Attribute",
687
- description: "Transport manifest code attribute (optional)"
605
+ title: "Schema Information"
688
606
  });
689
- var MassIDAttributeWeighingCaptureMethodSchema = NftAttributeSchema.extend({
690
- trait_type: z.literal("Weighing Capture Method"),
691
- value: NonEmptyStringSchema.max(100).meta({
692
- title: "Weighing Capture Method Value",
693
- description: "Method used to capture weight data",
694
- examples: ["Digital", "Manual", "Automated", "Electronic Scale"]
607
+ var RecordCreatorSchema = z.strictObject({
608
+ name: z.string().meta({
609
+ title: "Creator Name",
610
+ description: "Company or individual name that created this record",
611
+ examples: ["Carrot Foundation"]
612
+ }),
613
+ id: UuidSchema.meta({
614
+ title: "Creator ID",
615
+ description: "Unique identifier for the creator"
695
616
  })
696
617
  }).meta({
697
- title: "Weighing Capture Method Attribute",
698
- description: "Weighing capture method attribute (optional)"
618
+ title: "Creator",
619
+ description: "Entity that created this record"
699
620
  });
700
- var MassIDAttributeScaleTypeSchema = NftAttributeSchema.extend({
701
- trait_type: z.literal("Scale Type"),
702
- value: NonEmptyStringSchema.max(100).meta({
703
- title: "Scale Type Value",
704
- description: "Type of scale used for weighing",
621
+ var RecordRelationshipSchema = z.strictObject({
622
+ target_uri: IpfsUriSchema.meta({
623
+ title: "Target IPFS URI",
624
+ description: "Target IPFS URI of the referenced record"
625
+ }),
626
+ type: RecordRelationshipTypeSchema.meta({
627
+ title: "Relationship Type",
628
+ description: "Type of relationship to the referenced record"
629
+ }),
630
+ description: z.string().optional().meta({
631
+ title: "Relationship Description",
632
+ description: "Human-readable description of the relationship",
705
633
  examples: [
706
- "Weighbridge (Truck Scale)",
707
- "Floor Scale",
708
- "Bench Scale",
709
- "Crane Scale"
634
+ "This record supersedes the previous version",
635
+ "Related carbon credit batch",
636
+ "Source document for this verification",
637
+ "Child record derived from this parent",
638
+ "Updated version of original record"
710
639
  ]
711
640
  })
712
641
  }).meta({
713
- title: "Scale Type Attribute",
714
- description: "Scale type attribute (optional)"
715
- });
716
- var MassIDAttributeContainerTypeSchema = NftAttributeSchema.extend({
717
- trait_type: z.literal("Container Type"),
718
- value: NonEmptyStringSchema.max(100).meta({
719
- title: "Container Type Value",
720
- description: "Type of container used for waste storage or transport",
721
- examples: ["Truck", "Dumpster", "Roll-off Container", "Compactor", "Bin"]
722
- })
723
- }).meta({
724
- title: "Container Type Attribute",
725
- description: "Container type attribute (optional)"
726
- });
727
- var MassIDAttributePickUpDateSchema = NftAttributeSchema.extend({
728
- trait_type: z.literal("Pick-up Date"),
729
- value: UnixTimestampSchema.meta({
730
- title: "Pick-up Date Value",
731
- description: "Unix timestamp in milliseconds when the waste was picked up from the source",
732
- examples: [17105184e5, 17040672e5, 17152704e5]
733
- }),
734
- display_type: z.literal("date")
735
- }).meta({
736
- title: "Pick-up Date Attribute",
737
- description: "Pick-up date attribute with Unix timestamp"
738
- });
739
- var MassIDAttributeRecyclingDateSchema = NftAttributeSchema.extend({
740
- trait_type: z.literal("Recycling Date"),
741
- value: UnixTimestampSchema.meta({
742
- title: "Recycling Date Value",
743
- description: "Unix timestamp in milliseconds when the waste was recycled/processed",
744
- examples: [17106048e5, 17041536e5, 17153568e5]
745
- }),
746
- display_type: z.literal("date")
747
- }).meta({
748
- title: "Recycling Date Attribute",
749
- description: "Recycling date attribute with Unix timestamp"
750
- });
751
- var MassIDAttributesSchema = uniqueBy(
752
- z.union([
753
- MassIDAttributeWasteTypeSchema,
754
- MassIDAttributeWasteSubtypeSchema,
755
- MassIDAttributeWeightSchema,
756
- MassIDAttributeOriginCountrySchema,
757
- MassIDAttributeOriginMunicipalitySchema,
758
- MassIDAttributeOriginDivisionSchema,
759
- MassIDAttributeVehicleTypeSchema,
760
- MassIDAttributeRecyclingMethodSchema,
761
- MassIDAttributeProcessingTimeSchema,
762
- MassIDAttributeLocalWasteClassificationIdSchema,
763
- MassIDAttributeRecyclingManifestCodeSchema,
764
- MassIDAttributeTransportManifestCodeSchema,
765
- MassIDAttributeWeighingCaptureMethodSchema,
766
- MassIDAttributeScaleTypeSchema,
767
- MassIDAttributeContainerTypeSchema,
768
- MassIDAttributePickUpDateSchema,
769
- MassIDAttributeRecyclingDateSchema
770
- ]),
771
- (attr) => attr.trait_type
772
- ).min(12).max(17).meta({
773
- title: "MassID Attributes",
774
- description: "MassID NFT attributes array containing attributes selected from the available attribute types. The schema validates array length but does not enforce which specific attributes must be present."
775
- });
776
- var PrecisionLevelSchema = z.enum(["exact", "neighborhood", "city", "region", "country"]).meta({
777
- title: "Precision Level",
778
- description: "Level of coordinate precision",
779
- examples: ["city", "exact", "neighborhood"]
642
+ title: "Relationship",
643
+ description: "Relationship to another IPFS record"
780
644
  });
781
- var CoordinatesSchema = z.strictObject({
782
- latitude: LatitudeSchema.meta({
783
- title: "Latitude",
784
- description: "GPS latitude coordinate"
645
+ var RecordEnvironmentSchema = z.strictObject({
646
+ blockchain_network: z.enum(["mainnet", "testnet"]).meta({
647
+ title: "Blockchain Network",
648
+ description: "Blockchain Network Environment"
785
649
  }),
786
- longitude: LongitudeSchema.meta({
787
- title: "Longitude",
788
- description: "GPS longitude coordinate"
650
+ deployment: z.enum(["production", "development", "testing"]).meta({
651
+ title: "Deployment Environment",
652
+ description: "System environment where this record was generated"
789
653
  }),
790
- precision_level: PrecisionLevelSchema
654
+ data_set_name: z.enum(["TEST", "PROD"]).meta({
655
+ title: "Data Set Name",
656
+ description: "Name of the data set for this record"
657
+ })
791
658
  }).meta({
792
- title: "Coordinates",
793
- description: "GPS coordinates of the location"
659
+ title: "Environment",
660
+ description: "Environment information"
794
661
  });
795
- var LocationSchema = z.strictObject({
796
- id_hash: Sha256HashSchema.meta({
797
- title: "Location ID Hash",
798
- description: "Anonymized identifier for the location"
662
+ var BaseIpfsSchema = z.strictObject({
663
+ $schema: z.url("Must be a valid URI").meta({
664
+ title: "JSON Schema URI",
665
+ description: "URI of the JSON Schema used to validate this record",
666
+ example: "https://raw.githubusercontent.com/carrot-foundation/schemas/refs/heads/main/schemas/ipfs/shared/base/base.schema.json"
799
667
  }),
800
- municipality: NonEmptyStringSchema.max(50).meta({
801
- title: "Municipality",
802
- description: "Municipality or city name",
803
- examples: ["New York", "S\xE3o Paulo", "London", "Tokyo"]
668
+ schema: SchemaInfoSchema,
669
+ created_at: IsoTimestampSchema.meta({
670
+ title: "Created At",
671
+ description: "ISO 8601 creation timestamp for this record"
804
672
  }),
805
- administrative_division: NonEmptyStringSchema.max(50).meta({
806
- title: "Administrative Division",
807
- description: "State, province, or administrative region",
808
- examples: ["California", "Ontario", "Bavaria", "Queensland"]
673
+ external_id: ExternalIdSchema.meta({
674
+ title: "External ID",
675
+ description: "Off-chain reference ID (UUID from Carrot backend)"
809
676
  }),
810
- administrative_division_code: IsoAdministrativeDivisionCodeSchema.optional().meta({
811
- title: "Administrative Division Code",
812
- description: "ISO 3166-2 administrative division code"
677
+ external_url: ExternalUrlSchema.meta({
678
+ title: "External URL",
679
+ description: "External URL of the content"
813
680
  }),
814
- country: NonEmptyStringSchema.max(50).meta({
815
- title: "Country",
816
- description: "Full country name in English",
817
- examples: ["United States", "Canada", "Germany", "Australia"]
681
+ original_content_hash: Sha256HashSchema.meta({
682
+ title: "Original Content Hash",
683
+ description: "SHA-256 hash of the original JSON content including private data before schema validation"
818
684
  }),
819
- country_code: IsoCountryCodeSchema.meta({
820
- title: "Country Code",
821
- description: "ISO 3166-1 alpha-2 country code"
685
+ content_hash: Sha256HashSchema.meta({
686
+ title: "Content Hash",
687
+ description: "SHA-256 hash of RFC 8785 canonicalized JSON after schema validation"
822
688
  }),
823
- responsible_participant_id_hash: Sha256HashSchema.meta({
824
- title: "Responsible Participant ID Hash",
825
- description: "Anonymized ID of the participant responsible for this location"
689
+ creator: RecordCreatorSchema.optional(),
690
+ relationships: z.array(RecordRelationshipSchema).optional().meta({
691
+ title: "Relationships",
692
+ description: "References to other IPFS records this record relates to"
826
693
  }),
827
- coordinates: CoordinatesSchema,
828
- facility_type: FacilityTypeSchema.optional().meta({
829
- title: "Facility Type",
830
- description: "Type of facility at this location"
694
+ environment: RecordEnvironmentSchema.optional(),
695
+ data: z.record(z.string(), z.unknown()).optional().meta({
696
+ title: "Custom Data",
697
+ description: "Custom data block that includes the record's data"
831
698
  })
832
699
  }).meta({
833
- title: "Location",
834
- description: "Geographic location with address and coordinate information"
700
+ title: "Base IPFS Record",
701
+ description: "Base fields for all Carrot IPFS records, providing common structure for any JSON content stored in IPFS"
835
702
  });
836
- var ParticipantSchema = z.strictObject({
837
- id_hash: Sha256HashSchema.meta({
838
- title: "Participant ID Hash",
839
- description: "Anonymized identifier for the participant"
703
+ var NftSchemaTypeSchema = RecordSchemaTypeSchema.extract([
704
+ "MassID",
705
+ "RecycledID",
706
+ "GasID",
707
+ "PurchaseID"
708
+ ]).meta({
709
+ title: "NFT Schema Type",
710
+ description: "Type of schema for NFT records"
711
+ });
712
+ var BlockchainReferenceSchema = z.strictObject({
713
+ smart_contract_address: EthereumAddressSchema.meta({
714
+ title: "Smart Contract Address"
840
715
  }),
841
- name: ParticipantNameSchema.meta({
842
- title: "Participant Name",
843
- description: "Name of the participant"
716
+ chain_id: BlockchainChainIdSchema.meta({
717
+ title: "Chain ID",
718
+ description: "Blockchain chain ID"
844
719
  }),
845
- roles: uniqueArrayItems(
846
- ParticipantRoleSchema,
847
- "Participant roles must be unique"
848
- ).min(1).meta({
849
- title: "Participant Roles",
850
- description: "Roles of the participant in the waste management supply chain"
720
+ network_name: z.string().min(5).max(100).meta({
721
+ title: "Network Name",
722
+ description: "Name of the blockchain network"
723
+ }),
724
+ token_id: TokenIdSchema.meta({
725
+ title: "Token ID",
726
+ description: "NFT token ID"
851
727
  })
852
728
  }).meta({
853
- title: "Participant",
854
- description: "A participant in the waste management supply chain"
729
+ title: "Blockchain Information",
730
+ description: "Blockchain-specific information for the NFT"
855
731
  });
856
-
857
- // src/mass-id/mass-id.data.schema.ts
858
- var MassIDLocalClassificationSchema = z.strictObject({
859
- code: NonEmptyStringSchema.max(20).meta({
860
- title: "Classification Code",
861
- description: "Local waste classification code",
862
- examples: ["20 01 01", "D001", "EWC-150101", "IBAMA-A001"]
732
+ var ExternalLinkSchema = z.strictObject({
733
+ label: z.string().min(1).max(50).meta({
734
+ title: "Link Label",
735
+ description: "Display name for the external link"
863
736
  }),
864
- description: NonEmptyStringSchema.max(200).meta({
865
- title: "Classification Description",
866
- description: "Local waste classification description",
867
- examples: [
868
- "Paper and cardboard packaging",
869
- "Ignitable waste",
870
- "Paper and cardboard packaging waste",
871
- "Municipal solid waste - organic fraction"
872
- ]
737
+ url: z.url("Must be a valid URI").meta({
738
+ title: "Link URL",
739
+ description: "Direct URI to the linked resource"
873
740
  }),
874
- system: z.enum(["IBAMA"]).meta({
875
- title: "Classification System",
876
- description: "Classification system name - currently supports IBAMA (Instituto Brasileiro do Meio Ambiente e dos Recursos Naturais Renov\xE1veis)",
877
- examples: ["IBAMA"]
741
+ description: z.string().min(10).max(100).optional().meta({
742
+ title: "Link Description",
743
+ description: "Optional context about what the link provides"
878
744
  })
879
745
  }).meta({
880
- title: "Local Classification",
881
- description: "Local or regional waste classification codes and descriptions"
882
- });
883
- var MassIDMeasurementUnitSchema = z.enum(["kg", "ton"]).meta({
884
- title: "Measurement Unit",
885
- description: "Unit of measurement for the waste quantity",
886
- examples: ["kg", "ton"]
746
+ title: "External Link",
747
+ description: "External link with label and description"
887
748
  });
888
- var MassIDWastePropertiesSchema = z.strictObject({
889
- type: WasteTypeSchema.meta({
890
- title: "Waste Type",
891
- description: "Waste material category"
749
+ var NftAttributeSchema = z.strictObject({
750
+ trait_type: z.string().max(50).meta({
751
+ title: "Trait Type",
752
+ description: "Name of the trait or attribute"
892
753
  }),
893
- subtype: WasteSubtypeSchema.meta({
894
- title: "Waste Subtype",
895
- description: "Specific subcategory of waste material"
754
+ value: z.union([z.string(), z.number(), z.boolean()]).meta({
755
+ title: "Trait Value",
756
+ description: "Value of the trait - can be string, number, or boolean"
896
757
  }),
897
- local_classification: MassIDLocalClassificationSchema.optional(),
898
- measurement_unit: MassIDMeasurementUnitSchema,
899
- net_weight: NonNegativeFloatSchema.meta({
900
- title: "Net Weight",
901
- description: "Net weight of the waste batch in the specified measurement unit"
758
+ display_type: z.enum(["number", "date", "boost_number", "boost_percentage"]).optional().meta({
759
+ title: "Display Type",
760
+ description: "How the trait should be displayed in marketplace UIs"
761
+ }),
762
+ max_value: NonNegativeFloatSchema.optional().meta({
763
+ title: "Max Value",
764
+ description: "Maximum possible value for numeric traits"
902
765
  })
903
766
  }).meta({
904
- title: "Waste Properties",
905
- description: "Standardized waste material properties and regulatory information"
906
- });
907
- var EventAttributeFormatSchema = z.enum(["KILOGRAM", "DATE", "CURRENCY", "PERCENTAGE", "COORDINATE"]).meta({
908
- title: "Event Attribute Format",
909
- description: "Data format hint for proper display",
910
- examples: ["KILOGRAM", "DATE", "PERCENTAGE"]
767
+ title: "NFT Attribute",
768
+ description: "NFT attribute or trait with type and value"
911
769
  });
912
- var EventAttributeSchema = z.strictObject({
913
- name: NonEmptyStringSchema.max(100).meta({
914
- title: "Attribute Name",
915
- description: "Event attribute name",
916
- examples: [
917
- "temperature",
918
- "humidity",
919
- "contamination_percentage",
920
- "quality_grade",
921
- "batch_number",
922
- "operator_id",
923
- "equipment_used",
924
- "processing_cost"
925
- ]
770
+ var NftIpfsSchema = BaseIpfsSchema.safeExtend({
771
+ schema: BaseIpfsSchema.shape.schema.safeExtend({
772
+ type: NftSchemaTypeSchema.meta({
773
+ title: "NFT Schema Type",
774
+ description: "Type/category of this NFT schema"
775
+ })
926
776
  }),
927
- value: z.union([z.string(), z.number(), z.boolean()]).optional().meta({
928
- title: "Attribute Value",
929
- description: "Event attribute value",
777
+ blockchain: BlockchainReferenceSchema,
778
+ name: z.string().min(1).max(100).meta({
779
+ title: "NFT Name",
780
+ description: "Full display name for this NFT, including extra context",
930
781
  examples: [
931
- 25.5,
932
- "Grade A",
933
- true,
934
- "BATCH-2024-001",
935
- 12.75,
936
- "Shredder-X200",
937
- false,
938
- "OP-456"
782
+ "MassID #123 \u2022 Organic \u2022 3.0t",
783
+ "RecycledID #456 \u2022 Plastic \u2022 2.5t",
784
+ "GasID #789 \u2022 Methane \u2022 1000 m\xB3"
939
785
  ]
940
786
  }),
941
- preserved_sensitivity: z.boolean().optional().meta({
942
- title: "Preserved Sensitivity",
943
- description: "Indicates if the attribute contains sensitive information that was preserved"
944
- }),
945
- format: EventAttributeFormatSchema.optional()
946
- }).meta({
947
- title: "Event Attribute",
948
- description: "Additional attribute specific to an event"
949
- });
950
- var EventAttachmentSchema = z.strictObject({
951
- type: NonEmptyStringSchema.max(50).meta({
952
- title: "Attachment Type",
953
- description: "Type of supporting attachment",
954
- examples: [
955
- "Waste Transfer Note",
956
- "Certificate of Disposal",
957
- "Certificate of Final Destination",
958
- "Quality Assessment Report",
959
- "Transport Manifest",
960
- "Processing Receipt",
961
- "Environmental Permit",
962
- "Invoice"
963
- ]
787
+ short_name: z.string().min(1).max(50).meta({
788
+ title: "Short Name",
789
+ description: "Compact name for UI summaries, tables, or tooltips",
790
+ examples: ["MassID #123", "RecycledID #456", "GasID #789"]
964
791
  }),
965
- document_number: NonEmptyStringSchema.max(50).optional().meta({
966
- title: "Document Number",
967
- description: "Official document number if applicable",
792
+ description: z.string().min(10).max(500).meta({
793
+ title: "Description",
794
+ description: "Human-readable summary of the NFT's role and context. Ideally, maximum 300 characters.",
968
795
  examples: [
969
- "WTN-2024-001234",
970
- "CD-ENV-456789",
971
- "INV-2024-QTR1-789",
972
- "PERMIT-EPA-2024-001",
973
- "MANIFEST-DOT-567890"
796
+ "This MassID represents 3 metric tons of organic food waste from Enlatados Produ\xE7\xE3o, tracked through complete chain of custody from generation to composting.",
797
+ "This RecycledID represents 2.5 metric tons of recycled plastic bottles processed by Green Solutions Ltd."
974
798
  ]
975
799
  }),
976
- reference: NonEmptyStringSchema.meta({
977
- title: "Attachment Reference",
978
- description: "Reference to attachment (IPFS hash, file name, or external URL)",
979
- examples: [
980
- "QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o",
981
- "waste_transfer_note_2024_001.pdf",
982
- "https://docs.example.com/certificates/disposal_cert_456.pdf",
983
- "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
984
- "processing_receipt_20240315.jpg"
985
- ]
800
+ image: IpfsUriSchema.meta({
801
+ title: "Image URI",
802
+ description: "IPFS URI pointing to the preview image"
986
803
  }),
987
- issue_timestamp: UnixTimestampSchema.optional().meta({
988
- title: "Issue Timestamp",
989
- description: "Unix timestamp in milliseconds when the attachment was issued",
990
- examples: [17105184e5, 17040672e5, 17152704e5]
804
+ background_color: HexColorSchema.optional().meta({
805
+ title: "Background Color",
806
+ description: "Hex color code for marketplace background display"
991
807
  }),
992
- issuer: NonEmptyStringSchema.max(100).optional().meta({
993
- title: "Attachment Issuer",
994
- description: "Entity that issued the attachment",
808
+ animation_url: IpfsUriSchema.optional().meta({
809
+ title: "Animation URL",
810
+ description: "IPFS URI pointing to an animated or interactive media file",
995
811
  examples: [
996
- "Environmental Protection Agency",
997
- "Waste Management Solutions Ltd",
998
- "Green Recycling Corp",
999
- "City Waste Authority",
1000
- "EcoProcess Industries",
1001
- "Regional Environmental Office"
812
+ "ipfs://QmAnimation123/mass-id-animation.mp4",
813
+ "ipfs://QmInteractive456/recycled-visualization.webm"
1002
814
  ]
1003
- })
1004
- }).meta({
1005
- title: "Event Attachment",
1006
- description: "Supporting event attachment"
1007
- });
1008
- var MassIDChainOfCustodyEventSchema = z.strictObject({
1009
- event_id: UuidSchema.meta({
1010
- title: "Event ID",
1011
- description: "Unique event identifier"
1012
- }),
1013
- event_name: NonEmptyStringSchema.max(50).meta({
1014
- title: "Event Name",
1015
- description: "Name of custody or processing event",
1016
- examples: ["Sorting", "Processing", "Recycling", "Weighing"]
1017
815
  }),
1018
- description: NonEmptyStringSchema.max(200).optional().meta({
1019
- title: "Event Description",
1020
- description: "Detailed description of what happened during this event",
816
+ external_links: uniqueBy(
817
+ ExternalLinkSchema,
818
+ (link) => link.url,
819
+ "External link URLs must be unique"
820
+ ).max(10).optional().meta({
821
+ title: "External Links",
822
+ description: "Optional list of public resource links with labels",
1021
823
  examples: [
1022
- "Waste collected from residential area using collection truck",
1023
- "Material sorted into recyclable and non-recyclable fractions",
1024
- "Plastic waste processed through shredding and washing",
1025
- "Waste transferred to authorized recycling facility",
1026
- "Final disposal at licensed landfill site",
1027
- "Quality inspection and contamination assessment completed"
1028
- ]
1029
- }),
1030
- timestamp: UnixTimestampSchema.meta({
1031
- title: "Event Timestamp",
1032
- description: "Unix timestamp in milliseconds when the event occurred",
1033
- examples: [17105184e5, 17040672e5, 17152704e5]
1034
- }),
1035
- participant_id_hash: Sha256HashSchema.meta({
1036
- title: "Participant ID Hash",
1037
- description: "Reference to participant in the participants array"
1038
- }),
1039
- location_id_hash: Sha256HashSchema.meta({
1040
- title: "Location ID Hash",
1041
- description: "Reference to location in the locations array"
1042
- }),
1043
- weight: NonNegativeFloatSchema.optional().meta({
1044
- title: "Event Weight",
1045
- description: "Mass weight after this event"
1046
- }),
1047
- attributes: z.array(EventAttributeSchema).optional().meta({
1048
- title: "Event Attributes",
1049
- description: "Additional attributes specific to this event"
1050
- }),
1051
- attachments: z.array(EventAttachmentSchema).optional().meta({
1052
- title: "Event Attachments",
1053
- description: "Associated attachments for this event"
1054
- })
1055
- }).meta({
1056
- title: "Chain of Custody Event",
1057
- description: "Chain of custody event"
1058
- });
1059
- var MassIDChainOfCustodySchema = z.strictObject({
1060
- events: z.array(MassIDChainOfCustodyEventSchema).min(1).meta({
1061
- title: "Custody Events",
1062
- description: "Chronological sequence of custody transfer and processing events"
1063
- }),
1064
- total_duration_minutes: MinutesSchema.meta({
1065
- title: "Total Duration (minutes)",
1066
- description: "Total time from first to last event in minutes"
1067
- })
1068
- }).meta({
1069
- title: "Chain of Custody",
1070
- description: "Complete chain of custody tracking from waste generation to final processing"
1071
- });
1072
- var MassIDGeographicDataSchema = z.strictObject({
1073
- from_location_id_hash: Sha256HashSchema.meta({
1074
- title: "From Location ID Hash",
1075
- description: "Reference hash of the location where the waste started movement"
1076
- }),
1077
- to_location_id_hash: Sha256HashSchema.meta({
1078
- title: "To Location ID Hash",
1079
- description: "Reference hash of the location where the waste ended movement"
1080
- }),
1081
- first_reported_timestamp: UnixTimestampSchema.meta({
1082
- title: "First Reported Timestamp",
1083
- description: "Unix timestamp in milliseconds when the waste was first reported/collected at the origin location",
1084
- examples: [17105184e5, 17040672e5, 17152704e5]
1085
- }),
1086
- last_reported_timestamp: UnixTimestampSchema.meta({
1087
- title: "Last Reported Timestamp",
1088
- description: "Unix timestamp in milliseconds when the waste was last reported/processed at the destination location",
1089
- examples: [17106048e5, 17041536e5, 17153568e5]
1090
- })
1091
- }).refine((data) => {
1092
- return data.first_reported_timestamp <= data.last_reported_timestamp;
1093
- }, "first_reported_timestamp must be before or equal to last_reported_timestamp").meta({
1094
- title: "Geographic Data",
1095
- description: "Simplified geographic information tracking waste movement from origin to destination with temporal bounds"
1096
- });
1097
- var MassIDDataSchema = z.strictObject({
1098
- waste_properties: MassIDWastePropertiesSchema,
1099
- locations: uniqueBy(
1100
- LocationSchema,
1101
- (loc) => loc.id_hash,
1102
- "Location ID hashes must be unique"
1103
- ).min(1).meta({
1104
- title: "Locations",
1105
- description: "All locations referenced in this MassID, indexed by ID"
1106
- }),
1107
- participants: uniqueBy(
1108
- ParticipantSchema,
1109
- (p) => p.id_hash,
1110
- "Participant ID hashes must be unique"
1111
- ).min(1).meta({
1112
- title: "Participants",
1113
- description: "All participants referenced in this MassID, indexed by ID"
1114
- }),
1115
- chain_of_custody: MassIDChainOfCustodySchema,
1116
- geographic_data: MassIDGeographicDataSchema
1117
- }).refine((data) => {
1118
- const participantIdSet = new Set(
1119
- data.participants.map((participant) => participant.id_hash)
1120
- );
1121
- const eventParticipantIds = data.chain_of_custody.events.map(
1122
- (event) => event.participant_id_hash
1123
- );
1124
- const allEventParticipantsExist = eventParticipantIds.every(
1125
- (participantId) => participantIdSet.has(participantId)
1126
- );
1127
- return allEventParticipantsExist;
1128
- }, "All participant ID hashes in chain of custody events must exist in participants array").refine((data) => {
1129
- const locationIdSet = new Set(
1130
- data.locations.map((location) => location.id_hash)
1131
- );
1132
- const eventLocationIds = data.chain_of_custody.events.map(
1133
- (event) => event.location_id_hash
1134
- );
1135
- const allEventLocationsExist = eventLocationIds.every(
1136
- (locationId) => locationIdSet.has(locationId)
1137
- );
1138
- return allEventLocationsExist;
1139
- }, "All location ID hashes in chain of custody events must exist in locations array").meta({
1140
- title: "MassID Data",
1141
- description: "MassID data containing waste tracking and chain of custody information"
824
+ [
825
+ {
826
+ label: "Carrot Explorer",
827
+ url: "https://explore.carrot.eco/document/ad44dd3f-f176-4b98-bf78-5ee6e77d0530",
828
+ description: "Complete chain of custody and audit trail"
829
+ },
830
+ {
831
+ label: "Carrot White Paper",
832
+ url: "https://carrot.eco/whitepaper.pdf",
833
+ description: "Carrot Foundation technical and impact white paper"
834
+ }
835
+ ]
836
+ ]
837
+ }),
838
+ attributes: uniqueBy(
839
+ NftAttributeSchema,
840
+ (attr) => attr.trait_type,
841
+ "Attribute trait_type values must be unique"
842
+ ).meta({
843
+ title: "NFT Attributes",
844
+ description: "List of visual traits and filterable attributes compatible with NFT marketplaces",
845
+ examples: [
846
+ [
847
+ {
848
+ trait_type: "Waste Type",
849
+ value: "Organic"
850
+ },
851
+ {
852
+ trait_type: "Waste Subtype",
853
+ value: "Food, Food Waste and Beverages"
854
+ },
855
+ {
856
+ trait_type: "Weight (kg)",
857
+ value: 3e3,
858
+ display_type: "number"
859
+ },
860
+ {
861
+ trait_type: "Origin Country",
862
+ value: "Brazil"
863
+ },
864
+ {
865
+ trait_type: "Pick-up Date",
866
+ value: "2024-12-05",
867
+ display_type: "date"
868
+ }
869
+ ]
870
+ ]
871
+ })
872
+ }).meta({
873
+ title: "NFT IPFS Record",
874
+ description: "NFT-specific fields for Carrot IPFS records"
1142
875
  });
1143
876
  function getSchemaBaseUrl() {
1144
877
  return `https://raw.githubusercontent.com/carrot-foundation/schemas/refs/tags/${getSchemaVersionOrDefault()}/schemas/ipfs`;
@@ -1148,402 +881,648 @@ function buildSchemaUrl(schemaPath) {
1148
881
  return `${getSchemaBaseUrl()}/${cleanPath}`;
1149
882
  }
1150
883
  function getSchemaVersionOrDefault() {
1151
- return "0.1.34";
884
+ return "0.1.36";
1152
885
  }
1153
-
1154
- // src/mass-id/mass-id.schema.ts
1155
- var MassIDIpfsSchemaMeta = {
1156
- title: "MassID NFT IPFS Record",
1157
- description: "Complete MassID NFT IPFS record including fixed attributes and detailed waste tracking data",
1158
- $id: buildSchemaUrl("mass-id/mass-id.schema.json"),
1159
- version: getSchemaVersionOrDefault()
1160
- };
1161
- var MassIDIpfsSchema = NftIpfsSchema.safeExtend({
1162
- schema: NftIpfsSchema.shape.schema.safeExtend({
1163
- type: z.literal("MassID").meta({
1164
- title: "MassID Schema Type",
1165
- description: "MassID NFT schema type"
1166
- })
1167
- }),
1168
- attributes: MassIDAttributesSchema,
1169
- data: MassIDDataSchema
1170
- }).meta(MassIDIpfsSchemaMeta);
1171
- var GasIDAttributeMethodologySchema = NftAttributeSchema.extend({
886
+ var MethodologyAttributeSchema = NftAttributeSchema.extend({
1172
887
  trait_type: z.literal("Methodology"),
1173
- value: NonEmptyStringSchema.max(100).meta({
1174
- title: "Methodology Value",
1175
- description: "Name of the carbon methodology used for certification",
1176
- examples: ["BOLD Carbon (CH\u2084)"]
1177
- })
888
+ value: MethodologyNameSchema
1178
889
  }).meta({
1179
890
  title: "Methodology Attribute",
1180
- description: "Methodology attribute"
1181
- });
1182
- var GasIDAttributeGasTypeSchema = NftAttributeSchema.extend({
1183
- trait_type: z.literal("Gas Type"),
1184
- value: NonEmptyStringSchema.max(100).meta({
1185
- title: "Gas Type Value",
1186
- description: "Type of gas prevented",
1187
- examples: ["Methane (CH\u2084)", "Carbon Dioxide (CO\u2082)"]
1188
- })
1189
- }).meta({
1190
- title: "Gas Type Attribute",
1191
- description: "Gas type attribute"
1192
- });
1193
- var GasIDAttributeCo2ePreventedSchema = NftAttributeSchema.extend({
1194
- trait_type: z.literal("CO\u2082e Prevented (kg)"),
1195
- value: NonNegativeFloatSchema.meta({
1196
- title: "CO\u2082e Prevented Value",
1197
- description: "Total CO\u2082 equivalent emissions prevented in kilograms"
1198
- }),
1199
- display_type: z.literal("number")
1200
- }).meta({
1201
- title: "CO\u2082e Prevented Attribute",
1202
- description: "CO\u2082e prevented attribute with numeric display"
891
+ description: "Methodology used for certification"
1203
892
  });
1204
- var GasIDAttributeCreditAmountSchema = NftAttributeSchema.extend({
893
+ var CreditAmountAttributeSchema = NftAttributeSchema.extend({
1205
894
  trait_type: z.literal("Credit Amount"),
1206
- value: NonNegativeFloatSchema.meta({
1207
- title: "Credit Amount Value",
1208
- description: "Amount of credits issued"
1209
- }),
895
+ value: CreditAmountSchema,
1210
896
  display_type: z.literal("number")
1211
897
  }).meta({
1212
898
  title: "Credit Amount Attribute",
1213
899
  description: "Credit amount attribute with numeric display"
1214
900
  });
1215
- var GasIDAttributeCreditTypeSchema = NftAttributeSchema.extend({
901
+ var CreditTypeAttributeSchema = NftAttributeSchema.extend({
1216
902
  trait_type: z.literal("Credit Type"),
1217
- value: NonEmptyStringSchema.max(100).meta({
1218
- title: "Credit Type Value",
1219
- description: "Type of credit issued",
1220
- examples: ["Carrot Carbon"]
1221
- })
903
+ value: CreditTypeSchema
1222
904
  }).meta({
1223
905
  title: "Credit Type Attribute",
1224
906
  description: "Credit type attribute"
1225
907
  });
1226
- var GasIDAttributeSourceWasteTypeSchema = NftAttributeSchema.extend({
908
+ var SourceWasteTypeAttributeSchema = NftAttributeSchema.extend({
1227
909
  trait_type: z.literal("Source Waste Type"),
1228
910
  value: WasteTypeSchema
1229
911
  }).meta({
1230
912
  title: "Source Waste Type Attribute",
1231
913
  description: "Source waste type attribute"
1232
914
  });
1233
- var GasIDAttributeSourceWeightSchema = NftAttributeSchema.extend({
915
+ var SourceWeightAttributeSchema = NftAttributeSchema.extend({
1234
916
  trait_type: z.literal("Source Weight (kg)"),
1235
- value: WeightKgSchema,
917
+ value: WeightKgSchema.meta({
918
+ title: "Source Weight",
919
+ description: "Weight of the source waste in kilograms"
920
+ }),
1236
921
  display_type: z.literal("number")
1237
922
  }).meta({
1238
923
  title: "Source Weight Attribute",
1239
924
  description: "Source weight attribute with numeric display"
1240
925
  });
1241
- var GasIDAttributeOriginCountrySchema = NftAttributeSchema.extend({
926
+ var OriginCountryAttributeSchema = NftAttributeSchema.extend({
1242
927
  trait_type: z.literal("Origin Country"),
1243
- value: NonEmptyStringSchema.max(100).meta({
1244
- title: "Origin Country Value",
1245
- description: "Country where the waste was generated",
1246
- examples: ["Brazil"]
1247
- })
928
+ value: CountryNameSchema
1248
929
  }).meta({
1249
930
  title: "Origin Country Attribute",
1250
931
  description: "Origin country attribute"
1251
932
  });
1252
- var GasIDAttributeOriginMunicipalitySchema = NftAttributeSchema.extend({
933
+ var OriginMunicipalityAttributeSchema = NftAttributeSchema.extend({
1253
934
  trait_type: z.literal("Origin Municipality"),
1254
- value: NonEmptyStringSchema.max(100).meta({
1255
- title: "Origin Municipality Value",
1256
- description: "Municipality where the waste was generated",
1257
- examples: ["Macap\xE1"]
1258
- })
935
+ value: MunicipalitySchema
1259
936
  }).meta({
1260
937
  title: "Origin Municipality Attribute",
1261
938
  description: "Origin municipality attribute"
1262
939
  });
1263
- var GasIDAttributeRecyclerSchema = NftAttributeSchema.extend({
940
+ var RecyclerAttributeSchema = NftAttributeSchema.extend({
1264
941
  trait_type: z.literal("Recycler"),
1265
942
  value: NonEmptyStringSchema.max(100).meta({
1266
- title: "Recycler Value",
943
+ title: "Recycler",
1267
944
  description: "Organization that processed the waste",
1268
- examples: ["Eco Reciclagem"]
945
+ example: "Eco Reciclagem"
1269
946
  })
1270
947
  }).meta({
1271
948
  title: "Recycler Attribute",
1272
949
  description: "Recycler attribute"
1273
950
  });
1274
- var GasIDAttributeMassIDTokenIdSchema = NftAttributeSchema.extend({
951
+ var MassIDTokenIdAttributeSchema = NftAttributeSchema.extend({
1275
952
  trait_type: z.literal("MassID"),
1276
- value: NonEmptyStringSchema.regex(
1277
- /^#\d+$/,
1278
- "Must match pattern #<token_id>"
1279
- ).meta({
1280
- title: "MassID Token ID Value",
1281
- description: "Token ID of the source MassID NFT",
1282
- examples: ["#123"]
953
+ value: StringifiedTokenIdSchema.meta({
954
+ title: "MassID Token ID",
955
+ description: "Token ID of the source MassID NFT as #<token_id>"
1283
956
  })
1284
957
  }).meta({
1285
958
  title: "MassID Token ID Attribute",
1286
959
  description: "MassID token ID attribute"
1287
960
  });
1288
- var GasIDAttributeMassIDRecyclingDateSchema = NftAttributeSchema.extend({
961
+ var MassIDRecyclingDateAttributeSchema = NftAttributeSchema.omit({
962
+ max_value: true
963
+ }).extend({
1289
964
  trait_type: z.literal("MassID Recycling Date"),
1290
- value: IsoDateSchema.meta({
1291
- title: "MassID Recycling Date Value",
1292
- description: "Date when the source waste was recycled",
1293
- examples: ["2025-02-22"]
965
+ value: UnixTimestampSchema.meta({
966
+ title: "MassID Recycling Date",
967
+ description: "Unix timestamp in milliseconds when the source waste was recycled"
1294
968
  }),
1295
969
  display_type: z.literal("date")
1296
970
  }).meta({
1297
971
  title: "MassID Recycling Date Attribute",
1298
- description: "MassID recycling date attribute with date display"
972
+ description: "MassID recycling date attribute using Unix timestamp in milliseconds"
1299
973
  });
1300
- var GasIDAttributesSchema = z.tuple([
1301
- GasIDAttributeMethodologySchema,
1302
- GasIDAttributeGasTypeSchema,
1303
- GasIDAttributeCo2ePreventedSchema,
1304
- GasIDAttributeCreditAmountSchema,
1305
- GasIDAttributeCreditTypeSchema,
1306
- GasIDAttributeSourceWasteTypeSchema,
1307
- GasIDAttributeSourceWeightSchema,
1308
- GasIDAttributeOriginCountrySchema,
1309
- GasIDAttributeOriginMunicipalitySchema,
1310
- GasIDAttributeRecyclerSchema,
1311
- GasIDAttributeMassIDTokenIdSchema,
1312
- GasIDAttributeMassIDRecyclingDateSchema
1313
- ]).meta({
1314
- title: "GasID NFT Attribute Array",
1315
- description: "Schema for the fixed set of GasID NFT attributes, enforcing order and type for each trait"
974
+
975
+ // src/mass-id/mass-id.attributes.ts
976
+ var MassIDAttributeWasteTypeSchema = NftAttributeSchema.extend({
977
+ trait_type: z.literal("Waste Type"),
978
+ value: WasteTypeSchema
979
+ }).meta({
980
+ title: "Waste Type Attribute",
981
+ description: "Waste type attribute"
1316
982
  });
1317
- var WasteClassificationSchema = z.strictObject({
1318
- primary_type: WasteTypeSchema.meta({
1319
- title: "Source Waste Primary Type",
1320
- description: "Primary type of the source waste"
1321
- }),
1322
- subtype: WasteSubtypeSchema.meta({
1323
- title: "Source Waste Subtype",
1324
- description: "Subtype of the source waste"
983
+ var MassIDAttributeWasteSubtypeSchema = NftAttributeSchema.extend({
984
+ trait_type: z.literal("Waste Subtype"),
985
+ value: WasteSubtypeSchema
986
+ }).meta({
987
+ title: "Waste Subtype Attribute",
988
+ description: "Waste subtype attribute"
989
+ });
990
+ var MassIDAttributeWeightSchema = NftAttributeSchema.extend({
991
+ trait_type: z.literal("Weight (kg)"),
992
+ value: WeightKgSchema,
993
+ display_type: z.literal("number")
994
+ }).meta({
995
+ title: "Weight Attribute",
996
+ description: "Weight attribute with numeric display"
997
+ });
998
+ var MassIDAttributeOriginCountrySchema = OriginCountryAttributeSchema.extend({
999
+ value: CountryNameSchema
1000
+ });
1001
+ var MassIDAttributeOriginMunicipalitySchema = OriginMunicipalityAttributeSchema.extend({
1002
+ value: MunicipalitySchema
1003
+ });
1004
+ var MassIDAttributeOriginDivisionSchema = NftAttributeSchema.extend({
1005
+ trait_type: z.literal("Origin Administrative Division"),
1006
+ value: AdministrativeDivisionSchema
1007
+ }).meta({
1008
+ title: "Origin Administrative Division Attribute",
1009
+ description: "Origin administrative division attribute"
1010
+ });
1011
+ var MassIDAttributeVehicleTypeSchema = NftAttributeSchema.extend({
1012
+ trait_type: z.literal("Vehicle Type"),
1013
+ value: NonEmptyStringSchema.max(100).meta({
1014
+ title: "Vehicle Type",
1015
+ description: "Type of vehicle used for waste transportation",
1016
+ examples: ["Garbage Truck", "Box Truck", "Flatbed Truck", "Roll-off Truck"]
1017
+ })
1018
+ }).meta({
1019
+ title: "Vehicle Type Attribute",
1020
+ description: "Vehicle type attribute"
1021
+ });
1022
+ var MassIDAttributeRecyclingMethodSchema = NftAttributeSchema.extend({
1023
+ trait_type: z.literal("Recycling Method"),
1024
+ value: NonEmptyStringSchema.max(100).meta({
1025
+ title: "Recycling Method",
1026
+ description: "Method used for recycling or processing the waste",
1027
+ examples: [
1028
+ "Composting",
1029
+ "Mechanical Recycling",
1030
+ "Incineration with Energy Recovery"
1031
+ ]
1032
+ })
1033
+ }).meta({
1034
+ title: "Recycling Method Attribute",
1035
+ description: "Recycling method attribute"
1036
+ });
1037
+ var MassIDAttributeProcessingTimeSchema = NftAttributeSchema.extend({
1038
+ trait_type: z.literal("Processing Time (hours)"),
1039
+ value: HoursSchema,
1040
+ trait_description: NonEmptyStringSchema.max(200).optional().meta({
1041
+ title: "Processing Time Description",
1042
+ description: "Custom description for the processing time"
1043
+ })
1044
+ }).meta({
1045
+ title: "Processing Time Attribute",
1046
+ description: "Processing time attribute with optional trait description"
1047
+ });
1048
+ var MassIDAttributeLocalWasteClassificationIdSchema = NftAttributeSchema.extend({
1049
+ trait_type: z.literal("Local Waste Classification ID"),
1050
+ value: NonEmptyStringSchema.max(100).meta({
1051
+ title: "Local Waste Classification ID",
1052
+ description: "Local or regional waste classification identifier",
1053
+ examples: ["04 02 20", "IBAMA-A001", "EWC-150101"]
1054
+ })
1055
+ }).meta({
1056
+ title: "Local Waste Classification ID Attribute",
1057
+ description: "Local waste classification ID attribute"
1058
+ });
1059
+ var MassIDAttributeRecyclingManifestCodeSchema = NftAttributeSchema.extend({
1060
+ trait_type: z.literal("Recycling Manifest Code"),
1061
+ value: NonEmptyStringSchema.max(100).meta({
1062
+ title: "Recycling Manifest Code",
1063
+ description: "Concatenated recycling manifest code (Document Type + Document Number)",
1064
+ examples: ["CDF-2353", "RC-12345", "REC-MANIFEST-789"]
1065
+ })
1066
+ }).meta({
1067
+ title: "Recycling Manifest Code Attribute",
1068
+ description: "Recycling manifest code attribute (optional)"
1069
+ });
1070
+ var MassIDAttributeTransportManifestCodeSchema = NftAttributeSchema.extend({
1071
+ trait_type: z.literal("Transport Manifest Code"),
1072
+ value: NonEmptyStringSchema.max(100).meta({
1073
+ title: "Transport Manifest Code",
1074
+ description: "Concatenated transport manifest code (Document Type + Document Number)",
1075
+ examples: ["MTR-4126", "TRN-67890", "TRANS-MANIFEST-456"]
1076
+ })
1077
+ }).meta({
1078
+ title: "Transport Manifest Code Attribute",
1079
+ description: "Transport manifest code attribute (optional)"
1080
+ });
1081
+ var MassIDAttributeWeighingCaptureMethodSchema = NftAttributeSchema.extend({
1082
+ trait_type: z.literal("Weighing Capture Method"),
1083
+ value: NonEmptyStringSchema.max(100).meta({
1084
+ title: "Weighing Capture Method",
1085
+ description: "Method used to capture weight data",
1086
+ examples: ["Digital", "Manual", "Automated", "Electronic Scale"]
1087
+ })
1088
+ }).meta({
1089
+ title: "Weighing Capture Method Attribute",
1090
+ description: "Weighing capture method attribute (optional)"
1091
+ });
1092
+ var MassIDAttributeScaleTypeSchema = NftAttributeSchema.extend({
1093
+ trait_type: z.literal("Scale Type"),
1094
+ value: NonEmptyStringSchema.max(100).meta({
1095
+ title: "Scale Type",
1096
+ description: "Type of scale used for weighing",
1097
+ examples: [
1098
+ "Weighbridge (Truck Scale)",
1099
+ "Floor Scale",
1100
+ "Bench Scale",
1101
+ "Crane Scale"
1102
+ ]
1103
+ })
1104
+ }).meta({
1105
+ title: "Scale Type Attribute",
1106
+ description: "Scale type attribute (optional)"
1107
+ });
1108
+ var MassIDAttributeContainerTypeSchema = NftAttributeSchema.extend({
1109
+ trait_type: z.literal("Container Type"),
1110
+ value: NonEmptyStringSchema.max(100).meta({
1111
+ title: "Container Type",
1112
+ description: "Type of container used for waste storage or transport",
1113
+ examples: ["Truck", "Dumpster", "Roll-off Container", "Compactor", "Bin"]
1114
+ })
1115
+ }).meta({
1116
+ title: "Container Type Attribute",
1117
+ description: "Container type attribute (optional)"
1118
+ });
1119
+ var MassIDAttributePickUpDateSchema = NftAttributeSchema.extend({
1120
+ trait_type: z.literal("Pick-up Date"),
1121
+ value: UnixTimestampSchema.meta({
1122
+ title: "Pick-up Date",
1123
+ description: "Unix timestamp in milliseconds when the waste was picked up from the source",
1124
+ examples: [17105184e5, 17040672e5, 17152704e5]
1325
1125
  }),
1326
- net_weight_kg: WeightKgSchema.meta({
1327
- title: "Source Waste Net Weight",
1328
- description: "Net weight of the source waste"
1329
- })
1126
+ display_type: z.literal("date")
1330
1127
  }).meta({
1331
- title: "Waste Classification",
1332
- description: "Classification of the source waste (MassID)"
1128
+ title: "Pick-up Date Attribute",
1129
+ description: "Pick-up date attribute with Unix timestamp"
1333
1130
  });
1334
- var AccreditedParticipantSchema = z.strictObject({
1335
- participant_id: UuidSchema.meta({
1336
- title: "Participant ID",
1337
- description: "Unique identifier for the participant"
1338
- }),
1339
- name: ParticipantNameSchema.meta({
1340
- title: "Participant Name",
1341
- description: "Name of the participant"
1131
+ var MassIDAttributeRecyclingDateSchema = NftAttributeSchema.extend({
1132
+ trait_type: z.literal("Recycling Date"),
1133
+ value: UnixTimestampSchema.meta({
1134
+ title: "Recycling Date",
1135
+ description: "Unix timestamp in milliseconds when the waste was recycled/processed",
1136
+ examples: [17106048e5, 17041536e5, 17153568e5]
1342
1137
  }),
1343
- role: ParticipantRoleSchema.meta({
1344
- title: "Participant Role",
1345
- description: "Role of the participant in the supply chain"
1138
+ display_type: z.literal("date")
1139
+ }).meta({
1140
+ title: "Recycling Date Attribute",
1141
+ description: "Recycling date attribute with Unix timestamp"
1142
+ });
1143
+ var MassIDAttributesSchema = uniqueBy(
1144
+ z.union([
1145
+ MassIDAttributeWasteTypeSchema,
1146
+ MassIDAttributeWasteSubtypeSchema,
1147
+ MassIDAttributeWeightSchema,
1148
+ MassIDAttributeOriginCountrySchema,
1149
+ MassIDAttributeOriginMunicipalitySchema,
1150
+ MassIDAttributeOriginDivisionSchema,
1151
+ MassIDAttributeVehicleTypeSchema,
1152
+ MassIDAttributeRecyclingMethodSchema,
1153
+ MassIDAttributeProcessingTimeSchema,
1154
+ MassIDAttributeLocalWasteClassificationIdSchema,
1155
+ MassIDAttributeRecyclingManifestCodeSchema,
1156
+ MassIDAttributeTransportManifestCodeSchema,
1157
+ MassIDAttributeWeighingCaptureMethodSchema,
1158
+ MassIDAttributeScaleTypeSchema,
1159
+ MassIDAttributeContainerTypeSchema,
1160
+ MassIDAttributePickUpDateSchema,
1161
+ MassIDAttributeRecyclingDateSchema
1162
+ ]),
1163
+ (attr) => attr.trait_type
1164
+ ).min(12).max(17).meta({
1165
+ title: "MassID Attributes",
1166
+ description: "MassID NFT attributes array containing attributes selected from the available attribute types. The schema validates array length but does not enforce which specific attributes must be present."
1167
+ });
1168
+ var MassIDLocalClassificationSchema = z.strictObject({
1169
+ code: NonEmptyStringSchema.max(20).meta({
1170
+ title: "Classification Code",
1171
+ description: "Local waste classification code",
1172
+ examples: ["20 01 01", "D001", "EWC-150101", "IBAMA-A001"]
1346
1173
  }),
1347
- accreditation_id: UuidSchema.meta({
1348
- title: "Accreditation ID",
1349
- description: "Unique identifier for the participant accreditation"
1174
+ description: NonEmptyStringSchema.max(200).meta({
1175
+ title: "Classification Description",
1176
+ description: "Local waste classification description",
1177
+ examples: [
1178
+ "Paper and cardboard packaging",
1179
+ "Ignitable waste",
1180
+ "Paper and cardboard packaging waste",
1181
+ "Municipal solid waste - organic fraction"
1182
+ ]
1350
1183
  }),
1351
- external_url: ExternalUrlSchema.meta({
1352
- title: "Participant Accreditation External URL",
1353
- description: "URL to view the participant accreditation on Carrot Explorer"
1184
+ system: z.enum(["IBAMA"]).meta({
1185
+ title: "Classification System",
1186
+ description: "Classification system name - currently supports IBAMA (Instituto Brasileiro do Meio Ambiente e dos Recursos Naturais Renov\xE1veis)",
1187
+ examples: ["IBAMA"]
1354
1188
  })
1355
1189
  }).meta({
1356
- title: "Accredited Participant",
1357
- description: "Participant with valid accreditation in the supply chain"
1190
+ title: "Local Classification",
1191
+ description: "Local or regional waste classification codes and descriptions"
1358
1192
  });
1359
- var AccreditedParticipantsSchema = z.array(AccreditedParticipantSchema).min(1).meta({
1360
- title: "Accredited Participants",
1361
- description: "List of participants with valid accreditations"
1193
+ var MassIDMeasurementUnitSchema = z.enum(["kg", "ton"]).meta({
1194
+ title: "Measurement Unit",
1195
+ description: "Unit of measurement for the waste quantity",
1196
+ examples: ["kg", "ton"]
1362
1197
  });
1363
- var RewardAllocationSchema = z.strictObject({
1364
- participant_id: UuidSchema.meta({
1365
- title: "Participant ID",
1366
- description: "Unique identifier for the participant receiving the reward"
1367
- }),
1368
- participant_name: ParticipantNameSchema.meta({
1369
- title: "Participant Name",
1370
- description: "Name of the participant receiving the reward"
1371
- }),
1372
- role: ParticipantRoleSchema.meta({
1373
- title: "Participant Role",
1374
- description: "Role of the participant in the supply chain"
1375
- }),
1376
- reward_percentage: PercentageSchema.meta({
1377
- title: "Reward Percentage",
1378
- description: "Reward percentage allocated to the participant"
1198
+ var MassIDWastePropertiesSchema = z.strictObject({
1199
+ type: WasteTypeSchema.meta({
1200
+ title: "Waste Type",
1201
+ description: "Waste material category"
1379
1202
  }),
1380
- large_business_discount_applied: z.boolean().optional().meta({
1381
- title: "Large Business Discount Applied",
1382
- description: "Whether the large business discount was applied"
1203
+ subtype: WasteSubtypeSchema.meta({
1204
+ title: "Waste Subtype",
1205
+ description: "Specific subcategory of waste material"
1383
1206
  }),
1384
- effective_percentage: PercentageSchema.meta({
1385
- title: "Effective Percentage",
1386
- description: "Effective percentage of the reward after discounts"
1207
+ local_classification: MassIDLocalClassificationSchema.optional(),
1208
+ measurement_unit: MassIDMeasurementUnitSchema,
1209
+ net_weight: NonNegativeFloatSchema.meta({
1210
+ title: "Net Weight",
1211
+ description: "Net weight of the waste batch in the specified measurement unit"
1387
1212
  })
1388
1213
  }).meta({
1389
- title: "Reward Allocation",
1390
- description: "Reward allocation for a specific participant"
1214
+ title: "Waste Properties",
1215
+ description: "Standardized waste material properties and regulatory information"
1391
1216
  });
1392
- var DistributionNotesSchema = z.strictObject({
1393
- large_business_discount_applied: NonEmptyStringSchema.optional().meta({
1394
- title: "Large Business Discount Applied",
1395
- description: "Description of the large business discount applied",
1217
+ var EventAttributeFormatSchema = z.enum(["KILOGRAM", "DATE", "CURRENCY", "PERCENTAGE", "COORDINATE"]).meta({
1218
+ title: "Event Attribute Format",
1219
+ description: "Data format hint for proper display",
1220
+ examples: ["KILOGRAM", "DATE", "PERCENTAGE"]
1221
+ });
1222
+ var EventAttributeSchema = z.strictObject({
1223
+ name: NonEmptyStringSchema.max(100).meta({
1224
+ title: "Attribute Name",
1225
+ description: "Event attribute name",
1396
1226
  examples: [
1397
- "50% reduction applied to participants with >$4M annual revenue"
1227
+ "temperature",
1228
+ "humidity",
1229
+ "contamination_percentage",
1230
+ "quality_grade",
1231
+ "batch_number",
1232
+ "operator_id",
1233
+ "equipment_used",
1234
+ "processing_cost"
1398
1235
  ]
1399
1236
  }),
1400
- redirected_rewards: NonEmptyStringSchema.optional().meta({
1401
- title: "Redirected Rewards",
1402
- description: "Description of the redirected rewards",
1237
+ value: z.union([z.string(), z.number(), z.boolean()]).optional().meta({
1238
+ title: "Attribute Value",
1239
+ description: "Event attribute value",
1403
1240
  examples: [
1404
- "Discounted rewards from large businesses redirected to accredited NGOs"
1241
+ 25.5,
1242
+ "Grade A",
1243
+ true,
1244
+ "BATCH-2024-001",
1245
+ 12.75,
1246
+ "Shredder-X200",
1247
+ false,
1248
+ "OP-456"
1405
1249
  ]
1406
- })
1250
+ }),
1251
+ preserved_sensitivity: z.boolean().optional().meta({
1252
+ title: "Preserved Sensitivity",
1253
+ description: "Indicates if the attribute contains sensitive information that was preserved"
1254
+ }),
1255
+ format: EventAttributeFormatSchema.optional()
1407
1256
  }).meta({
1408
- title: "Distribution Notes",
1409
- description: "Additional notes about the reward distribution"
1257
+ title: "Event Attribute",
1258
+ description: "Additional attribute specific to an event"
1410
1259
  });
1411
- var ParticipantRewardsSchema = z.strictObject({
1412
- distribution_basis: NonEmptyStringSchema.max(200).meta({
1413
- title: "Distribution Basis",
1414
- description: "Basis for the rewards distribution"
1260
+ var EventAttachmentSchema = z.strictObject({
1261
+ type: NonEmptyStringSchema.max(50).meta({
1262
+ title: "Attachment Type",
1263
+ description: "Type of supporting attachment",
1264
+ examples: [
1265
+ "Waste Transfer Note",
1266
+ "Certificate of Disposal",
1267
+ "Certificate of Final Destination",
1268
+ "Quality Assessment Report",
1269
+ "Transport Manifest",
1270
+ "Processing Receipt",
1271
+ "Environmental Permit",
1272
+ "Invoice"
1273
+ ]
1415
1274
  }),
1416
- reward_allocations: z.array(RewardAllocationSchema).min(1).meta({
1417
- title: "Reward Allocations",
1418
- description: "Rewards percentage allocated to each participant"
1275
+ document_number: NonEmptyStringSchema.max(50).optional().meta({
1276
+ title: "Document Number",
1277
+ description: "Official document number if applicable",
1278
+ examples: [
1279
+ "WTN-2024-001234",
1280
+ "CD-ENV-456789",
1281
+ "INV-2024-QTR1-789",
1282
+ "PERMIT-EPA-2024-001",
1283
+ "MANIFEST-DOT-567890"
1284
+ ]
1419
1285
  }),
1420
- distribution_notes: DistributionNotesSchema.optional().meta({
1421
- title: "Distribution Notes",
1422
- description: "Additional notes about the reward distribution"
1286
+ reference: NonEmptyStringSchema.meta({
1287
+ title: "Attachment Reference",
1288
+ description: "Reference to attachment (IPFS hash, file name, or external URL)",
1289
+ examples: [
1290
+ "QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o",
1291
+ "waste_transfer_note_2024_001.pdf",
1292
+ "https://docs.example.com/certificates/disposal_cert_456.pdf",
1293
+ "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
1294
+ "processing_receipt_20240315.jpg"
1295
+ ]
1296
+ }),
1297
+ issue_timestamp: UnixTimestampSchema.optional().meta({
1298
+ title: "Issue Timestamp",
1299
+ description: "Unix timestamp in milliseconds when the attachment was issued",
1300
+ examples: [17105184e5, 17040672e5, 17152704e5]
1301
+ }),
1302
+ issuer: NonEmptyStringSchema.max(100).optional().meta({
1303
+ title: "Attachment Issuer",
1304
+ description: "Entity that issued the attachment",
1305
+ examples: [
1306
+ "Environmental Protection Agency",
1307
+ "Waste Management Solutions Ltd",
1308
+ "Green Recycling Corp",
1309
+ "City Waste Authority",
1310
+ "EcoProcess Industries",
1311
+ "Regional Environmental Office"
1312
+ ]
1423
1313
  })
1424
1314
  }).meta({
1425
- title: "Participant Rewards",
1426
- description: "Rewards distribution to participants"
1427
- });
1428
- var MethodologyComplianceSchema = z.enum(["PASSED", "FAILED"]).meta({
1429
- title: "Methodology Compliance",
1430
- description: "Result of methodology compliance check",
1431
- examples: ["PASSED", "FAILED"]
1315
+ title: "Event Attachment",
1316
+ description: "Supporting event attachment"
1432
1317
  });
1433
- var AuditReferenceSchema = z.strictObject({
1434
- date: IsoDateSchema.meta({
1435
- title: "Audit Date",
1436
- description: "Date when the audit was completed"
1318
+ var MassIDChainOfCustodyEventSchema = z.strictObject({
1319
+ event_id: UuidSchema.meta({
1320
+ title: "Event ID",
1321
+ description: "Unique event identifier"
1322
+ }),
1323
+ event_name: NonEmptyStringSchema.max(50).meta({
1324
+ title: "Event Name",
1325
+ description: "Name of custody or processing event",
1326
+ examples: ["Sorting", "Processing", "Recycling", "Weighing"]
1437
1327
  }),
1438
- external_id: ExternalIdSchema.meta({
1439
- title: "Audit External ID",
1440
- description: "Unique identifier for the audit"
1328
+ description: NonEmptyStringSchema.max(200).optional().meta({
1329
+ title: "Event Description",
1330
+ description: "Detailed description of what happened during this event",
1331
+ examples: [
1332
+ "Waste collected from residential area using collection truck",
1333
+ "Material sorted into recyclable and non-recyclable fractions",
1334
+ "Plastic waste processed through shredding and washing",
1335
+ "Waste transferred to authorized recycling facility",
1336
+ "Final disposal at licensed landfill site",
1337
+ "Quality inspection and contamination assessment completed"
1338
+ ]
1441
1339
  }),
1442
- external_url: ExternalUrlSchema.meta({
1443
- title: "Audit External URL",
1444
- description: "URL to view the audit on Carrot Explorer"
1340
+ timestamp: UnixTimestampSchema.meta({
1341
+ title: "Event Timestamp",
1342
+ description: "Unix timestamp in milliseconds when the event occurred",
1343
+ examples: [17105184e5, 17040672e5, 17152704e5]
1445
1344
  }),
1446
- methodology_compliance: MethodologyComplianceSchema.meta({
1447
- title: "Methodology Compliance",
1448
- description: "Result of methodology compliance check"
1345
+ participant_id_hash: Sha256HashSchema.meta({
1346
+ title: "Participant ID Hash",
1347
+ description: "Reference to participant in the participants array"
1449
1348
  }),
1450
- rules_executed: NonNegativeIntegerSchema.meta({
1451
- title: "Rules Executed",
1452
- description: "Number of rules executed during the audit"
1349
+ location_id_hash: Sha256HashSchema.meta({
1350
+ title: "Location ID Hash",
1351
+ description: "Reference to location in the locations array"
1453
1352
  }),
1454
- report: IpfsUriSchema.meta({
1455
- title: "Audit Report",
1456
- description: "IPFS URI of the audit report"
1353
+ weight: NonNegativeFloatSchema.optional().meta({
1354
+ title: "Event Weight",
1355
+ description: "Mass weight after this event"
1356
+ }),
1357
+ attributes: z.array(EventAttributeSchema).optional().meta({
1358
+ title: "Event Attributes",
1359
+ description: "Additional attributes specific to this event"
1360
+ }),
1361
+ attachments: z.array(EventAttachmentSchema).optional().meta({
1362
+ title: "Event Attachments",
1363
+ description: "Associated attachments for this event"
1457
1364
  })
1458
1365
  }).meta({
1459
- title: "Audit Reference",
1460
- description: "Reference to an audit record"
1366
+ title: "Chain of Custody Event",
1367
+ description: "Chain of custody event"
1461
1368
  });
1462
- var GasIDReferenceSchema = z.strictObject({
1463
- external_id: ExternalIdSchema.meta({
1464
- title: "GasID External ID",
1465
- description: "Unique identifier for the GasID"
1466
- }),
1467
- token_id: TokenIdSchema.meta({
1468
- title: "GasID Token ID",
1469
- description: "NFT token ID of the GasID"
1470
- }),
1471
- external_url: ExternalUrlSchema.meta({
1472
- title: "GasID External URL",
1473
- description: "URL to view the GasID on Carrot Explorer"
1369
+ var MassIDChainOfCustodySchema = z.strictObject({
1370
+ events: z.array(MassIDChainOfCustodyEventSchema).min(1).meta({
1371
+ title: "Custody Events",
1372
+ description: "Chronological sequence of custody transfer and processing events"
1474
1373
  }),
1475
- uri: IpfsUriSchema.meta({
1476
- title: "GasID IPFS URI",
1477
- description: "IPFS URI of the GasID record"
1374
+ total_duration_minutes: MinutesSchema.meta({
1375
+ title: "Total Duration (minutes)",
1376
+ description: "Total time from first to last event in minutes"
1478
1377
  })
1479
1378
  }).meta({
1480
- title: "GasID Reference",
1481
- description: "Reference to a GasID record"
1379
+ title: "Chain of Custody",
1380
+ description: "Complete chain of custody tracking from waste generation to final processing"
1482
1381
  });
1483
- var MassIDReferenceSchema = z.strictObject({
1484
- external_id: ExternalIdSchema.meta({
1485
- title: "MassID External ID",
1486
- description: "Unique identifier for the MassID"
1382
+ var MassIDGeographicDataSchema = z.strictObject({
1383
+ from_location_id_hash: Sha256HashSchema.meta({
1384
+ title: "From Location ID Hash",
1385
+ description: "Reference hash of the location where the waste started movement"
1487
1386
  }),
1488
- token_id: TokenIdSchema.meta({
1489
- title: "MassID Token ID",
1490
- description: "NFT token ID of the MassID"
1387
+ to_location_id_hash: Sha256HashSchema.meta({
1388
+ title: "To Location ID Hash",
1389
+ description: "Reference hash of the location where the waste ended movement"
1491
1390
  }),
1492
- external_url: ExternalUrlSchema.meta({
1493
- title: "MassID External URL",
1494
- description: "URL to view the MassID on Carrot Explorer"
1391
+ first_reported_timestamp: UnixTimestampSchema.meta({
1392
+ title: "First Reported Timestamp",
1393
+ description: "Unix timestamp in milliseconds when the waste was first reported/collected at the origin location",
1394
+ examples: [17105184e5, 17040672e5, 17152704e5]
1495
1395
  }),
1496
- uri: IpfsUriSchema.meta({
1497
- title: "MassID IPFS URI",
1498
- description: "IPFS URI of the MassID record"
1396
+ last_reported_timestamp: UnixTimestampSchema.meta({
1397
+ title: "Last Reported Timestamp",
1398
+ description: "Unix timestamp in milliseconds when the waste was last reported/processed at the destination location",
1399
+ examples: [17106048e5, 17041536e5, 17153568e5]
1499
1400
  })
1500
- }).meta({
1501
- title: "MassID Reference",
1502
- description: "Reference to a MassID record"
1401
+ }).refine((data) => {
1402
+ return data.first_reported_timestamp <= data.last_reported_timestamp;
1403
+ }, "first_reported_timestamp must be before or equal to last_reported_timestamp").meta({
1404
+ title: "Geographic Data",
1405
+ description: "Simplified geographic information tracking waste movement from origin to destination with temporal bounds"
1503
1406
  });
1504
- var MethodologyReferenceSchema = z.strictObject({
1505
- external_id: ExternalIdSchema.meta({
1506
- title: "Methodology External ID",
1507
- description: "Unique identifier for the methodology"
1508
- }),
1509
- name: NonEmptyStringSchema.min(5).max(150).meta({
1510
- title: "Methodology Name",
1511
- description: "Human-readable name of the methodology",
1512
- examples: ["BOLD Carbon (CH\u2084)", "BOLD Recycling"]
1407
+ var MassIDDataSchema = z.strictObject({
1408
+ waste_properties: MassIDWastePropertiesSchema,
1409
+ locations: uniqueBy(
1410
+ LocationSchema,
1411
+ (loc) => loc.id_hash,
1412
+ "Location ID hashes must be unique"
1413
+ ).min(1).meta({
1414
+ title: "Locations",
1415
+ description: "All locations referenced in this MassID, indexed by ID"
1513
1416
  }),
1514
- version: SemanticVersionSchema.meta({
1515
- title: "Methodology Version",
1516
- description: "Version of the methodology"
1417
+ participants: uniqueBy(
1418
+ ParticipantSchema,
1419
+ (p) => p.id_hash,
1420
+ "Participant ID hashes must be unique"
1421
+ ).min(1).meta({
1422
+ title: "Participants",
1423
+ description: "All participants referenced in this MassID, indexed by ID"
1517
1424
  }),
1518
- external_url: ExternalUrlSchema.meta({
1519
- title: "Methodology External URL",
1520
- description: "URL to view the methodology on Carrot Explorer"
1425
+ chain_of_custody: MassIDChainOfCustodySchema,
1426
+ geographic_data: MassIDGeographicDataSchema
1427
+ }).refine((data) => {
1428
+ const participantIdSet = new Set(
1429
+ data.participants.map((participant) => participant.id_hash)
1430
+ );
1431
+ const eventParticipantIds = data.chain_of_custody.events.map(
1432
+ (event) => event.participant_id_hash
1433
+ );
1434
+ const allEventParticipantsExist = eventParticipantIds.every(
1435
+ (participantId) => participantIdSet.has(participantId)
1436
+ );
1437
+ return allEventParticipantsExist;
1438
+ }, "All participant ID hashes in chain of custody events must exist in participants array").refine((data) => {
1439
+ const locationIdSet = new Set(
1440
+ data.locations.map((location) => location.id_hash)
1441
+ );
1442
+ const eventLocationIds = data.chain_of_custody.events.map(
1443
+ (event) => event.location_id_hash
1444
+ );
1445
+ const allEventLocationsExist = eventLocationIds.every(
1446
+ (locationId) => locationIdSet.has(locationId)
1447
+ );
1448
+ return allEventLocationsExist;
1449
+ }, "All location ID hashes in chain of custody events must exist in locations array").meta({
1450
+ title: "MassID Data",
1451
+ description: "MassID data containing waste tracking and chain of custody information"
1452
+ });
1453
+ var MassIDIpfsSchemaMeta = {
1454
+ title: "MassID NFT IPFS Record",
1455
+ description: "Complete MassID NFT IPFS record including fixed attributes and detailed waste tracking data",
1456
+ $id: buildSchemaUrl("mass-id/mass-id.schema.json"),
1457
+ version: getSchemaVersionOrDefault()
1458
+ };
1459
+ var MassIDIpfsSchema = NftIpfsSchema.safeExtend({
1460
+ schema: NftIpfsSchema.shape.schema.safeExtend({
1461
+ type: z.literal("MassID").meta({
1462
+ title: "MassID Schema Type",
1463
+ description: "MassID NFT schema type"
1464
+ })
1521
1465
  }),
1522
- uri: IpfsUriSchema.optional().meta({
1523
- title: "Methodology IPFS URI",
1524
- description: "IPFS URI to the methodology record"
1466
+ attributes: MassIDAttributesSchema,
1467
+ data: MassIDDataSchema
1468
+ }).meta(MassIDIpfsSchemaMeta);
1469
+ var GasIDAttributeMethodologySchema = MethodologyAttributeSchema;
1470
+ var GasIDAttributeGasTypeSchema = NftAttributeSchema.extend({
1471
+ trait_type: z.literal("Gas Type"),
1472
+ value: NonEmptyStringSchema.max(100).meta({
1473
+ title: "Gas Type",
1474
+ description: "Type of gas prevented",
1475
+ examples: ["Methane (CH\u2084)", "Carbon Dioxide (CO\u2082)"]
1525
1476
  })
1526
1477
  }).meta({
1527
- title: "Methodology Reference",
1528
- description: "Reference to a methodology record"
1478
+ title: "Gas Type Attribute",
1479
+ description: "Gas type attribute"
1480
+ });
1481
+ var GasIDAttributeCo2ePreventedSchema = NftAttributeSchema.extend({
1482
+ trait_type: z.literal("CO\u2082e Prevented (kg)"),
1483
+ value: NonNegativeFloatSchema.meta({
1484
+ title: "CO\u2082e Prevented",
1485
+ description: "Total CO\u2082 equivalent emissions prevented in kilograms"
1486
+ }),
1487
+ display_type: z.literal("number")
1488
+ }).meta({
1489
+ title: "CO\u2082e Prevented Attribute",
1490
+ description: "CO\u2082e prevented attribute with numeric display"
1491
+ });
1492
+ var GasIDAttributeCreditAmountSchema = CreditAmountAttributeSchema;
1493
+ var GasIDAttributeCreditTypeSchema = CreditTypeAttributeSchema;
1494
+ var GasIDAttributeSourceWasteTypeSchema = SourceWasteTypeAttributeSchema;
1495
+ var GasIDAttributeSourceWeightSchema = SourceWeightAttributeSchema;
1496
+ var GasIDAttributeOriginCountrySchema = OriginCountryAttributeSchema;
1497
+ var GasIDAttributeOriginMunicipalitySchema = OriginMunicipalityAttributeSchema;
1498
+ var GasIDAttributeRecyclerSchema = RecyclerAttributeSchema;
1499
+ var GasIDAttributeMassIDTokenIdSchema = MassIDTokenIdAttributeSchema;
1500
+ var GasIDAttributeMassIDRecyclingDateSchema = MassIDRecyclingDateAttributeSchema;
1501
+ var GasIDAttributesSchema = z.tuple([
1502
+ GasIDAttributeMethodologySchema,
1503
+ GasIDAttributeGasTypeSchema,
1504
+ GasIDAttributeCo2ePreventedSchema,
1505
+ GasIDAttributeCreditAmountSchema,
1506
+ GasIDAttributeCreditTypeSchema,
1507
+ GasIDAttributeSourceWasteTypeSchema,
1508
+ GasIDAttributeSourceWeightSchema,
1509
+ GasIDAttributeOriginCountrySchema,
1510
+ GasIDAttributeOriginMunicipalitySchema,
1511
+ GasIDAttributeRecyclerSchema,
1512
+ GasIDAttributeMassIDTokenIdSchema,
1513
+ GasIDAttributeMassIDRecyclingDateSchema
1514
+ ]).meta({
1515
+ title: "GasID NFT Attribute Array",
1516
+ description: "Schema for the fixed set of GasID NFT attributes, enforcing order and type for each trait"
1529
1517
  });
1530
-
1531
- // src/gas-id/gas-id.data.schema.ts
1532
1518
  var GasIDSummarySchema = z.strictObject({
1533
1519
  gas_type: NonEmptyStringSchema.meta({
1534
1520
  title: "Gas Type",
1535
1521
  description: "Type of gas prevented",
1536
1522
  examples: ["Methane (CH\u2084)", "Carbon Dioxide (CO\u2082)"]
1537
1523
  }),
1538
- credit_type: NonEmptyStringSchema.meta({
1539
- title: "Credit Type",
1540
- description: "Type of credit issued",
1541
- examples: ["Carrot Carbon (C-CARB)", "Carbon Credit"]
1542
- }),
1543
- credit_amount: NonNegativeFloatSchema.meta({
1544
- title: "Credit Amount",
1545
- description: "Amount of credits issued"
1546
- }),
1524
+ credit_type: CreditTypeSchema,
1525
+ credit_amount: CreditAmountSchema,
1547
1526
  prevented_co2e_kg: WeightKgSchema.meta({
1548
1527
  title: "Prevented Emissions (CO\u2082e kg)",
1549
1528
  description: "CO\u2082e weight of the prevented emissions"
@@ -1632,7 +1611,87 @@ var GasIDIpfsSchema = NftIpfsSchema.safeExtend({
1632
1611
  attributes: GasIDAttributesSchema,
1633
1612
  data: GasIDDataSchema
1634
1613
  }).meta(GasIDIpfsSchemaMeta);
1614
+ var RecycledIDAttributeMethodologySchema = MethodologyAttributeSchema;
1615
+ var RecycledIDAttributeRecycledMassWeightSchema = NftAttributeSchema.extend({
1616
+ trait_type: z.literal("Recycled Mass Weight (kg)"),
1617
+ value: WeightKgSchema.meta({
1618
+ title: "Recycled Mass Weight",
1619
+ description: "Total weight of recycled materials in kilograms"
1620
+ }),
1621
+ display_type: z.literal("number")
1622
+ }).meta({
1623
+ title: "Recycled Mass Weight Attribute",
1624
+ description: "Recycled mass weight attribute with numeric display"
1625
+ });
1626
+ var RecycledIDAttributeCreditAmountSchema = CreditAmountAttributeSchema;
1627
+ var RecycledIDAttributeCreditTypeSchema = CreditTypeAttributeSchema;
1628
+ var RecycledIDAttributeSourceWasteTypeSchema = SourceWasteTypeAttributeSchema;
1629
+ var RecycledIDAttributeSourceWeightSchema = SourceWeightAttributeSchema;
1630
+ var RecycledIDAttributeOriginCountrySchema = OriginCountryAttributeSchema;
1631
+ var RecycledIDAttributeOriginMunicipalitySchema = OriginMunicipalityAttributeSchema;
1632
+ var RecycledIDAttributeRecyclerSchema = RecyclerAttributeSchema;
1633
+ var RecycledIDAttributeMassIDTokenIdSchema = MassIDTokenIdAttributeSchema;
1634
+ var RecycledIDAttributeMassIDRecyclingDateSchema = MassIDRecyclingDateAttributeSchema;
1635
+ var RecycledIDAttributesSchema = z.tuple([
1636
+ RecycledIDAttributeMethodologySchema,
1637
+ RecycledIDAttributeRecycledMassWeightSchema,
1638
+ RecycledIDAttributeCreditAmountSchema,
1639
+ RecycledIDAttributeCreditTypeSchema,
1640
+ RecycledIDAttributeSourceWasteTypeSchema,
1641
+ RecycledIDAttributeSourceWeightSchema,
1642
+ RecycledIDAttributeOriginCountrySchema,
1643
+ RecycledIDAttributeOriginMunicipalitySchema,
1644
+ RecycledIDAttributeRecyclerSchema,
1645
+ RecycledIDAttributeMassIDTokenIdSchema,
1646
+ RecycledIDAttributeMassIDRecyclingDateSchema
1647
+ ]).meta({
1648
+ title: "RecycledID NFT Attribute Array",
1649
+ description: "Schema for the fixed set of RecycledID NFT attributes, enforcing order and type for each trait"
1650
+ });
1651
+ var RecycledIDSummarySchema = z.strictObject({
1652
+ recycled_mass_kg: WeightKgSchema.meta({
1653
+ title: "Recycled Mass Weight",
1654
+ description: "Total weight of materials successfully recycled"
1655
+ }),
1656
+ credit_type: CreditTypeSchema,
1657
+ credit_amount: CreditAmountSchema
1658
+ }).meta({
1659
+ title: "RecycledID Summary",
1660
+ description: "Summary information for the RecycledID certificate"
1661
+ });
1662
+ var RecycledIDDataSchema = z.strictObject({
1663
+ summary: RecycledIDSummarySchema,
1664
+ methodology: MethodologyReferenceSchema,
1665
+ audit: AuditReferenceSchema,
1666
+ mass_id: MassIDReferenceSchema,
1667
+ waste_classification: WasteClassificationSchema,
1668
+ origin_location: LocationSchema.meta({
1669
+ title: "RecycledID Origin Location",
1670
+ description: "Source waste origin location details"
1671
+ }),
1672
+ accredited_participants: AccreditedParticipantsSchema,
1673
+ participant_rewards: ParticipantRewardsSchema.optional()
1674
+ }).meta({
1675
+ title: "RecycledID Data",
1676
+ description: "Complete data structure for RecycledID certificate"
1677
+ });
1678
+ var RecycledIDIpfsSchemaMeta = {
1679
+ title: "RecycledID NFT IPFS Record",
1680
+ description: "Complete RecycledID NFT IPFS record including fixed attributes and recycling outcome data",
1681
+ $id: buildSchemaUrl("recycled-id/recycled-id.schema.json"),
1682
+ version: getSchemaVersionOrDefault()
1683
+ };
1684
+ var RecycledIDIpfsSchema = NftIpfsSchema.safeExtend({
1685
+ schema: NftIpfsSchema.shape.schema.safeExtend({
1686
+ type: z.literal("RecycledID").meta({
1687
+ title: "RecycledID Schema Type",
1688
+ description: "RecycledID NFT schema type"
1689
+ })
1690
+ }),
1691
+ attributes: RecycledIDAttributesSchema,
1692
+ data: RecycledIDDataSchema
1693
+ }).meta(RecycledIDIpfsSchemaMeta);
1635
1694
 
1636
- export { AccreditedParticipantSchema, AccreditedParticipantsSchema, AuditReferenceSchema, BaseIpfsSchema, BlockchainChainIdSchema, CoordinatesSchema, DistributionNotesSchema, EthereumAddressSchema, ExternalIdSchema, ExternalUrlSchema, FacilityTypeSchema, GasIDAttributesSchema, GasIDDataSchema, GasIDIpfsSchema, GasIDIpfsSchemaMeta, GasIDReferenceSchema, HexColorSchema, HoursSchema, IpfsUriSchema, IsoAdministrativeDivisionCodeSchema, IsoCountryCodeSchema, IsoDateSchema, IsoTimestampSchema, Keccak256HashSchema, LatitudeSchema, LocationSchema, LongitudeSchema, MassIDAttributesSchema, MassIDDataSchema, MassIDIpfsSchema, MassIDIpfsSchemaMeta, MassIDReferenceSchema, MethodologyComplianceSchema, MethodologyReferenceSchema, MinutesSchema, NftAttributeSchema, NftIpfsSchema, NonEmptyStringSchema, NonNegativeFloatSchema, NonNegativeIntegerSchema, ParticipantNameSchema, ParticipantRewardsSchema, ParticipantRoleSchema, ParticipantSchema, PercentageSchema, PositiveIntegerSchema, RecordEnvironmentSchema, RecordRelationshipTypeSchema, RecordSchemaTypeSchema, RewardAllocationSchema, SemanticVersionSchema, Sha256HashSchema, SlugSchema, TokenIdSchema, TokenSymbolSchema, UnixTimestampSchema, UuidSchema, WasteClassificationSchema, WasteSubtypeSchema, WasteTypeSchema, WeightKgSchema, buildSchemaUrl, getSchemaBaseUrl, getSchemaVersionOrDefault, uniqueArrayItems, uniqueBy };
1695
+ export { AccreditedParticipantSchema, AccreditedParticipantsSchema, AdministrativeDivisionSchema, AuditReferenceSchema, BaseIpfsSchema, BlockchainChainIdSchema, CoordinatesSchema, CountryNameSchema, CreditAmountAttributeSchema, CreditAmountSchema, CreditTypeAttributeSchema, CreditTypeSchema, DistributionNotesSchema, EthereumAddressSchema, ExternalIdSchema, ExternalUrlSchema, FacilityTypeSchema, GasIDAttributesSchema, GasIDDataSchema, GasIDIpfsSchema, GasIDIpfsSchemaMeta, GasIDReferenceSchema, HexColorSchema, HoursSchema, IpfsUriSchema, IsoAdministrativeDivisionCodeSchema, IsoCountryCodeSchema, IsoDateSchema, IsoTimestampSchema, Keccak256HashSchema, LatitudeSchema, LocationSchema, LongitudeSchema, MassIDAttributesSchema, MassIDDataSchema, MassIDIpfsSchema, MassIDIpfsSchemaMeta, MassIDRecyclingDateAttributeSchema, MassIDReferenceSchema, MassIDTokenIdAttributeSchema, MethodologyAttributeSchema, MethodologyComplianceSchema, MethodologyNameSchema, MethodologyReferenceSchema, MinutesSchema, MunicipalitySchema, NftAttributeSchema, NftIpfsSchema, NonEmptyStringSchema, NonNegativeFloatSchema, NonNegativeIntegerSchema, OriginCountryAttributeSchema, OriginMunicipalityAttributeSchema, ParticipantNameSchema, ParticipantRewardsSchema, ParticipantRoleSchema, ParticipantSchema, PercentageSchema, PositiveIntegerSchema, RecordEnvironmentSchema, RecordRelationshipTypeSchema, RecordSchemaTypeSchema, RecycledIDAttributesSchema, RecycledIDDataSchema, RecycledIDIpfsSchema, RecycledIDIpfsSchemaMeta, RecyclerAttributeSchema, RewardAllocationSchema, SemanticVersionSchema, Sha256HashSchema, SlugSchema, SourceWasteTypeAttributeSchema, SourceWeightAttributeSchema, StringifiedTokenIdSchema, TokenIdSchema, TokenSymbolSchema, UnixTimestampSchema, UuidSchema, WasteClassificationSchema, WasteSubtypeSchema, WasteTypeSchema, WeightKgSchema, buildSchemaUrl, getSchemaBaseUrl, getSchemaVersionOrDefault, uniqueArrayItems, uniqueBy };
1637
1696
  //# sourceMappingURL=index.js.map
1638
1697
  //# sourceMappingURL=index.js.map