@carrot-foundation/schemas 0.1.25 → 0.1.26
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.cjs +766 -668
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +478 -94
- package/dist/index.d.ts +478 -94
- package/dist/index.js +766 -669
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schemas/ipfs/mass-id/mass-id.example.json +34 -6
- package/schemas/ipfs/mass-id/mass-id.schema.json +835 -242
package/dist/index.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var zod = require('zod');
|
|
4
4
|
|
|
5
|
-
// src/mass-id/mass-id.
|
|
5
|
+
// src/mass-id/mass-id.attributes.ts
|
|
6
6
|
var UuidSchema = zod.z.uuidv4("Must be a valid UUID v4 string").meta({
|
|
7
7
|
title: "UUID",
|
|
8
8
|
description: "A universally unique identifier version 4",
|
|
@@ -81,7 +81,7 @@ NonEmptyStringSchema.regex(
|
|
|
81
81
|
description: "URL-friendly identifier with lowercase letters, numbers, and hyphens",
|
|
82
82
|
examples: ["mass-id-123", "recycled-plastic", "organic-waste"]
|
|
83
83
|
});
|
|
84
|
-
var WasteTypeSchema = NonEmptyStringSchema.meta({
|
|
84
|
+
var WasteTypeSchema = NonEmptyStringSchema.max(100).meta({
|
|
85
85
|
title: "Waste Type",
|
|
86
86
|
description: "Category or type of waste material",
|
|
87
87
|
examples: ["Organic", "Plastic", "Metal"]
|
|
@@ -251,65 +251,117 @@ var RecordRelationshipTypeSchema = zod.z.enum([
|
|
|
251
251
|
description: "Type of relationship between different entities in the system",
|
|
252
252
|
examples: ["mass-id", "audit", "collection"]
|
|
253
253
|
});
|
|
254
|
-
var
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
254
|
+
var SchemaInfoSchema = zod.z.strictObject({
|
|
255
|
+
hash: Keccak256HashSchema.meta({
|
|
256
|
+
title: "Schema Hash",
|
|
257
|
+
description: "Keccak256 hash of the JSON Schema this record was validated against"
|
|
258
|
+
}),
|
|
259
|
+
type: RecordSchemaTypeSchema.meta({
|
|
260
|
+
title: "Schema Type",
|
|
261
|
+
description: "Type/category of this schema"
|
|
262
|
+
}),
|
|
263
|
+
version: SemanticVersionSchema.meta({
|
|
264
|
+
title: "Schema Version",
|
|
265
|
+
description: "Version of the schema, using semantic versioning"
|
|
266
|
+
})
|
|
267
|
+
}).meta({
|
|
268
|
+
title: "Schema Information"
|
|
258
269
|
});
|
|
259
|
-
var
|
|
260
|
-
|
|
261
|
-
title: "
|
|
262
|
-
description: "
|
|
270
|
+
var RecordCreatorSchema = zod.z.strictObject({
|
|
271
|
+
name: zod.z.string().meta({
|
|
272
|
+
title: "Creator Name",
|
|
273
|
+
description: "Company or individual name that created this record",
|
|
274
|
+
examples: ["Carrot Foundation"]
|
|
263
275
|
}),
|
|
264
|
-
|
|
265
|
-
title: "
|
|
266
|
-
description: "
|
|
276
|
+
id: UuidSchema.meta({
|
|
277
|
+
title: "Creator ID",
|
|
278
|
+
description: "Unique identifier for the creator"
|
|
279
|
+
})
|
|
280
|
+
}).meta({
|
|
281
|
+
title: "Creator",
|
|
282
|
+
description: "Entity that created this record"
|
|
283
|
+
});
|
|
284
|
+
var RecordRelationshipSchema = zod.z.strictObject({
|
|
285
|
+
target_uri: IpfsUriSchema.meta({
|
|
286
|
+
title: "Target IPFS URI",
|
|
287
|
+
description: "Target IPFS URI of the referenced record"
|
|
267
288
|
}),
|
|
268
|
-
|
|
289
|
+
type: RecordRelationshipTypeSchema.meta({
|
|
290
|
+
title: "Relationship Type",
|
|
291
|
+
description: "Type of relationship to the referenced record"
|
|
292
|
+
}),
|
|
293
|
+
description: zod.z.string().optional().meta({
|
|
294
|
+
title: "Relationship Description",
|
|
295
|
+
description: "Human-readable description of the relationship",
|
|
296
|
+
examples: [
|
|
297
|
+
"This record supersedes the previous version",
|
|
298
|
+
"Related carbon credit batch",
|
|
299
|
+
"Source document for this verification",
|
|
300
|
+
"Child record derived from this parent",
|
|
301
|
+
"Updated version of original record"
|
|
302
|
+
]
|
|
303
|
+
})
|
|
269
304
|
}).meta({
|
|
270
|
-
title: "
|
|
271
|
-
description: "
|
|
305
|
+
title: "Relationship",
|
|
306
|
+
description: "Relationship to another IPFS record"
|
|
272
307
|
});
|
|
273
|
-
var
|
|
274
|
-
|
|
275
|
-
title: "
|
|
276
|
-
description: "
|
|
308
|
+
var RecordEnvironmentSchema = zod.z.strictObject({
|
|
309
|
+
blockchain_network: zod.z.enum(["mainnet", "testnet"]).meta({
|
|
310
|
+
title: "Blockchain Network",
|
|
311
|
+
description: "Blockchain Network Environment"
|
|
277
312
|
}),
|
|
278
|
-
|
|
279
|
-
title: "
|
|
280
|
-
description: "
|
|
281
|
-
examples: ["New York", "S\xE3o Paulo", "London", "Tokyo"]
|
|
313
|
+
deployment: zod.z.enum(["production", "development", "testing"]).meta({
|
|
314
|
+
title: "Deployment Environment",
|
|
315
|
+
description: "System environment where this record was generated"
|
|
282
316
|
}),
|
|
283
|
-
|
|
284
|
-
title: "
|
|
285
|
-
description: "
|
|
286
|
-
|
|
317
|
+
data_set_name: zod.z.enum(["TEST", "PROD"]).meta({
|
|
318
|
+
title: "Data Set Name",
|
|
319
|
+
description: "Name of the data set for this record"
|
|
320
|
+
})
|
|
321
|
+
}).meta({
|
|
322
|
+
title: "Environment",
|
|
323
|
+
description: "Environment information"
|
|
324
|
+
});
|
|
325
|
+
var BaseIpfsSchema = zod.z.strictObject({
|
|
326
|
+
$schema: zod.z.url("Must be a valid URI").meta({
|
|
327
|
+
title: "JSON Schema URI",
|
|
328
|
+
description: "URI of the JSON Schema used to validate this record",
|
|
329
|
+
example: "https://raw.githubusercontent.com/carrot-foundation/schemas/refs/heads/main/schemas/ipfs/shared/base/base.schema.json"
|
|
287
330
|
}),
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
331
|
+
schema: SchemaInfoSchema,
|
|
332
|
+
created_at: IsoTimestampSchema.meta({
|
|
333
|
+
title: "Created At",
|
|
334
|
+
description: "ISO 8601 creation timestamp for this record"
|
|
291
335
|
}),
|
|
292
|
-
|
|
293
|
-
title: "
|
|
294
|
-
description: "
|
|
295
|
-
examples: ["United States", "Canada", "Germany", "Australia"]
|
|
336
|
+
external_id: ExternalIdSchema.meta({
|
|
337
|
+
title: "External ID",
|
|
338
|
+
description: "Off-chain reference ID (UUID from Carrot backend)"
|
|
296
339
|
}),
|
|
297
|
-
|
|
298
|
-
title: "
|
|
299
|
-
description: "
|
|
340
|
+
external_url: ExternalUrlSchema.meta({
|
|
341
|
+
title: "External URL",
|
|
342
|
+
description: "External URL of the content"
|
|
300
343
|
}),
|
|
301
|
-
|
|
302
|
-
title: "
|
|
303
|
-
description: "
|
|
344
|
+
original_content_hash: Sha256HashSchema.meta({
|
|
345
|
+
title: "Original Content Hash",
|
|
346
|
+
description: "SHA-256 hash of the original JSON content including private data before schema validation"
|
|
304
347
|
}),
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
348
|
+
content_hash: Sha256HashSchema.meta({
|
|
349
|
+
title: "Content Hash",
|
|
350
|
+
description: "SHA-256 hash of RFC 8785 canonicalized JSON after schema validation"
|
|
351
|
+
}),
|
|
352
|
+
creator: RecordCreatorSchema.optional(),
|
|
353
|
+
relationships: zod.z.array(RecordRelationshipSchema).optional().meta({
|
|
354
|
+
title: "Relationships",
|
|
355
|
+
description: "References to other IPFS records this record relates to"
|
|
356
|
+
}),
|
|
357
|
+
environment: RecordEnvironmentSchema.optional(),
|
|
358
|
+
data: zod.z.record(zod.z.string(), zod.z.unknown()).optional().meta({
|
|
359
|
+
title: "Custom Data",
|
|
360
|
+
description: "Custom data block that includes the record's data"
|
|
309
361
|
})
|
|
310
362
|
}).meta({
|
|
311
|
-
title: "
|
|
312
|
-
description: "
|
|
363
|
+
title: "Base IPFS Record",
|
|
364
|
+
description: "Base fields for all Carrot IPFS records, providing common structure for any JSON content stored in IPFS"
|
|
313
365
|
});
|
|
314
366
|
function uniqueArrayItems(schema, errorMessage = "Array items must be unique") {
|
|
315
367
|
return zod.z.array(schema).refine((items) => new Set(items).size === items.length, {
|
|
@@ -328,604 +380,764 @@ function uniqueBy(schema, selector, errorMessage = "Items must be unique") {
|
|
|
328
380
|
);
|
|
329
381
|
}
|
|
330
382
|
|
|
331
|
-
// src/shared/
|
|
332
|
-
var
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
383
|
+
// src/shared/nft.schema.ts
|
|
384
|
+
var NftSchemaTypeSchema = RecordSchemaTypeSchema.extract([
|
|
385
|
+
"MassID",
|
|
386
|
+
"RecycledID",
|
|
387
|
+
"GasID",
|
|
388
|
+
"PurchaseID"
|
|
389
|
+
]).meta({
|
|
390
|
+
title: "NFT Schema Type",
|
|
391
|
+
description: "Type of schema for NFT records"
|
|
392
|
+
});
|
|
393
|
+
var BlockchainReferenceSchema = zod.z.strictObject({
|
|
394
|
+
smart_contract_address: EthereumAddressSchema.meta({
|
|
395
|
+
title: "Smart Contract Address"
|
|
336
396
|
}),
|
|
337
|
-
|
|
338
|
-
title: "
|
|
339
|
-
description: "
|
|
397
|
+
chain_id: BlockchainChainIdSchema.meta({
|
|
398
|
+
title: "Chain ID",
|
|
399
|
+
description: "Blockchain chain ID"
|
|
340
400
|
}),
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
"
|
|
344
|
-
)
|
|
345
|
-
|
|
346
|
-
|
|
401
|
+
network_name: zod.z.string().min(5).max(100).meta({
|
|
402
|
+
title: "Network Name",
|
|
403
|
+
description: "Name of the blockchain network"
|
|
404
|
+
}),
|
|
405
|
+
token_id: TokenIdSchema.meta({
|
|
406
|
+
title: "Token ID",
|
|
407
|
+
description: "NFT token ID"
|
|
347
408
|
})
|
|
348
409
|
}).meta({
|
|
349
|
-
title: "
|
|
350
|
-
description: "
|
|
410
|
+
title: "Blockchain Information",
|
|
411
|
+
description: "Blockchain-specific information for the NFT"
|
|
351
412
|
});
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
title: "Classification Code",
|
|
357
|
-
description: "Local waste classification code",
|
|
358
|
-
examples: ["20 01 01", "D001", "EWC-150101", "IBAMA-A001"]
|
|
413
|
+
var ExternalLinkSchema = zod.z.strictObject({
|
|
414
|
+
label: zod.z.string().min(1).max(50).meta({
|
|
415
|
+
title: "Link Label",
|
|
416
|
+
description: "Display name for the external link"
|
|
359
417
|
}),
|
|
360
|
-
|
|
361
|
-
title: "
|
|
362
|
-
description: "
|
|
363
|
-
examples: [
|
|
364
|
-
"Paper and cardboard packaging",
|
|
365
|
-
"Ignitable waste",
|
|
366
|
-
"Paper and cardboard packaging waste",
|
|
367
|
-
"Municipal solid waste - organic fraction"
|
|
368
|
-
]
|
|
418
|
+
url: zod.z.url("Must be a valid URI").meta({
|
|
419
|
+
title: "Link URL",
|
|
420
|
+
description: "Direct URI to the linked resource"
|
|
369
421
|
}),
|
|
370
|
-
|
|
371
|
-
title: "
|
|
372
|
-
description: "
|
|
373
|
-
examples: ["IBAMA"]
|
|
422
|
+
description: zod.z.string().min(10).max(100).optional().meta({
|
|
423
|
+
title: "Link Description",
|
|
424
|
+
description: "Optional context about what the link provides"
|
|
374
425
|
})
|
|
375
426
|
}).meta({
|
|
376
|
-
title: "
|
|
377
|
-
description: "
|
|
378
|
-
});
|
|
379
|
-
var MassIDMeasurementUnitSchema = zod.z.enum(["kg", "ton"]).meta({
|
|
380
|
-
title: "Measurement Unit",
|
|
381
|
-
description: "Unit of measurement for the waste quantity",
|
|
382
|
-
examples: ["kg", "ton"]
|
|
383
|
-
});
|
|
384
|
-
var ContaminationLevelSchema = zod.z.enum(["None", "Low", "Medium", "High"]).meta({
|
|
385
|
-
title: "Contamination Level",
|
|
386
|
-
description: "Level of contamination in the waste batch",
|
|
387
|
-
examples: ["Low", "Medium", "None"]
|
|
427
|
+
title: "External Link",
|
|
428
|
+
description: "External link with label and description"
|
|
388
429
|
});
|
|
389
|
-
var
|
|
390
|
-
|
|
391
|
-
title: "
|
|
392
|
-
description: "
|
|
430
|
+
var NftAttributeSchema = zod.z.strictObject({
|
|
431
|
+
trait_type: zod.z.string().max(50).meta({
|
|
432
|
+
title: "Trait Type",
|
|
433
|
+
description: "Name of the trait or attribute"
|
|
393
434
|
}),
|
|
394
|
-
|
|
395
|
-
title: "
|
|
396
|
-
description: "
|
|
435
|
+
value: zod.z.union([zod.z.string(), zod.z.number(), zod.z.boolean()]).meta({
|
|
436
|
+
title: "Trait Value",
|
|
437
|
+
description: "Value of the trait - can be string, number, or boolean"
|
|
397
438
|
}),
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
title: "Net Weight",
|
|
402
|
-
description: "Net weight of the waste batch in the specified measurement unit"
|
|
439
|
+
display_type: zod.z.enum(["number", "date", "boost_number", "boost_percentage"]).optional().meta({
|
|
440
|
+
title: "Display Type",
|
|
441
|
+
description: "How the trait should be displayed in marketplace UIs"
|
|
403
442
|
}),
|
|
404
|
-
|
|
443
|
+
max_value: NonNegativeFloatSchema.optional().meta({
|
|
444
|
+
title: "Max Value",
|
|
445
|
+
description: "Maximum possible value for numeric traits"
|
|
446
|
+
})
|
|
405
447
|
}).meta({
|
|
406
|
-
title: "
|
|
407
|
-
description: "
|
|
408
|
-
});
|
|
409
|
-
var EventAttributeFormatSchema = zod.z.enum(["KILOGRAM", "DATE", "CURRENCY", "PERCENTAGE", "COORDINATE"]).meta({
|
|
410
|
-
title: "Event Attribute Format",
|
|
411
|
-
description: "Data format hint for proper display",
|
|
412
|
-
examples: ["KILOGRAM", "DATE", "PERCENTAGE"]
|
|
448
|
+
title: "NFT Attribute",
|
|
449
|
+
description: "NFT attribute or trait with type and value"
|
|
413
450
|
});
|
|
414
|
-
var
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
"humidity",
|
|
421
|
-
"contamination_percentage",
|
|
422
|
-
"quality_grade",
|
|
423
|
-
"batch_number",
|
|
424
|
-
"operator_id",
|
|
425
|
-
"equipment_used",
|
|
426
|
-
"processing_cost"
|
|
427
|
-
]
|
|
451
|
+
var NftIpfsSchema = BaseIpfsSchema.safeExtend({
|
|
452
|
+
schema: BaseIpfsSchema.shape.schema.safeExtend({
|
|
453
|
+
type: NftSchemaTypeSchema.meta({
|
|
454
|
+
title: "NFT Schema Type",
|
|
455
|
+
description: "Type/category of this NFT schema"
|
|
456
|
+
})
|
|
428
457
|
}),
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
458
|
+
blockchain: BlockchainReferenceSchema,
|
|
459
|
+
name: zod.z.string().min(1).max(100).meta({
|
|
460
|
+
title: "NFT Name",
|
|
461
|
+
description: "Full display name for this NFT, including extra context",
|
|
432
462
|
examples: [
|
|
433
|
-
|
|
434
|
-
"
|
|
435
|
-
|
|
436
|
-
"BATCH-2024-001",
|
|
437
|
-
12.75,
|
|
438
|
-
"Shredder-X200",
|
|
439
|
-
false,
|
|
440
|
-
"OP-456"
|
|
463
|
+
"MassID #123 \u2022 Organic \u2022 3.0t",
|
|
464
|
+
"RecycledID #456 \u2022 Plastic \u2022 2.5t",
|
|
465
|
+
"GasID #789 \u2022 Methane \u2022 1000 m\xB3"
|
|
441
466
|
]
|
|
442
467
|
}),
|
|
443
|
-
|
|
444
|
-
title: "
|
|
445
|
-
description: "
|
|
468
|
+
short_name: zod.z.string().min(1).max(50).meta({
|
|
469
|
+
title: "Short Name",
|
|
470
|
+
description: "Compact name for UI summaries, tables, or tooltips",
|
|
471
|
+
examples: ["MassID #123", "RecycledID #456", "GasID #789"]
|
|
446
472
|
}),
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
description: "Additional attribute specific to an event"
|
|
451
|
-
});
|
|
452
|
-
var EventAttachmentSchema = zod.z.strictObject({
|
|
453
|
-
type: NonEmptyStringSchema.max(50).meta({
|
|
454
|
-
title: "Attachment Type",
|
|
455
|
-
description: "Type of supporting attachment",
|
|
473
|
+
description: zod.z.string().min(10).max(500).meta({
|
|
474
|
+
title: "Description",
|
|
475
|
+
description: "Human-readable summary of the NFT's role and context. Ideally, maximum 300 characters.",
|
|
456
476
|
examples: [
|
|
457
|
-
"
|
|
458
|
-
"
|
|
459
|
-
"Certificate of Final Destination",
|
|
460
|
-
"Quality Assessment Report",
|
|
461
|
-
"Transport Manifest",
|
|
462
|
-
"Processing Receipt",
|
|
463
|
-
"Environmental Permit",
|
|
464
|
-
"Invoice"
|
|
477
|
+
"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.",
|
|
478
|
+
"This RecycledID represents 2.5 metric tons of recycled plastic bottles processed by Green Solutions Ltd."
|
|
465
479
|
]
|
|
466
480
|
}),
|
|
467
|
-
|
|
468
|
-
title: "
|
|
469
|
-
description: "
|
|
481
|
+
image: IpfsUriSchema.meta({
|
|
482
|
+
title: "Image URI",
|
|
483
|
+
description: "IPFS URI pointing to the preview image"
|
|
484
|
+
}),
|
|
485
|
+
background_color: HexColorSchema.optional().meta({
|
|
486
|
+
title: "Background Color",
|
|
487
|
+
description: "Hex color code for marketplace background display"
|
|
488
|
+
}),
|
|
489
|
+
animation_url: IpfsUriSchema.optional().meta({
|
|
490
|
+
title: "Animation URL",
|
|
491
|
+
description: "IPFS URI pointing to an animated or interactive media file",
|
|
470
492
|
examples: [
|
|
471
|
-
"
|
|
472
|
-
"
|
|
473
|
-
"INV-2024-QTR1-789",
|
|
474
|
-
"PERMIT-EPA-2024-001",
|
|
475
|
-
"MANIFEST-DOT-567890"
|
|
493
|
+
"ipfs://QmAnimation123/mass-id-animation.mp4",
|
|
494
|
+
"ipfs://QmInteractive456/recycled-visualization.webm"
|
|
476
495
|
]
|
|
477
496
|
}),
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
497
|
+
external_links: uniqueBy(
|
|
498
|
+
ExternalLinkSchema,
|
|
499
|
+
(link) => link.url,
|
|
500
|
+
"External link URLs must be unique"
|
|
501
|
+
).max(10).optional().meta({
|
|
502
|
+
title: "External Links",
|
|
503
|
+
description: "Optional list of public resource links with labels",
|
|
481
504
|
examples: [
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
505
|
+
[
|
|
506
|
+
{
|
|
507
|
+
label: "Carrot Explorer",
|
|
508
|
+
url: "https://explore.carrot.eco/document/ad44dd3f-f176-4b98-bf78-5ee6e77d0530",
|
|
509
|
+
description: "Complete chain of custody and audit trail"
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
label: "Carrot White Paper",
|
|
513
|
+
url: "https://carrot.eco/whitepaper.pdf",
|
|
514
|
+
description: "Carrot Foundation technical and impact white paper"
|
|
515
|
+
}
|
|
516
|
+
]
|
|
487
517
|
]
|
|
488
518
|
}),
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
title: "
|
|
495
|
-
description: "
|
|
519
|
+
attributes: uniqueBy(
|
|
520
|
+
NftAttributeSchema,
|
|
521
|
+
(attr) => attr.trait_type,
|
|
522
|
+
"Attribute trait_type values must be unique"
|
|
523
|
+
).meta({
|
|
524
|
+
title: "NFT Attributes",
|
|
525
|
+
description: "List of visual traits and filterable attributes compatible with NFT marketplaces",
|
|
496
526
|
examples: [
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
527
|
+
[
|
|
528
|
+
{
|
|
529
|
+
trait_type: "Waste Type",
|
|
530
|
+
value: "Organic"
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
trait_type: "Waste Subtype",
|
|
534
|
+
value: "Food, Food Waste and Beverages"
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
trait_type: "Weight (kg)",
|
|
538
|
+
value: 3e3,
|
|
539
|
+
display_type: "number"
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
trait_type: "Origin Country",
|
|
543
|
+
value: "Brazil"
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
trait_type: "Pick-up Date",
|
|
547
|
+
value: "2024-12-05",
|
|
548
|
+
display_type: "date"
|
|
549
|
+
}
|
|
550
|
+
]
|
|
503
551
|
]
|
|
504
552
|
})
|
|
505
553
|
}).meta({
|
|
506
|
-
title: "
|
|
507
|
-
description: "
|
|
554
|
+
title: "NFT IPFS Record",
|
|
555
|
+
description: "NFT-specific fields for Carrot IPFS records"
|
|
508
556
|
});
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
title: "
|
|
537
|
-
description: "
|
|
538
|
-
|
|
539
|
-
location_id_hash: Sha256HashSchema.meta({
|
|
540
|
-
title: "Location ID Hash",
|
|
541
|
-
description: "Reference to location in the locations array"
|
|
542
|
-
}),
|
|
543
|
-
weight: NonNegativeFloatSchema.optional().meta({
|
|
544
|
-
title: "Event Weight",
|
|
545
|
-
description: "Mass weight after this event"
|
|
546
|
-
}),
|
|
547
|
-
attributes: zod.z.array(EventAttributeSchema).optional().meta({
|
|
548
|
-
title: "Event Attributes",
|
|
549
|
-
description: "Additional attributes specific to this event"
|
|
550
|
-
}),
|
|
551
|
-
attachments: zod.z.array(EventAttachmentSchema).optional().meta({
|
|
552
|
-
title: "Event Attachments",
|
|
553
|
-
description: "Associated attachments for this event"
|
|
557
|
+
|
|
558
|
+
// src/mass-id/mass-id.attributes.ts
|
|
559
|
+
var MassIDAttributeWasteTypeSchema = NftAttributeSchema.extend({
|
|
560
|
+
trait_type: zod.z.literal("Waste Type"),
|
|
561
|
+
value: WasteTypeSchema
|
|
562
|
+
}).meta({
|
|
563
|
+
title: "Waste Type Attribute",
|
|
564
|
+
description: "Waste type attribute"
|
|
565
|
+
});
|
|
566
|
+
var MassIDAttributeWasteSubtypeSchema = NftAttributeSchema.extend({
|
|
567
|
+
trait_type: zod.z.literal("Waste Subtype"),
|
|
568
|
+
value: WasteSubtypeSchema
|
|
569
|
+
}).meta({
|
|
570
|
+
title: "Waste Subtype Attribute",
|
|
571
|
+
description: "Waste subtype attribute"
|
|
572
|
+
});
|
|
573
|
+
var MassIDAttributeWeightSchema = NftAttributeSchema.extend({
|
|
574
|
+
trait_type: zod.z.literal("Weight (kg)"),
|
|
575
|
+
value: WeightKgSchema,
|
|
576
|
+
display_type: zod.z.literal("number")
|
|
577
|
+
}).meta({
|
|
578
|
+
title: "Weight Attribute",
|
|
579
|
+
description: "Weight attribute with numeric display"
|
|
580
|
+
});
|
|
581
|
+
var MassIDAttributeOriginCountrySchema = NftAttributeSchema.extend({
|
|
582
|
+
trait_type: zod.z.literal("Origin Country"),
|
|
583
|
+
value: NonEmptyStringSchema.max(100).meta({
|
|
584
|
+
title: "Origin Country Value",
|
|
585
|
+
description: "Country where the waste was generated",
|
|
586
|
+
examples: ["Brazil", "United States", "Germany", "Japan"]
|
|
554
587
|
})
|
|
555
588
|
}).meta({
|
|
556
|
-
title: "
|
|
557
|
-
description: "
|
|
589
|
+
title: "Origin Country Attribute",
|
|
590
|
+
description: "Origin country attribute"
|
|
558
591
|
});
|
|
559
|
-
var
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
title: "Total Duration (hours)",
|
|
566
|
-
description: "Total time from first to last event in hours"
|
|
592
|
+
var MassIDAttributeOriginMunicipalitySchema = NftAttributeSchema.extend({
|
|
593
|
+
trait_type: zod.z.literal("Origin Municipality"),
|
|
594
|
+
value: NonEmptyStringSchema.max(100).meta({
|
|
595
|
+
title: "Origin Municipality Value",
|
|
596
|
+
description: "Municipality where the waste was generated",
|
|
597
|
+
examples: ["S\xE3o Paulo", "New York", "Berlin", "Tokyo"]
|
|
567
598
|
})
|
|
568
599
|
}).meta({
|
|
569
|
-
title: "
|
|
570
|
-
description: "
|
|
600
|
+
title: "Origin Municipality Attribute",
|
|
601
|
+
description: "Origin municipality attribute"
|
|
571
602
|
});
|
|
572
|
-
var
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
title: "To Location ID Hash",
|
|
579
|
-
description: "Reference hash of the location where the waste ended movement"
|
|
580
|
-
}),
|
|
581
|
-
first_reported_timestamp: IsoTimestampSchema.meta({
|
|
582
|
-
title: "First Reported Timestamp",
|
|
583
|
-
description: "ISO 8601 timestamp when the waste was first reported/collected at the origin location"
|
|
584
|
-
}),
|
|
585
|
-
last_reported_timestamp: IsoTimestampSchema.meta({
|
|
586
|
-
title: "Last Reported Timestamp",
|
|
587
|
-
description: "ISO 8601 timestamp when the waste was last reported/processed at the destination location"
|
|
603
|
+
var MassIDAttributeOriginDivisionSchema = NftAttributeSchema.extend({
|
|
604
|
+
trait_type: zod.z.literal("Origin Administrative Division"),
|
|
605
|
+
value: NonEmptyStringSchema.max(100).meta({
|
|
606
|
+
title: "Origin Division Value",
|
|
607
|
+
description: "Administrative division (state/province) where the waste was generated",
|
|
608
|
+
examples: ["S\xE3o Paulo", "California", "Bavaria"]
|
|
588
609
|
})
|
|
589
|
-
}).
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
return first <= last;
|
|
593
|
-
}, "first_reported_timestamp must be before or equal to last_reported_timestamp").meta({
|
|
594
|
-
title: "Geographic Data",
|
|
595
|
-
description: "Simplified geographic information tracking waste movement from origin to destination with temporal bounds"
|
|
596
|
-
});
|
|
597
|
-
var MassIDDataSchema = zod.z.strictObject({
|
|
598
|
-
waste_properties: MassIDWastePropertiesSchema,
|
|
599
|
-
locations: uniqueBy(
|
|
600
|
-
LocationSchema,
|
|
601
|
-
(loc) => loc.id_hash,
|
|
602
|
-
"Location ID hashes must be unique"
|
|
603
|
-
).min(1).meta({
|
|
604
|
-
title: "Locations",
|
|
605
|
-
description: "All locations referenced in this MassID, indexed by ID"
|
|
606
|
-
}),
|
|
607
|
-
participants: uniqueBy(
|
|
608
|
-
ParticipantSchema,
|
|
609
|
-
(p) => p.id_hash,
|
|
610
|
-
"Participant ID hashes must be unique"
|
|
611
|
-
).min(1).meta({
|
|
612
|
-
title: "Participants",
|
|
613
|
-
description: "All participants referenced in this MassID, indexed by ID"
|
|
614
|
-
}),
|
|
615
|
-
chain_of_custody: MassIDChainOfCustodySchema,
|
|
616
|
-
geographic_data: MassIDGeographicDataSchema
|
|
617
|
-
}).refine((data) => {
|
|
618
|
-
const participantIdSet = new Set(
|
|
619
|
-
data.participants.map((participant) => participant.id_hash)
|
|
620
|
-
);
|
|
621
|
-
const eventParticipantIds = data.chain_of_custody.events.map(
|
|
622
|
-
(event) => event.participant_id_hash
|
|
623
|
-
);
|
|
624
|
-
const allEventParticipantsExist = eventParticipantIds.every(
|
|
625
|
-
(participantId) => participantIdSet.has(participantId)
|
|
626
|
-
);
|
|
627
|
-
return allEventParticipantsExist;
|
|
628
|
-
}, "All participant ID hashes in chain of custody events must exist in participants array").refine((data) => {
|
|
629
|
-
const locationIdSet = new Set(
|
|
630
|
-
data.locations.map((location) => location.id_hash)
|
|
631
|
-
);
|
|
632
|
-
const eventLocationIds = data.chain_of_custody.events.map(
|
|
633
|
-
(event) => event.location_id_hash
|
|
634
|
-
);
|
|
635
|
-
const allEventLocationsExist = eventLocationIds.every(
|
|
636
|
-
(locationId) => locationIdSet.has(locationId)
|
|
637
|
-
);
|
|
638
|
-
return allEventLocationsExist;
|
|
639
|
-
}, "All location ID hashes in chain of custody events must exist in locations array").meta({
|
|
640
|
-
title: "MassID Data",
|
|
641
|
-
description: "MassID data containing waste tracking and chain of custody information"
|
|
610
|
+
}).meta({
|
|
611
|
+
title: "Origin Administrative Division Attribute",
|
|
612
|
+
description: "Origin administrative division attribute"
|
|
642
613
|
});
|
|
643
|
-
var
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
title: "Schema Type",
|
|
650
|
-
description: "Type/category of this schema"
|
|
651
|
-
}),
|
|
652
|
-
version: SemanticVersionSchema.meta({
|
|
653
|
-
title: "Schema Version",
|
|
654
|
-
description: "Version of the schema, using semantic versioning"
|
|
614
|
+
var MassIDAttributeVehicleTypeSchema = NftAttributeSchema.extend({
|
|
615
|
+
trait_type: zod.z.literal("Vehicle Type"),
|
|
616
|
+
value: NonEmptyStringSchema.max(100).meta({
|
|
617
|
+
title: "Vehicle Type Value",
|
|
618
|
+
description: "Type of vehicle used for waste transportation",
|
|
619
|
+
examples: ["Garbage Truck", "Box Truck", "Flatbed Truck", "Roll-off Truck"]
|
|
655
620
|
})
|
|
656
621
|
}).meta({
|
|
657
|
-
title: "
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
622
|
+
title: "Vehicle Type Attribute",
|
|
623
|
+
description: "Vehicle type attribute"
|
|
624
|
+
});
|
|
625
|
+
var MassIDAttributeRecyclingMethodSchema = NftAttributeSchema.extend({
|
|
626
|
+
trait_type: zod.z.literal("Recycling Method"),
|
|
627
|
+
value: NonEmptyStringSchema.max(100).meta({
|
|
628
|
+
title: "Recycling Method Value",
|
|
629
|
+
description: "Method used for recycling or processing the waste",
|
|
630
|
+
examples: [
|
|
631
|
+
"Composting",
|
|
632
|
+
"Mechanical Recycling",
|
|
633
|
+
"Incineration with Energy Recovery"
|
|
634
|
+
]
|
|
668
635
|
})
|
|
669
636
|
}).meta({
|
|
670
|
-
title: "
|
|
671
|
-
description: "
|
|
672
|
-
});
|
|
673
|
-
var
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
description:
|
|
683
|
-
|
|
684
|
-
|
|
637
|
+
title: "Recycling Method Attribute",
|
|
638
|
+
description: "Recycling method attribute"
|
|
639
|
+
});
|
|
640
|
+
var MassIDAttributeProcessingTimeSchema = NftAttributeSchema.extend({
|
|
641
|
+
trait_type: zod.z.literal("Processing Time (hours)"),
|
|
642
|
+
value: HoursSchema,
|
|
643
|
+
trait_description: NonEmptyStringSchema.max(200).optional().meta({
|
|
644
|
+
title: "Processing Time Description",
|
|
645
|
+
description: "Custom description for the processing time"
|
|
646
|
+
})
|
|
647
|
+
}).meta({
|
|
648
|
+
title: "Processing Time Attribute",
|
|
649
|
+
description: "Processing time attribute with optional trait description"
|
|
650
|
+
});
|
|
651
|
+
var MassIDAttributeLocalWasteClassificationIdSchema = NftAttributeSchema.extend({
|
|
652
|
+
trait_type: zod.z.literal("Local Waste Classification ID"),
|
|
653
|
+
value: NonEmptyStringSchema.max(100).meta({
|
|
654
|
+
title: "Local Waste Classification ID Value",
|
|
655
|
+
description: "Local or regional waste classification identifier",
|
|
656
|
+
examples: ["04 02 20", "IBAMA-A001", "EWC-150101"]
|
|
657
|
+
})
|
|
658
|
+
}).meta({
|
|
659
|
+
title: "Local Waste Classification ID Attribute",
|
|
660
|
+
description: "Local waste classification ID attribute"
|
|
661
|
+
});
|
|
662
|
+
var MassIDAttributeRecyclingManifestCodeSchema = NftAttributeSchema.extend({
|
|
663
|
+
trait_type: zod.z.literal("Recycling Manifest Code"),
|
|
664
|
+
value: NonEmptyStringSchema.max(100).meta({
|
|
665
|
+
title: "Recycling Manifest Code Value",
|
|
666
|
+
description: "Concatenated recycling manifest code (Document Type + Document Number)",
|
|
667
|
+
examples: ["CDF-2353", "RC-12345", "REC-MANIFEST-789"]
|
|
668
|
+
})
|
|
669
|
+
}).meta({
|
|
670
|
+
title: "Recycling Manifest Code Attribute",
|
|
671
|
+
description: "Recycling manifest code attribute (optional)"
|
|
672
|
+
});
|
|
673
|
+
var MassIDAttributeTransportManifestCodeSchema = NftAttributeSchema.extend({
|
|
674
|
+
trait_type: zod.z.literal("Transport Manifest Code"),
|
|
675
|
+
value: NonEmptyStringSchema.max(100).meta({
|
|
676
|
+
title: "Transport Manifest Code Value",
|
|
677
|
+
description: "Concatenated transport manifest code (Document Type + Document Number)",
|
|
678
|
+
examples: ["MTR-4126", "TRN-67890", "TRANS-MANIFEST-456"]
|
|
679
|
+
})
|
|
680
|
+
}).meta({
|
|
681
|
+
title: "Transport Manifest Code Attribute",
|
|
682
|
+
description: "Transport manifest code attribute (optional)"
|
|
683
|
+
});
|
|
684
|
+
var MassIDAttributeWeighingCaptureMethodSchema = NftAttributeSchema.extend({
|
|
685
|
+
trait_type: zod.z.literal("Weighing Capture Method"),
|
|
686
|
+
value: NonEmptyStringSchema.max(100).meta({
|
|
687
|
+
title: "Weighing Capture Method Value",
|
|
688
|
+
description: "Method used to capture weight data",
|
|
689
|
+
examples: ["Digital", "Manual", "Automated", "Electronic Scale"]
|
|
690
|
+
})
|
|
691
|
+
}).meta({
|
|
692
|
+
title: "Weighing Capture Method Attribute",
|
|
693
|
+
description: "Weighing capture method attribute (optional)"
|
|
694
|
+
});
|
|
695
|
+
var MassIDAttributeScaleTypeSchema = NftAttributeSchema.extend({
|
|
696
|
+
trait_type: zod.z.literal("Scale Type"),
|
|
697
|
+
value: NonEmptyStringSchema.max(100).meta({
|
|
698
|
+
title: "Scale Type Value",
|
|
699
|
+
description: "Type of scale used for weighing",
|
|
685
700
|
examples: [
|
|
686
|
-
"
|
|
687
|
-
"
|
|
688
|
-
"
|
|
689
|
-
"
|
|
690
|
-
"Updated version of original record"
|
|
701
|
+
"Weighbridge (Truck Scale)",
|
|
702
|
+
"Floor Scale",
|
|
703
|
+
"Bench Scale",
|
|
704
|
+
"Crane Scale"
|
|
691
705
|
]
|
|
692
706
|
})
|
|
693
707
|
}).meta({
|
|
694
|
-
title: "
|
|
695
|
-
description: "
|
|
708
|
+
title: "Scale Type Attribute",
|
|
709
|
+
description: "Scale type attribute (optional)"
|
|
710
|
+
});
|
|
711
|
+
var MassIDAttributeContainerTypeSchema = NftAttributeSchema.extend({
|
|
712
|
+
trait_type: zod.z.literal("Container Type"),
|
|
713
|
+
value: NonEmptyStringSchema.max(100).meta({
|
|
714
|
+
title: "Container Type Value",
|
|
715
|
+
description: "Type of container used for waste storage or transport",
|
|
716
|
+
examples: ["Truck", "Dumpster", "Roll-off Container", "Compactor", "Bin"]
|
|
717
|
+
})
|
|
718
|
+
}).meta({
|
|
719
|
+
title: "Container Type Attribute",
|
|
720
|
+
description: "Container type attribute (optional)"
|
|
696
721
|
});
|
|
697
|
-
var
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
722
|
+
var MassIDAttributePickUpDateSchema = NftAttributeSchema.extend({
|
|
723
|
+
trait_type: zod.z.literal("Pick-up Date"),
|
|
724
|
+
value: UnixTimestampSchema.meta({
|
|
725
|
+
title: "Pick-up Date Value",
|
|
726
|
+
description: "Unix timestamp in milliseconds when the waste was picked up from the source",
|
|
727
|
+
examples: [17105184e5, 17040672e5, 17152704e5]
|
|
701
728
|
}),
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
729
|
+
display_type: zod.z.literal("date")
|
|
730
|
+
}).meta({
|
|
731
|
+
title: "Pick-up Date Attribute",
|
|
732
|
+
description: "Pick-up date attribute with Unix timestamp"
|
|
733
|
+
});
|
|
734
|
+
var MassIDAttributeRecyclingDateSchema = NftAttributeSchema.extend({
|
|
735
|
+
trait_type: zod.z.literal("Recycling Date"),
|
|
736
|
+
value: UnixTimestampSchema.meta({
|
|
737
|
+
title: "Recycling Date Value",
|
|
738
|
+
description: "Unix timestamp in milliseconds when the waste was recycled/processed",
|
|
739
|
+
examples: [17106048e5, 17041536e5, 17153568e5]
|
|
705
740
|
}),
|
|
706
|
-
|
|
707
|
-
title: "Data Set Name",
|
|
708
|
-
description: "Name of the data set for this record"
|
|
709
|
-
})
|
|
741
|
+
display_type: zod.z.literal("date")
|
|
710
742
|
}).meta({
|
|
711
|
-
title: "
|
|
712
|
-
description: "
|
|
743
|
+
title: "Recycling Date Attribute",
|
|
744
|
+
description: "Recycling date attribute with Unix timestamp"
|
|
745
|
+
});
|
|
746
|
+
var MassIDAttributesSchema = uniqueBy(
|
|
747
|
+
zod.z.union([
|
|
748
|
+
MassIDAttributeWasteTypeSchema,
|
|
749
|
+
MassIDAttributeWasteSubtypeSchema,
|
|
750
|
+
MassIDAttributeWeightSchema,
|
|
751
|
+
MassIDAttributeOriginCountrySchema,
|
|
752
|
+
MassIDAttributeOriginMunicipalitySchema,
|
|
753
|
+
MassIDAttributeOriginDivisionSchema,
|
|
754
|
+
MassIDAttributeVehicleTypeSchema,
|
|
755
|
+
MassIDAttributeRecyclingMethodSchema,
|
|
756
|
+
MassIDAttributeProcessingTimeSchema,
|
|
757
|
+
MassIDAttributeLocalWasteClassificationIdSchema,
|
|
758
|
+
MassIDAttributeRecyclingManifestCodeSchema,
|
|
759
|
+
MassIDAttributeTransportManifestCodeSchema,
|
|
760
|
+
MassIDAttributeWeighingCaptureMethodSchema,
|
|
761
|
+
MassIDAttributeScaleTypeSchema,
|
|
762
|
+
MassIDAttributeContainerTypeSchema,
|
|
763
|
+
MassIDAttributePickUpDateSchema,
|
|
764
|
+
MassIDAttributeRecyclingDateSchema
|
|
765
|
+
]),
|
|
766
|
+
(attr) => attr.trait_type
|
|
767
|
+
).min(12).max(17).meta({
|
|
768
|
+
title: "MassID Attributes",
|
|
769
|
+
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."
|
|
713
770
|
});
|
|
714
|
-
var
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
771
|
+
var PrecisionLevelSchema = zod.z.enum(["exact", "neighborhood", "city", "region", "country"]).meta({
|
|
772
|
+
title: "Precision Level",
|
|
773
|
+
description: "Level of coordinate precision",
|
|
774
|
+
examples: ["city", "exact", "neighborhood"]
|
|
775
|
+
});
|
|
776
|
+
var CoordinatesSchema = zod.z.strictObject({
|
|
777
|
+
latitude: LatitudeSchema.meta({
|
|
778
|
+
title: "Latitude",
|
|
779
|
+
description: "GPS latitude coordinate"
|
|
719
780
|
}),
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
description: "ISO 8601 creation timestamp for this record"
|
|
781
|
+
longitude: LongitudeSchema.meta({
|
|
782
|
+
title: "Longitude",
|
|
783
|
+
description: "GPS longitude coordinate"
|
|
724
784
|
}),
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
785
|
+
precision_level: PrecisionLevelSchema
|
|
786
|
+
}).meta({
|
|
787
|
+
title: "Coordinates",
|
|
788
|
+
description: "GPS coordinates of the location"
|
|
789
|
+
});
|
|
790
|
+
var LocationSchema = zod.z.strictObject({
|
|
791
|
+
id_hash: Sha256HashSchema.meta({
|
|
792
|
+
title: "Location ID Hash",
|
|
793
|
+
description: "Anonymized identifier for the location"
|
|
728
794
|
}),
|
|
729
|
-
|
|
730
|
-
title: "
|
|
731
|
-
description: "
|
|
795
|
+
municipality: NonEmptyStringSchema.max(50).meta({
|
|
796
|
+
title: "Municipality",
|
|
797
|
+
description: "Municipality or city name",
|
|
798
|
+
examples: ["New York", "S\xE3o Paulo", "London", "Tokyo"]
|
|
732
799
|
}),
|
|
733
|
-
|
|
734
|
-
title: "
|
|
735
|
-
description: "
|
|
800
|
+
administrative_division: NonEmptyStringSchema.max(50).meta({
|
|
801
|
+
title: "Administrative Division",
|
|
802
|
+
description: "State, province, or administrative region",
|
|
803
|
+
examples: ["California", "Ontario", "Bavaria", "Queensland"]
|
|
736
804
|
}),
|
|
737
|
-
|
|
738
|
-
title: "
|
|
739
|
-
description: "
|
|
805
|
+
administrative_division_code: IsoAdministrativeDivisionCodeSchema.optional().meta({
|
|
806
|
+
title: "Administrative Division Code",
|
|
807
|
+
description: "ISO 3166-2 administrative division code"
|
|
740
808
|
}),
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
809
|
+
country: NonEmptyStringSchema.max(50).meta({
|
|
810
|
+
title: "Country",
|
|
811
|
+
description: "Full country name in English",
|
|
812
|
+
examples: ["United States", "Canada", "Germany", "Australia"]
|
|
745
813
|
}),
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
814
|
+
country_code: IsoCountryCodeSchema.meta({
|
|
815
|
+
title: "Country Code",
|
|
816
|
+
description: "ISO 3166-1 alpha-2 country code"
|
|
817
|
+
}),
|
|
818
|
+
responsible_participant_id_hash: Sha256HashSchema.meta({
|
|
819
|
+
title: "Responsible Participant ID Hash",
|
|
820
|
+
description: "Anonymized ID of the participant responsible for this location"
|
|
821
|
+
}),
|
|
822
|
+
coordinates: CoordinatesSchema,
|
|
823
|
+
facility_type: FacilityTypeSchema.optional().meta({
|
|
824
|
+
title: "Facility Type",
|
|
825
|
+
description: "Type of facility at this location"
|
|
750
826
|
})
|
|
751
827
|
}).meta({
|
|
752
|
-
title: "
|
|
753
|
-
description: "
|
|
828
|
+
title: "Location",
|
|
829
|
+
description: "Geographic location with address and coordinate information"
|
|
830
|
+
});
|
|
831
|
+
var ParticipantSchema = zod.z.strictObject({
|
|
832
|
+
id_hash: Sha256HashSchema.meta({
|
|
833
|
+
title: "Participant ID Hash",
|
|
834
|
+
description: "Anonymized identifier for the participant"
|
|
835
|
+
}),
|
|
836
|
+
name: ParticipantNameSchema.meta({
|
|
837
|
+
title: "Participant Name",
|
|
838
|
+
description: "Name of the participant"
|
|
839
|
+
}),
|
|
840
|
+
roles: uniqueArrayItems(
|
|
841
|
+
ParticipantRoleSchema,
|
|
842
|
+
"Participant roles must be unique"
|
|
843
|
+
).min(1).meta({
|
|
844
|
+
title: "Participant Roles",
|
|
845
|
+
description: "Roles of the participant in the waste management supply chain"
|
|
846
|
+
})
|
|
847
|
+
}).meta({
|
|
848
|
+
title: "Participant",
|
|
849
|
+
description: "A participant in the waste management supply chain"
|
|
754
850
|
});
|
|
755
851
|
|
|
756
|
-
// src/
|
|
757
|
-
var
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
852
|
+
// src/mass-id/mass-id.data.schema.ts
|
|
853
|
+
var MassIDLocalClassificationSchema = zod.z.strictObject({
|
|
854
|
+
code: NonEmptyStringSchema.max(20).meta({
|
|
855
|
+
title: "Classification Code",
|
|
856
|
+
description: "Local waste classification code",
|
|
857
|
+
examples: ["20 01 01", "D001", "EWC-150101", "IBAMA-A001"]
|
|
858
|
+
}),
|
|
859
|
+
description: NonEmptyStringSchema.max(200).meta({
|
|
860
|
+
title: "Classification Description",
|
|
861
|
+
description: "Local waste classification description",
|
|
862
|
+
examples: [
|
|
863
|
+
"Paper and cardboard packaging",
|
|
864
|
+
"Ignitable waste",
|
|
865
|
+
"Paper and cardboard packaging waste",
|
|
866
|
+
"Municipal solid waste - organic fraction"
|
|
867
|
+
]
|
|
868
|
+
}),
|
|
869
|
+
system: zod.z.enum(["IBAMA"]).meta({
|
|
870
|
+
title: "Classification System",
|
|
871
|
+
description: "Classification system name - currently supports IBAMA (Instituto Brasileiro do Meio Ambiente e dos Recursos Naturais Renov\xE1veis)",
|
|
872
|
+
examples: ["IBAMA"]
|
|
873
|
+
})
|
|
874
|
+
}).meta({
|
|
875
|
+
title: "Local Classification",
|
|
876
|
+
description: "Local or regional waste classification codes and descriptions"
|
|
765
877
|
});
|
|
766
|
-
var
|
|
767
|
-
|
|
768
|
-
|
|
878
|
+
var MassIDMeasurementUnitSchema = zod.z.enum(["kg", "ton"]).meta({
|
|
879
|
+
title: "Measurement Unit",
|
|
880
|
+
description: "Unit of measurement for the waste quantity",
|
|
881
|
+
examples: ["kg", "ton"]
|
|
882
|
+
});
|
|
883
|
+
var ContaminationLevelSchema = zod.z.enum(["None", "Low", "Medium", "High"]).meta({
|
|
884
|
+
title: "Contamination Level",
|
|
885
|
+
description: "Level of contamination in the waste batch",
|
|
886
|
+
examples: ["Low", "Medium", "None"]
|
|
887
|
+
});
|
|
888
|
+
var MassIDWastePropertiesSchema = zod.z.strictObject({
|
|
889
|
+
type: WasteTypeSchema.meta({
|
|
890
|
+
title: "Waste Type",
|
|
891
|
+
description: "Waste material category"
|
|
769
892
|
}),
|
|
770
|
-
|
|
771
|
-
title: "
|
|
772
|
-
description: "
|
|
893
|
+
subtype: WasteSubtypeSchema.meta({
|
|
894
|
+
title: "Waste Subtype",
|
|
895
|
+
description: "Specific subcategory of waste material"
|
|
773
896
|
}),
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
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"
|
|
777
902
|
}),
|
|
778
|
-
|
|
779
|
-
title: "Token ID",
|
|
780
|
-
description: "NFT token ID"
|
|
781
|
-
})
|
|
903
|
+
contamination_level: ContaminationLevelSchema.optional()
|
|
782
904
|
}).meta({
|
|
783
|
-
title: "
|
|
784
|
-
description: "
|
|
905
|
+
title: "Waste Properties",
|
|
906
|
+
description: "Standardized waste material properties and regulatory information"
|
|
785
907
|
});
|
|
786
|
-
var
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
908
|
+
var EventAttributeFormatSchema = zod.z.enum(["KILOGRAM", "DATE", "CURRENCY", "PERCENTAGE", "COORDINATE"]).meta({
|
|
909
|
+
title: "Event Attribute Format",
|
|
910
|
+
description: "Data format hint for proper display",
|
|
911
|
+
examples: ["KILOGRAM", "DATE", "PERCENTAGE"]
|
|
912
|
+
});
|
|
913
|
+
var EventAttributeSchema = zod.z.strictObject({
|
|
914
|
+
name: NonEmptyStringSchema.max(100).meta({
|
|
915
|
+
title: "Attribute Name",
|
|
916
|
+
description: "Event attribute name",
|
|
917
|
+
examples: [
|
|
918
|
+
"temperature",
|
|
919
|
+
"humidity",
|
|
920
|
+
"contamination_percentage",
|
|
921
|
+
"quality_grade",
|
|
922
|
+
"batch_number",
|
|
923
|
+
"operator_id",
|
|
924
|
+
"equipment_used",
|
|
925
|
+
"processing_cost"
|
|
926
|
+
]
|
|
790
927
|
}),
|
|
791
|
-
|
|
792
|
-
title: "
|
|
793
|
-
description: "
|
|
928
|
+
value: zod.z.union([zod.z.string(), zod.z.number(), zod.z.boolean()]).optional().meta({
|
|
929
|
+
title: "Attribute Value",
|
|
930
|
+
description: "Event attribute value",
|
|
931
|
+
examples: [
|
|
932
|
+
25.5,
|
|
933
|
+
"Grade A",
|
|
934
|
+
true,
|
|
935
|
+
"BATCH-2024-001",
|
|
936
|
+
12.75,
|
|
937
|
+
"Shredder-X200",
|
|
938
|
+
false,
|
|
939
|
+
"OP-456"
|
|
940
|
+
]
|
|
794
941
|
}),
|
|
795
|
-
|
|
796
|
-
title: "
|
|
797
|
-
description: "
|
|
798
|
-
})
|
|
942
|
+
preserved_sensitivity: zod.z.boolean().optional().meta({
|
|
943
|
+
title: "Preserved Sensitivity",
|
|
944
|
+
description: "Indicates if the attribute contains sensitive information that was preserved"
|
|
945
|
+
}),
|
|
946
|
+
format: EventAttributeFormatSchema.optional()
|
|
799
947
|
}).meta({
|
|
800
|
-
title: "
|
|
801
|
-
description: "
|
|
948
|
+
title: "Event Attribute",
|
|
949
|
+
description: "Additional attribute specific to an event"
|
|
802
950
|
});
|
|
803
|
-
var
|
|
804
|
-
|
|
805
|
-
title: "
|
|
806
|
-
description: "
|
|
951
|
+
var EventAttachmentSchema = zod.z.strictObject({
|
|
952
|
+
type: NonEmptyStringSchema.max(50).meta({
|
|
953
|
+
title: "Attachment Type",
|
|
954
|
+
description: "Type of supporting attachment",
|
|
955
|
+
examples: [
|
|
956
|
+
"Waste Transfer Note",
|
|
957
|
+
"Certificate of Disposal",
|
|
958
|
+
"Certificate of Final Destination",
|
|
959
|
+
"Quality Assessment Report",
|
|
960
|
+
"Transport Manifest",
|
|
961
|
+
"Processing Receipt",
|
|
962
|
+
"Environmental Permit",
|
|
963
|
+
"Invoice"
|
|
964
|
+
]
|
|
807
965
|
}),
|
|
808
|
-
|
|
809
|
-
title: "
|
|
810
|
-
description: "
|
|
966
|
+
document_number: NonEmptyStringSchema.max(50).optional().meta({
|
|
967
|
+
title: "Document Number",
|
|
968
|
+
description: "Official document number if applicable",
|
|
969
|
+
examples: [
|
|
970
|
+
"WTN-2024-001234",
|
|
971
|
+
"CD-ENV-456789",
|
|
972
|
+
"INV-2024-QTR1-789",
|
|
973
|
+
"PERMIT-EPA-2024-001",
|
|
974
|
+
"MANIFEST-DOT-567890"
|
|
975
|
+
]
|
|
811
976
|
}),
|
|
812
|
-
|
|
813
|
-
title: "
|
|
814
|
-
description: "
|
|
977
|
+
reference: NonEmptyStringSchema.meta({
|
|
978
|
+
title: "Attachment Reference",
|
|
979
|
+
description: "Reference to attachment (IPFS hash, file name, or external URL)",
|
|
980
|
+
examples: [
|
|
981
|
+
"QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o",
|
|
982
|
+
"waste_transfer_note_2024_001.pdf",
|
|
983
|
+
"https://docs.example.com/certificates/disposal_cert_456.pdf",
|
|
984
|
+
"bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
|
|
985
|
+
"processing_receipt_20240315.jpg"
|
|
986
|
+
]
|
|
815
987
|
}),
|
|
816
|
-
|
|
817
|
-
title: "
|
|
818
|
-
description: "
|
|
988
|
+
issue_date: IsoDateSchema.optional().meta({
|
|
989
|
+
title: "Issue Date",
|
|
990
|
+
description: "Date the attachment was issued"
|
|
991
|
+
}),
|
|
992
|
+
issuer: NonEmptyStringSchema.max(100).optional().meta({
|
|
993
|
+
title: "Attachment Issuer",
|
|
994
|
+
description: "Entity that issued the attachment",
|
|
995
|
+
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"
|
|
1002
|
+
]
|
|
819
1003
|
})
|
|
820
1004
|
}).meta({
|
|
821
|
-
title: "
|
|
822
|
-
description: "
|
|
1005
|
+
title: "Event Attachment",
|
|
1006
|
+
description: "Supporting event attachment"
|
|
823
1007
|
});
|
|
824
|
-
var
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
description: "Type/category of this NFT schema"
|
|
829
|
-
})
|
|
1008
|
+
var MassIDChainOfCustodyEventSchema = zod.z.strictObject({
|
|
1009
|
+
event_id: UuidSchema.meta({
|
|
1010
|
+
title: "Event ID",
|
|
1011
|
+
description: "Unique event identifier"
|
|
830
1012
|
}),
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
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
|
+
}),
|
|
1018
|
+
description: NonEmptyStringSchema.max(200).optional().meta({
|
|
1019
|
+
title: "Event Description",
|
|
1020
|
+
description: "Detailed description of what happened during this event",
|
|
835
1021
|
examples: [
|
|
836
|
-
"
|
|
837
|
-
"
|
|
838
|
-
"
|
|
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"
|
|
839
1028
|
]
|
|
840
1029
|
}),
|
|
841
|
-
|
|
842
|
-
title: "
|
|
843
|
-
description: "
|
|
844
|
-
examples: ["MassID #123", "RecycledID #456", "GasID #789"]
|
|
1030
|
+
timestamp: IsoTimestampSchema.meta({
|
|
1031
|
+
title: "Event Timestamp",
|
|
1032
|
+
description: "ISO 8601 timestamp when the event occurred"
|
|
845
1033
|
}),
|
|
846
|
-
|
|
847
|
-
title: "
|
|
848
|
-
description: "
|
|
849
|
-
examples: [
|
|
850
|
-
"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.",
|
|
851
|
-
"This RecycledID represents 2.5 metric tons of recycled plastic bottles processed by Green Solutions Ltd."
|
|
852
|
-
]
|
|
1034
|
+
participant_id_hash: Sha256HashSchema.meta({
|
|
1035
|
+
title: "Participant ID Hash",
|
|
1036
|
+
description: "Reference to participant in the participants array"
|
|
853
1037
|
}),
|
|
854
|
-
|
|
855
|
-
title: "
|
|
856
|
-
description: "
|
|
1038
|
+
location_id_hash: Sha256HashSchema.meta({
|
|
1039
|
+
title: "Location ID Hash",
|
|
1040
|
+
description: "Reference to location in the locations array"
|
|
857
1041
|
}),
|
|
858
|
-
|
|
859
|
-
title: "
|
|
860
|
-
description: "
|
|
1042
|
+
weight: NonNegativeFloatSchema.optional().meta({
|
|
1043
|
+
title: "Event Weight",
|
|
1044
|
+
description: "Mass weight after this event"
|
|
861
1045
|
}),
|
|
862
|
-
|
|
863
|
-
title: "
|
|
864
|
-
description: "
|
|
865
|
-
examples: [
|
|
866
|
-
"ipfs://QmAnimation123/mass-id-animation.mp4",
|
|
867
|
-
"ipfs://QmInteractive456/recycled-visualization.webm"
|
|
868
|
-
]
|
|
1046
|
+
attributes: zod.z.array(EventAttributeSchema).optional().meta({
|
|
1047
|
+
title: "Event Attributes",
|
|
1048
|
+
description: "Additional attributes specific to this event"
|
|
869
1049
|
}),
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
description: "Complete chain of custody and audit trail"
|
|
883
|
-
},
|
|
884
|
-
{
|
|
885
|
-
label: "Carrot White Paper",
|
|
886
|
-
url: "https://carrot.eco/whitepaper.pdf",
|
|
887
|
-
description: "Carrot Foundation technical and impact white paper"
|
|
888
|
-
}
|
|
889
|
-
]
|
|
890
|
-
]
|
|
1050
|
+
attachments: zod.z.array(EventAttachmentSchema).optional().meta({
|
|
1051
|
+
title: "Event Attachments",
|
|
1052
|
+
description: "Associated attachments for this event"
|
|
1053
|
+
})
|
|
1054
|
+
}).meta({
|
|
1055
|
+
title: "Chain of Custody Event",
|
|
1056
|
+
description: "Chain of custody event"
|
|
1057
|
+
});
|
|
1058
|
+
var MassIDChainOfCustodySchema = zod.z.strictObject({
|
|
1059
|
+
events: zod.z.array(MassIDChainOfCustodyEventSchema).min(1).meta({
|
|
1060
|
+
title: "Custody Events",
|
|
1061
|
+
description: "Chronological sequence of custody transfer and processing events"
|
|
891
1062
|
}),
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
"Attribute trait_type values must be unique"
|
|
896
|
-
).meta({
|
|
897
|
-
title: "NFT Attributes",
|
|
898
|
-
description: "List of visual traits and filterable attributes compatible with NFT marketplaces",
|
|
899
|
-
examples: [
|
|
900
|
-
[
|
|
901
|
-
{
|
|
902
|
-
trait_type: "Waste Type",
|
|
903
|
-
value: "Organic"
|
|
904
|
-
},
|
|
905
|
-
{
|
|
906
|
-
trait_type: "Waste Subtype",
|
|
907
|
-
value: "Food, Food Waste and Beverages"
|
|
908
|
-
},
|
|
909
|
-
{
|
|
910
|
-
trait_type: "Weight (kg)",
|
|
911
|
-
value: 3e3,
|
|
912
|
-
display_type: "number"
|
|
913
|
-
},
|
|
914
|
-
{
|
|
915
|
-
trait_type: "Origin Country",
|
|
916
|
-
value: "Brazil"
|
|
917
|
-
},
|
|
918
|
-
{
|
|
919
|
-
trait_type: "Pick-up Date",
|
|
920
|
-
value: "2024-12-05",
|
|
921
|
-
display_type: "date"
|
|
922
|
-
}
|
|
923
|
-
]
|
|
924
|
-
]
|
|
1063
|
+
total_duration_hours: HoursSchema.meta({
|
|
1064
|
+
title: "Total Duration (hours)",
|
|
1065
|
+
description: "Total time from first to last event in hours"
|
|
925
1066
|
})
|
|
926
1067
|
}).meta({
|
|
927
|
-
title: "
|
|
928
|
-
description: "
|
|
1068
|
+
title: "Chain of Custody",
|
|
1069
|
+
description: "Complete chain of custody tracking from waste generation to final processing"
|
|
1070
|
+
});
|
|
1071
|
+
var MassIDGeographicDataSchema = zod.z.strictObject({
|
|
1072
|
+
from_location_id_hash: Sha256HashSchema.meta({
|
|
1073
|
+
title: "From Location ID Hash",
|
|
1074
|
+
description: "Reference hash of the location where the waste started movement"
|
|
1075
|
+
}),
|
|
1076
|
+
to_location_id_hash: Sha256HashSchema.meta({
|
|
1077
|
+
title: "To Location ID Hash",
|
|
1078
|
+
description: "Reference hash of the location where the waste ended movement"
|
|
1079
|
+
}),
|
|
1080
|
+
first_reported_timestamp: IsoTimestampSchema.meta({
|
|
1081
|
+
title: "First Reported Timestamp",
|
|
1082
|
+
description: "ISO 8601 timestamp when the waste was first reported/collected at the origin location"
|
|
1083
|
+
}),
|
|
1084
|
+
last_reported_timestamp: IsoTimestampSchema.meta({
|
|
1085
|
+
title: "Last Reported Timestamp",
|
|
1086
|
+
description: "ISO 8601 timestamp when the waste was last reported/processed at the destination location"
|
|
1087
|
+
})
|
|
1088
|
+
}).refine((data) => {
|
|
1089
|
+
const first = new Date(data.first_reported_timestamp);
|
|
1090
|
+
const last = new Date(data.last_reported_timestamp);
|
|
1091
|
+
return first <= last;
|
|
1092
|
+
}, "first_reported_timestamp must be before or equal to last_reported_timestamp").meta({
|
|
1093
|
+
title: "Geographic Data",
|
|
1094
|
+
description: "Simplified geographic information tracking waste movement from origin to destination with temporal bounds"
|
|
1095
|
+
});
|
|
1096
|
+
var MassIDDataSchema = zod.z.strictObject({
|
|
1097
|
+
waste_properties: MassIDWastePropertiesSchema,
|
|
1098
|
+
locations: uniqueBy(
|
|
1099
|
+
LocationSchema,
|
|
1100
|
+
(loc) => loc.id_hash,
|
|
1101
|
+
"Location ID hashes must be unique"
|
|
1102
|
+
).min(1).meta({
|
|
1103
|
+
title: "Locations",
|
|
1104
|
+
description: "All locations referenced in this MassID, indexed by ID"
|
|
1105
|
+
}),
|
|
1106
|
+
participants: uniqueBy(
|
|
1107
|
+
ParticipantSchema,
|
|
1108
|
+
(p) => p.id_hash,
|
|
1109
|
+
"Participant ID hashes must be unique"
|
|
1110
|
+
).min(1).meta({
|
|
1111
|
+
title: "Participants",
|
|
1112
|
+
description: "All participants referenced in this MassID, indexed by ID"
|
|
1113
|
+
}),
|
|
1114
|
+
chain_of_custody: MassIDChainOfCustodySchema,
|
|
1115
|
+
geographic_data: MassIDGeographicDataSchema
|
|
1116
|
+
}).refine((data) => {
|
|
1117
|
+
const participantIdSet = new Set(
|
|
1118
|
+
data.participants.map((participant) => participant.id_hash)
|
|
1119
|
+
);
|
|
1120
|
+
const eventParticipantIds = data.chain_of_custody.events.map(
|
|
1121
|
+
(event) => event.participant_id_hash
|
|
1122
|
+
);
|
|
1123
|
+
const allEventParticipantsExist = eventParticipantIds.every(
|
|
1124
|
+
(participantId) => participantIdSet.has(participantId)
|
|
1125
|
+
);
|
|
1126
|
+
return allEventParticipantsExist;
|
|
1127
|
+
}, "All participant ID hashes in chain of custody events must exist in participants array").refine((data) => {
|
|
1128
|
+
const locationIdSet = new Set(
|
|
1129
|
+
data.locations.map((location) => location.id_hash)
|
|
1130
|
+
);
|
|
1131
|
+
const eventLocationIds = data.chain_of_custody.events.map(
|
|
1132
|
+
(event) => event.location_id_hash
|
|
1133
|
+
);
|
|
1134
|
+
const allEventLocationsExist = eventLocationIds.every(
|
|
1135
|
+
(locationId) => locationIdSet.has(locationId)
|
|
1136
|
+
);
|
|
1137
|
+
return allEventLocationsExist;
|
|
1138
|
+
}, "All location ID hashes in chain of custody events must exist in locations array").meta({
|
|
1139
|
+
title: "MassID Data",
|
|
1140
|
+
description: "MassID data containing waste tracking and chain of custody information"
|
|
929
1141
|
});
|
|
930
1142
|
|
|
931
1143
|
// src/shared/schema-version.ts
|
|
@@ -941,115 +1153,6 @@ function getSchemaVersionOrDefault() {
|
|
|
941
1153
|
}
|
|
942
1154
|
|
|
943
1155
|
// src/mass-id/mass-id.schema.ts
|
|
944
|
-
var AttributeWasteTypeSchema = zod.z.strictObject({
|
|
945
|
-
trait_type: zod.z.literal("Waste Type"),
|
|
946
|
-
value: WasteTypeSchema
|
|
947
|
-
}).meta({
|
|
948
|
-
title: "Waste Type Attribute",
|
|
949
|
-
description: "Waste type attribute"
|
|
950
|
-
});
|
|
951
|
-
var AttributeWasteSubtypeSchema = zod.z.strictObject({
|
|
952
|
-
trait_type: zod.z.literal("Waste Subtype"),
|
|
953
|
-
value: WasteSubtypeSchema
|
|
954
|
-
}).meta({
|
|
955
|
-
title: "Waste Subtype Attribute",
|
|
956
|
-
description: "Waste subtype attribute"
|
|
957
|
-
});
|
|
958
|
-
var AttributeWeightSchema = zod.z.strictObject({
|
|
959
|
-
trait_type: zod.z.literal("Weight (kg)"),
|
|
960
|
-
value: WeightKgSchema,
|
|
961
|
-
display_type: zod.z.literal("number")
|
|
962
|
-
}).meta({
|
|
963
|
-
title: "Weight Attribute",
|
|
964
|
-
description: "Weight attribute with numeric display"
|
|
965
|
-
});
|
|
966
|
-
var AttributeOriginCountrySchema = zod.z.strictObject({
|
|
967
|
-
trait_type: zod.z.literal("Origin Country"),
|
|
968
|
-
value: zod.z.string().max(100).meta({
|
|
969
|
-
title: "Origin Country Value",
|
|
970
|
-
description: "Country where the waste was generated"
|
|
971
|
-
})
|
|
972
|
-
}).meta({
|
|
973
|
-
title: "Origin Country Attribute",
|
|
974
|
-
description: "Origin country attribute"
|
|
975
|
-
});
|
|
976
|
-
var AttributeOriginMunicipalitySchema = zod.z.strictObject({
|
|
977
|
-
trait_type: zod.z.literal("Origin Municipality"),
|
|
978
|
-
value: zod.z.string().max(100).meta({
|
|
979
|
-
title: "Origin Municipality Value",
|
|
980
|
-
description: "Municipality where the waste was generated"
|
|
981
|
-
})
|
|
982
|
-
}).meta({
|
|
983
|
-
title: "Origin Municipality Attribute",
|
|
984
|
-
description: "Origin municipality attribute"
|
|
985
|
-
});
|
|
986
|
-
var AttributeOriginDivisionSchema = zod.z.strictObject({
|
|
987
|
-
trait_type: zod.z.literal("Origin Administrative Division"),
|
|
988
|
-
value: zod.z.string().max(100).meta({
|
|
989
|
-
title: "Origin Division Value",
|
|
990
|
-
description: "Administrative division (state/province) where the waste was generated"
|
|
991
|
-
})
|
|
992
|
-
}).meta({
|
|
993
|
-
title: "Origin Administrative Division Attribute",
|
|
994
|
-
description: "Origin administrative division attribute"
|
|
995
|
-
});
|
|
996
|
-
var AttributeRecyclerSchema = zod.z.strictObject({
|
|
997
|
-
trait_type: zod.z.literal("Recycler"),
|
|
998
|
-
value: zod.z.string().max(100).meta({
|
|
999
|
-
title: "Recycler Value",
|
|
1000
|
-
description: "Organization that processed the waste"
|
|
1001
|
-
})
|
|
1002
|
-
}).meta({
|
|
1003
|
-
title: "Recycler Attribute",
|
|
1004
|
-
description: "Recycler attribute"
|
|
1005
|
-
});
|
|
1006
|
-
var AttributeIntegratorSchema = zod.z.strictObject({
|
|
1007
|
-
trait_type: zod.z.literal("Integrator"),
|
|
1008
|
-
value: zod.z.string().max(100).meta({
|
|
1009
|
-
title: "Integrator Value",
|
|
1010
|
-
description: "Organization that integrated the waste into the Carrot network"
|
|
1011
|
-
})
|
|
1012
|
-
}).meta({
|
|
1013
|
-
title: "Integrator Attribute",
|
|
1014
|
-
description: "Integrator attribute"
|
|
1015
|
-
});
|
|
1016
|
-
var AttributePickUpDateSchema = zod.z.strictObject({
|
|
1017
|
-
trait_type: zod.z.literal("Pick-up Date"),
|
|
1018
|
-
value: UnixTimestampSchema.meta({
|
|
1019
|
-
title: "Pick-up Date Value",
|
|
1020
|
-
description: "Unix timestamp in milliseconds when the waste was picked up from the source"
|
|
1021
|
-
}),
|
|
1022
|
-
display_type: zod.z.literal("date")
|
|
1023
|
-
}).meta({
|
|
1024
|
-
title: "Pick-up Date Attribute",
|
|
1025
|
-
description: "Pick-up date attribute with Unix timestamp"
|
|
1026
|
-
});
|
|
1027
|
-
var AttributeRecyclingDateSchema = zod.z.strictObject({
|
|
1028
|
-
trait_type: zod.z.literal("Recycling Date"),
|
|
1029
|
-
value: zod.z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Must be a valid date in YYYY-MM-DD format").meta({
|
|
1030
|
-
title: "Recycling Date Value",
|
|
1031
|
-
description: "Date when the waste was recycled/processed"
|
|
1032
|
-
}),
|
|
1033
|
-
display_type: zod.z.literal("date")
|
|
1034
|
-
}).meta({
|
|
1035
|
-
title: "Recycling Date Attribute",
|
|
1036
|
-
description: "Recycling date attribute"
|
|
1037
|
-
});
|
|
1038
|
-
var MassIDAttributesSchema = zod.z.tuple([
|
|
1039
|
-
AttributeWasteTypeSchema,
|
|
1040
|
-
AttributeWasteSubtypeSchema,
|
|
1041
|
-
AttributeWeightSchema,
|
|
1042
|
-
AttributeOriginCountrySchema,
|
|
1043
|
-
AttributeOriginMunicipalitySchema,
|
|
1044
|
-
AttributeOriginDivisionSchema,
|
|
1045
|
-
AttributeRecyclerSchema,
|
|
1046
|
-
AttributeIntegratorSchema,
|
|
1047
|
-
AttributePickUpDateSchema,
|
|
1048
|
-
AttributeRecyclingDateSchema
|
|
1049
|
-
]).meta({
|
|
1050
|
-
title: "MassID Attributes",
|
|
1051
|
-
description: "Fixed set of MassID NFT attributes in required order"
|
|
1052
|
-
});
|
|
1053
1156
|
var MassIDIpfsSchemaMeta = {
|
|
1054
1157
|
title: "MassID NFT IPFS Record",
|
|
1055
1158
|
description: "Complete MassID NFT IPFS record including fixed attributes and detailed waste tracking data",
|
|
@@ -1063,16 +1166,11 @@ var MassIDIpfsSchema = NftIpfsSchema.safeExtend({
|
|
|
1063
1166
|
description: "MassID NFT schema type"
|
|
1064
1167
|
})
|
|
1065
1168
|
}),
|
|
1066
|
-
attributes: MassIDAttributesSchema
|
|
1067
|
-
|
|
1068
|
-
description: "Fixed set of MassID NFT attributes enforcing order and type for each trait"
|
|
1069
|
-
}).check(zod.z.minLength(10), zod.z.maxLength(10)),
|
|
1070
|
-
data: MassIDDataSchema.meta({
|
|
1071
|
-
title: "MassID Data",
|
|
1072
|
-
description: "MassID-specific data containing waste tracking and chain of custody information"
|
|
1073
|
-
})
|
|
1169
|
+
attributes: MassIDAttributesSchema,
|
|
1170
|
+
data: MassIDDataSchema
|
|
1074
1171
|
}).meta(MassIDIpfsSchemaMeta);
|
|
1075
1172
|
|
|
1173
|
+
exports.MassIDAttributesSchema = MassIDAttributesSchema;
|
|
1076
1174
|
exports.MassIDDataSchema = MassIDDataSchema;
|
|
1077
1175
|
exports.MassIDIpfsSchema = MassIDIpfsSchema;
|
|
1078
1176
|
exports.MassIDIpfsSchemaMeta = MassIDIpfsSchemaMeta;
|