@carrot-foundation/schemas 0.1.40 → 0.1.42
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 +626 -706
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +526 -845
- package/dist/index.d.ts +526 -845
- package/dist/index.js +625 -703
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schemas/ipfs/collection/collection.example.json +4 -8
- package/schemas/ipfs/collection/collection.schema.json +19 -131
- package/schemas/ipfs/credit/credit.example.json +4 -8
- package/schemas/ipfs/credit/credit.schema.json +19 -131
- package/schemas/ipfs/credit-purchase-receipt/credit-purchase-receipt.example.json +15 -19
- package/schemas/ipfs/credit-purchase-receipt/credit-purchase-receipt.schema.json +163 -263
- package/schemas/ipfs/credit-retirement-receipt/credit-retirement-receipt.example.json +15 -19
- package/schemas/ipfs/credit-retirement-receipt/credit-retirement-receipt.schema.json +162 -259
- package/schemas/ipfs/gas-id/gas-id.example.json +7 -11
- package/schemas/ipfs/gas-id/gas-id.schema.json +137 -772
- package/schemas/ipfs/mass-id/mass-id.example.json +4 -4
- package/schemas/ipfs/mass-id/mass-id.schema.json +88 -237
- package/schemas/ipfs/mass-id-audit/mass-id-audit.example.json +6 -10
- package/schemas/ipfs/mass-id-audit/mass-id-audit.schema.json +37 -158
- package/schemas/ipfs/methodology/methodology.example.json +4 -29
- package/schemas/ipfs/methodology/methodology.schema.json +23 -147
- package/schemas/ipfs/recycled-id/recycled-id.example.json +8 -12
- package/schemas/ipfs/recycled-id/recycled-id.schema.json +136 -720
package/dist/index.cjs
CHANGED
|
@@ -5,69 +5,6 @@ require('fs');
|
|
|
5
5
|
require('path');
|
|
6
6
|
|
|
7
7
|
// src/mass-id/mass-id.attributes.ts
|
|
8
|
-
var UuidSchema = zod.z.uuidv4("Must be a valid UUID v4 string").meta({
|
|
9
|
-
title: "UUID",
|
|
10
|
-
description: "A universally unique identifier version 4",
|
|
11
|
-
examples: [
|
|
12
|
-
"ad44dd3f-f176-4b98-bf78-5ee6e77d0530",
|
|
13
|
-
"6f520d88-864d-432d-bf9f-5c3166c4818f",
|
|
14
|
-
"f77afa89-1c58-40fd-9bf5-8a86703a8af4"
|
|
15
|
-
]
|
|
16
|
-
});
|
|
17
|
-
var EthereumAddressSchema = zod.z.string().regex(
|
|
18
|
-
/^0x[a-f0-9]{40}$/,
|
|
19
|
-
"Must be a valid Ethereum address in lowercase hexadecimal format"
|
|
20
|
-
).meta({
|
|
21
|
-
title: "Ethereum Address",
|
|
22
|
-
description: "A valid Ethereum address in hexadecimal format",
|
|
23
|
-
examples: [
|
|
24
|
-
"0x1234567890abcdef1234567890abcdef12345678",
|
|
25
|
-
"0xabcdef1234567890abcdef1234567890abcdef12"
|
|
26
|
-
]
|
|
27
|
-
});
|
|
28
|
-
var IsoTimestampSchema = zod.z.iso.datetime().meta({
|
|
29
|
-
title: "ISO Timestamp",
|
|
30
|
-
description: "ISO 8601 formatted timestamp with timezone information",
|
|
31
|
-
examples: ["2024-12-05T11:02:47.000Z", "2025-02-22T10:35:12.000Z"]
|
|
32
|
-
});
|
|
33
|
-
var IsoDateSchema = zod.z.iso.date("Must be a valid ISO 8601 date (YYYY-MM-DD)").meta({
|
|
34
|
-
title: "ISO Date",
|
|
35
|
-
description: "ISO 8601 formatted date in YYYY-MM-DD format",
|
|
36
|
-
examples: ["2024-12-05", "2025-02-22", "2024-02-10"]
|
|
37
|
-
});
|
|
38
|
-
var UnixTimestampSchema = zod.z.number().int().positive().meta({
|
|
39
|
-
title: "Unix Timestamp",
|
|
40
|
-
description: "Unix timestamp in milliseconds since epoch (January 1, 1970 00:00:00 UTC)",
|
|
41
|
-
examples: [17040672e5, 17356896e5, 1762371245149]
|
|
42
|
-
});
|
|
43
|
-
var IsoCountryCodeSchema = zod.z.string().regex(/^[A-Z]{2}$/, "Must be a valid ISO 3166-1 alpha-2 country code").meta({
|
|
44
|
-
title: "ISO Country Code",
|
|
45
|
-
description: "Two-letter country code following ISO 3166-1 alpha-2 standard",
|
|
46
|
-
examples: ["BR", "US", "DE"]
|
|
47
|
-
});
|
|
48
|
-
var IsoAdministrativeDivisionCodeSchema = zod.z.string().regex(
|
|
49
|
-
/^[A-Z]{2}-[A-Z0-9]{1,3}$/,
|
|
50
|
-
"Must be a valid ISO 3166-2 administrative division code"
|
|
51
|
-
).meta({
|
|
52
|
-
title: "ISO Administrative Division Code",
|
|
53
|
-
description: "Administrative division code following ISO 3166-2 standard",
|
|
54
|
-
examples: ["BR-AP", "BR-ES", "US-CA"]
|
|
55
|
-
});
|
|
56
|
-
var LatitudeSchema = zod.z.number().min(-90).max(90).multipleOf(1e-3).meta({
|
|
57
|
-
title: "Latitude",
|
|
58
|
-
description: "Geographic latitude coordinate in decimal degrees with maximum 3 decimal places precision (~100m-1km accuracy for city-level, non-PII compliance)",
|
|
59
|
-
examples: [-0.02, -20.38, 40.713]
|
|
60
|
-
});
|
|
61
|
-
var LongitudeSchema = zod.z.number().min(-180).max(180).multipleOf(1e-3).meta({
|
|
62
|
-
title: "Longitude",
|
|
63
|
-
description: "Geographic longitude coordinate in decimal degrees with maximum 3 decimal places precision (~100m-1km accuracy for city-level, non-PII compliance)",
|
|
64
|
-
examples: [-51.06, -40.34, -74.006]
|
|
65
|
-
});
|
|
66
|
-
var WeightKgSchema = zod.z.number().min(0).meta({
|
|
67
|
-
title: "Weight (kg)",
|
|
68
|
-
description: "Weight measurement in kilograms",
|
|
69
|
-
examples: [3e3, 1500, 500]
|
|
70
|
-
});
|
|
71
8
|
var NonEmptyStringSchema = zod.z.string().min(1, "Cannot be empty").meta({
|
|
72
9
|
title: "Non-Empty String",
|
|
73
10
|
description: "A string that contains at least one character",
|
|
@@ -98,14 +35,6 @@ var MethodologyNameSchema = NonEmptyStringSchema.max(100).meta({
|
|
|
98
35
|
description: "Name of the methodology used for certification",
|
|
99
36
|
examples: ["BOLD Recycling", "BOLD Carbon (CH\u2084)"]
|
|
100
37
|
});
|
|
101
|
-
var StringifiedTokenIdSchema = NonEmptyStringSchema.regex(
|
|
102
|
-
/^#\d+$/,
|
|
103
|
-
"Must match pattern #<token_id>"
|
|
104
|
-
).meta({
|
|
105
|
-
title: "Token ID",
|
|
106
|
-
description: "Token ID represented as #<token_id>",
|
|
107
|
-
example: "#123"
|
|
108
|
-
});
|
|
109
38
|
var SlugSchema = NonEmptyStringSchema.regex(
|
|
110
39
|
/^[a-z0-9-]+$/,
|
|
111
40
|
"Must contain only lowercase letters, numbers, and hyphens"
|
|
@@ -119,16 +48,6 @@ var CollectionSlugSchema = SlugSchema.meta({
|
|
|
119
48
|
description: "URL-friendly identifier for a collection",
|
|
120
49
|
examples: ["bold-cold-start-carazinho", "bold-brazil"]
|
|
121
50
|
});
|
|
122
|
-
var WasteTypeSchema = NonEmptyStringSchema.max(100).meta({
|
|
123
|
-
title: "Waste Type",
|
|
124
|
-
description: "Category or type of waste material",
|
|
125
|
-
examples: ["Organic", "Plastic", "Metal"]
|
|
126
|
-
});
|
|
127
|
-
var WasteSubtypeSchema = NonEmptyStringSchema.max(100).meta({
|
|
128
|
-
title: "Waste Subtype",
|
|
129
|
-
description: "Specific subcategory of waste within a waste type",
|
|
130
|
-
examples: ["Food, Food Waste and Beverages", "PET Bottles", "Aluminum Cans"]
|
|
131
|
-
});
|
|
132
51
|
var ParticipantRoleSchema = NonEmptyStringSchema.max(100).meta({
|
|
133
52
|
title: "Participant Role",
|
|
134
53
|
description: "Role that a participant plays in the waste management supply chain",
|
|
@@ -139,29 +58,40 @@ var ParticipantNameSchema = NonEmptyStringSchema.max(100).meta({
|
|
|
139
58
|
description: "Name of a participant in the waste management system",
|
|
140
59
|
examples: ["Enlatados Produ\xE7\xE3o", "Eco Reciclagem", "Green Tech Corp"]
|
|
141
60
|
});
|
|
142
|
-
var
|
|
143
|
-
title: "
|
|
144
|
-
description: "
|
|
145
|
-
examples: [
|
|
61
|
+
var WasteTypeSchema = NonEmptyStringSchema.max(100).meta({
|
|
62
|
+
title: "Waste Type",
|
|
63
|
+
description: "Category or type of waste material",
|
|
64
|
+
examples: ["Organic", "Plastic", "Metal"]
|
|
146
65
|
});
|
|
147
|
-
var
|
|
148
|
-
title: "
|
|
149
|
-
description: "
|
|
150
|
-
examples: ["
|
|
66
|
+
var WasteSubtypeSchema = NonEmptyStringSchema.max(100).meta({
|
|
67
|
+
title: "Waste Subtype",
|
|
68
|
+
description: "Specific subcategory of waste within a waste type",
|
|
69
|
+
examples: ["Food, Food Waste and Beverages", "Domestic Sludge"]
|
|
151
70
|
});
|
|
152
|
-
var
|
|
153
|
-
title: "
|
|
154
|
-
description: "
|
|
71
|
+
var CreditTypeSchema = NonEmptyStringSchema.max(100).meta({
|
|
72
|
+
title: "Credit Type",
|
|
73
|
+
description: "Type of credit issued",
|
|
74
|
+
examples: ["Organic", "Carbon (CH\u2084)"]
|
|
155
75
|
});
|
|
156
|
-
var
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
76
|
+
var HexColorSchema = NonEmptyStringSchema.regex(
|
|
77
|
+
/^#[0-9A-F]{6}$/,
|
|
78
|
+
"Must be a hex color code with # prefix and uppercase"
|
|
79
|
+
).meta({
|
|
80
|
+
title: "Hex Color",
|
|
81
|
+
description: "Hexadecimal color code with hash prefix",
|
|
82
|
+
examples: ["#2D5A27", "#FF5733"]
|
|
83
|
+
});
|
|
84
|
+
var NonNegativeFloatSchema = zod.z.number().min(0).meta({
|
|
85
|
+
title: "Non-Negative Float",
|
|
86
|
+
description: "Floating-point number that is zero or positive",
|
|
87
|
+
examples: [0, 45.2, 72.5]
|
|
88
|
+
});
|
|
89
|
+
var WeightKgSchema = NonNegativeFloatSchema.meta({
|
|
90
|
+
title: "Weight (kg)",
|
|
91
|
+
description: "Weight measurement in kilograms",
|
|
92
|
+
examples: [3e3, 1500, 500]
|
|
163
93
|
});
|
|
164
|
-
var PercentageSchema =
|
|
94
|
+
var PercentageSchema = NonNegativeFloatSchema.max(100).meta({
|
|
165
95
|
title: "Percentage",
|
|
166
96
|
description: "Percentage value between 0 and 100",
|
|
167
97
|
examples: [50, 75.5, 100]
|
|
@@ -176,48 +106,107 @@ var PositiveIntegerSchema = zod.z.number().int().min(1).meta({
|
|
|
176
106
|
description: "Integer value that is greater than zero",
|
|
177
107
|
examples: [1, 123, 456]
|
|
178
108
|
});
|
|
179
|
-
var NonNegativeFloatSchema = zod.z.number().min(0).meta({
|
|
180
|
-
title: "Non-Negative Float",
|
|
181
|
-
description: "Floating-point number that is zero or positive",
|
|
182
|
-
examples: [0, 45.2, 72.5]
|
|
183
|
-
});
|
|
184
|
-
var CreditTypeSchema = NonEmptyStringSchema.max(100).meta({
|
|
185
|
-
title: "Credit Type",
|
|
186
|
-
description: "Type of credit issued",
|
|
187
|
-
examples: ["Organic", "Carbon (CH\u2084)"]
|
|
188
|
-
});
|
|
189
109
|
var CreditAmountSchema = NonNegativeFloatSchema.meta({
|
|
190
110
|
title: "Credit Amount",
|
|
191
111
|
description: "Amount of credits issued"
|
|
192
112
|
});
|
|
193
|
-
var
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
113
|
+
var IsoTimestampSchema = zod.z.string().datetime({
|
|
114
|
+
message: "Must be a valid ISO 8601 timestamp with timezone information",
|
|
115
|
+
offset: true
|
|
116
|
+
}).meta({
|
|
117
|
+
title: "ISO Timestamp",
|
|
118
|
+
description: "ISO 8601 formatted timestamp with timezone information",
|
|
119
|
+
examples: ["2024-12-05T11:02:47.000Z"]
|
|
120
|
+
});
|
|
121
|
+
var IsoDateSchema = zod.z.iso.date("Must be a valid ISO 8601 date (YYYY-MM-DD)").meta({
|
|
122
|
+
title: "ISO Date",
|
|
123
|
+
description: "ISO 8601 formatted date in YYYY-MM-DD format",
|
|
124
|
+
examples: ["2024-12-05"]
|
|
197
125
|
});
|
|
198
|
-
var
|
|
199
|
-
title: "
|
|
200
|
-
description: "
|
|
201
|
-
examples: [
|
|
126
|
+
var UnixTimestampSchema = zod.z.number().int().positive().meta({
|
|
127
|
+
title: "Unix Timestamp",
|
|
128
|
+
description: "Unix timestamp in milliseconds since epoch (January 1, 1970 00:00:00 UTC)",
|
|
129
|
+
examples: [17040672e5]
|
|
202
130
|
});
|
|
203
|
-
var
|
|
204
|
-
|
|
205
|
-
"
|
|
131
|
+
var IsoCountryCodeSchema = zod.z.string().regex(/^[A-Z]{2}$/, "Must be a valid ISO 3166-1 alpha-2 country code").meta({
|
|
132
|
+
title: "ISO Country Code",
|
|
133
|
+
description: "Two-letter country code following ISO 3166-1 alpha-2 standard",
|
|
134
|
+
examples: ["BR", "US", "DE"]
|
|
135
|
+
});
|
|
136
|
+
var IsoAdministrativeDivisionCodeSchema = zod.z.string().regex(
|
|
137
|
+
/^[A-Z]{2}-[A-Z0-9]{1,3}$/,
|
|
138
|
+
"Must be a valid ISO 3166-2 administrative division code"
|
|
206
139
|
).meta({
|
|
207
|
-
title: "
|
|
208
|
-
description: "
|
|
209
|
-
examples: [
|
|
210
|
-
"ipfs://QmTy8w65yBXgyfG2ZBg5TrfB2hPjrDQH3RCQFJGkARStJb/mass-id-organic.png",
|
|
211
|
-
"ipfs://QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o"
|
|
212
|
-
]
|
|
140
|
+
title: "ISO Administrative Division Code",
|
|
141
|
+
description: "Administrative division code following ISO 3166-2 standard",
|
|
142
|
+
examples: ["BR-AP", "BR-ES", "US-CA"]
|
|
213
143
|
});
|
|
214
|
-
var
|
|
215
|
-
|
|
216
|
-
"
|
|
144
|
+
var LatitudeSchema = zod.z.number().min(-90).max(90).multipleOf(1e-3).meta({
|
|
145
|
+
title: "Latitude",
|
|
146
|
+
description: "Geographic latitude coordinate in decimal degrees with maximum 3 decimal places precision (~100m-1km accuracy for city-level)",
|
|
147
|
+
examples: [-0.02, -20.38, 40.713]
|
|
148
|
+
});
|
|
149
|
+
var LongitudeSchema = zod.z.number().min(-180).max(180).multipleOf(1e-3).meta({
|
|
150
|
+
title: "Longitude",
|
|
151
|
+
description: "Geographic longitude coordinate in decimal degrees with maximum 3 decimal places precision (~100m-1km accuracy for city-level)",
|
|
152
|
+
examples: [-51.06, -40.34, -74.006]
|
|
153
|
+
});
|
|
154
|
+
var BLOCKCHAIN_NETWORK_CONFIG = {
|
|
155
|
+
mainnet: { chain_id: 137, network_name: "Polygon" },
|
|
156
|
+
testnet: { chain_id: 80002, network_name: "Amoy" }
|
|
157
|
+
};
|
|
158
|
+
var ALLOWED_BLOCKCHAIN_NETWORKS = Object.values(
|
|
159
|
+
BLOCKCHAIN_NETWORK_CONFIG
|
|
160
|
+
);
|
|
161
|
+
var BLOCKCHAIN_CHAIN_IDS = [
|
|
162
|
+
BLOCKCHAIN_NETWORK_CONFIG.mainnet.chain_id,
|
|
163
|
+
BLOCKCHAIN_NETWORK_CONFIG.testnet.chain_id
|
|
164
|
+
];
|
|
165
|
+
var BLOCKCHAIN_NETWORK_NAMES = [
|
|
166
|
+
BLOCKCHAIN_NETWORK_CONFIG.mainnet.network_name,
|
|
167
|
+
BLOCKCHAIN_NETWORK_CONFIG.testnet.network_name
|
|
168
|
+
];
|
|
169
|
+
var EthereumAddressSchema = zod.z.string().regex(
|
|
170
|
+
/^0x[a-f0-9]{40}$/,
|
|
171
|
+
"Must be a valid Ethereum address in lowercase hexadecimal format"
|
|
217
172
|
).meta({
|
|
218
|
-
title: "
|
|
219
|
-
description: "
|
|
220
|
-
examples: ["
|
|
173
|
+
title: "Ethereum Address",
|
|
174
|
+
description: "A valid Ethereum address in hexadecimal format",
|
|
175
|
+
examples: ["0x1234567890abcdef1234567890abcdef12345678"]
|
|
176
|
+
});
|
|
177
|
+
var BlockchainChainIdSchema = zod.z.union([
|
|
178
|
+
zod.z.literal(BLOCKCHAIN_NETWORK_CONFIG.mainnet.chain_id),
|
|
179
|
+
zod.z.literal(BLOCKCHAIN_NETWORK_CONFIG.testnet.chain_id)
|
|
180
|
+
]).meta({
|
|
181
|
+
title: "Chain ID",
|
|
182
|
+
description: "Supported Polygon chain identifiers",
|
|
183
|
+
examples: BLOCKCHAIN_CHAIN_IDS
|
|
184
|
+
});
|
|
185
|
+
var BlockchainNetworkNameSchema = zod.z.enum(BLOCKCHAIN_NETWORK_NAMES).meta({
|
|
186
|
+
title: "Blockchain Network Name",
|
|
187
|
+
description: "Supported Polygon network names",
|
|
188
|
+
examples: BLOCKCHAIN_NETWORK_NAMES
|
|
189
|
+
});
|
|
190
|
+
var SmartContractAddressSchema = EthereumAddressSchema.meta({
|
|
191
|
+
title: "Smart Contract Address",
|
|
192
|
+
description: "Address of the smart contract"
|
|
193
|
+
});
|
|
194
|
+
var SmartContractSchema = zod.z.strictObject({
|
|
195
|
+
address: SmartContractAddressSchema,
|
|
196
|
+
chain_id: BlockchainChainIdSchema,
|
|
197
|
+
network_name: BlockchainNetworkNameSchema
|
|
198
|
+
}).meta({
|
|
199
|
+
title: "Smart Contract",
|
|
200
|
+
description: "Smart contract details for on-chain references"
|
|
201
|
+
});
|
|
202
|
+
var UuidSchema = zod.z.uuidv4().meta({
|
|
203
|
+
title: "UUID V4",
|
|
204
|
+
description: "A universally unique identifier version 4",
|
|
205
|
+
examples: ["ad44dd3f-f176-4b98-bf78-5ee6e77d0530"]
|
|
206
|
+
});
|
|
207
|
+
var ExternalIdSchema = UuidSchema.meta({
|
|
208
|
+
title: "External ID",
|
|
209
|
+
description: "UUID identifier for external system references"
|
|
221
210
|
});
|
|
222
211
|
var TokenIdSchema = NonEmptyStringSchema.regex(
|
|
223
212
|
/^\d+$/,
|
|
@@ -225,50 +214,52 @@ var TokenIdSchema = NonEmptyStringSchema.regex(
|
|
|
225
214
|
).meta({
|
|
226
215
|
title: "Token ID",
|
|
227
216
|
description: "Numeric identifier for blockchain tokens as string",
|
|
228
|
-
examples: ["
|
|
217
|
+
examples: ["456789", "1000000"]
|
|
229
218
|
});
|
|
230
|
-
var
|
|
231
|
-
|
|
232
|
-
"Must
|
|
219
|
+
var StringifiedTokenIdSchema = NonEmptyStringSchema.regex(
|
|
220
|
+
/^#\d+$/,
|
|
221
|
+
"Must match pattern #<token_id>"
|
|
233
222
|
).meta({
|
|
234
|
-
title: "
|
|
235
|
-
description: "
|
|
236
|
-
|
|
223
|
+
title: "Token ID",
|
|
224
|
+
description: "Token ID represented as #<token_id>",
|
|
225
|
+
example: "#123"
|
|
237
226
|
});
|
|
238
227
|
var Sha256HashSchema = zod.z.hash("sha256", {
|
|
239
228
|
error: "Must be a SHA256 hash as 32-byte hex string"
|
|
240
229
|
}).meta({
|
|
241
230
|
format: void 0,
|
|
242
|
-
title: "
|
|
231
|
+
title: "SHA-256 Hash",
|
|
243
232
|
description: "SHA-256 cryptographic hash as hexadecimal string",
|
|
244
233
|
examples: [
|
|
245
|
-
"87f633634cc4b02f628685651f0a29b7bfa22a0bd841f725c6772dd00a58d489"
|
|
246
|
-
"6e83b8e6373847bbdc056549bedda38dc88854ce41ba4fca11e0fc6ce3e07ef6"
|
|
234
|
+
"87f633634cc4b02f628685651f0a29b7bfa22a0bd841f725c6772dd00a58d489"
|
|
247
235
|
]
|
|
248
236
|
});
|
|
249
|
-
var
|
|
250
|
-
title: "
|
|
251
|
-
description: "
|
|
252
|
-
examples: [
|
|
253
|
-
"ac08c3cf2e175e55961d6affdb38bc24591b84ceef7f3707c69ae3d52c148b2f",
|
|
254
|
-
"b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2"
|
|
255
|
-
]
|
|
237
|
+
var ExternalUrlSchema = zod.z.url().meta({
|
|
238
|
+
title: "External URL",
|
|
239
|
+
description: "URL pointing to external resources",
|
|
240
|
+
examples: ["https://explore.carrot.eco/", "https://whitepaper.carrot.eco/"]
|
|
256
241
|
});
|
|
257
|
-
var
|
|
258
|
-
|
|
259
|
-
|
|
242
|
+
var ipfsUriPattern = /^ipfs:\/\/(?:Qm[1-9A-HJ-NP-Za-km-z]{44}|[bB][a-z2-7]{58,}|[zZ][1-9A-HJ-NP-Za-km-z]{48,})(?:\/[^\s]*)?$/;
|
|
243
|
+
var IpfsUriSchema = NonEmptyStringSchema.regex(
|
|
244
|
+
ipfsUriPattern,
|
|
245
|
+
"Must be a valid IPFS URI with CID"
|
|
246
|
+
).meta({
|
|
247
|
+
title: "IPFS URI",
|
|
248
|
+
description: "InterPlanetary File System URI pointing to distributed content",
|
|
260
249
|
examples: [
|
|
261
|
-
"
|
|
262
|
-
"
|
|
250
|
+
"ipfs://bafybeigdyrztvzl5cceubvaxob7iqh6f3f7s36c74ojav2xsz2uib2g3vm/mass-id-organic.png",
|
|
251
|
+
"ipfs://bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku"
|
|
263
252
|
]
|
|
264
253
|
});
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
254
|
+
|
|
255
|
+
// src/shared/schemas/primitives/version.schema.ts
|
|
256
|
+
var SemanticVersionSchema = NonEmptyStringSchema.regex(
|
|
257
|
+
/^v?\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/,
|
|
258
|
+
"Must be a valid semantic version string"
|
|
259
|
+
).meta({
|
|
260
|
+
title: "Semantic Version",
|
|
261
|
+
description: "Version string following semantic versioning specification",
|
|
262
|
+
examples: ["0.1.0", "1.0.0", "2.1.3"]
|
|
272
263
|
});
|
|
273
264
|
var RecordSchemaTypeSchema = zod.z.enum([
|
|
274
265
|
"MassID",
|
|
@@ -298,368 +289,21 @@ var CreditTokenSymbolSchema = TokenSymbolSchema.meta({
|
|
|
298
289
|
description: "Symbol of the credit token (e.g., C-CARB, C-BIOW)",
|
|
299
290
|
examples: ["C-CARB", "C-BIOW"]
|
|
300
291
|
});
|
|
301
|
-
var RecordRelationshipTypeSchema = zod.z.enum([
|
|
302
|
-
"collection",
|
|
303
|
-
"credit",
|
|
304
|
-
"gas-id",
|
|
305
|
-
"mass-id",
|
|
306
|
-
"mass-id-audit",
|
|
307
|
-
"methodology",
|
|
308
|
-
"credit-purchase-receipt",
|
|
309
|
-
"credit-retirement-receipt",
|
|
310
|
-
"recycled-id"
|
|
311
|
-
]).meta({
|
|
312
|
-
title: "Relationship Type",
|
|
313
|
-
description: "Type of relationship between different entities in the system",
|
|
314
|
-
examples: ["mass-id", "collection", "credit-purchase-receipt"]
|
|
315
|
-
});
|
|
316
|
-
function uniqueArrayItems(schema, errorMessage = "Array items must be unique") {
|
|
317
|
-
return zod.z.array(schema).refine((items) => new Set(items).size === items.length, {
|
|
318
|
-
message: errorMessage
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
function uniqueBy(schema, selector, errorMessage = "Items must be unique") {
|
|
322
|
-
return zod.z.array(schema).refine(
|
|
323
|
-
(items) => {
|
|
324
|
-
const values = items.map(selector);
|
|
325
|
-
return new Set(values).size === values.length;
|
|
326
|
-
},
|
|
327
|
-
{
|
|
328
|
-
message: errorMessage
|
|
329
|
-
}
|
|
330
|
-
);
|
|
331
|
-
}
|
|
332
292
|
|
|
333
|
-
// src/shared/
|
|
334
|
-
var
|
|
335
|
-
|
|
336
|
-
title: "
|
|
337
|
-
description: "
|
|
338
|
-
}),
|
|
339
|
-
name: ParticipantNameSchema.meta({
|
|
340
|
-
title: "Participant Name",
|
|
341
|
-
description: "Name of the participant"
|
|
293
|
+
// src/shared/schemas/core/base.schema.ts
|
|
294
|
+
var SchemaInfoSchema = zod.z.strictObject({
|
|
295
|
+
hash: Sha256HashSchema.meta({
|
|
296
|
+
title: "Schema Hash",
|
|
297
|
+
description: "SHA-256 hash of the JSON Schema this record was validated against"
|
|
342
298
|
}),
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
"
|
|
346
|
-
|
|
347
|
-
title: "Participant Roles",
|
|
348
|
-
description: "Roles of the participant in the waste management supply chain"
|
|
299
|
+
type: RecordSchemaTypeSchema,
|
|
300
|
+
version: SemanticVersionSchema.meta({
|
|
301
|
+
title: "Schema Version",
|
|
302
|
+
description: "Version of the schema, using semantic versioning"
|
|
349
303
|
})
|
|
350
304
|
}).meta({
|
|
351
|
-
title: "
|
|
352
|
-
description: "
|
|
353
|
-
});
|
|
354
|
-
var PrecisionLevelSchema = zod.z.enum(["exact", "neighborhood", "city", "region", "country"]).meta({
|
|
355
|
-
title: "Coordinate Precision Level",
|
|
356
|
-
description: "Level of coordinate precision",
|
|
357
|
-
examples: ["city", "exact", "neighborhood"]
|
|
358
|
-
});
|
|
359
|
-
var CoordinatesSchema = zod.z.strictObject({
|
|
360
|
-
latitude: LatitudeSchema,
|
|
361
|
-
longitude: LongitudeSchema,
|
|
362
|
-
precision_level: PrecisionLevelSchema
|
|
363
|
-
}).meta({
|
|
364
|
-
title: "Coordinates",
|
|
365
|
-
description: "GPS coordinates of the location"
|
|
366
|
-
});
|
|
367
|
-
var LocationSchema = zod.z.strictObject({
|
|
368
|
-
id_hash: Sha256HashSchema.meta({
|
|
369
|
-
title: "Location ID Hash",
|
|
370
|
-
description: "Anonymized identifier for the location"
|
|
371
|
-
}),
|
|
372
|
-
municipality: MunicipalitySchema,
|
|
373
|
-
administrative_division: AdministrativeDivisionSchema,
|
|
374
|
-
administrative_division_code: IsoAdministrativeDivisionCodeSchema.optional(),
|
|
375
|
-
country: CountryNameSchema,
|
|
376
|
-
country_code: IsoCountryCodeSchema,
|
|
377
|
-
responsible_participant_id_hash: Sha256HashSchema.meta({
|
|
378
|
-
title: "Responsible Participant ID Hash",
|
|
379
|
-
description: "Anonymized ID of the participant responsible for this location"
|
|
380
|
-
}),
|
|
381
|
-
coordinates: CoordinatesSchema
|
|
382
|
-
}).meta({
|
|
383
|
-
title: "Location",
|
|
384
|
-
description: "Geographic location with address and coordinate information"
|
|
385
|
-
});
|
|
386
|
-
var MethodologyComplianceSchema = zod.z.enum(["PASSED", "FAILED"]).meta({
|
|
387
|
-
title: "Methodology Compliance",
|
|
388
|
-
description: "Result of methodology compliance check",
|
|
389
|
-
examples: ["PASSED", "FAILED"]
|
|
390
|
-
});
|
|
391
|
-
var AuditReferenceSchema = zod.z.strictObject({
|
|
392
|
-
date: IsoDateSchema.meta({
|
|
393
|
-
title: "Audit Date",
|
|
394
|
-
description: "Date when the audit was completed"
|
|
395
|
-
}),
|
|
396
|
-
external_id: ExternalIdSchema.meta({
|
|
397
|
-
title: "Audit External ID",
|
|
398
|
-
description: "Unique identifier for the audit"
|
|
399
|
-
}),
|
|
400
|
-
external_url: ExternalUrlSchema.meta({
|
|
401
|
-
title: "Audit External URL",
|
|
402
|
-
description: "URL to view the audit on Carrot Explorer"
|
|
403
|
-
}),
|
|
404
|
-
methodology_compliance: MethodologyComplianceSchema.meta({
|
|
405
|
-
title: "Methodology Compliance",
|
|
406
|
-
description: "Result of methodology compliance check"
|
|
407
|
-
}),
|
|
408
|
-
rules_executed: NonNegativeIntegerSchema.meta({
|
|
409
|
-
title: "Rules Executed",
|
|
410
|
-
description: "Number of rules executed during the audit"
|
|
411
|
-
}),
|
|
412
|
-
report: IpfsUriSchema.meta({
|
|
413
|
-
title: "Audit Report",
|
|
414
|
-
description: "IPFS URI of the audit report"
|
|
415
|
-
})
|
|
416
|
-
}).meta({
|
|
417
|
-
title: "Audit Reference",
|
|
418
|
-
description: "Reference to an audit record"
|
|
419
|
-
});
|
|
420
|
-
var GasIDReferenceSchema = zod.z.strictObject({
|
|
421
|
-
external_id: ExternalIdSchema.meta({
|
|
422
|
-
title: "GasID External ID",
|
|
423
|
-
description: "Unique identifier for the GasID"
|
|
424
|
-
}),
|
|
425
|
-
token_id: TokenIdSchema.meta({
|
|
426
|
-
title: "GasID Token ID",
|
|
427
|
-
description: "NFT token ID of the GasID"
|
|
428
|
-
}),
|
|
429
|
-
external_url: ExternalUrlSchema.meta({
|
|
430
|
-
title: "GasID External URL",
|
|
431
|
-
description: "URL to view the GasID on Carrot Explorer"
|
|
432
|
-
}),
|
|
433
|
-
uri: IpfsUriSchema.meta({
|
|
434
|
-
title: "GasID IPFS URI",
|
|
435
|
-
description: "IPFS URI of the GasID record"
|
|
436
|
-
})
|
|
437
|
-
}).meta({
|
|
438
|
-
title: "GasID Reference",
|
|
439
|
-
description: "Reference to a GasID record"
|
|
440
|
-
});
|
|
441
|
-
var MassIDReferenceSchema = zod.z.strictObject({
|
|
442
|
-
external_id: ExternalIdSchema.meta({
|
|
443
|
-
title: "MassID External ID",
|
|
444
|
-
description: "Unique identifier for the MassID"
|
|
445
|
-
}),
|
|
446
|
-
token_id: TokenIdSchema.meta({
|
|
447
|
-
title: "MassID Token ID",
|
|
448
|
-
description: "NFT token ID of the MassID"
|
|
449
|
-
}),
|
|
450
|
-
external_url: ExternalUrlSchema.meta({
|
|
451
|
-
title: "MassID External URL",
|
|
452
|
-
description: "URL to view the MassID on Carrot Explorer"
|
|
453
|
-
}),
|
|
454
|
-
uri: IpfsUriSchema.meta({
|
|
455
|
-
title: "MassID IPFS URI",
|
|
456
|
-
description: "IPFS URI of the MassID record"
|
|
457
|
-
})
|
|
458
|
-
}).meta({
|
|
459
|
-
title: "MassID Reference",
|
|
460
|
-
description: "Reference to a MassID record"
|
|
461
|
-
});
|
|
462
|
-
var MethodologyReferenceSchema = zod.z.strictObject({
|
|
463
|
-
external_id: ExternalIdSchema.meta({
|
|
464
|
-
title: "Methodology External ID",
|
|
465
|
-
description: "Unique identifier for the methodology"
|
|
466
|
-
}),
|
|
467
|
-
name: NonEmptyStringSchema.min(5).max(150).meta({
|
|
468
|
-
title: "Methodology Name",
|
|
469
|
-
description: "Human-readable name of the methodology",
|
|
470
|
-
examples: ["BOLD Carbon (CH\u2084)", "BOLD Recycling"]
|
|
471
|
-
}),
|
|
472
|
-
version: SemanticVersionSchema.meta({
|
|
473
|
-
title: "Methodology Version",
|
|
474
|
-
description: "Version of the methodology"
|
|
475
|
-
}),
|
|
476
|
-
external_url: ExternalUrlSchema.meta({
|
|
477
|
-
title: "Methodology External URL",
|
|
478
|
-
description: "URL to view the methodology on Carrot Explorer"
|
|
479
|
-
}),
|
|
480
|
-
uri: IpfsUriSchema.optional().meta({
|
|
481
|
-
title: "Methodology IPFS URI",
|
|
482
|
-
description: "IPFS URI to the methodology record"
|
|
483
|
-
})
|
|
484
|
-
}).meta({
|
|
485
|
-
title: "Methodology Reference",
|
|
486
|
-
description: "Reference to a methodology record"
|
|
487
|
-
});
|
|
488
|
-
var WasteClassificationSchema = zod.z.strictObject({
|
|
489
|
-
primary_type: WasteTypeSchema.meta({
|
|
490
|
-
title: "Source Waste Primary Type",
|
|
491
|
-
description: "Primary type of the source waste"
|
|
492
|
-
}),
|
|
493
|
-
subtype: WasteSubtypeSchema.meta({
|
|
494
|
-
title: "Source Waste Subtype",
|
|
495
|
-
description: "Subtype of the source waste"
|
|
496
|
-
}),
|
|
497
|
-
net_weight_kg: WeightKgSchema.meta({
|
|
498
|
-
title: "Source Waste Net Weight",
|
|
499
|
-
description: "Net weight of the source waste"
|
|
500
|
-
})
|
|
501
|
-
}).meta({
|
|
502
|
-
title: "Waste Classification",
|
|
503
|
-
description: "Classification of the source waste (MassID)"
|
|
504
|
-
});
|
|
505
|
-
var AccreditedParticipantSchema = zod.z.strictObject({
|
|
506
|
-
participant_id: UuidSchema.meta({
|
|
507
|
-
title: "Participant ID",
|
|
508
|
-
description: "Unique identifier for the participant"
|
|
509
|
-
}),
|
|
510
|
-
name: ParticipantNameSchema.meta({
|
|
511
|
-
title: "Participant Name",
|
|
512
|
-
description: "Name of the participant"
|
|
513
|
-
}),
|
|
514
|
-
role: ParticipantRoleSchema.meta({
|
|
515
|
-
title: "Participant Role",
|
|
516
|
-
description: "Role of the participant in the supply chain"
|
|
517
|
-
}),
|
|
518
|
-
accreditation_id: UuidSchema.meta({
|
|
519
|
-
title: "Accreditation ID",
|
|
520
|
-
description: "Unique identifier for the participant accreditation"
|
|
521
|
-
}),
|
|
522
|
-
external_url: ExternalUrlSchema.meta({
|
|
523
|
-
title: "Participant Accreditation External URL",
|
|
524
|
-
description: "URL to view the participant accreditation on Carrot Explorer"
|
|
525
|
-
})
|
|
526
|
-
}).meta({
|
|
527
|
-
title: "Accredited Participant",
|
|
528
|
-
description: "Participant with valid accreditation in the supply chain"
|
|
529
|
-
});
|
|
530
|
-
var AccreditedParticipantsSchema = zod.z.array(AccreditedParticipantSchema).min(1).meta({
|
|
531
|
-
title: "Accredited Participants",
|
|
532
|
-
description: "List of participants with valid accreditations"
|
|
533
|
-
});
|
|
534
|
-
var RewardAllocationSchema = zod.z.strictObject({
|
|
535
|
-
participant_id: UuidSchema.meta({
|
|
536
|
-
title: "Participant ID",
|
|
537
|
-
description: "Unique identifier for the participant receiving the reward"
|
|
538
|
-
}),
|
|
539
|
-
participant_name: ParticipantNameSchema.meta({
|
|
540
|
-
title: "Participant Name",
|
|
541
|
-
description: "Name of the participant receiving the reward"
|
|
542
|
-
}),
|
|
543
|
-
role: ParticipantRoleSchema.meta({
|
|
544
|
-
title: "Participant Role",
|
|
545
|
-
description: "Role of the participant in the supply chain"
|
|
546
|
-
}),
|
|
547
|
-
reward_percentage: PercentageSchema.meta({
|
|
548
|
-
title: "Reward Percentage",
|
|
549
|
-
description: "Reward percentage allocated to the participant"
|
|
550
|
-
}),
|
|
551
|
-
large_business_discount_applied: zod.z.boolean().optional().meta({
|
|
552
|
-
title: "Large Business Discount Applied",
|
|
553
|
-
description: "Whether the large business discount was applied"
|
|
554
|
-
}),
|
|
555
|
-
effective_percentage: PercentageSchema.meta({
|
|
556
|
-
title: "Effective Percentage",
|
|
557
|
-
description: "Effective percentage of the reward after discounts"
|
|
558
|
-
})
|
|
559
|
-
}).meta({
|
|
560
|
-
title: "Reward Allocation",
|
|
561
|
-
description: "Reward allocation for a specific participant"
|
|
562
|
-
});
|
|
563
|
-
var DistributionNotesSchema = zod.z.strictObject({
|
|
564
|
-
large_business_discount_applied: NonEmptyStringSchema.optional().meta({
|
|
565
|
-
title: "Large Business Discount Applied",
|
|
566
|
-
description: "Description of the large business discount applied",
|
|
567
|
-
examples: [
|
|
568
|
-
"50% reduction applied to participants with >$4M annual revenue"
|
|
569
|
-
]
|
|
570
|
-
}),
|
|
571
|
-
redirected_rewards: NonEmptyStringSchema.optional().meta({
|
|
572
|
-
title: "Redirected Rewards",
|
|
573
|
-
description: "Description of the redirected rewards",
|
|
574
|
-
examples: [
|
|
575
|
-
"Discounted rewards from large businesses redirected to accredited NGOs"
|
|
576
|
-
]
|
|
577
|
-
})
|
|
578
|
-
}).meta({
|
|
579
|
-
title: "Distribution Notes",
|
|
580
|
-
description: "Additional notes about the reward distribution"
|
|
581
|
-
});
|
|
582
|
-
var ParticipantRewardsSchema = zod.z.strictObject({
|
|
583
|
-
distribution_basis: NonEmptyStringSchema.max(200).meta({
|
|
584
|
-
title: "Distribution Basis",
|
|
585
|
-
description: "Basis for the rewards distribution"
|
|
586
|
-
}),
|
|
587
|
-
reward_allocations: zod.z.array(RewardAllocationSchema).min(1).meta({
|
|
588
|
-
title: "Reward Allocations",
|
|
589
|
-
description: "Rewards percentage allocated to each participant"
|
|
590
|
-
}),
|
|
591
|
-
distribution_notes: DistributionNotesSchema.optional().meta({
|
|
592
|
-
title: "Distribution Notes",
|
|
593
|
-
description: "Additional notes about the reward distribution"
|
|
594
|
-
})
|
|
595
|
-
}).meta({
|
|
596
|
-
title: "Participant Rewards",
|
|
597
|
-
description: "Rewards distribution to participants"
|
|
598
|
-
});
|
|
599
|
-
var SchemaHashSchema = zod.z.union([
|
|
600
|
-
Keccak256HashSchema,
|
|
601
|
-
zod.z.string().regex(
|
|
602
|
-
/^0x[a-fA-F0-9]{64}$/,
|
|
603
|
-
"Must be a Keccak256 hash as 0x-prefixed hex string"
|
|
604
|
-
)
|
|
605
|
-
]).meta({
|
|
606
|
-
title: "Schema Hash",
|
|
607
|
-
description: "Keccak256 hash of the JSON Schema this record was validated against",
|
|
608
|
-
examples: [
|
|
609
|
-
"ac08c3cf2e175e55961d6affdb38bc24591b84ceef7f3707c69ae3d52c148b2f",
|
|
610
|
-
"0xac08c3cf2e175e55961d6affdb38bc24591b84ceef7f3707c69ae3d52c148b2f"
|
|
611
|
-
]
|
|
612
|
-
});
|
|
613
|
-
var SchemaInfoSchema = zod.z.strictObject({
|
|
614
|
-
hash: SchemaHashSchema,
|
|
615
|
-
type: RecordSchemaTypeSchema.meta({
|
|
616
|
-
title: "Schema Type",
|
|
617
|
-
description: "Type/category of this schema"
|
|
618
|
-
}),
|
|
619
|
-
version: SemanticVersionSchema.meta({
|
|
620
|
-
title: "Schema Version",
|
|
621
|
-
description: "Version of the schema, using semantic versioning"
|
|
622
|
-
})
|
|
623
|
-
}).meta({
|
|
624
|
-
title: "Schema Information"
|
|
625
|
-
});
|
|
626
|
-
var RecordCreatorSchema = zod.z.strictObject({
|
|
627
|
-
name: zod.z.string().meta({
|
|
628
|
-
title: "Creator Name",
|
|
629
|
-
description: "Company or individual name that created this record",
|
|
630
|
-
examples: ["Carrot Foundation"]
|
|
631
|
-
}),
|
|
632
|
-
id: UuidSchema.meta({
|
|
633
|
-
title: "Creator ID",
|
|
634
|
-
description: "Unique identifier for the creator"
|
|
635
|
-
})
|
|
636
|
-
}).meta({
|
|
637
|
-
title: "Creator",
|
|
638
|
-
description: "Entity that created this record"
|
|
639
|
-
});
|
|
640
|
-
var RecordRelationshipSchema = zod.z.strictObject({
|
|
641
|
-
target_uri: IpfsUriSchema.meta({
|
|
642
|
-
title: "Target IPFS URI",
|
|
643
|
-
description: "Target IPFS URI of the referenced record"
|
|
644
|
-
}),
|
|
645
|
-
type: RecordRelationshipTypeSchema.meta({
|
|
646
|
-
title: "Relationship Type",
|
|
647
|
-
description: "Type of relationship to the referenced record"
|
|
648
|
-
}),
|
|
649
|
-
description: zod.z.string().optional().meta({
|
|
650
|
-
title: "Relationship Description",
|
|
651
|
-
description: "Human-readable description of the relationship",
|
|
652
|
-
examples: [
|
|
653
|
-
"This record supersedes the previous version",
|
|
654
|
-
"Related carbon credit batch",
|
|
655
|
-
"Source document for this verification",
|
|
656
|
-
"Child record derived from this parent",
|
|
657
|
-
"Updated version of original record"
|
|
658
|
-
]
|
|
659
|
-
})
|
|
660
|
-
}).meta({
|
|
661
|
-
title: "Relationship",
|
|
662
|
-
description: "Relationship to another IPFS record"
|
|
305
|
+
title: "Schema Information",
|
|
306
|
+
description: "Information about the schema used to validate this record"
|
|
663
307
|
});
|
|
664
308
|
var RecordEnvironmentSchema = zod.z.strictObject({
|
|
665
309
|
blockchain_network: zod.z.enum(["mainnet", "testnet"]).meta({
|
|
@@ -675,8 +319,8 @@ var RecordEnvironmentSchema = zod.z.strictObject({
|
|
|
675
319
|
description: "Name of the data set for this record"
|
|
676
320
|
})
|
|
677
321
|
}).meta({
|
|
678
|
-
title: "Environment",
|
|
679
|
-
description: "Environment information"
|
|
322
|
+
title: "Record Environment",
|
|
323
|
+
description: "Environment information for the record"
|
|
680
324
|
});
|
|
681
325
|
var BaseIpfsSchema = zod.z.strictObject({
|
|
682
326
|
$schema: zod.z.url("Must be a valid URI").meta({
|
|
@@ -686,17 +330,11 @@ var BaseIpfsSchema = zod.z.strictObject({
|
|
|
686
330
|
}),
|
|
687
331
|
schema: SchemaInfoSchema,
|
|
688
332
|
created_at: IsoTimestampSchema.meta({
|
|
689
|
-
title: "Created At",
|
|
690
|
-
description: "ISO 8601 creation timestamp for this record"
|
|
691
|
-
}),
|
|
692
|
-
external_id: ExternalIdSchema.meta({
|
|
693
|
-
title: "External ID",
|
|
694
|
-
description: "Off-chain reference ID (UUID from Carrot backend)"
|
|
695
|
-
}),
|
|
696
|
-
external_url: ExternalUrlSchema.meta({
|
|
697
|
-
title: "External URL",
|
|
698
|
-
description: "External URL of the content"
|
|
333
|
+
title: "Created At",
|
|
334
|
+
description: "ISO 8601 creation timestamp for this record"
|
|
699
335
|
}),
|
|
336
|
+
external_id: ExternalIdSchema,
|
|
337
|
+
external_url: ExternalUrlSchema,
|
|
700
338
|
original_content_hash: Sha256HashSchema.meta({
|
|
701
339
|
title: "Original Content Hash",
|
|
702
340
|
description: "SHA-256 hash of the original JSON content including private data before schema validation"
|
|
@@ -705,11 +343,6 @@ var BaseIpfsSchema = zod.z.strictObject({
|
|
|
705
343
|
title: "Content Hash",
|
|
706
344
|
description: "SHA-256 hash of RFC 8785 canonicalized JSON after schema validation"
|
|
707
345
|
}),
|
|
708
|
-
creator: RecordCreatorSchema.optional(),
|
|
709
|
-
relationships: zod.z.array(RecordRelationshipSchema).optional().meta({
|
|
710
|
-
title: "Relationships",
|
|
711
|
-
description: "References to other IPFS records this record relates to"
|
|
712
|
-
}),
|
|
713
346
|
environment: RecordEnvironmentSchema.optional(),
|
|
714
347
|
data: zod.z.record(zod.z.string(), zod.z.unknown()).optional().meta({
|
|
715
348
|
title: "Custom Data",
|
|
@@ -719,6 +352,24 @@ var BaseIpfsSchema = zod.z.strictObject({
|
|
|
719
352
|
title: "Base IPFS Record",
|
|
720
353
|
description: "Base fields for all Carrot IPFS records, providing common structure for any JSON content stored in IPFS"
|
|
721
354
|
});
|
|
355
|
+
function uniqueArrayItems(schema, errorMessage = "Array items must be unique") {
|
|
356
|
+
return zod.z.array(schema).refine((items) => new Set(items).size === items.length, {
|
|
357
|
+
message: errorMessage
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
function uniqueBy(schema, selector, errorMessage = "Items must be unique") {
|
|
361
|
+
return zod.z.array(schema).refine(
|
|
362
|
+
(items) => {
|
|
363
|
+
const values = items.map(selector);
|
|
364
|
+
return new Set(values).size === values.length;
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
message: errorMessage
|
|
368
|
+
}
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// src/shared/schemas/core/nft.schema.ts
|
|
722
373
|
var NftSchemaTypeSchema = RecordSchemaTypeSchema.extract([
|
|
723
374
|
"MassID",
|
|
724
375
|
"RecycledID",
|
|
@@ -730,31 +381,38 @@ var NftSchemaTypeSchema = RecordSchemaTypeSchema.extract([
|
|
|
730
381
|
description: "Type of schema for NFT records"
|
|
731
382
|
});
|
|
732
383
|
var BlockchainReferenceSchema = zod.z.strictObject({
|
|
733
|
-
smart_contract_address:
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
chain_id: BlockchainChainIdSchema.meta({
|
|
737
|
-
title: "Chain ID",
|
|
738
|
-
description: "Blockchain chain ID"
|
|
739
|
-
}),
|
|
740
|
-
network_name: zod.z.string().min(5).max(100).meta({
|
|
741
|
-
title: "Network Name",
|
|
742
|
-
description: "Name of the blockchain network"
|
|
743
|
-
}),
|
|
384
|
+
smart_contract_address: SmartContractAddressSchema,
|
|
385
|
+
chain_id: BlockchainChainIdSchema,
|
|
386
|
+
network_name: BlockchainNetworkNameSchema,
|
|
744
387
|
token_id: TokenIdSchema.meta({
|
|
745
|
-
title: "Token ID",
|
|
746
388
|
description: "NFT token ID"
|
|
747
389
|
})
|
|
390
|
+
}).superRefine((value, ctx) => {
|
|
391
|
+
const matchedNetwork = ALLOWED_BLOCKCHAIN_NETWORKS.find(
|
|
392
|
+
(network) => network.chain_id === value.chain_id && network.network_name === value.network_name
|
|
393
|
+
);
|
|
394
|
+
if (!matchedNetwork) {
|
|
395
|
+
ctx.addIssue({
|
|
396
|
+
code: "custom",
|
|
397
|
+
message: "chain_id and network_name must match a supported network: 137/Polygon (mainnet) or 80002/Amoy (testnet)",
|
|
398
|
+
path: ["chain_id"]
|
|
399
|
+
});
|
|
400
|
+
ctx.addIssue({
|
|
401
|
+
code: "custom",
|
|
402
|
+
message: "chain_id and network_name must match a supported network: 137/Polygon (mainnet) or 80002/Amoy (testnet)",
|
|
403
|
+
path: ["network_name"]
|
|
404
|
+
});
|
|
405
|
+
}
|
|
748
406
|
}).meta({
|
|
749
407
|
title: "Blockchain Information",
|
|
750
408
|
description: "Blockchain-specific information for the NFT"
|
|
751
409
|
});
|
|
752
410
|
var ExternalLinkSchema = zod.z.strictObject({
|
|
753
|
-
label:
|
|
411
|
+
label: NonEmptyStringSchema.max(50).meta({
|
|
754
412
|
title: "Link Label",
|
|
755
413
|
description: "Display name for the external link"
|
|
756
414
|
}),
|
|
757
|
-
url:
|
|
415
|
+
url: ExternalUrlSchema.meta({
|
|
758
416
|
title: "Link URL",
|
|
759
417
|
description: "Direct URI to the linked resource"
|
|
760
418
|
}),
|
|
@@ -767,7 +425,7 @@ var ExternalLinkSchema = zod.z.strictObject({
|
|
|
767
425
|
description: "External link with label and description"
|
|
768
426
|
});
|
|
769
427
|
var NftAttributeSchema = zod.z.strictObject({
|
|
770
|
-
trait_type:
|
|
428
|
+
trait_type: NonEmptyStringSchema.max(50).meta({
|
|
771
429
|
title: "Trait Type",
|
|
772
430
|
description: "Name of the trait or attribute"
|
|
773
431
|
}),
|
|
@@ -795,7 +453,7 @@ var NftIpfsSchema = BaseIpfsSchema.safeExtend({
|
|
|
795
453
|
})
|
|
796
454
|
}),
|
|
797
455
|
blockchain: BlockchainReferenceSchema,
|
|
798
|
-
name:
|
|
456
|
+
name: NonEmptyStringSchema.max(100).meta({
|
|
799
457
|
title: "NFT Name",
|
|
800
458
|
description: "Full display name for this NFT, including extra context",
|
|
801
459
|
examples: [
|
|
@@ -804,12 +462,12 @@ var NftIpfsSchema = BaseIpfsSchema.safeExtend({
|
|
|
804
462
|
"GasID #789 \u2022 Methane \u2022 1000 m\xB3"
|
|
805
463
|
]
|
|
806
464
|
}),
|
|
807
|
-
short_name:
|
|
465
|
+
short_name: NonEmptyStringSchema.max(50).meta({
|
|
808
466
|
title: "Short Name",
|
|
809
467
|
description: "Compact name for UI summaries, tables, or tooltips",
|
|
810
468
|
examples: ["MassID #123", "RecycledID #456", "GasID #789"]
|
|
811
469
|
}),
|
|
812
|
-
description:
|
|
470
|
+
description: NonEmptyStringSchema.max(500).meta({
|
|
813
471
|
title: "Description",
|
|
814
472
|
description: "Human-readable summary of the NFT's role and context. Ideally, maximum 300 characters.",
|
|
815
473
|
examples: [
|
|
@@ -829,31 +487,17 @@ var NftIpfsSchema = BaseIpfsSchema.safeExtend({
|
|
|
829
487
|
title: "Animation URL",
|
|
830
488
|
description: "IPFS URI pointing to an animated or interactive media file",
|
|
831
489
|
examples: [
|
|
832
|
-
"ipfs://
|
|
833
|
-
"ipfs://
|
|
490
|
+
"ipfs://bafybeigdyrztvzl5cceubvaxob7iqh6f3f7s36c74ojav2xsz2uib2g3vm/mass-id-animation.mp4",
|
|
491
|
+
"ipfs://bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku/recycled-visualization.webm"
|
|
834
492
|
]
|
|
835
493
|
}),
|
|
836
494
|
external_links: uniqueBy(
|
|
837
495
|
ExternalLinkSchema,
|
|
838
496
|
(link) => link.url,
|
|
839
497
|
"External link URLs must be unique"
|
|
840
|
-
).
|
|
498
|
+
).optional().meta({
|
|
841
499
|
title: "External Links",
|
|
842
|
-
description: "Optional list of public resource links with labels"
|
|
843
|
-
examples: [
|
|
844
|
-
[
|
|
845
|
-
{
|
|
846
|
-
label: "Carrot Explorer",
|
|
847
|
-
url: "https://explore.carrot.eco/document/ad44dd3f-f176-4b98-bf78-5ee6e77d0530",
|
|
848
|
-
description: "Complete chain of custody and audit trail"
|
|
849
|
-
},
|
|
850
|
-
{
|
|
851
|
-
label: "Carrot White Paper",
|
|
852
|
-
url: "https://carrot.eco/whitepaper.pdf",
|
|
853
|
-
description: "Carrot Foundation technical and impact white paper"
|
|
854
|
-
}
|
|
855
|
-
]
|
|
856
|
-
]
|
|
500
|
+
description: "Optional list of public resource links with labels"
|
|
857
501
|
}),
|
|
858
502
|
attributes: uniqueBy(
|
|
859
503
|
NftAttributeSchema,
|
|
@@ -861,48 +505,32 @@ var NftIpfsSchema = BaseIpfsSchema.safeExtend({
|
|
|
861
505
|
"Attribute trait_type values must be unique"
|
|
862
506
|
).meta({
|
|
863
507
|
title: "NFT Attributes",
|
|
864
|
-
description: "List of visual traits and filterable attributes compatible with NFT marketplaces"
|
|
865
|
-
examples: [
|
|
866
|
-
[
|
|
867
|
-
{
|
|
868
|
-
trait_type: "Waste Type",
|
|
869
|
-
value: "Organic"
|
|
870
|
-
},
|
|
871
|
-
{
|
|
872
|
-
trait_type: "Waste Subtype",
|
|
873
|
-
value: "Food, Food Waste and Beverages"
|
|
874
|
-
},
|
|
875
|
-
{
|
|
876
|
-
trait_type: "Weight (kg)",
|
|
877
|
-
value: 3e3,
|
|
878
|
-
display_type: "number"
|
|
879
|
-
},
|
|
880
|
-
{
|
|
881
|
-
trait_type: "Origin Country",
|
|
882
|
-
value: "Brazil"
|
|
883
|
-
},
|
|
884
|
-
{
|
|
885
|
-
trait_type: "Pick-up Date",
|
|
886
|
-
value: "2024-12-05",
|
|
887
|
-
display_type: "date"
|
|
888
|
-
}
|
|
889
|
-
]
|
|
890
|
-
]
|
|
508
|
+
description: "List of visual traits and filterable attributes compatible with NFT marketplaces"
|
|
891
509
|
})
|
|
510
|
+
}).superRefine((value, ctx) => {
|
|
511
|
+
const environmentNetwork = value.environment?.blockchain_network;
|
|
512
|
+
if (!environmentNetwork) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
const config = BLOCKCHAIN_NETWORK_CONFIG[environmentNetwork];
|
|
516
|
+
if (value.blockchain.chain_id !== config.chain_id) {
|
|
517
|
+
ctx.addIssue({
|
|
518
|
+
code: "custom",
|
|
519
|
+
message: `blockchain.chain_id must be ${config.chain_id} when environment.blockchain_network is ${environmentNetwork}`,
|
|
520
|
+
path: ["blockchain", "chain_id"]
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
if (value.blockchain.network_name !== config.network_name) {
|
|
524
|
+
ctx.addIssue({
|
|
525
|
+
code: "custom",
|
|
526
|
+
message: `blockchain.network_name must be ${config.network_name} when environment.blockchain_network is ${environmentNetwork}`,
|
|
527
|
+
path: ["blockchain", "network_name"]
|
|
528
|
+
});
|
|
529
|
+
}
|
|
892
530
|
}).meta({
|
|
893
531
|
title: "NFT IPFS Record",
|
|
894
532
|
description: "NFT-specific fields for Carrot IPFS records"
|
|
895
533
|
});
|
|
896
|
-
function getSchemaBaseUrl() {
|
|
897
|
-
return `https://raw.githubusercontent.com/carrot-foundation/schemas/refs/tags/${getSchemaVersionOrDefault()}/schemas/ipfs`;
|
|
898
|
-
}
|
|
899
|
-
function buildSchemaUrl(schemaPath) {
|
|
900
|
-
const cleanPath = schemaPath.startsWith("/") ? schemaPath.slice(1) : schemaPath;
|
|
901
|
-
return `${getSchemaBaseUrl()}/${cleanPath}`;
|
|
902
|
-
}
|
|
903
|
-
function getSchemaVersionOrDefault() {
|
|
904
|
-
return "0.1.40";
|
|
905
|
-
}
|
|
906
534
|
var MethodologyAttributeSchema = NftAttributeSchema.safeExtend({
|
|
907
535
|
trait_type: zod.z.literal("Methodology"),
|
|
908
536
|
value: MethodologyNameSchema
|
|
@@ -965,121 +593,377 @@ var RecyclerAttributeSchema = NftAttributeSchema.safeExtend({
|
|
|
965
593
|
example: "Eco Reciclagem"
|
|
966
594
|
})
|
|
967
595
|
}).meta({
|
|
968
|
-
title: "Recycler Attribute",
|
|
969
|
-
description: "Recycler attribute"
|
|
596
|
+
title: "Recycler Attribute",
|
|
597
|
+
description: "Recycler attribute"
|
|
598
|
+
});
|
|
599
|
+
var MassIDTokenIdAttributeSchema = NftAttributeSchema.safeExtend({
|
|
600
|
+
trait_type: zod.z.literal("MassID"),
|
|
601
|
+
value: StringifiedTokenIdSchema.meta({
|
|
602
|
+
title: "MassID Token ID",
|
|
603
|
+
description: "Token ID of the source MassID NFT as #<token_id>"
|
|
604
|
+
})
|
|
605
|
+
}).meta({
|
|
606
|
+
title: "MassID Token ID Attribute",
|
|
607
|
+
description: "MassID token ID attribute"
|
|
608
|
+
});
|
|
609
|
+
var MassIDRecyclingDateAttributeSchema = NftAttributeSchema.omit({
|
|
610
|
+
max_value: true
|
|
611
|
+
}).safeExtend({
|
|
612
|
+
trait_type: zod.z.literal("MassID Recycling Date"),
|
|
613
|
+
value: UnixTimestampSchema.meta({
|
|
614
|
+
title: "MassID Recycling Date",
|
|
615
|
+
description: "Unix timestamp in milliseconds when the source waste was recycled"
|
|
616
|
+
}),
|
|
617
|
+
display_type: zod.z.literal("date")
|
|
618
|
+
}).meta({
|
|
619
|
+
title: "MassID Recycling Date Attribute",
|
|
620
|
+
description: "MassID recycling date attribute using Unix timestamp in milliseconds"
|
|
621
|
+
});
|
|
622
|
+
var MethodologyComplianceSchema = zod.z.enum(["PASSED", "FAILED"]).meta({
|
|
623
|
+
title: "Methodology Compliance",
|
|
624
|
+
description: "Result of methodology compliance check",
|
|
625
|
+
examples: ["PASSED", "FAILED"]
|
|
626
|
+
});
|
|
627
|
+
var AuditReferenceSchema = zod.z.strictObject({
|
|
628
|
+
date: IsoDateSchema.meta({
|
|
629
|
+
title: "Audit Date",
|
|
630
|
+
description: "Date when the audit was completed"
|
|
631
|
+
}),
|
|
632
|
+
external_id: ExternalIdSchema.meta({
|
|
633
|
+
title: "Audit External ID",
|
|
634
|
+
description: "Unique identifier for the audit"
|
|
635
|
+
}),
|
|
636
|
+
external_url: ExternalUrlSchema.meta({
|
|
637
|
+
title: "Audit External URL",
|
|
638
|
+
description: "URL to view the audit on Carrot Explorer"
|
|
639
|
+
}),
|
|
640
|
+
methodology_compliance: MethodologyComplianceSchema.meta({
|
|
641
|
+
title: "Methodology Compliance",
|
|
642
|
+
description: "Result of methodology compliance check"
|
|
643
|
+
}),
|
|
644
|
+
rules_executed: NonNegativeIntegerSchema.meta({
|
|
645
|
+
title: "Rules Executed",
|
|
646
|
+
description: "Number of rules executed during the audit"
|
|
647
|
+
}),
|
|
648
|
+
report: IpfsUriSchema.meta({
|
|
649
|
+
title: "Audit Report",
|
|
650
|
+
description: "IPFS URI of the audit report"
|
|
651
|
+
})
|
|
652
|
+
}).meta({
|
|
653
|
+
title: "Audit Reference",
|
|
654
|
+
description: "Reference to an audit record"
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
// src/shared/schemas/audit.schema.ts
|
|
658
|
+
var AuditRuleDefinitionSchema = zod.z.strictObject({
|
|
659
|
+
rule_id: UuidSchema.meta({
|
|
660
|
+
title: "Rule ID",
|
|
661
|
+
description: "Unique identifier for the audit rule"
|
|
662
|
+
}),
|
|
663
|
+
rule_slug: SlugSchema.meta({
|
|
664
|
+
title: "Rule Slug",
|
|
665
|
+
description: "URL-friendly identifier for the rule"
|
|
666
|
+
}),
|
|
667
|
+
rule_name: NonEmptyStringSchema.max(100).meta({
|
|
668
|
+
title: "Rule Name",
|
|
669
|
+
description: "Human-readable name of the rule",
|
|
670
|
+
examples: ["Waste Mass is Unique", "No Conflicting GasID or Credit"]
|
|
671
|
+
}),
|
|
672
|
+
description: zod.z.string().min(10).max(500).meta({
|
|
673
|
+
title: "Rule Description",
|
|
674
|
+
description: "Detailed description of what the rule validates and why it is necessary",
|
|
675
|
+
examples: [
|
|
676
|
+
"Validates that each MassID is unique within the system to prevent duplicate entries"
|
|
677
|
+
]
|
|
678
|
+
}),
|
|
679
|
+
source_code_url: zod.z.url().regex(/^https:\/\/github\.com\/.*$/, "Must be a GitHub URL").meta({
|
|
680
|
+
title: "Rule Source Code URL",
|
|
681
|
+
description: "GitHub URL pointing to the implementation source code for this rule",
|
|
682
|
+
examples: [
|
|
683
|
+
"https://github.com/carrot-foundation/methodologies/blob/main/bold-carbon/rules/waste-mass-unique.js"
|
|
684
|
+
]
|
|
685
|
+
}),
|
|
686
|
+
execution_order: PositiveIntegerSchema.meta({
|
|
687
|
+
title: "Rule Execution Order",
|
|
688
|
+
description: "Sequential order in which this rule must be executed"
|
|
689
|
+
})
|
|
690
|
+
}).meta({
|
|
691
|
+
title: "Audit Rule Definition",
|
|
692
|
+
description: "Definition of an audit rule that must be executed for methodology compliance"
|
|
693
|
+
});
|
|
694
|
+
var AuditRuleDefinitionsSchema = zod.z.array(AuditRuleDefinitionSchema).min(1).meta({
|
|
695
|
+
title: "Audit Rule Definitions",
|
|
696
|
+
description: "List of audit rules that must be executed to check methodology compliance"
|
|
697
|
+
});
|
|
698
|
+
var AuditRuleExecutionResultSchema = zod.z.strictObject({
|
|
699
|
+
rule_name: NonEmptyStringSchema.meta({
|
|
700
|
+
title: "Rule Name",
|
|
701
|
+
description: "Human-readable name of the audit rule"
|
|
702
|
+
}),
|
|
703
|
+
rule_id: UuidSchema.meta({
|
|
704
|
+
title: "Rule ID",
|
|
705
|
+
description: "Unique identifier for the rule"
|
|
706
|
+
}),
|
|
707
|
+
rule_slug: SlugSchema.meta({
|
|
708
|
+
title: "Rule Slug",
|
|
709
|
+
description: "URL-friendly identifier for the rule"
|
|
710
|
+
}),
|
|
711
|
+
execution_order: PositiveIntegerSchema.meta({
|
|
712
|
+
title: "Rule Execution Order",
|
|
713
|
+
description: "Sequential order in which this rule was executed"
|
|
714
|
+
}),
|
|
715
|
+
result: MethodologyComplianceSchema.meta({
|
|
716
|
+
title: "Rule Execution Result",
|
|
717
|
+
description: "Result of the rule execution"
|
|
718
|
+
}),
|
|
719
|
+
description: zod.z.string().min(1).max(2e3).meta({
|
|
720
|
+
title: "Rule Description",
|
|
721
|
+
description: "Detailed description of what this rule validates"
|
|
722
|
+
}),
|
|
723
|
+
rule_processor_checksum: NonEmptyStringSchema.max(200).meta({
|
|
724
|
+
title: "Rule Processor Checksum",
|
|
725
|
+
description: "Checksum for rule processor integrity verification"
|
|
726
|
+
}),
|
|
727
|
+
rule_source_code_version: NonEmptyStringSchema.max(200).meta({
|
|
728
|
+
title: "Rule Source Code Version",
|
|
729
|
+
description: "Version identifier for the rule source code"
|
|
730
|
+
})
|
|
731
|
+
}).meta({
|
|
732
|
+
title: "Audit Rule Execution Result",
|
|
733
|
+
description: "Detailed result of an audit rule execution"
|
|
734
|
+
});
|
|
735
|
+
var AuditRuleExecutionResultsSchema = zod.z.array(AuditRuleExecutionResultSchema).meta({
|
|
736
|
+
title: "Audit Rule Execution Results",
|
|
737
|
+
description: "Detailed results of each audit rule execution"
|
|
738
|
+
});
|
|
739
|
+
var ParticipantSchema = zod.z.strictObject({
|
|
740
|
+
id_hash: Sha256HashSchema.meta({
|
|
741
|
+
title: "Participant ID Hash",
|
|
742
|
+
description: "Anonymized identifier for the participant"
|
|
743
|
+
}),
|
|
744
|
+
name: ParticipantNameSchema,
|
|
745
|
+
roles: uniqueArrayItems(
|
|
746
|
+
ParticipantRoleSchema,
|
|
747
|
+
"Participant roles must be unique"
|
|
748
|
+
).min(1).meta({
|
|
749
|
+
title: "Participant Roles",
|
|
750
|
+
description: "Roles of the participant in the waste management supply chain"
|
|
751
|
+
})
|
|
752
|
+
}).meta({
|
|
753
|
+
title: "Participant",
|
|
754
|
+
description: "A participant in the waste management supply chain"
|
|
755
|
+
});
|
|
756
|
+
var PrecisionLevelSchema = zod.z.enum(["city", "region", "country"]).meta({
|
|
757
|
+
title: "Coordinate Precision Level",
|
|
758
|
+
description: "Level of coordinate precision",
|
|
759
|
+
examples: ["city"]
|
|
760
|
+
});
|
|
761
|
+
var CoordinatesSchema = zod.z.strictObject({
|
|
762
|
+
latitude: LatitudeSchema,
|
|
763
|
+
longitude: LongitudeSchema,
|
|
764
|
+
precision_level: PrecisionLevelSchema
|
|
765
|
+
}).meta({
|
|
766
|
+
title: "Coordinates",
|
|
767
|
+
description: "GPS coordinates of the location"
|
|
768
|
+
});
|
|
769
|
+
var LocationSchema = zod.z.strictObject({
|
|
770
|
+
id_hash: Sha256HashSchema.meta({
|
|
771
|
+
title: "Location ID Hash",
|
|
772
|
+
description: "Anonymized identifier for the location"
|
|
773
|
+
}),
|
|
774
|
+
municipality: MunicipalitySchema,
|
|
775
|
+
administrative_division: AdministrativeDivisionSchema,
|
|
776
|
+
administrative_division_code: IsoAdministrativeDivisionCodeSchema.optional(),
|
|
777
|
+
country: CountryNameSchema,
|
|
778
|
+
country_code: IsoCountryCodeSchema,
|
|
779
|
+
responsible_participant_id_hash: Sha256HashSchema.meta({
|
|
780
|
+
title: "Responsible Participant ID Hash",
|
|
781
|
+
description: "Anonymized ID of the participant responsible for this location"
|
|
782
|
+
}),
|
|
783
|
+
coordinates: CoordinatesSchema
|
|
784
|
+
}).meta({
|
|
785
|
+
title: "Location",
|
|
786
|
+
description: "Geographic location with address and coordinate information"
|
|
787
|
+
});
|
|
788
|
+
var GasIDReferenceSchema = zod.z.strictObject({
|
|
789
|
+
external_id: ExternalIdSchema.meta({
|
|
790
|
+
title: "GasID External ID",
|
|
791
|
+
description: "Unique identifier for the GasID"
|
|
792
|
+
}),
|
|
793
|
+
token_id: TokenIdSchema.meta({
|
|
794
|
+
title: "GasID Token ID",
|
|
795
|
+
description: "NFT token ID of the GasID"
|
|
796
|
+
}),
|
|
797
|
+
external_url: ExternalUrlSchema.meta({
|
|
798
|
+
title: "GasID External URL",
|
|
799
|
+
description: "URL to view the GasID on Carrot Explorer"
|
|
800
|
+
}),
|
|
801
|
+
uri: IpfsUriSchema.meta({
|
|
802
|
+
title: "GasID IPFS URI",
|
|
803
|
+
description: "IPFS URI of the GasID record"
|
|
804
|
+
})
|
|
805
|
+
}).meta({
|
|
806
|
+
title: "GasID Reference",
|
|
807
|
+
description: "Reference to a GasID record"
|
|
970
808
|
});
|
|
971
|
-
var
|
|
972
|
-
|
|
973
|
-
|
|
809
|
+
var MassIDReferenceSchema = zod.z.strictObject({
|
|
810
|
+
external_id: ExternalIdSchema.meta({
|
|
811
|
+
title: "MassID External ID",
|
|
812
|
+
description: "Unique identifier for the MassID"
|
|
813
|
+
}),
|
|
814
|
+
token_id: TokenIdSchema.meta({
|
|
974
815
|
title: "MassID Token ID",
|
|
975
|
-
description: "
|
|
816
|
+
description: "NFT token ID of the MassID"
|
|
817
|
+
}),
|
|
818
|
+
external_url: ExternalUrlSchema.meta({
|
|
819
|
+
title: "MassID External URL",
|
|
820
|
+
description: "URL to view the MassID on Carrot Explorer"
|
|
821
|
+
}),
|
|
822
|
+
uri: IpfsUriSchema.meta({
|
|
823
|
+
title: "MassID IPFS URI",
|
|
824
|
+
description: "IPFS URI of the MassID record"
|
|
976
825
|
})
|
|
977
826
|
}).meta({
|
|
978
|
-
title: "MassID
|
|
979
|
-
description: "
|
|
827
|
+
title: "MassID Reference",
|
|
828
|
+
description: "Reference to a MassID record"
|
|
980
829
|
});
|
|
981
|
-
var
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
value: UnixTimestampSchema.meta({
|
|
986
|
-
title: "MassID Recycling Date",
|
|
987
|
-
description: "Unix timestamp in milliseconds when the source waste was recycled"
|
|
830
|
+
var MethodologyReferenceSchema = zod.z.strictObject({
|
|
831
|
+
external_id: ExternalIdSchema.meta({
|
|
832
|
+
title: "Methodology External ID",
|
|
833
|
+
description: "Unique identifier for the methodology"
|
|
988
834
|
}),
|
|
989
|
-
|
|
835
|
+
name: NonEmptyStringSchema.min(5).max(150).meta({
|
|
836
|
+
title: "Methodology Name",
|
|
837
|
+
description: "Human-readable name of the methodology",
|
|
838
|
+
examples: ["BOLD Carbon (CH\u2084)", "BOLD Recycling"]
|
|
839
|
+
}),
|
|
840
|
+
version: SemanticVersionSchema.meta({
|
|
841
|
+
title: "Methodology Version",
|
|
842
|
+
description: "Version of the methodology"
|
|
843
|
+
}),
|
|
844
|
+
external_url: ExternalUrlSchema.meta({
|
|
845
|
+
title: "Methodology External URL",
|
|
846
|
+
description: "URL to view the methodology on Carrot Explorer"
|
|
847
|
+
}),
|
|
848
|
+
uri: IpfsUriSchema.optional().meta({
|
|
849
|
+
title: "Methodology IPFS URI",
|
|
850
|
+
description: "IPFS URI to the methodology record"
|
|
851
|
+
})
|
|
990
852
|
}).meta({
|
|
991
|
-
title: "
|
|
992
|
-
description: "
|
|
853
|
+
title: "Methodology Reference",
|
|
854
|
+
description: "Reference to a methodology record"
|
|
993
855
|
});
|
|
994
|
-
var
|
|
995
|
-
|
|
996
|
-
title: "
|
|
997
|
-
description: "
|
|
856
|
+
var WasteClassificationSchema = zod.z.strictObject({
|
|
857
|
+
primary_type: WasteTypeSchema.meta({
|
|
858
|
+
title: "Source Waste Primary Type",
|
|
859
|
+
description: "Primary type of the source waste"
|
|
998
860
|
}),
|
|
999
|
-
|
|
1000
|
-
title: "
|
|
1001
|
-
description: "
|
|
861
|
+
subtype: WasteSubtypeSchema.meta({
|
|
862
|
+
title: "Source Waste Subtype",
|
|
863
|
+
description: "Subtype of the source waste"
|
|
1002
864
|
}),
|
|
1003
|
-
|
|
1004
|
-
title: "
|
|
1005
|
-
description: "
|
|
1006
|
-
|
|
865
|
+
net_weight_kg: WeightKgSchema.meta({
|
|
866
|
+
title: "Source Waste Net Weight",
|
|
867
|
+
description: "Net weight of the source waste"
|
|
868
|
+
})
|
|
869
|
+
}).meta({
|
|
870
|
+
title: "Waste Classification",
|
|
871
|
+
description: "Classification of the source waste (MassID)"
|
|
872
|
+
});
|
|
873
|
+
var AccreditedParticipantSchema = zod.z.strictObject({
|
|
874
|
+
participant_id: UuidSchema.meta({
|
|
875
|
+
title: "Participant ID",
|
|
876
|
+
description: "Unique identifier for the participant"
|
|
1007
877
|
}),
|
|
1008
|
-
|
|
1009
|
-
title: "
|
|
1010
|
-
description: "
|
|
1011
|
-
examples: [
|
|
1012
|
-
"Validates that each MassID is unique within the system to prevent duplicate entries"
|
|
1013
|
-
]
|
|
878
|
+
name: ParticipantNameSchema.meta({
|
|
879
|
+
title: "Participant Name",
|
|
880
|
+
description: "Name of the participant"
|
|
1014
881
|
}),
|
|
1015
|
-
|
|
1016
|
-
title: "
|
|
1017
|
-
description: "
|
|
1018
|
-
examples: [
|
|
1019
|
-
"https://github.com/carrot-foundation/methodologies/blob/main/bold-carbon/rules/waste-mass-unique.js"
|
|
1020
|
-
]
|
|
882
|
+
role: ParticipantRoleSchema.meta({
|
|
883
|
+
title: "Participant Role",
|
|
884
|
+
description: "Role of the participant in the supply chain"
|
|
1021
885
|
}),
|
|
1022
|
-
|
|
1023
|
-
title: "
|
|
1024
|
-
description: "
|
|
886
|
+
accreditation_id: UuidSchema.meta({
|
|
887
|
+
title: "Accreditation ID",
|
|
888
|
+
description: "Unique identifier for the participant accreditation"
|
|
1025
889
|
}),
|
|
1026
|
-
|
|
1027
|
-
title: "
|
|
1028
|
-
description: "
|
|
890
|
+
external_url: ExternalUrlSchema.meta({
|
|
891
|
+
title: "Participant Accreditation External URL",
|
|
892
|
+
description: "URL to view the participant accreditation on Carrot Explorer"
|
|
1029
893
|
})
|
|
1030
894
|
}).meta({
|
|
1031
|
-
title: "
|
|
1032
|
-
description: "
|
|
895
|
+
title: "Accredited Participant",
|
|
896
|
+
description: "Participant with valid accreditation in the supply chain"
|
|
1033
897
|
});
|
|
1034
|
-
var
|
|
1035
|
-
title: "
|
|
1036
|
-
description: "List of
|
|
898
|
+
var AccreditedParticipantsSchema = zod.z.array(AccreditedParticipantSchema).min(1).meta({
|
|
899
|
+
title: "Accredited Participants",
|
|
900
|
+
description: "List of participants with valid accreditations"
|
|
1037
901
|
});
|
|
1038
|
-
var
|
|
1039
|
-
|
|
1040
|
-
title: "
|
|
1041
|
-
description: "
|
|
1042
|
-
}),
|
|
1043
|
-
rule_id: UuidSchema.meta({
|
|
1044
|
-
title: "Rule ID",
|
|
1045
|
-
description: "Unique identifier for the rule"
|
|
902
|
+
var RewardAllocationSchema = zod.z.strictObject({
|
|
903
|
+
participant_id: UuidSchema.meta({
|
|
904
|
+
title: "Participant ID",
|
|
905
|
+
description: "Unique identifier for the participant receiving the reward"
|
|
1046
906
|
}),
|
|
1047
|
-
|
|
1048
|
-
title: "
|
|
1049
|
-
description: "
|
|
907
|
+
participant_name: ParticipantNameSchema.meta({
|
|
908
|
+
title: "Participant Name",
|
|
909
|
+
description: "Name of the participant receiving the reward"
|
|
1050
910
|
}),
|
|
1051
|
-
|
|
1052
|
-
title: "
|
|
1053
|
-
description: "
|
|
911
|
+
role: ParticipantRoleSchema.meta({
|
|
912
|
+
title: "Participant Role",
|
|
913
|
+
description: "Role of the participant in the supply chain"
|
|
1054
914
|
}),
|
|
1055
|
-
|
|
1056
|
-
title: "
|
|
1057
|
-
description: "
|
|
915
|
+
reward_percentage: PercentageSchema.meta({
|
|
916
|
+
title: "Reward Percentage",
|
|
917
|
+
description: "Reward percentage allocated to the participant"
|
|
1058
918
|
}),
|
|
1059
|
-
|
|
1060
|
-
title: "
|
|
1061
|
-
description: "
|
|
919
|
+
large_business_discount_applied: zod.z.boolean().optional().meta({
|
|
920
|
+
title: "Large Business Discount Applied",
|
|
921
|
+
description: "Whether the large business discount was applied"
|
|
1062
922
|
}),
|
|
1063
|
-
|
|
1064
|
-
title: "
|
|
1065
|
-
description: "
|
|
923
|
+
effective_percentage: PercentageSchema.meta({
|
|
924
|
+
title: "Effective Percentage",
|
|
925
|
+
description: "Effective percentage of the reward after discounts"
|
|
926
|
+
})
|
|
927
|
+
}).meta({
|
|
928
|
+
title: "Reward Allocation",
|
|
929
|
+
description: "Reward allocation for a specific participant"
|
|
930
|
+
});
|
|
931
|
+
var DistributionNotesSchema = zod.z.strictObject({
|
|
932
|
+
large_business_discount_applied: NonEmptyStringSchema.optional().meta({
|
|
933
|
+
title: "Large Business Discount Applied",
|
|
934
|
+
description: "Description of the large business discount applied",
|
|
935
|
+
examples: [
|
|
936
|
+
"50% reduction applied to participants with >$4M annual revenue"
|
|
937
|
+
]
|
|
1066
938
|
}),
|
|
1067
|
-
|
|
1068
|
-
title: "
|
|
1069
|
-
description: "
|
|
939
|
+
redirected_rewards: NonEmptyStringSchema.optional().meta({
|
|
940
|
+
title: "Redirected Rewards",
|
|
941
|
+
description: "Description of the redirected rewards",
|
|
942
|
+
examples: [
|
|
943
|
+
"Discounted rewards from large businesses redirected to accredited NGOs"
|
|
944
|
+
]
|
|
1070
945
|
})
|
|
1071
946
|
}).meta({
|
|
1072
|
-
title: "
|
|
1073
|
-
description: "
|
|
947
|
+
title: "Distribution Notes",
|
|
948
|
+
description: "Additional notes about the reward distribution"
|
|
1074
949
|
});
|
|
1075
|
-
var
|
|
1076
|
-
|
|
1077
|
-
|
|
950
|
+
var ParticipantRewardsSchema = zod.z.strictObject({
|
|
951
|
+
distribution_basis: NonEmptyStringSchema.max(200).meta({
|
|
952
|
+
title: "Distribution Basis",
|
|
953
|
+
description: "Basis for the rewards distribution"
|
|
954
|
+
}),
|
|
955
|
+
reward_allocations: zod.z.array(RewardAllocationSchema).min(1).meta({
|
|
956
|
+
title: "Reward Allocations",
|
|
957
|
+
description: "Rewards percentage allocated to each participant"
|
|
958
|
+
}),
|
|
959
|
+
distribution_notes: DistributionNotesSchema.optional().meta({
|
|
960
|
+
title: "Distribution Notes",
|
|
961
|
+
description: "Additional notes about the reward distribution"
|
|
962
|
+
})
|
|
963
|
+
}).meta({
|
|
964
|
+
title: "Participant Rewards",
|
|
965
|
+
description: "Rewards distribution to participants"
|
|
1078
966
|
});
|
|
1079
|
-
var EPSILON = 1e-9;
|
|
1080
|
-
function nearlyEqual(a, b, epsilon = EPSILON) {
|
|
1081
|
-
return Math.abs(a - b) <= epsilon;
|
|
1082
|
-
}
|
|
1083
967
|
var SummaryBaseSchema = zod.z.strictObject({
|
|
1084
968
|
total_certificates: PositiveIntegerSchema.meta({
|
|
1085
969
|
title: "Total Certificates",
|
|
@@ -1251,8 +1135,22 @@ function createReceiptCertificateSchema(params) {
|
|
|
1251
1135
|
...params.additionalShape
|
|
1252
1136
|
}).meta(params.meta);
|
|
1253
1137
|
}
|
|
1138
|
+
function getSchemaBaseUrl() {
|
|
1139
|
+
return `https://raw.githubusercontent.com/carrot-foundation/schemas/refs/tags/${getSchemaVersionOrDefault()}/schemas/ipfs`;
|
|
1140
|
+
}
|
|
1141
|
+
function buildSchemaUrl(schemaPath) {
|
|
1142
|
+
const cleanPath = schemaPath.startsWith("/") ? schemaPath.slice(1) : schemaPath;
|
|
1143
|
+
return `${getSchemaBaseUrl()}/${cleanPath}`;
|
|
1144
|
+
}
|
|
1145
|
+
function getSchemaVersionOrDefault() {
|
|
1146
|
+
return "0.1.42";
|
|
1147
|
+
}
|
|
1254
1148
|
|
|
1255
|
-
// src/shared/
|
|
1149
|
+
// src/shared/schema-validation.ts
|
|
1150
|
+
var EPSILON = 1e-9;
|
|
1151
|
+
function nearlyEqual(a, b, epsilon = EPSILON) {
|
|
1152
|
+
return Math.abs(a - b) <= epsilon;
|
|
1153
|
+
}
|
|
1256
1154
|
function buildMessage(message, value) {
|
|
1257
1155
|
return typeof message === "function" ? message(value) : message;
|
|
1258
1156
|
}
|
|
@@ -2171,8 +2069,17 @@ var GasIDIpfsSchema = NftIpfsSchema.safeExtend({
|
|
|
2171
2069
|
description: "GasID NFT schema type"
|
|
2172
2070
|
})
|
|
2173
2071
|
}),
|
|
2174
|
-
attributes: GasIDAttributesSchema,
|
|
2175
2072
|
data: GasIDDataSchema
|
|
2073
|
+
}).superRefine((value, ctx) => {
|
|
2074
|
+
const attributesResult = GasIDAttributesSchema.safeParse(value.attributes);
|
|
2075
|
+
if (!attributesResult.success) {
|
|
2076
|
+
attributesResult.error.issues.forEach((issue) => {
|
|
2077
|
+
ctx.addIssue({
|
|
2078
|
+
...issue,
|
|
2079
|
+
path: ["attributes", ...issue.path ?? []]
|
|
2080
|
+
});
|
|
2081
|
+
});
|
|
2082
|
+
}
|
|
2176
2083
|
}).meta(GasIDIpfsSchemaMeta);
|
|
2177
2084
|
var RecycledIDAttributeMethodologySchema = MethodologyAttributeSchema;
|
|
2178
2085
|
var RecycledIDAttributeRecycledMassWeightSchema = NftAttributeSchema.safeExtend({
|
|
@@ -2251,8 +2158,19 @@ var RecycledIDIpfsSchema = NftIpfsSchema.safeExtend({
|
|
|
2251
2158
|
description: "RecycledID NFT schema type"
|
|
2252
2159
|
})
|
|
2253
2160
|
}),
|
|
2254
|
-
attributes: RecycledIDAttributesSchema,
|
|
2255
2161
|
data: RecycledIDDataSchema
|
|
2162
|
+
}).superRefine((value, ctx) => {
|
|
2163
|
+
const attributesResult = RecycledIDAttributesSchema.safeParse(
|
|
2164
|
+
value.attributes
|
|
2165
|
+
);
|
|
2166
|
+
if (!attributesResult.success) {
|
|
2167
|
+
attributesResult.error.issues.forEach((issue) => {
|
|
2168
|
+
ctx.addIssue({
|
|
2169
|
+
...issue,
|
|
2170
|
+
path: ["attributes", ...issue.path ?? []]
|
|
2171
|
+
});
|
|
2172
|
+
});
|
|
2173
|
+
}
|
|
2256
2174
|
}).meta(RecycledIDIpfsSchemaMeta);
|
|
2257
2175
|
var CreditPurchaseReceiptCreditAttributeSchema = NftAttributeSchema.safeExtend({
|
|
2258
2176
|
trait_type: TokenSymbolSchema.meta({
|
|
@@ -3343,7 +3261,9 @@ var CollectionSchema = BaseIpfsSchema.safeExtend({
|
|
|
3343
3261
|
image: IpfsUriSchema.meta({
|
|
3344
3262
|
title: "Collection Image",
|
|
3345
3263
|
description: "IPFS URI pointing to the collection's visual representation",
|
|
3346
|
-
examples: [
|
|
3264
|
+
examples: [
|
|
3265
|
+
"ipfs://bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku/collection-icon.png"
|
|
3266
|
+
]
|
|
3347
3267
|
}),
|
|
3348
3268
|
description: zod.z.string().min(50).max(1e3).meta({
|
|
3349
3269
|
title: "Collection Description",
|
|
@@ -3385,7 +3305,9 @@ var CreditSchema = BaseIpfsSchema.safeExtend({
|
|
|
3385
3305
|
image: IpfsUriSchema.meta({
|
|
3386
3306
|
title: "Token Image",
|
|
3387
3307
|
description: "IPFS URI pointing to the token's visual representation image",
|
|
3388
|
-
examples: [
|
|
3308
|
+
examples: [
|
|
3309
|
+
"ipfs://bafybeigdyrztvzl5cceubvaxob7iqh6f3f7s36c74ojav2xsz2uib2g3vm/credit-icon.png"
|
|
3310
|
+
]
|
|
3389
3311
|
}),
|
|
3390
3312
|
description: zod.z.string().min(50).max(1e3).meta({
|
|
3391
3313
|
title: "Token Description",
|
|
@@ -3508,6 +3430,7 @@ var MassIDAuditSchema = BaseIpfsSchema.safeExtend({
|
|
|
3508
3430
|
data: MassIDAuditDataSchema
|
|
3509
3431
|
}).meta(MassIDAuditSchemaMeta);
|
|
3510
3432
|
|
|
3433
|
+
exports.ALLOWED_BLOCKCHAIN_NETWORKS = ALLOWED_BLOCKCHAIN_NETWORKS;
|
|
3511
3434
|
exports.AccreditedParticipantSchema = AccreditedParticipantSchema;
|
|
3512
3435
|
exports.AccreditedParticipantsSchema = AccreditedParticipantsSchema;
|
|
3513
3436
|
exports.AdministrativeDivisionSchema = AdministrativeDivisionSchema;
|
|
@@ -3516,6 +3439,7 @@ exports.AuditRuleDefinitionSchema = AuditRuleDefinitionSchema;
|
|
|
3516
3439
|
exports.AuditRuleDefinitionsSchema = AuditRuleDefinitionsSchema;
|
|
3517
3440
|
exports.AuditRuleExecutionResultSchema = AuditRuleExecutionResultSchema;
|
|
3518
3441
|
exports.AuditRuleExecutionResultsSchema = AuditRuleExecutionResultsSchema;
|
|
3442
|
+
exports.BLOCKCHAIN_NETWORK_CONFIG = BLOCKCHAIN_NETWORK_CONFIG;
|
|
3519
3443
|
exports.BaseIpfsSchema = BaseIpfsSchema;
|
|
3520
3444
|
exports.BlockchainChainIdSchema = BlockchainChainIdSchema;
|
|
3521
3445
|
exports.BlockchainNetworkNameSchema = BlockchainNetworkNameSchema;
|
|
@@ -3553,14 +3477,12 @@ exports.GasIDIpfsSchema = GasIDIpfsSchema;
|
|
|
3553
3477
|
exports.GasIDIpfsSchemaMeta = GasIDIpfsSchemaMeta;
|
|
3554
3478
|
exports.GasIDReferenceSchema = GasIDReferenceSchema;
|
|
3555
3479
|
exports.HexColorSchema = HexColorSchema;
|
|
3556
|
-
exports.HoursSchema = HoursSchema;
|
|
3557
3480
|
exports.IbamaWasteClassificationSchema = IbamaWasteClassificationSchema;
|
|
3558
3481
|
exports.IpfsUriSchema = IpfsUriSchema;
|
|
3559
3482
|
exports.IsoAdministrativeDivisionCodeSchema = IsoAdministrativeDivisionCodeSchema;
|
|
3560
3483
|
exports.IsoCountryCodeSchema = IsoCountryCodeSchema;
|
|
3561
3484
|
exports.IsoDateSchema = IsoDateSchema;
|
|
3562
3485
|
exports.IsoTimestampSchema = IsoTimestampSchema;
|
|
3563
|
-
exports.Keccak256HashSchema = Keccak256HashSchema;
|
|
3564
3486
|
exports.LatitudeSchema = LatitudeSchema;
|
|
3565
3487
|
exports.LocationSchema = LocationSchema;
|
|
3566
3488
|
exports.LongitudeSchema = LongitudeSchema;
|
|
@@ -3582,7 +3504,6 @@ exports.MethodologyNameSchema = MethodologyNameSchema;
|
|
|
3582
3504
|
exports.MethodologyReferenceSchema = MethodologyReferenceSchema;
|
|
3583
3505
|
exports.MethodologySchema = MethodologySchema;
|
|
3584
3506
|
exports.MethodologySchemaMeta = MethodologySchemaMeta;
|
|
3585
|
-
exports.MinutesSchema = MinutesSchema;
|
|
3586
3507
|
exports.MunicipalitySchema = MunicipalitySchema;
|
|
3587
3508
|
exports.NftAttributeSchema = NftAttributeSchema;
|
|
3588
3509
|
exports.NftIpfsSchema = NftIpfsSchema;
|
|
@@ -3599,7 +3520,6 @@ exports.PercentageSchema = PercentageSchema;
|
|
|
3599
3520
|
exports.PositiveIntegerSchema = PositiveIntegerSchema;
|
|
3600
3521
|
exports.ReceiptIdentitySchema = ReceiptIdentitySchema;
|
|
3601
3522
|
exports.RecordEnvironmentSchema = RecordEnvironmentSchema;
|
|
3602
|
-
exports.RecordRelationshipTypeSchema = RecordRelationshipTypeSchema;
|
|
3603
3523
|
exports.RecordSchemaTypeSchema = RecordSchemaTypeSchema;
|
|
3604
3524
|
exports.RecycledIDAttributesSchema = RecycledIDAttributesSchema;
|
|
3605
3525
|
exports.RecycledIDDataSchema = RecycledIDDataSchema;
|