@carrot-foundation/schemas 0.1.56 → 0.1.57
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 +514 -522
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2007 -2255
- package/dist/index.d.ts +2007 -2255
- package/dist/index.js +507 -522
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schemas/ipfs/collection/collection.example.json +5 -5
- package/schemas/ipfs/collection/collection.schema.json +2 -2
- package/schemas/ipfs/credit/credit.example.json +5 -5
- package/schemas/ipfs/credit/credit.schema.json +2 -2
- package/schemas/ipfs/credit-purchase-receipt/credit-purchase-receipt.example.json +72 -128
- package/schemas/ipfs/credit-purchase-receipt/credit-purchase-receipt.schema.json +268 -594
- package/schemas/ipfs/credit-retirement-receipt/credit-retirement-receipt.example.json +54 -102
- package/schemas/ipfs/credit-retirement-receipt/credit-retirement-receipt.schema.json +163 -369
- package/schemas/ipfs/gas-id/gas-id.example.json +5 -5
- package/schemas/ipfs/gas-id/gas-id.schema.json +2 -2
- package/schemas/ipfs/mass-id/mass-id.example.json +5 -5
- package/schemas/ipfs/mass-id/mass-id.schema.json +2 -2
- package/schemas/ipfs/mass-id-audit/mass-id-audit.example.json +5 -5
- package/schemas/ipfs/mass-id-audit/mass-id-audit.schema.json +2 -2
- package/schemas/ipfs/methodology/methodology.example.json +5 -5
- package/schemas/ipfs/methodology/methodology.schema.json +2 -2
- package/schemas/ipfs/recycled-id/recycled-id.example.json +5 -5
- package/schemas/ipfs/recycled-id/recycled-id.schema.json +2 -2
- package/schemas/schema-hashes.json +10 -10
package/dist/index.cjs
CHANGED
|
@@ -29271,54 +29271,33 @@ var SummaryBaseSchema = zod.z.strictObject({
|
|
|
29271
29271
|
total_certificates: PositiveIntegerSchema.meta({
|
|
29272
29272
|
title: "Total Certificates",
|
|
29273
29273
|
description: "Total number of certificates represented in the receipt"
|
|
29274
|
-
}),
|
|
29275
|
-
credit_symbols: uniqueArrayItems(
|
|
29276
|
-
CreditTokenSymbolSchema,
|
|
29277
|
-
"Credit symbols must be unique"
|
|
29278
|
-
).min(1).meta({
|
|
29279
|
-
title: "Credit Symbols",
|
|
29280
|
-
description: "Array of credit token symbols represented in the receipt"
|
|
29281
|
-
}),
|
|
29282
|
-
certificate_types: uniqueArrayItems(
|
|
29283
|
-
RecordSchemaTypeSchema.extract(["GasID", "RecycledID"]),
|
|
29284
|
-
"Certificate types must be unique"
|
|
29285
|
-
).min(1).meta({
|
|
29286
|
-
title: "Certificate Types",
|
|
29287
|
-
description: "Array of certificate types represented in the receipt"
|
|
29288
|
-
}),
|
|
29289
|
-
collection_slugs: uniqueArrayItems(
|
|
29290
|
-
CollectionSlugSchema,
|
|
29291
|
-
"Collection slugs must be unique"
|
|
29292
|
-
).min(1).meta({
|
|
29293
|
-
title: "Collection Slugs",
|
|
29294
|
-
description: "Array of collection slugs represented in the receipt"
|
|
29295
29274
|
})
|
|
29296
29275
|
});
|
|
29297
29276
|
var CreditPurchaseReceiptSummarySchema = SummaryBaseSchema.extend({
|
|
29298
|
-
|
|
29299
|
-
title: "Total USDC
|
|
29277
|
+
total_amount_usdc: NonNegativeFloatSchema.meta({
|
|
29278
|
+
title: "Total Amount (USDC)",
|
|
29300
29279
|
description: "Total amount paid in USDC for the purchase"
|
|
29301
29280
|
}),
|
|
29302
29281
|
total_credits: CreditAmountSchema.meta({
|
|
29303
29282
|
title: "Total Credits",
|
|
29304
29283
|
description: "Total amount of credits purchased"
|
|
29305
29284
|
}),
|
|
29306
|
-
|
|
29307
|
-
title: "
|
|
29308
|
-
description: "
|
|
29285
|
+
purchased_at: IsoDateTimeSchema.meta({
|
|
29286
|
+
title: "Purchased At",
|
|
29287
|
+
description: "ISO 8601 timestamp when the purchase was completed"
|
|
29309
29288
|
})
|
|
29310
29289
|
}).meta({
|
|
29311
29290
|
title: "Credit Purchase Receipt Summary",
|
|
29312
29291
|
description: "Summary totals for the credit purchase including amounts and collections represented"
|
|
29313
29292
|
});
|
|
29314
29293
|
var CreditRetirementReceiptSummarySchema = SummaryBaseSchema.extend({
|
|
29315
|
-
|
|
29316
|
-
title: "Total
|
|
29294
|
+
total_credits_retired: CreditAmountSchema.meta({
|
|
29295
|
+
title: "Total Credits Retired",
|
|
29317
29296
|
description: "Total amount of credits retired"
|
|
29318
29297
|
}),
|
|
29319
|
-
|
|
29320
|
-
title: "
|
|
29321
|
-
description: "
|
|
29298
|
+
retired_at: IsoDateTimeSchema.meta({
|
|
29299
|
+
title: "Retired At",
|
|
29300
|
+
description: "ISO 8601 timestamp when the retirement occurred"
|
|
29322
29301
|
})
|
|
29323
29302
|
}).meta({
|
|
29324
29303
|
title: "Credit Retirement Receipt Summary",
|
|
@@ -29342,14 +29321,17 @@ var ReceiptIdentitySchema = zod.z.strictObject({
|
|
|
29342
29321
|
title: "Identity",
|
|
29343
29322
|
description: "Participant identity information"
|
|
29344
29323
|
});
|
|
29345
|
-
var
|
|
29346
|
-
|
|
29324
|
+
var MassIDReferenceWithContractSchema = MassIDReferenceSchema.safeExtend({
|
|
29325
|
+
smart_contract_address: EthereumAddressSchema.meta({
|
|
29326
|
+
title: "Smart Contract Address",
|
|
29327
|
+
description: "Ethereum address of the smart contract"
|
|
29328
|
+
})
|
|
29347
29329
|
}).meta({
|
|
29348
29330
|
title: "MassID Reference with Smart Contract",
|
|
29349
|
-
description: "Reference to a MassID record
|
|
29331
|
+
description: "Reference to a MassID record with smart contract address"
|
|
29350
29332
|
});
|
|
29351
29333
|
function createReceiptCollectionSchema(params) {
|
|
29352
|
-
const {
|
|
29334
|
+
const { meta } = params;
|
|
29353
29335
|
return zod.z.strictObject({
|
|
29354
29336
|
slug: CollectionSlugSchema,
|
|
29355
29337
|
external_id: ExternalIdSchema.meta({
|
|
@@ -29361,16 +29343,19 @@ function createReceiptCollectionSchema(params) {
|
|
|
29361
29343
|
title: "Collection External URL",
|
|
29362
29344
|
description: "External URL for the collection"
|
|
29363
29345
|
}),
|
|
29364
|
-
|
|
29365
|
-
title: "Collection URI",
|
|
29346
|
+
ipfs_uri: IpfsUriSchema.meta({
|
|
29347
|
+
title: "Collection IPFS URI",
|
|
29366
29348
|
description: "IPFS URI for the collection metadata"
|
|
29367
29349
|
}),
|
|
29368
|
-
|
|
29350
|
+
smart_contract_address: EthereumAddressSchema.meta({
|
|
29351
|
+
title: "Smart Contract Address",
|
|
29352
|
+
description: "Ethereum address of the smart contract"
|
|
29353
|
+
})
|
|
29369
29354
|
}).meta(meta);
|
|
29370
29355
|
}
|
|
29371
29356
|
function createReceiptCreditSchema(params) {
|
|
29372
|
-
const {
|
|
29373
|
-
|
|
29357
|
+
const { meta } = params;
|
|
29358
|
+
return zod.z.strictObject({
|
|
29374
29359
|
slug: SlugSchema.meta({
|
|
29375
29360
|
title: "Credit Slug",
|
|
29376
29361
|
description: "URL-friendly identifier for the credit"
|
|
@@ -29387,24 +29372,52 @@ function createReceiptCreditSchema(params) {
|
|
|
29387
29372
|
title: "Credit External URL",
|
|
29388
29373
|
description: "External URL for the credit"
|
|
29389
29374
|
}),
|
|
29390
|
-
|
|
29391
|
-
title: "Credit URI",
|
|
29375
|
+
ipfs_uri: IpfsUriSchema.meta({
|
|
29376
|
+
title: "Credit IPFS URI",
|
|
29392
29377
|
description: "IPFS URI for the credit details"
|
|
29393
29378
|
}),
|
|
29394
|
-
|
|
29395
|
-
|
|
29396
|
-
|
|
29397
|
-
|
|
29398
|
-
|
|
29399
|
-
}
|
|
29400
|
-
return zod.z.strictObject(creditShape).meta(meta);
|
|
29379
|
+
smart_contract_address: EthereumAddressSchema.meta({
|
|
29380
|
+
title: "Smart Contract Address",
|
|
29381
|
+
description: "Ethereum address of the smart contract"
|
|
29382
|
+
})
|
|
29383
|
+
}).meta(meta);
|
|
29401
29384
|
}
|
|
29385
|
+
var CertificateCollectionItemPurchaseSchema = zod.z.strictObject({
|
|
29386
|
+
slug: CollectionSlugSchema.meta({
|
|
29387
|
+
title: "Collection Slug",
|
|
29388
|
+
description: "Slug of the collection"
|
|
29389
|
+
}),
|
|
29390
|
+
purchased_amount: CreditAmountSchema.meta({
|
|
29391
|
+
title: "Collection Purchased Amount",
|
|
29392
|
+
description: "Credits purchased from this collection for this certificate"
|
|
29393
|
+
}),
|
|
29394
|
+
retired_amount: CreditAmountSchema.meta({
|
|
29395
|
+
title: "Collection Retired Amount",
|
|
29396
|
+
description: "Credits retired from this collection for this certificate (0 if none)"
|
|
29397
|
+
})
|
|
29398
|
+
}).meta({
|
|
29399
|
+
title: "Certificate Collection Item (Purchase)",
|
|
29400
|
+
description: "Collection reference with purchased and retired amounts for a certificate in a purchase receipt"
|
|
29401
|
+
});
|
|
29402
|
+
var CertificateCollectionItemRetirementSchema = zod.z.strictObject({
|
|
29403
|
+
slug: CollectionSlugSchema.meta({
|
|
29404
|
+
title: "Collection Slug",
|
|
29405
|
+
description: "Slug of the collection"
|
|
29406
|
+
}),
|
|
29407
|
+
retired_amount: CreditAmountSchema.meta({
|
|
29408
|
+
title: "Collection Retired Amount",
|
|
29409
|
+
description: "Credits retired from this collection for this certificate"
|
|
29410
|
+
})
|
|
29411
|
+
}).meta({
|
|
29412
|
+
title: "Certificate Collection Item (Retirement)",
|
|
29413
|
+
description: "Collection reference with retired amount for a certificate in a retirement receipt"
|
|
29414
|
+
});
|
|
29402
29415
|
var certificateBaseShape = {
|
|
29403
29416
|
token_id: TokenIdSchema.meta({
|
|
29404
29417
|
title: "Certificate Token ID",
|
|
29405
29418
|
description: "Token ID of the certificate"
|
|
29406
29419
|
}),
|
|
29407
|
-
type:
|
|
29420
|
+
type: zod.z.enum(["GasID", "RecycledID"]).meta({
|
|
29408
29421
|
title: "Certificate Type",
|
|
29409
29422
|
description: "Type of certificate (e.g., GasID, RecycledID)"
|
|
29410
29423
|
}),
|
|
@@ -29416,20 +29429,19 @@ var certificateBaseShape = {
|
|
|
29416
29429
|
title: "Certificate External URL",
|
|
29417
29430
|
description: "External URL for the certificate"
|
|
29418
29431
|
}),
|
|
29419
|
-
|
|
29420
|
-
title: "Certificate URI",
|
|
29432
|
+
ipfs_uri: IpfsUriSchema.meta({
|
|
29433
|
+
title: "Certificate IPFS URI",
|
|
29421
29434
|
description: "IPFS URI for the certificate metadata"
|
|
29422
29435
|
}),
|
|
29423
|
-
|
|
29424
|
-
|
|
29425
|
-
|
|
29426
|
-
description: "Slug of the collection this certificate belongs to"
|
|
29436
|
+
smart_contract_address: EthereumAddressSchema.meta({
|
|
29437
|
+
title: "Smart Contract Address",
|
|
29438
|
+
description: "Ethereum address of the smart contract"
|
|
29427
29439
|
}),
|
|
29428
29440
|
total_amount: CreditAmountSchema.meta({
|
|
29429
29441
|
title: "Certificate Total Amount",
|
|
29430
29442
|
description: "Total credits available in this certificate"
|
|
29431
29443
|
}),
|
|
29432
|
-
mass_id:
|
|
29444
|
+
mass_id: MassIDReferenceWithContractSchema
|
|
29433
29445
|
};
|
|
29434
29446
|
function createReceiptCertificateSchema(params) {
|
|
29435
29447
|
return zod.z.strictObject({
|
|
@@ -29445,7 +29457,7 @@ function buildSchemaUrl(schemaPath) {
|
|
|
29445
29457
|
return `${getSchemaBaseUrl()}/${cleanPath}`;
|
|
29446
29458
|
}
|
|
29447
29459
|
function getSchemaVersionOrDefault() {
|
|
29448
|
-
return "0.1.
|
|
29460
|
+
return "0.1.57";
|
|
29449
29461
|
}
|
|
29450
29462
|
|
|
29451
29463
|
// src/shared/schema-validation.ts
|
|
@@ -29601,6 +29613,104 @@ function validateAttributesForItems(params) {
|
|
|
29601
29613
|
}
|
|
29602
29614
|
});
|
|
29603
29615
|
}
|
|
29616
|
+
function validateCertificateCollectionSlugs(params) {
|
|
29617
|
+
const {
|
|
29618
|
+
ctx,
|
|
29619
|
+
certificateCollections,
|
|
29620
|
+
validCollectionSlugs,
|
|
29621
|
+
certificateIndex,
|
|
29622
|
+
message = "certificate.collections[].slug must match a collection slug in collections"
|
|
29623
|
+
} = params;
|
|
29624
|
+
certificateCollections.forEach((collectionItem, collectionIndex) => {
|
|
29625
|
+
if (!validCollectionSlugs.has(collectionItem.slug)) {
|
|
29626
|
+
ctx.addIssue({
|
|
29627
|
+
code: "custom",
|
|
29628
|
+
message,
|
|
29629
|
+
path: [
|
|
29630
|
+
"certificates",
|
|
29631
|
+
certificateIndex,
|
|
29632
|
+
"collections",
|
|
29633
|
+
collectionIndex,
|
|
29634
|
+
"slug"
|
|
29635
|
+
]
|
|
29636
|
+
});
|
|
29637
|
+
}
|
|
29638
|
+
});
|
|
29639
|
+
}
|
|
29640
|
+
function validateRetirementReceiptRequirement(params) {
|
|
29641
|
+
const {
|
|
29642
|
+
ctx,
|
|
29643
|
+
hasRetirementReceipt,
|
|
29644
|
+
totalRetiredAmount,
|
|
29645
|
+
messageWhenPresentButNoRetired = "retirement_receipt is present but no certificate has retired_amount greater than 0",
|
|
29646
|
+
messageWhenRetiredButNotPresent = "certificates with retired amounts > 0 require retirement_receipt"
|
|
29647
|
+
} = params;
|
|
29648
|
+
if (hasRetirementReceipt) {
|
|
29649
|
+
if (totalRetiredAmount === 0) {
|
|
29650
|
+
ctx.addIssue({
|
|
29651
|
+
code: "custom",
|
|
29652
|
+
message: messageWhenPresentButNoRetired,
|
|
29653
|
+
path: ["retirement_receipt"]
|
|
29654
|
+
});
|
|
29655
|
+
}
|
|
29656
|
+
} else if (totalRetiredAmount > 0) {
|
|
29657
|
+
ctx.addIssue({
|
|
29658
|
+
code: "custom",
|
|
29659
|
+
message: messageWhenRetiredButNotPresent,
|
|
29660
|
+
path: ["retirement_receipt"]
|
|
29661
|
+
});
|
|
29662
|
+
}
|
|
29663
|
+
}
|
|
29664
|
+
function validateCollectionsHaveRetiredAmounts(params) {
|
|
29665
|
+
const {
|
|
29666
|
+
ctx,
|
|
29667
|
+
collections,
|
|
29668
|
+
retiredTotalsBySlug,
|
|
29669
|
+
message = "collection must be referenced by at least one certificate with retired amounts > 0"
|
|
29670
|
+
} = params;
|
|
29671
|
+
collections.forEach((collection, index) => {
|
|
29672
|
+
const retiredTotal = retiredTotalsBySlug.get(String(collection.slug)) ?? 0;
|
|
29673
|
+
if (retiredTotal === 0) {
|
|
29674
|
+
ctx.addIssue({
|
|
29675
|
+
code: "custom",
|
|
29676
|
+
message,
|
|
29677
|
+
path: ["collections", index, "slug"]
|
|
29678
|
+
});
|
|
29679
|
+
}
|
|
29680
|
+
});
|
|
29681
|
+
}
|
|
29682
|
+
function validateCreditSlugExists(params) {
|
|
29683
|
+
const {
|
|
29684
|
+
ctx,
|
|
29685
|
+
creditSlug,
|
|
29686
|
+
validCreditSlugs,
|
|
29687
|
+
path,
|
|
29688
|
+
message = "credit_slug must match a credit slug in credits"
|
|
29689
|
+
} = params;
|
|
29690
|
+
if (!validCreditSlugs.has(creditSlug)) {
|
|
29691
|
+
ctx.addIssue({
|
|
29692
|
+
code: "custom",
|
|
29693
|
+
message,
|
|
29694
|
+
path
|
|
29695
|
+
});
|
|
29696
|
+
}
|
|
29697
|
+
}
|
|
29698
|
+
function validateCreditSymbolExists(params) {
|
|
29699
|
+
const {
|
|
29700
|
+
ctx,
|
|
29701
|
+
creditSymbol,
|
|
29702
|
+
validCreditSymbols,
|
|
29703
|
+
path,
|
|
29704
|
+
message = "credit_symbol must match a credit symbol in credits"
|
|
29705
|
+
} = params;
|
|
29706
|
+
if (!validCreditSymbols.has(creditSymbol)) {
|
|
29707
|
+
ctx.addIssue({
|
|
29708
|
+
code: "custom",
|
|
29709
|
+
message,
|
|
29710
|
+
path
|
|
29711
|
+
});
|
|
29712
|
+
}
|
|
29713
|
+
}
|
|
29604
29714
|
function canonicalizeForHash(value) {
|
|
29605
29715
|
const canonical = canonicalize__default.default(value);
|
|
29606
29716
|
if (canonical === void 0) {
|
|
@@ -30382,9 +30492,9 @@ var CreditPurchaseReceiptTotalCreditsAttributeSchema = createNumericAttributeSch
|
|
|
30382
30492
|
description: "Total number of credits purchased across all tokens",
|
|
30383
30493
|
valueSchema: CreditAmountSchema
|
|
30384
30494
|
});
|
|
30385
|
-
var
|
|
30386
|
-
traitType: "Total USDC
|
|
30387
|
-
title: "Total USDC
|
|
30495
|
+
var CreditPurchaseReceiptPurchasePriceAttributeSchema = createNumericAttributeSchema({
|
|
30496
|
+
traitType: "Total Amount (USDC)",
|
|
30497
|
+
title: "Total Amount (USDC)",
|
|
30388
30498
|
description: "Total USDC amount paid for the purchase",
|
|
30389
30499
|
valueSchema: CreditAmountSchema
|
|
30390
30500
|
});
|
|
@@ -30399,43 +30509,48 @@ var CreditPurchaseReceiptCertificatesAttributeSchema = createNumericAttributeSch
|
|
|
30399
30509
|
description: "Total number of certificates purchased",
|
|
30400
30510
|
valueSchema: PositiveIntegerSchema
|
|
30401
30511
|
});
|
|
30402
|
-
var
|
|
30512
|
+
var CreditPurchaseReceiptBuyerAttributeSchema = NftAttributeSchema.omit({
|
|
30403
30513
|
display_type: true,
|
|
30404
30514
|
max_value: true
|
|
30405
30515
|
}).safeExtend({
|
|
30406
|
-
trait_type: zod.z.literal("
|
|
30516
|
+
trait_type: zod.z.literal("Buyer"),
|
|
30407
30517
|
value: NonEmptyStringSchema.max(100).meta({
|
|
30408
|
-
title: "
|
|
30409
|
-
description: "Organization or individual
|
|
30518
|
+
title: "Buyer",
|
|
30519
|
+
description: "Organization or individual purchasing the credits",
|
|
30410
30520
|
examples: ["EcoTech Solutions Inc."]
|
|
30411
30521
|
})
|
|
30412
30522
|
}).meta({
|
|
30413
|
-
title: "
|
|
30414
|
-
description: "Attribute containing the
|
|
30523
|
+
title: "Buyer Attribute",
|
|
30524
|
+
description: "Attribute containing the buyer display name"
|
|
30415
30525
|
});
|
|
30416
|
-
var
|
|
30417
|
-
|
|
30418
|
-
|
|
30419
|
-
|
|
30420
|
-
|
|
30421
|
-
|
|
30422
|
-
|
|
30526
|
+
var CreditPurchaseReceiptRetirementDateAttributeSchema = createDateAttributeSchema({
|
|
30527
|
+
traitType: "Retirement Date",
|
|
30528
|
+
title: "Retirement Date",
|
|
30529
|
+
description: "Unix timestamp in milliseconds when credits were retired (if retirement occurred)"
|
|
30530
|
+
});
|
|
30531
|
+
var CreditPurchaseReceiptRetirementReceiptAttributeSchema = NftAttributeSchema.safeExtend({
|
|
30532
|
+
trait_type: zod.z.literal("Retirement Receipt"),
|
|
30533
|
+
value: StringifiedTokenIdSchema.meta({
|
|
30534
|
+
title: "Retirement Receipt Token ID",
|
|
30535
|
+
description: "Token ID of the retirement receipt NFT as #<token_id> (if retirement occurred)"
|
|
30536
|
+
})
|
|
30423
30537
|
}).meta({
|
|
30424
|
-
title: "
|
|
30425
|
-
description: "
|
|
30538
|
+
title: "Retirement Receipt Attribute",
|
|
30539
|
+
description: "Retirement receipt token ID attribute"
|
|
30426
30540
|
});
|
|
30427
30541
|
var REQUIRED_CREDIT_PURCHASE_RECEIPT_ATTRIBUTES = [
|
|
30428
30542
|
CreditPurchaseReceiptTotalCreditsAttributeSchema,
|
|
30429
|
-
|
|
30543
|
+
CreditPurchaseReceiptPurchasePriceAttributeSchema,
|
|
30430
30544
|
CreditPurchaseReceiptPurchaseDateAttributeSchema,
|
|
30431
30545
|
CreditPurchaseReceiptCertificatesAttributeSchema
|
|
30432
30546
|
];
|
|
30433
30547
|
var CONDITIONAL_CREDIT_PURCHASE_RECEIPT_ATTRIBUTES = [
|
|
30434
|
-
|
|
30548
|
+
CreditPurchaseReceiptBuyerAttributeSchema,
|
|
30549
|
+
CreditPurchaseReceiptRetirementDateAttributeSchema,
|
|
30550
|
+
CreditPurchaseReceiptRetirementReceiptAttributeSchema
|
|
30435
30551
|
];
|
|
30436
30552
|
var DYNAMIC_CREDIT_PURCHASE_RECEIPT_ATTRIBUTES = [
|
|
30437
|
-
CreditPurchaseReceiptCreditAttributeSchema
|
|
30438
|
-
CreditPurchaseReceiptCollectionAttributeSchema
|
|
30553
|
+
CreditPurchaseReceiptCreditAttributeSchema
|
|
30439
30554
|
];
|
|
30440
30555
|
var CreditPurchaseReceiptAttributesSchema = createOrderedAttributesSchema({
|
|
30441
30556
|
required: REQUIRED_CREDIT_PURCHASE_RECEIPT_ATTRIBUTES,
|
|
@@ -30444,68 +30559,37 @@ var CreditPurchaseReceiptAttributesSchema = createOrderedAttributesSchema({
|
|
|
30444
30559
|
...DYNAMIC_CREDIT_PURCHASE_RECEIPT_ATTRIBUTES
|
|
30445
30560
|
],
|
|
30446
30561
|
title: "Credit Purchase Receipt NFT Attribute Array",
|
|
30447
|
-
description: "Attributes for credit purchase receipts including per-credit breakdowns, totals,
|
|
30562
|
+
description: "Attributes for credit purchase receipts including per-credit breakdowns, totals, buyer, purchase date, and optional retirement info. Fixed required attributes: Total Credits Purchased, Total Amount (USDC), Purchase Date, Certificates Purchased. Conditional attributes: Buyer (required when buyer.identity.name is provided), Retirement Date (optional, when retirement_receipt is present), Retirement Receipt (optional, when retirement_receipt is present). Dynamic attributes: Credit attributes (one per credit symbol in data.credits).",
|
|
30448
30563
|
uniqueBySelector: (attribute) => attribute.trait_type,
|
|
30449
30564
|
requiredTraitTypes: [
|
|
30450
30565
|
"Total Credits Purchased",
|
|
30451
|
-
"Total USDC
|
|
30566
|
+
"Total Amount (USDC)",
|
|
30452
30567
|
"Purchase Date",
|
|
30453
30568
|
"Certificates Purchased"
|
|
30454
30569
|
]
|
|
30455
30570
|
});
|
|
30456
30571
|
var CreditPurchaseReceiptIdentitySchema = ReceiptIdentitySchema;
|
|
30457
|
-
var
|
|
30572
|
+
var CreditPurchaseReceiptBuyerSchema = zod.z.strictObject({
|
|
30458
30573
|
wallet_address: EthereumAddressSchema.meta({
|
|
30459
|
-
title: "
|
|
30460
|
-
description: "Ethereum address
|
|
30574
|
+
title: "Buyer Wallet Address",
|
|
30575
|
+
description: "Ethereum address receiving the credits"
|
|
30461
30576
|
}),
|
|
30462
|
-
|
|
30463
|
-
}).meta({
|
|
30464
|
-
title: "Receiver",
|
|
30465
|
-
description: "Receiver wallet and optional identity information"
|
|
30466
|
-
});
|
|
30467
|
-
var CreditPurchaseReceiptBuyerSchema = zod.z.strictObject({
|
|
30468
|
-
buyer_id: ExternalIdSchema.meta({
|
|
30577
|
+
id: ExternalIdSchema.optional().meta({
|
|
30469
30578
|
title: "Buyer ID",
|
|
30470
30579
|
description: "Unique identifier for the buyer"
|
|
30471
30580
|
}),
|
|
30472
30581
|
identity: CreditPurchaseReceiptIdentitySchema.optional()
|
|
30473
30582
|
}).meta({
|
|
30474
30583
|
title: "Buyer",
|
|
30475
|
-
description: "Buyer
|
|
30476
|
-
});
|
|
30477
|
-
var CreditPurchaseReceiptPartiesSchema = zod.z.strictObject({
|
|
30478
|
-
payer: EthereumAddressSchema.meta({
|
|
30479
|
-
title: "Payer Wallet Address",
|
|
30480
|
-
description: "Ethereum address paying for the purchase"
|
|
30481
|
-
}),
|
|
30482
|
-
receiver: CreditPurchaseReceiptReceiverSchema,
|
|
30483
|
-
buyer: CreditPurchaseReceiptBuyerSchema.optional()
|
|
30484
|
-
}).meta({
|
|
30485
|
-
title: "Parties",
|
|
30486
|
-
description: "Parties involved in the purchase including payer, receiver, and optional buyer"
|
|
30584
|
+
description: "Buyer information including wallet address, optional ID, and optional identity"
|
|
30487
30585
|
});
|
|
30488
30586
|
var CreditPurchaseReceiptCollectionSchema = createReceiptCollectionSchema({
|
|
30489
|
-
amountKey: "credit_amount",
|
|
30490
|
-
amountMeta: {
|
|
30491
|
-
title: "Collection Credit Amount",
|
|
30492
|
-
description: "Total credits purchased from this collection"
|
|
30493
|
-
},
|
|
30494
30587
|
meta: {
|
|
30495
30588
|
title: "Collection",
|
|
30496
30589
|
description: "Collection included in the purchase"
|
|
30497
30590
|
}
|
|
30498
30591
|
});
|
|
30499
30592
|
var CreditPurchaseReceiptCreditSchema = createReceiptCreditSchema({
|
|
30500
|
-
amountKey: "purchase_amount",
|
|
30501
|
-
amountMeta: {
|
|
30502
|
-
title: "Credit Purchase Amount",
|
|
30503
|
-
description: "Total credits purchased for this credit type"
|
|
30504
|
-
},
|
|
30505
|
-
retirementAmountMeta: {
|
|
30506
|
-
title: "Credit Retirement Amount",
|
|
30507
|
-
description: "Credits retired immediately for this credit type during purchase"
|
|
30508
|
-
},
|
|
30509
30593
|
meta: {
|
|
30510
30594
|
title: "Credit",
|
|
30511
30595
|
description: "Credit token included in the purchase"
|
|
@@ -30513,18 +30597,18 @@ var CreditPurchaseReceiptCreditSchema = createReceiptCreditSchema({
|
|
|
30513
30597
|
});
|
|
30514
30598
|
var CreditPurchaseReceiptCertificateSchema = createReceiptCertificateSchema({
|
|
30515
30599
|
additionalShape: {
|
|
30516
|
-
purchased_amount: CreditAmountSchema.meta({
|
|
30517
|
-
title: "Certificate Purchased Amount",
|
|
30518
|
-
description: "Credits purchased from this certificate"
|
|
30519
|
-
}),
|
|
30520
|
-
retired_amount: CreditAmountSchema.meta({
|
|
30521
|
-
title: "Certificate Retired Amount",
|
|
30522
|
-
description: "Credits retired from this certificate during the purchase (0 if none)"
|
|
30523
|
-
}),
|
|
30524
30600
|
credit_slug: SlugSchema.meta({
|
|
30525
30601
|
title: "Credit Slug",
|
|
30526
30602
|
description: "Slug of the credit type for this certificate",
|
|
30527
30603
|
examples: ["carbon", "organic"]
|
|
30604
|
+
}),
|
|
30605
|
+
collections: uniqueBy(
|
|
30606
|
+
CertificateCollectionItemPurchaseSchema,
|
|
30607
|
+
(item) => item.slug,
|
|
30608
|
+
"Collection slugs within certificate collections must be unique"
|
|
30609
|
+
).min(1).meta({
|
|
30610
|
+
title: "Certificate Collections",
|
|
30611
|
+
description: "Collections associated with this certificate, each with purchased and retired amounts"
|
|
30528
30612
|
})
|
|
30529
30613
|
},
|
|
30530
30614
|
meta: {
|
|
@@ -30533,15 +30617,10 @@ var CreditPurchaseReceiptCertificateSchema = createReceiptCertificateSchema({
|
|
|
30533
30617
|
}
|
|
30534
30618
|
});
|
|
30535
30619
|
var CreditPurchaseReceiptParticipantRewardSchema = zod.z.strictObject({
|
|
30536
|
-
|
|
30620
|
+
participant_id_hash: Sha256HashSchema.meta({
|
|
30537
30621
|
title: "Participant ID Hash",
|
|
30538
30622
|
description: "Hash representing the participant identifier (SHA-256 hex string)"
|
|
30539
30623
|
}),
|
|
30540
|
-
participant_name: NonEmptyStringSchema.max(100).meta({
|
|
30541
|
-
title: "Participant Name",
|
|
30542
|
-
description: "Legal name of the participant receiving the reward",
|
|
30543
|
-
examples: ["EcoTech Solutions Inc.", "Green Tech Corp"]
|
|
30544
|
-
}),
|
|
30545
30624
|
roles: uniqueArrayItems(
|
|
30546
30625
|
ParticipantRoleSchema,
|
|
30547
30626
|
"Participant roles must be unique"
|
|
@@ -30570,28 +30649,21 @@ var CreditPurchaseReceiptRetirementReceiptSchema = zod.z.strictObject({
|
|
|
30570
30649
|
title: "Retirement Receipt External URL",
|
|
30571
30650
|
description: "External URL for the retirement receipt"
|
|
30572
30651
|
}),
|
|
30573
|
-
|
|
30574
|
-
title: "Retirement Receipt URI",
|
|
30652
|
+
ipfs_uri: IpfsUriSchema.meta({
|
|
30653
|
+
title: "Retirement Receipt IPFS URI",
|
|
30575
30654
|
description: "IPFS URI for the retirement receipt metadata"
|
|
30576
30655
|
}),
|
|
30577
|
-
|
|
30656
|
+
smart_contract_address: EthereumAddressSchema.meta({
|
|
30657
|
+
title: "Smart Contract Address",
|
|
30658
|
+
description: "Ethereum address of the smart contract"
|
|
30659
|
+
})
|
|
30578
30660
|
}).meta({
|
|
30579
30661
|
title: "Retirement Receipt Reference",
|
|
30580
30662
|
description: "Reference to the retirement receipt NFT"
|
|
30581
30663
|
});
|
|
30582
|
-
var CreditPurchaseReceiptRetirementSchema = zod.z.strictObject({
|
|
30583
|
-
beneficiary_id: ExternalIdSchema.meta({
|
|
30584
|
-
title: "Retirement Beneficiary ID",
|
|
30585
|
-
description: "UUID identifying the beneficiary of the retirement (bytes16 normalized to UUID)"
|
|
30586
|
-
}),
|
|
30587
|
-
retirement_receipt: CreditPurchaseReceiptRetirementReceiptSchema.optional()
|
|
30588
|
-
}).meta({
|
|
30589
|
-
title: "Retirement",
|
|
30590
|
-
description: "Immediate retirement details performed as part of purchase"
|
|
30591
|
-
});
|
|
30592
30664
|
var CreditPurchaseReceiptDataSchema = zod.z.strictObject({
|
|
30593
30665
|
summary: CreditPurchaseReceiptSummarySchema,
|
|
30594
|
-
|
|
30666
|
+
buyer: CreditPurchaseReceiptBuyerSchema,
|
|
30595
30667
|
collections: uniqueBy(
|
|
30596
30668
|
CreditPurchaseReceiptCollectionSchema,
|
|
30597
30669
|
(collection) => collection.slug,
|
|
@@ -30618,41 +30690,14 @@ var CreditPurchaseReceiptDataSchema = zod.z.strictObject({
|
|
|
30618
30690
|
}),
|
|
30619
30691
|
participant_rewards: uniqueBy(
|
|
30620
30692
|
CreditPurchaseReceiptParticipantRewardSchema,
|
|
30621
|
-
(reward) => reward.
|
|
30622
|
-
"Participant
|
|
30693
|
+
(reward) => reward.participant_id_hash,
|
|
30694
|
+
"Participant participant_id_hash must be unique"
|
|
30623
30695
|
).min(1).meta({
|
|
30624
30696
|
title: "Participant Rewards",
|
|
30625
30697
|
description: "Rewards distributed to participants in the supply chain for this purchase"
|
|
30626
30698
|
}),
|
|
30627
|
-
|
|
30699
|
+
retirement_receipt: CreditPurchaseReceiptRetirementReceiptSchema.optional()
|
|
30628
30700
|
}).superRefine((data, ctx) => {
|
|
30629
|
-
const retirementProvided = Boolean(data.retirement);
|
|
30630
|
-
const creditsWithRetirement = data.credits.reduce(
|
|
30631
|
-
(indices, credit, index) => {
|
|
30632
|
-
const retirementAmount = Number(credit.retirement_amount ?? 0);
|
|
30633
|
-
if (retirementAmount > 0) {
|
|
30634
|
-
indices.push(index);
|
|
30635
|
-
}
|
|
30636
|
-
return indices;
|
|
30637
|
-
},
|
|
30638
|
-
[]
|
|
30639
|
-
);
|
|
30640
|
-
if (retirementProvided && creditsWithRetirement.length === 0) {
|
|
30641
|
-
ctx.addIssue({
|
|
30642
|
-
code: "custom",
|
|
30643
|
-
message: "retirement is present but no credit has retirement_amount greater than 0",
|
|
30644
|
-
path: ["retirement"]
|
|
30645
|
-
});
|
|
30646
|
-
}
|
|
30647
|
-
if (!retirementProvided && creditsWithRetirement.length > 0) {
|
|
30648
|
-
creditsWithRetirement.forEach((index) => {
|
|
30649
|
-
ctx.addIssue({
|
|
30650
|
-
code: "custom",
|
|
30651
|
-
message: "credit retirement_amount greater than 0 requires retirement details",
|
|
30652
|
-
path: ["credits", index, "retirement_amount"]
|
|
30653
|
-
});
|
|
30654
|
-
});
|
|
30655
|
-
}
|
|
30656
30701
|
validateCountMatches({
|
|
30657
30702
|
ctx,
|
|
30658
30703
|
actualCount: data.certificates.length,
|
|
@@ -30666,140 +30711,82 @@ var CreditPurchaseReceiptDataSchema = zod.z.strictObject({
|
|
|
30666
30711
|
const creditSlugs = new Set(
|
|
30667
30712
|
data.credits.map((credit) => String(credit.slug))
|
|
30668
30713
|
);
|
|
30669
|
-
const creditSymbols = new Set(
|
|
30670
|
-
data.credits.map((credit) => String(credit.symbol))
|
|
30671
|
-
);
|
|
30672
|
-
const certificateTypes = new Set(
|
|
30673
|
-
data.certificates.map((certificate) => String(certificate.type))
|
|
30674
|
-
);
|
|
30675
|
-
validateSummaryListMatchesData({
|
|
30676
|
-
ctx,
|
|
30677
|
-
summaryValues: data.summary.credit_symbols,
|
|
30678
|
-
dataValues: creditSymbols,
|
|
30679
|
-
summaryPath: ["summary", "credit_symbols"],
|
|
30680
|
-
missingFromDataMessage: "summary.credit_symbols must reference symbols from credits",
|
|
30681
|
-
missingFromSummaryMessage: "All credit symbols must be listed in summary.credit_symbols"
|
|
30682
|
-
});
|
|
30683
|
-
validateSummaryListMatchesData({
|
|
30684
|
-
ctx,
|
|
30685
|
-
summaryValues: data.summary.collection_slugs,
|
|
30686
|
-
dataValues: collectionSlugs,
|
|
30687
|
-
summaryPath: ["summary", "collection_slugs"],
|
|
30688
|
-
missingFromDataMessage: "summary.collection_slugs must reference slugs from collections",
|
|
30689
|
-
missingFromSummaryMessage: "All collection slugs must be listed in summary.collection_slugs"
|
|
30690
|
-
});
|
|
30691
|
-
validateSummaryListMatchesData({
|
|
30692
|
-
ctx,
|
|
30693
|
-
summaryValues: data.summary.certificate_types,
|
|
30694
|
-
dataValues: certificateTypes,
|
|
30695
|
-
summaryPath: ["summary", "certificate_types"],
|
|
30696
|
-
missingFromDataMessage: "summary.certificate_types must reference types present in certificates",
|
|
30697
|
-
missingFromSummaryMessage: "All certificate types must be listed in summary.certificate_types"
|
|
30698
|
-
});
|
|
30699
30714
|
const creditPurchaseTotalsBySlug = /* @__PURE__ */ new Map();
|
|
30700
30715
|
const creditRetiredTotalsBySlug = /* @__PURE__ */ new Map();
|
|
30701
|
-
const
|
|
30716
|
+
const collectionPurchasedTotalsBySlug = /* @__PURE__ */ new Map();
|
|
30717
|
+
const collectionRetiredTotalsBySlug = /* @__PURE__ */ new Map();
|
|
30702
30718
|
let totalCreditsFromCertificates = 0;
|
|
30703
30719
|
data.certificates.forEach((certificate, index) => {
|
|
30704
|
-
|
|
30705
|
-
ctx
|
|
30706
|
-
|
|
30707
|
-
|
|
30708
|
-
|
|
30709
|
-
|
|
30710
|
-
|
|
30711
|
-
|
|
30712
|
-
|
|
30713
|
-
|
|
30714
|
-
|
|
30715
|
-
|
|
30716
|
-
|
|
30717
|
-
}
|
|
30718
|
-
|
|
30719
|
-
|
|
30720
|
-
|
|
30721
|
-
|
|
30722
|
-
|
|
30723
|
-
|
|
30724
|
-
|
|
30725
|
-
|
|
30720
|
+
validateCreditSlugExists({
|
|
30721
|
+
ctx,
|
|
30722
|
+
creditSlug: certificate.credit_slug,
|
|
30723
|
+
validCreditSlugs: creditSlugs,
|
|
30724
|
+
path: ["certificates", index, "credit_slug"]
|
|
30725
|
+
});
|
|
30726
|
+
let certificatePurchasedTotal = 0;
|
|
30727
|
+
let certificateRetiredTotal = 0;
|
|
30728
|
+
validateCertificateCollectionSlugs({
|
|
30729
|
+
ctx,
|
|
30730
|
+
certificateCollections: certificate.collections,
|
|
30731
|
+
validCollectionSlugs: collectionSlugs,
|
|
30732
|
+
certificateIndex: index
|
|
30733
|
+
});
|
|
30734
|
+
certificate.collections.forEach((collectionItem, collectionIndex) => {
|
|
30735
|
+
if (collectionItem.retired_amount > collectionItem.purchased_amount) {
|
|
30736
|
+
ctx.addIssue({
|
|
30737
|
+
code: "custom",
|
|
30738
|
+
message: "certificate.collections[].retired_amount cannot exceed purchased_amount",
|
|
30739
|
+
path: [
|
|
30740
|
+
"certificates",
|
|
30741
|
+
index,
|
|
30742
|
+
"collections",
|
|
30743
|
+
collectionIndex,
|
|
30744
|
+
"retired_amount"
|
|
30745
|
+
]
|
|
30746
|
+
});
|
|
30747
|
+
}
|
|
30748
|
+
certificatePurchasedTotal += Number(collectionItem.purchased_amount);
|
|
30749
|
+
certificateRetiredTotal += Number(collectionItem.retired_amount);
|
|
30750
|
+
collectionPurchasedTotalsBySlug.set(
|
|
30751
|
+
collectionItem.slug,
|
|
30752
|
+
(collectionPurchasedTotalsBySlug.get(collectionItem.slug) ?? 0) + Number(collectionItem.purchased_amount)
|
|
30753
|
+
);
|
|
30754
|
+
collectionRetiredTotalsBySlug.set(
|
|
30755
|
+
collectionItem.slug,
|
|
30756
|
+
(collectionRetiredTotalsBySlug.get(collectionItem.slug) ?? 0) + Number(collectionItem.retired_amount)
|
|
30757
|
+
);
|
|
30758
|
+
});
|
|
30759
|
+
if (certificatePurchasedTotal > certificate.total_amount) {
|
|
30726
30760
|
ctx.addIssue({
|
|
30727
30761
|
code: "custom",
|
|
30728
|
-
message: "purchased_amount cannot exceed total_amount",
|
|
30729
|
-
path: ["certificates", index
|
|
30762
|
+
message: "Sum of certificate.collections[].purchased_amount cannot exceed certificate.total_amount",
|
|
30763
|
+
path: ["certificates", index]
|
|
30730
30764
|
});
|
|
30731
30765
|
}
|
|
30732
|
-
totalCreditsFromCertificates +=
|
|
30766
|
+
totalCreditsFromCertificates += certificatePurchasedTotal;
|
|
30733
30767
|
creditPurchaseTotalsBySlug.set(
|
|
30734
30768
|
String(certificate.credit_slug),
|
|
30735
|
-
(creditPurchaseTotalsBySlug.get(certificate.credit_slug) ?? 0) +
|
|
30769
|
+
(creditPurchaseTotalsBySlug.get(certificate.credit_slug) ?? 0) + certificatePurchasedTotal
|
|
30736
30770
|
);
|
|
30737
30771
|
creditRetiredTotalsBySlug.set(
|
|
30738
30772
|
String(certificate.credit_slug),
|
|
30739
|
-
(creditRetiredTotalsBySlug.get(certificate.credit_slug) ?? 0) +
|
|
30740
|
-
);
|
|
30741
|
-
collectionTotalsBySlug.set(
|
|
30742
|
-
String(certificate.collection_slug),
|
|
30743
|
-
(collectionTotalsBySlug.get(certificate.collection_slug) ?? 0) + Number(certificate.purchased_amount)
|
|
30773
|
+
(creditRetiredTotalsBySlug.get(certificate.credit_slug) ?? 0) + certificateRetiredTotal
|
|
30744
30774
|
);
|
|
30745
30775
|
});
|
|
30746
|
-
const
|
|
30747
|
-
(
|
|
30748
|
-
|
|
30749
|
-
);
|
|
30750
|
-
const totalCreditsFromCredits = data.credits.reduce(
|
|
30751
|
-
(sum, credit) => sum + Number(credit.purchase_amount),
|
|
30752
|
-
0
|
|
30753
|
-
);
|
|
30776
|
+
const certificateCollectionRetiredTotal = Array.from(
|
|
30777
|
+
collectionRetiredTotalsBySlug.values()
|
|
30778
|
+
).reduce((sum, amount) => sum + amount, 0);
|
|
30754
30779
|
validateTotalMatches({
|
|
30755
30780
|
ctx,
|
|
30756
30781
|
actualTotal: totalCreditsFromCertificates,
|
|
30757
30782
|
expectedTotal: data.summary.total_credits,
|
|
30758
30783
|
path: ["summary", "total_credits"],
|
|
30759
|
-
message: "summary.total_credits must equal sum of
|
|
30784
|
+
message: "summary.total_credits must equal sum of certificate.collections[].purchased_amount"
|
|
30760
30785
|
});
|
|
30761
|
-
|
|
30786
|
+
validateRetirementReceiptRequirement({
|
|
30762
30787
|
ctx,
|
|
30763
|
-
|
|
30764
|
-
|
|
30765
|
-
path: ["summary", "total_credits"],
|
|
30766
|
-
message: "summary.total_credits must equal sum of credits.purchase_amount"
|
|
30767
|
-
});
|
|
30768
|
-
validateTotalMatches({
|
|
30769
|
-
ctx,
|
|
30770
|
-
actualTotal: totalCreditsFromCollections,
|
|
30771
|
-
expectedTotal: data.summary.total_credits,
|
|
30772
|
-
path: ["summary", "total_credits"],
|
|
30773
|
-
message: "summary.total_credits must equal sum of collections.credit_amount"
|
|
30774
|
-
});
|
|
30775
|
-
data.credits.forEach((credit, index) => {
|
|
30776
|
-
const purchasedTotal = creditPurchaseTotalsBySlug.get(String(credit.slug)) ?? 0;
|
|
30777
|
-
if (!nearlyEqual(Number(credit.purchase_amount), purchasedTotal)) {
|
|
30778
|
-
ctx.addIssue({
|
|
30779
|
-
code: "custom",
|
|
30780
|
-
message: "credit.purchase_amount must equal sum of certificate purchased_amount for the credit slug",
|
|
30781
|
-
path: ["credits", index, "purchase_amount"]
|
|
30782
|
-
});
|
|
30783
|
-
}
|
|
30784
|
-
const retiredTotal = creditRetiredTotalsBySlug.get(String(credit.slug)) ?? 0;
|
|
30785
|
-
const retirementAmount = Number(credit.retirement_amount ?? 0);
|
|
30786
|
-
if (!nearlyEqual(retirementAmount, retiredTotal)) {
|
|
30787
|
-
ctx.addIssue({
|
|
30788
|
-
code: "custom",
|
|
30789
|
-
message: "credit.retirement_amount must equal sum of certificate retired_amount for the credit slug",
|
|
30790
|
-
path: ["credits", index, "retirement_amount"]
|
|
30791
|
-
});
|
|
30792
|
-
}
|
|
30793
|
-
});
|
|
30794
|
-
data.collections.forEach((collection, index) => {
|
|
30795
|
-
const purchasedTotal = collectionTotalsBySlug.get(String(collection.slug)) ?? 0;
|
|
30796
|
-
if (!nearlyEqual(Number(collection.credit_amount), purchasedTotal)) {
|
|
30797
|
-
ctx.addIssue({
|
|
30798
|
-
code: "custom",
|
|
30799
|
-
message: "collection.credit_amount must equal sum of certificate purchased_amount for the collection slug",
|
|
30800
|
-
path: ["collections", index, "credit_amount"]
|
|
30801
|
-
});
|
|
30802
|
-
}
|
|
30788
|
+
hasRetirementReceipt: !!data.retirement_receipt,
|
|
30789
|
+
totalRetiredAmount: certificateCollectionRetiredTotal
|
|
30803
30790
|
});
|
|
30804
30791
|
const participantRewardTotal = data.participant_rewards.reduce(
|
|
30805
30792
|
(sum, reward) => sum + Number(reward.usdc_amount),
|
|
@@ -30808,9 +30795,9 @@ var CreditPurchaseReceiptDataSchema = zod.z.strictObject({
|
|
|
30808
30795
|
validateTotalMatches({
|
|
30809
30796
|
ctx,
|
|
30810
30797
|
actualTotal: participantRewardTotal,
|
|
30811
|
-
expectedTotal: data.summary.
|
|
30812
|
-
path: ["summary", "
|
|
30813
|
-
message: "summary.
|
|
30798
|
+
expectedTotal: data.summary.total_amount_usdc,
|
|
30799
|
+
path: ["summary", "total_amount_usdc"],
|
|
30800
|
+
message: "summary.total_amount_usdc must equal sum of participant_rewards.usdc_amount"
|
|
30814
30801
|
});
|
|
30815
30802
|
}).meta({
|
|
30816
30803
|
title: "Credit Purchase Receipt Data",
|
|
@@ -30848,10 +30835,10 @@ var CreditPurchaseReceiptIpfsSchema = NftIpfsSchema.safeExtend({
|
|
|
30848
30835
|
validateAttributeValue({
|
|
30849
30836
|
ctx,
|
|
30850
30837
|
attributeByTraitType,
|
|
30851
|
-
traitType: "Total USDC
|
|
30852
|
-
expectedValue: data.summary.
|
|
30853
|
-
missingMessage: 'Attribute "Total USDC
|
|
30854
|
-
mismatchMessage: 'Attribute "Total USDC
|
|
30838
|
+
traitType: "Total Amount (USDC)",
|
|
30839
|
+
expectedValue: data.summary.total_amount_usdc,
|
|
30840
|
+
missingMessage: 'Attribute "Total Amount (USDC)" is required',
|
|
30841
|
+
mismatchMessage: 'Attribute "Total Amount (USDC)" must match data.summary.total_amount_usdc'
|
|
30855
30842
|
});
|
|
30856
30843
|
validateAttributeValue({
|
|
30857
30844
|
ctx,
|
|
@@ -30861,44 +30848,86 @@ var CreditPurchaseReceiptIpfsSchema = NftIpfsSchema.safeExtend({
|
|
|
30861
30848
|
missingMessage: 'Attribute "Certificates Purchased" is required',
|
|
30862
30849
|
mismatchMessage: 'Attribute "Certificates Purchased" must match data.summary.total_certificates'
|
|
30863
30850
|
});
|
|
30864
|
-
const
|
|
30865
|
-
if (
|
|
30851
|
+
const buyerName = data.buyer.identity?.name;
|
|
30852
|
+
if (buyerName) {
|
|
30866
30853
|
validateAttributeValue({
|
|
30867
30854
|
ctx,
|
|
30868
30855
|
attributeByTraitType,
|
|
30869
|
-
traitType: "
|
|
30870
|
-
expectedValue: String(
|
|
30871
|
-
missingMessage: 'Attribute "
|
|
30872
|
-
mismatchMessage: 'Attribute "
|
|
30856
|
+
traitType: "Buyer",
|
|
30857
|
+
expectedValue: String(buyerName),
|
|
30858
|
+
missingMessage: 'Attribute "Buyer" is required when buyer.identity.name is provided',
|
|
30859
|
+
mismatchMessage: 'Attribute "Buyer" must match buyer.identity.name'
|
|
30873
30860
|
});
|
|
30874
30861
|
}
|
|
30875
|
-
|
|
30876
|
-
|
|
30877
|
-
|
|
30878
|
-
|
|
30879
|
-
|
|
30880
|
-
|
|
30881
|
-
|
|
30882
|
-
|
|
30883
|
-
|
|
30884
|
-
|
|
30885
|
-
|
|
30886
|
-
|
|
30887
|
-
|
|
30888
|
-
|
|
30889
|
-
|
|
30890
|
-
|
|
30891
|
-
|
|
30892
|
-
|
|
30862
|
+
const purchaseDateAttribute = attributeByTraitType.get("Purchase Date");
|
|
30863
|
+
if (purchaseDateAttribute) {
|
|
30864
|
+
const dateMs = Date.parse(data.summary.purchased_at);
|
|
30865
|
+
if (Number.isNaN(dateMs)) {
|
|
30866
|
+
ctx.addIssue({
|
|
30867
|
+
code: "custom",
|
|
30868
|
+
message: "data.summary.purchased_at must be a valid ISO 8601 date-time string",
|
|
30869
|
+
path: ["data", "summary", "purchased_at"]
|
|
30870
|
+
});
|
|
30871
|
+
} else if (purchaseDateAttribute.value !== dateMs) {
|
|
30872
|
+
ctx.addIssue({
|
|
30873
|
+
code: "custom",
|
|
30874
|
+
message: 'Attribute "Purchase Date" must match data.summary.purchased_at as a Unix timestamp in milliseconds',
|
|
30875
|
+
path: ["attributes"]
|
|
30876
|
+
});
|
|
30877
|
+
}
|
|
30878
|
+
} else {
|
|
30879
|
+
ctx.addIssue({
|
|
30880
|
+
code: "custom",
|
|
30881
|
+
message: 'Attribute "Purchase Date" is required',
|
|
30882
|
+
path: ["attributes"]
|
|
30883
|
+
});
|
|
30884
|
+
}
|
|
30885
|
+
if (data.retirement_receipt) {
|
|
30886
|
+
const retirementReceiptAttribute = attributeByTraitType.get("Retirement Receipt");
|
|
30887
|
+
if (retirementReceiptAttribute) {
|
|
30888
|
+
const expectedTokenId = `#${data.retirement_receipt.token_id}`;
|
|
30889
|
+
if (retirementReceiptAttribute.value !== expectedTokenId) {
|
|
30890
|
+
ctx.addIssue({
|
|
30891
|
+
code: "custom",
|
|
30892
|
+
message: 'Attribute "Retirement Receipt" must match retirement_receipt.token_id as #<token_id> when present',
|
|
30893
|
+
path: ["attributes"]
|
|
30894
|
+
});
|
|
30895
|
+
}
|
|
30896
|
+
}
|
|
30897
|
+
}
|
|
30898
|
+
const creditTotalsBySymbol = /* @__PURE__ */ new Map();
|
|
30899
|
+
data.certificates.forEach((certificate) => {
|
|
30900
|
+
const credit = data.credits.find(
|
|
30901
|
+
(c) => c.slug === certificate.credit_slug
|
|
30902
|
+
);
|
|
30903
|
+
if (credit) {
|
|
30904
|
+
const certificatePurchasedTotal = certificate.collections.reduce(
|
|
30905
|
+
(sum, collection) => sum + Number(collection.purchased_amount),
|
|
30906
|
+
0
|
|
30907
|
+
);
|
|
30908
|
+
const currentTotal = creditTotalsBySymbol.get(credit.symbol) ?? 0;
|
|
30909
|
+
creditTotalsBySymbol.set(
|
|
30910
|
+
credit.symbol,
|
|
30911
|
+
currentTotal + certificatePurchasedTotal
|
|
30912
|
+
);
|
|
30913
|
+
}
|
|
30893
30914
|
});
|
|
30894
|
-
|
|
30895
|
-
|
|
30896
|
-
attributeByTraitType
|
|
30897
|
-
|
|
30898
|
-
|
|
30899
|
-
|
|
30900
|
-
|
|
30901
|
-
|
|
30915
|
+
data.credits.forEach((credit) => {
|
|
30916
|
+
const expectedTotal = creditTotalsBySymbol.get(credit.symbol) ?? 0;
|
|
30917
|
+
const attribute = attributeByTraitType.get(credit.symbol);
|
|
30918
|
+
if (!attribute) {
|
|
30919
|
+
ctx.addIssue({
|
|
30920
|
+
code: "custom",
|
|
30921
|
+
message: `Attribute for credit symbol ${credit.symbol} is required`,
|
|
30922
|
+
path: ["attributes"]
|
|
30923
|
+
});
|
|
30924
|
+
} else if (Number(attribute.value) !== expectedTotal) {
|
|
30925
|
+
ctx.addIssue({
|
|
30926
|
+
code: "custom",
|
|
30927
|
+
message: `Attribute for credit symbol ${credit.symbol} must match sum of certificate.collections[].purchased_amount for the credit symbol`,
|
|
30928
|
+
path: ["attributes"]
|
|
30929
|
+
});
|
|
30930
|
+
}
|
|
30902
30931
|
});
|
|
30903
30932
|
}).meta(CreditPurchaseReceiptIpfsSchemaMeta);
|
|
30904
30933
|
var CreditRetirementReceiptCreditAttributeSchema = NftAttributeSchema.safeExtend({
|
|
@@ -30951,16 +30980,20 @@ var CreditRetirementReceiptCertificatesAttributeSchema = createNumericAttributeS
|
|
|
30951
30980
|
description: "Total number of certificates retired",
|
|
30952
30981
|
valueSchema: PositiveIntegerSchema
|
|
30953
30982
|
});
|
|
30954
|
-
var
|
|
30955
|
-
|
|
30956
|
-
|
|
30957
|
-
|
|
30958
|
-
|
|
30959
|
-
|
|
30960
|
-
|
|
30983
|
+
var CreditRetirementReceiptPurchaseDateAttributeSchema = createDateAttributeSchema({
|
|
30984
|
+
traitType: "Purchase Date",
|
|
30985
|
+
title: "Purchase Date",
|
|
30986
|
+
description: "Unix timestamp in milliseconds when credits were purchased (if purchase_receipt is present)"
|
|
30987
|
+
});
|
|
30988
|
+
var CreditRetirementReceiptPurchaseReceiptAttributeSchema = NftAttributeSchema.safeExtend({
|
|
30989
|
+
trait_type: zod.z.literal("Purchase Receipt"),
|
|
30990
|
+
value: StringifiedTokenIdSchema.meta({
|
|
30991
|
+
title: "Purchase Receipt Token ID",
|
|
30992
|
+
description: "Token ID of the purchase receipt NFT as #<token_id> (if purchase_receipt is present)"
|
|
30993
|
+
})
|
|
30961
30994
|
}).meta({
|
|
30962
|
-
title: "
|
|
30963
|
-
description: "Attribute representing the
|
|
30995
|
+
title: "Purchase Receipt Attribute",
|
|
30996
|
+
description: "Attribute representing the purchase receipt token ID"
|
|
30964
30997
|
});
|
|
30965
30998
|
var REQUIRED_CREDIT_RETIREMENT_RECEIPT_ATTRIBUTES = [
|
|
30966
30999
|
CreditRetirementReceiptTotalCreditsAttributeSchema,
|
|
@@ -30969,11 +31002,12 @@ var REQUIRED_CREDIT_RETIREMENT_RECEIPT_ATTRIBUTES = [
|
|
|
30969
31002
|
CreditRetirementReceiptCertificatesAttributeSchema
|
|
30970
31003
|
];
|
|
30971
31004
|
var CONDITIONAL_CREDIT_RETIREMENT_RECEIPT_ATTRIBUTES = [
|
|
30972
|
-
CreditRetirementReceiptCreditHolderAttributeSchema
|
|
31005
|
+
CreditRetirementReceiptCreditHolderAttributeSchema,
|
|
31006
|
+
CreditRetirementReceiptPurchaseDateAttributeSchema,
|
|
31007
|
+
CreditRetirementReceiptPurchaseReceiptAttributeSchema
|
|
30973
31008
|
];
|
|
30974
31009
|
var DYNAMIC_CREDIT_RETIREMENT_RECEIPT_ATTRIBUTES = [
|
|
30975
|
-
CreditRetirementReceiptCreditAttributeSchema
|
|
30976
|
-
CreditRetirementReceiptCollectionAttributeSchema
|
|
31010
|
+
CreditRetirementReceiptCreditAttributeSchema
|
|
30977
31011
|
];
|
|
30978
31012
|
var CreditRetirementReceiptAttributesSchema = createOrderedAttributesSchema({
|
|
30979
31013
|
required: REQUIRED_CREDIT_RETIREMENT_RECEIPT_ATTRIBUTES,
|
|
@@ -30982,7 +31016,7 @@ var CreditRetirementReceiptAttributesSchema = createOrderedAttributesSchema({
|
|
|
30982
31016
|
...DYNAMIC_CREDIT_RETIREMENT_RECEIPT_ATTRIBUTES
|
|
30983
31017
|
],
|
|
30984
31018
|
title: "Credit Retirement Receipt NFT Attribute Array",
|
|
30985
|
-
description: "Attributes for credit retirement receipts including per-credit breakdowns, totals, beneficiary, credit holder, retirement date, certificate count, and
|
|
31019
|
+
description: "Attributes for credit retirement receipts including per-credit breakdowns, totals, beneficiary, credit holder, retirement date, certificate count, and optional purchase info. Fixed required attributes: Total Credits Retired, Beneficiary, Retirement Date, Certificates Retired. Conditional attributes: Credit Holder (required when credit_holder.identity.name is provided), Purchase Date (optional, when purchase_receipt is present), Purchase Receipt (optional, when purchase_receipt is present). Dynamic attributes: Credit attributes (one per credit symbol in data.credits).",
|
|
30986
31020
|
uniqueBySelector: (attribute) => attribute.trait_type,
|
|
30987
31021
|
requiredTraitTypes: [
|
|
30988
31022
|
"Total Credits Retired",
|
|
@@ -31013,22 +31047,12 @@ var CreditRetirementReceiptCreditHolderSchema = zod.z.strictObject({
|
|
|
31013
31047
|
description: "Credit holder wallet and optional identity information"
|
|
31014
31048
|
});
|
|
31015
31049
|
var CreditRetirementReceiptCollectionSchema = createReceiptCollectionSchema({
|
|
31016
|
-
amountKey: "amount",
|
|
31017
|
-
amountMeta: {
|
|
31018
|
-
title: "Collection Retirement Amount",
|
|
31019
|
-
description: "Total credits retired from this collection"
|
|
31020
|
-
},
|
|
31021
31050
|
meta: {
|
|
31022
31051
|
title: "Collection",
|
|
31023
31052
|
description: "Collection included in the retirement"
|
|
31024
31053
|
}
|
|
31025
31054
|
});
|
|
31026
31055
|
var CreditRetirementReceiptCreditSchema = createReceiptCreditSchema({
|
|
31027
|
-
amountKey: "amount",
|
|
31028
|
-
amountMeta: {
|
|
31029
|
-
title: "Credit Retirement Amount",
|
|
31030
|
-
description: "Total credits retired for this credit type"
|
|
31031
|
-
},
|
|
31032
31056
|
meta: {
|
|
31033
31057
|
title: "Credit",
|
|
31034
31058
|
description: "Credit token retired in this receipt"
|
|
@@ -31070,11 +31094,14 @@ var CreditPurchaseReceiptReferenceSchema = zod.z.strictObject({
|
|
|
31070
31094
|
title: "Purchase Receipt External URL",
|
|
31071
31095
|
description: "External URL for the purchase receipt"
|
|
31072
31096
|
}),
|
|
31073
|
-
|
|
31074
|
-
title: "Purchase Receipt URI",
|
|
31097
|
+
ipfs_uri: IpfsUriSchema.meta({
|
|
31098
|
+
title: "Purchase Receipt IPFS URI",
|
|
31075
31099
|
description: "IPFS URI for the purchase receipt metadata"
|
|
31076
31100
|
}),
|
|
31077
|
-
|
|
31101
|
+
smart_contract_address: EthereumAddressSchema.meta({
|
|
31102
|
+
title: "Smart Contract Address",
|
|
31103
|
+
description: "Ethereum address of the smart contract"
|
|
31104
|
+
})
|
|
31078
31105
|
}).meta({
|
|
31079
31106
|
title: "Credit Purchase Receipt Reference",
|
|
31080
31107
|
description: "Reference to the credit purchase receipt when retirement occurs during purchase"
|
|
@@ -31082,9 +31109,13 @@ var CreditPurchaseReceiptReferenceSchema = zod.z.strictObject({
|
|
|
31082
31109
|
var CreditRetirementReceiptCertificateSchema = createReceiptCertificateSchema(
|
|
31083
31110
|
{
|
|
31084
31111
|
additionalShape: {
|
|
31085
|
-
|
|
31086
|
-
|
|
31087
|
-
|
|
31112
|
+
collections: uniqueBy(
|
|
31113
|
+
CertificateCollectionItemRetirementSchema,
|
|
31114
|
+
(item) => item.slug,
|
|
31115
|
+
"Collection slugs within certificate collections must be unique"
|
|
31116
|
+
).min(1).meta({
|
|
31117
|
+
title: "Certificate Collections",
|
|
31118
|
+
description: "Collections associated with this certificate, each with retired amounts"
|
|
31088
31119
|
}),
|
|
31089
31120
|
credits_retired: uniqueBy(
|
|
31090
31121
|
CreditRetirementReceiptCertificateCreditSchema,
|
|
@@ -31134,15 +31165,15 @@ var CreditRetirementReceiptDataSchema = zod.z.strictObject({
|
|
|
31134
31165
|
const creditSymbols = new Set(
|
|
31135
31166
|
data.credits.map((credit) => String(credit.symbol))
|
|
31136
31167
|
);
|
|
31168
|
+
const creditSlugs = new Set(
|
|
31169
|
+
data.credits.map((credit) => String(credit.slug))
|
|
31170
|
+
);
|
|
31137
31171
|
const creditBySlug = new Map(
|
|
31138
31172
|
data.credits.map((credit) => [credit.slug, credit])
|
|
31139
31173
|
);
|
|
31140
31174
|
const collectionSlugs = new Set(
|
|
31141
31175
|
data.collections.map((collection) => String(collection.slug))
|
|
31142
31176
|
);
|
|
31143
|
-
const certificateTypes = new Set(
|
|
31144
|
-
data.certificates.map((certificate) => String(certificate.type))
|
|
31145
|
-
);
|
|
31146
31177
|
validateCountMatches({
|
|
31147
31178
|
ctx,
|
|
31148
31179
|
actualCount: data.certificates.length,
|
|
@@ -31150,87 +31181,70 @@ var CreditRetirementReceiptDataSchema = zod.z.strictObject({
|
|
|
31150
31181
|
path: ["summary", "total_certificates"],
|
|
31151
31182
|
message: "summary.total_certificates must equal the number of certificates"
|
|
31152
31183
|
});
|
|
31153
|
-
validateSummaryListMatchesData({
|
|
31154
|
-
ctx,
|
|
31155
|
-
summaryValues: data.summary.credit_symbols,
|
|
31156
|
-
dataValues: creditSymbols,
|
|
31157
|
-
summaryPath: ["summary", "credit_symbols"],
|
|
31158
|
-
missingFromDataMessage: "summary.credit_symbols must reference symbols from credits",
|
|
31159
|
-
missingFromSummaryMessage: "All credit symbols must be listed in summary.credit_symbols"
|
|
31160
|
-
});
|
|
31161
|
-
validateSummaryListMatchesData({
|
|
31162
|
-
ctx,
|
|
31163
|
-
summaryValues: data.summary.collection_slugs,
|
|
31164
|
-
dataValues: collectionSlugs,
|
|
31165
|
-
summaryPath: ["summary", "collection_slugs"],
|
|
31166
|
-
missingFromDataMessage: "summary.collection_slugs must reference slugs from collections",
|
|
31167
|
-
missingFromSummaryMessage: "All collection slugs must be listed in summary.collection_slugs"
|
|
31168
|
-
});
|
|
31169
|
-
validateSummaryListMatchesData({
|
|
31170
|
-
ctx,
|
|
31171
|
-
summaryValues: data.summary.certificate_types,
|
|
31172
|
-
dataValues: certificateTypes,
|
|
31173
|
-
summaryPath: ["summary", "certificate_types"],
|
|
31174
|
-
missingFromDataMessage: "summary.certificate_types must reference types present in certificates",
|
|
31175
|
-
missingFromSummaryMessage: "All certificate types must be listed in summary.certificate_types"
|
|
31176
|
-
});
|
|
31177
31184
|
const creditTotalsBySymbol = /* @__PURE__ */ new Map();
|
|
31178
|
-
const
|
|
31185
|
+
const collectionRetiredTotalsBySlug = /* @__PURE__ */ new Map();
|
|
31179
31186
|
let totalRetiredFromCertificates = 0;
|
|
31180
31187
|
data.certificates.forEach((certificate, index) => {
|
|
31181
|
-
|
|
31182
|
-
|
|
31183
|
-
|
|
31184
|
-
|
|
31185
|
-
|
|
31186
|
-
});
|
|
31187
|
-
}
|
|
31188
|
-
if (certificate.retired_amount > certificate.total_amount) {
|
|
31188
|
+
const certificateCollectionRetiredTotal = certificate.collections.reduce(
|
|
31189
|
+
(sum, item) => sum + Number(item.retired_amount),
|
|
31190
|
+
0
|
|
31191
|
+
);
|
|
31192
|
+
if (certificateCollectionRetiredTotal > certificate.total_amount) {
|
|
31189
31193
|
ctx.addIssue({
|
|
31190
31194
|
code: "custom",
|
|
31191
|
-
message: "retired_amount cannot exceed total_amount",
|
|
31192
|
-
path: ["certificates", index
|
|
31195
|
+
message: "Sum of certificate.collections[].retired_amount cannot exceed certificate.total_amount",
|
|
31196
|
+
path: ["certificates", index]
|
|
31193
31197
|
});
|
|
31194
31198
|
}
|
|
31199
|
+
validateCertificateCollectionSlugs({
|
|
31200
|
+
ctx,
|
|
31201
|
+
certificateCollections: certificate.collections,
|
|
31202
|
+
validCollectionSlugs: collectionSlugs,
|
|
31203
|
+
certificateIndex: index
|
|
31204
|
+
});
|
|
31205
|
+
certificate.collections.forEach((collectionItem) => {
|
|
31206
|
+
collectionRetiredTotalsBySlug.set(
|
|
31207
|
+
collectionItem.slug,
|
|
31208
|
+
(collectionRetiredTotalsBySlug.get(collectionItem.slug) ?? 0) + Number(collectionItem.retired_amount)
|
|
31209
|
+
);
|
|
31210
|
+
});
|
|
31195
31211
|
const creditsRetiredTotal = certificate.credits_retired.reduce(
|
|
31196
31212
|
(sum, credit) => sum + Number(credit.amount),
|
|
31197
31213
|
0
|
|
31198
31214
|
);
|
|
31199
|
-
if (!nearlyEqual(creditsRetiredTotal,
|
|
31215
|
+
if (!nearlyEqual(creditsRetiredTotal, certificateCollectionRetiredTotal)) {
|
|
31200
31216
|
ctx.addIssue({
|
|
31201
31217
|
code: "custom",
|
|
31202
|
-
message: "certificates.credits_retired amounts must sum to
|
|
31218
|
+
message: "certificates.credits_retired amounts must sum to certificate.collections[].retired_amount",
|
|
31203
31219
|
path: ["certificates", index, "credits_retired"]
|
|
31204
31220
|
});
|
|
31205
31221
|
}
|
|
31206
31222
|
certificate.credits_retired.forEach((credit, creditIndex) => {
|
|
31207
31223
|
const referencedCredit = creditBySlug.get(credit.credit_slug);
|
|
31208
|
-
|
|
31209
|
-
ctx
|
|
31210
|
-
|
|
31211
|
-
|
|
31212
|
-
|
|
31213
|
-
|
|
31214
|
-
|
|
31215
|
-
|
|
31216
|
-
|
|
31217
|
-
|
|
31218
|
-
|
|
31219
|
-
|
|
31220
|
-
|
|
31221
|
-
|
|
31222
|
-
|
|
31223
|
-
|
|
31224
|
-
|
|
31225
|
-
|
|
31226
|
-
|
|
31227
|
-
|
|
31228
|
-
|
|
31229
|
-
|
|
31230
|
-
|
|
31231
|
-
|
|
31232
|
-
});
|
|
31233
|
-
}
|
|
31224
|
+
validateCreditSlugExists({
|
|
31225
|
+
ctx,
|
|
31226
|
+
creditSlug: credit.credit_slug,
|
|
31227
|
+
validCreditSlugs: creditSlugs,
|
|
31228
|
+
path: [
|
|
31229
|
+
"certificates",
|
|
31230
|
+
index,
|
|
31231
|
+
"credits_retired",
|
|
31232
|
+
creditIndex,
|
|
31233
|
+
"credit_slug"
|
|
31234
|
+
]
|
|
31235
|
+
});
|
|
31236
|
+
validateCreditSymbolExists({
|
|
31237
|
+
ctx,
|
|
31238
|
+
creditSymbol: credit.credit_symbol,
|
|
31239
|
+
validCreditSymbols: creditSymbols,
|
|
31240
|
+
path: [
|
|
31241
|
+
"certificates",
|
|
31242
|
+
index,
|
|
31243
|
+
"credits_retired",
|
|
31244
|
+
creditIndex,
|
|
31245
|
+
"credit_symbol"
|
|
31246
|
+
]
|
|
31247
|
+
});
|
|
31234
31248
|
if (referencedCredit && referencedCredit.symbol !== credit.credit_symbol) {
|
|
31235
31249
|
ctx.addIssue({
|
|
31236
31250
|
code: "custom",
|
|
@@ -31249,83 +31263,19 @@ var CreditRetirementReceiptDataSchema = zod.z.strictObject({
|
|
|
31249
31263
|
(creditTotalsBySymbol.get(credit.credit_symbol) ?? 0) + credit.amount
|
|
31250
31264
|
);
|
|
31251
31265
|
});
|
|
31252
|
-
|
|
31253
|
-
String(certificate.collection_slug),
|
|
31254
|
-
(collectionTotalsBySlug.get(certificate.collection_slug) ?? 0) + Number(certificate.retired_amount)
|
|
31255
|
-
);
|
|
31256
|
-
totalRetiredFromCertificates += Number(certificate.retired_amount);
|
|
31257
|
-
});
|
|
31258
|
-
const totalRetiredFromCollections = data.collections.reduce(
|
|
31259
|
-
(sum, collection) => sum + Number(collection.amount),
|
|
31260
|
-
0
|
|
31261
|
-
);
|
|
31262
|
-
const totalRetiredFromCredits = data.credits.reduce(
|
|
31263
|
-
(sum, credit) => sum + Number(credit.amount),
|
|
31264
|
-
0
|
|
31265
|
-
);
|
|
31266
|
-
data.summary.credit_symbols.forEach((symbol) => {
|
|
31267
|
-
if ((creditTotalsBySymbol.get(symbol) ?? 0) === 0) {
|
|
31268
|
-
ctx.addIssue({
|
|
31269
|
-
code: "custom",
|
|
31270
|
-
message: "Each summary credit symbol must appear in certificates.credits_retired with a retired amount",
|
|
31271
|
-
path: ["summary", "credit_symbols"]
|
|
31272
|
-
});
|
|
31273
|
-
}
|
|
31266
|
+
totalRetiredFromCertificates += certificateCollectionRetiredTotal;
|
|
31274
31267
|
});
|
|
31275
31268
|
validateTotalMatches({
|
|
31276
31269
|
ctx,
|
|
31277
31270
|
actualTotal: totalRetiredFromCertificates,
|
|
31278
|
-
expectedTotal: data.summary.
|
|
31279
|
-
path: ["summary", "
|
|
31280
|
-
message: "summary.
|
|
31271
|
+
expectedTotal: data.summary.total_credits_retired,
|
|
31272
|
+
path: ["summary", "total_credits_retired"],
|
|
31273
|
+
message: "summary.total_credits_retired must equal sum of certificate.collections[].retired_amount"
|
|
31281
31274
|
});
|
|
31282
|
-
|
|
31275
|
+
validateCollectionsHaveRetiredAmounts({
|
|
31283
31276
|
ctx,
|
|
31284
|
-
|
|
31285
|
-
|
|
31286
|
-
path: ["summary", "total_retirement_amount"],
|
|
31287
|
-
message: "summary.total_retirement_amount must equal sum of credits.amount"
|
|
31288
|
-
});
|
|
31289
|
-
validateTotalMatches({
|
|
31290
|
-
ctx,
|
|
31291
|
-
actualTotal: totalRetiredFromCollections,
|
|
31292
|
-
expectedTotal: data.summary.total_retirement_amount,
|
|
31293
|
-
path: ["summary", "total_retirement_amount"],
|
|
31294
|
-
message: "summary.total_retirement_amount must equal sum of collections.amount"
|
|
31295
|
-
});
|
|
31296
|
-
data.credits.forEach((credit, index) => {
|
|
31297
|
-
const retiredTotal = creditTotalsBySymbol.get(String(credit.symbol)) ?? 0;
|
|
31298
|
-
if (!nearlyEqual(Number(credit.amount), retiredTotal)) {
|
|
31299
|
-
ctx.addIssue({
|
|
31300
|
-
code: "custom",
|
|
31301
|
-
message: "credit.amount must equal sum of retired amounts for the credit symbol across certificates",
|
|
31302
|
-
path: ["credits", index, "amount"]
|
|
31303
|
-
});
|
|
31304
|
-
}
|
|
31305
|
-
});
|
|
31306
|
-
data.collections.forEach((collection, index) => {
|
|
31307
|
-
const retiredTotal = collectionTotalsBySlug.get(String(collection.slug)) ?? 0;
|
|
31308
|
-
if (retiredTotal === 0) {
|
|
31309
|
-
ctx.addIssue({
|
|
31310
|
-
code: "custom",
|
|
31311
|
-
message: "collection must be referenced by at least one certificate with retired_amount > 0",
|
|
31312
|
-
path: ["collections", index, "slug"]
|
|
31313
|
-
});
|
|
31314
|
-
}
|
|
31315
|
-
if (Number(collection.amount) <= 0) {
|
|
31316
|
-
ctx.addIssue({
|
|
31317
|
-
code: "custom",
|
|
31318
|
-
message: "collection.amount must be greater than zero",
|
|
31319
|
-
path: ["collections", index, "amount"]
|
|
31320
|
-
});
|
|
31321
|
-
}
|
|
31322
|
-
if (!nearlyEqual(Number(collection.amount), retiredTotal)) {
|
|
31323
|
-
ctx.addIssue({
|
|
31324
|
-
code: "custom",
|
|
31325
|
-
message: "collection.amount must equal sum of certificate retired_amount for the collection slug",
|
|
31326
|
-
path: ["collections", index, "amount"]
|
|
31327
|
-
});
|
|
31328
|
-
}
|
|
31277
|
+
collections: data.collections,
|
|
31278
|
+
retiredTotalsBySlug: collectionRetiredTotalsBySlug
|
|
31329
31279
|
});
|
|
31330
31280
|
}).meta({
|
|
31331
31281
|
title: "Credit Retirement Receipt Data",
|
|
@@ -31359,9 +31309,9 @@ var CreditRetirementReceiptIpfsSchema = CreditRetirementReceiptIpfsSchemaBase.sa
|
|
|
31359
31309
|
ctx,
|
|
31360
31310
|
attributeByTraitType,
|
|
31361
31311
|
traitType: "Total Credits Retired",
|
|
31362
|
-
expectedValue: data.summary.
|
|
31312
|
+
expectedValue: data.summary.total_credits_retired,
|
|
31363
31313
|
missingMessage: 'Attribute "Total Credits Retired" is required',
|
|
31364
|
-
mismatchMessage: 'Attribute "Total Credits Retired" must match data.summary.
|
|
31314
|
+
mismatchMessage: 'Attribute "Total Credits Retired" must match data.summary.total_credits_retired'
|
|
31365
31315
|
});
|
|
31366
31316
|
validateAttributeValue({
|
|
31367
31317
|
ctx,
|
|
@@ -31390,33 +31340,68 @@ var CreditRetirementReceiptIpfsSchema = CreditRetirementReceiptIpfsSchemaBase.sa
|
|
|
31390
31340
|
mismatchMessage: 'Attribute "Credit Holder" must match credit_holder.identity.name'
|
|
31391
31341
|
});
|
|
31392
31342
|
}
|
|
31393
|
-
|
|
31394
|
-
|
|
31395
|
-
|
|
31396
|
-
|
|
31397
|
-
|
|
31398
|
-
|
|
31399
|
-
|
|
31400
|
-
|
|
31401
|
-
|
|
31402
|
-
|
|
31403
|
-
|
|
31404
|
-
|
|
31405
|
-
|
|
31406
|
-
|
|
31407
|
-
|
|
31408
|
-
|
|
31409
|
-
|
|
31410
|
-
|
|
31343
|
+
const retirementDateAttribute = attributeByTraitType.get("Retirement Date");
|
|
31344
|
+
if (retirementDateAttribute) {
|
|
31345
|
+
const dateMs = Date.parse(data.summary.retired_at);
|
|
31346
|
+
if (Number.isNaN(dateMs)) {
|
|
31347
|
+
ctx.addIssue({
|
|
31348
|
+
code: "custom",
|
|
31349
|
+
message: "data.summary.retired_at must be a valid ISO 8601 date-time string",
|
|
31350
|
+
path: ["data", "summary", "retired_at"]
|
|
31351
|
+
});
|
|
31352
|
+
} else if (retirementDateAttribute.value !== dateMs) {
|
|
31353
|
+
ctx.addIssue({
|
|
31354
|
+
code: "custom",
|
|
31355
|
+
message: 'Attribute "Retirement Date" must match data.summary.retired_at as a Unix timestamp in milliseconds',
|
|
31356
|
+
path: ["attributes"]
|
|
31357
|
+
});
|
|
31358
|
+
}
|
|
31359
|
+
} else {
|
|
31360
|
+
ctx.addIssue({
|
|
31361
|
+
code: "custom",
|
|
31362
|
+
message: 'Attribute "Retirement Date" is required',
|
|
31363
|
+
path: ["attributes"]
|
|
31364
|
+
});
|
|
31365
|
+
}
|
|
31366
|
+
if (data.purchase_receipt) {
|
|
31367
|
+
const purchaseReceiptAttribute = attributeByTraitType.get("Purchase Receipt");
|
|
31368
|
+
if (purchaseReceiptAttribute) {
|
|
31369
|
+
const expectedTokenId = `#${data.purchase_receipt.token_id}`;
|
|
31370
|
+
if (purchaseReceiptAttribute.value !== expectedTokenId) {
|
|
31371
|
+
ctx.addIssue({
|
|
31372
|
+
code: "custom",
|
|
31373
|
+
message: 'Attribute "Purchase Receipt" must match purchase_receipt.token_id as #<token_id> when present',
|
|
31374
|
+
path: ["attributes"]
|
|
31375
|
+
});
|
|
31376
|
+
}
|
|
31377
|
+
}
|
|
31378
|
+
}
|
|
31379
|
+
const creditTotalsBySymbol = /* @__PURE__ */ new Map();
|
|
31380
|
+
data.certificates.forEach((certificate) => {
|
|
31381
|
+
certificate.credits_retired.forEach((creditRetired) => {
|
|
31382
|
+
const currentTotal = creditTotalsBySymbol.get(creditRetired.credit_symbol) ?? 0;
|
|
31383
|
+
creditTotalsBySymbol.set(
|
|
31384
|
+
creditRetired.credit_symbol,
|
|
31385
|
+
currentTotal + Number(creditRetired.amount)
|
|
31386
|
+
);
|
|
31387
|
+
});
|
|
31411
31388
|
});
|
|
31412
|
-
|
|
31413
|
-
|
|
31414
|
-
attributeByTraitType
|
|
31415
|
-
|
|
31416
|
-
|
|
31417
|
-
|
|
31418
|
-
|
|
31419
|
-
|
|
31389
|
+
data.credits.forEach((credit) => {
|
|
31390
|
+
const expectedTotal = creditTotalsBySymbol.get(credit.symbol) ?? 0;
|
|
31391
|
+
const attribute = attributeByTraitType.get(credit.symbol);
|
|
31392
|
+
if (!attribute) {
|
|
31393
|
+
ctx.addIssue({
|
|
31394
|
+
code: "custom",
|
|
31395
|
+
message: `Attribute for credit symbol ${credit.symbol} is required`,
|
|
31396
|
+
path: ["attributes"]
|
|
31397
|
+
});
|
|
31398
|
+
} else if (Number(attribute.value) !== expectedTotal) {
|
|
31399
|
+
ctx.addIssue({
|
|
31400
|
+
code: "custom",
|
|
31401
|
+
message: `Attribute for credit symbol ${credit.symbol} must match sum of certificate credits_retired amounts for the credit symbol`,
|
|
31402
|
+
path: ["attributes"]
|
|
31403
|
+
});
|
|
31404
|
+
}
|
|
31420
31405
|
});
|
|
31421
31406
|
}).meta(CreditRetirementReceiptIpfsSchemaMeta);
|
|
31422
31407
|
var CollectionSchemaMeta = {
|
|
@@ -31605,6 +31590,8 @@ exports.BRAZIL_SUBDIVISION_CODES = BRAZIL_SUBDIVISION_CODES;
|
|
|
31605
31590
|
exports.BaseIpfsSchema = BaseIpfsSchema;
|
|
31606
31591
|
exports.BlockchainChainIdSchema = BlockchainChainIdSchema;
|
|
31607
31592
|
exports.BlockchainNetworkNameSchema = BlockchainNetworkNameSchema;
|
|
31593
|
+
exports.CertificateCollectionItemPurchaseSchema = CertificateCollectionItemPurchaseSchema;
|
|
31594
|
+
exports.CertificateCollectionItemRetirementSchema = CertificateCollectionItemRetirementSchema;
|
|
31608
31595
|
exports.CertificateIssuanceDateAttributeSchema = CertificateIssuanceDateAttributeSchema;
|
|
31609
31596
|
exports.CitySchema = CitySchema;
|
|
31610
31597
|
exports.CollectionNameSchema = CollectionNameSchema;
|
|
@@ -31666,8 +31653,8 @@ exports.MassIDIpfsSchema = MassIDIpfsSchema;
|
|
|
31666
31653
|
exports.MassIDIpfsSchemaMeta = MassIDIpfsSchemaMeta;
|
|
31667
31654
|
exports.MassIDRecyclingDateAttributeSchema = MassIDRecyclingDateAttributeSchema;
|
|
31668
31655
|
exports.MassIDReferenceSchema = MassIDReferenceSchema;
|
|
31656
|
+
exports.MassIDReferenceWithContractSchema = MassIDReferenceWithContractSchema;
|
|
31669
31657
|
exports.MassIDTokenIdAttributeSchema = MassIDTokenIdAttributeSchema;
|
|
31670
|
-
exports.MassIdReferenceWithContractSchema = MassIdReferenceWithContractSchema;
|
|
31671
31658
|
exports.MethodologyAttributeSchema = MethodologyAttributeSchema;
|
|
31672
31659
|
exports.MethodologyDataSchema = MethodologyDataSchema;
|
|
31673
31660
|
exports.MethodologyNameSchema = MethodologyNameSchema;
|
|
@@ -31736,9 +31723,14 @@ exports.uniqueArrayItems = uniqueArrayItems;
|
|
|
31736
31723
|
exports.uniqueBy = uniqueBy;
|
|
31737
31724
|
exports.validateAttributeValue = validateAttributeValue;
|
|
31738
31725
|
exports.validateAttributesForItems = validateAttributesForItems;
|
|
31726
|
+
exports.validateCertificateCollectionSlugs = validateCertificateCollectionSlugs;
|
|
31727
|
+
exports.validateCollectionsHaveRetiredAmounts = validateCollectionsHaveRetiredAmounts;
|
|
31739
31728
|
exports.validateCountMatches = validateCountMatches;
|
|
31729
|
+
exports.validateCreditSlugExists = validateCreditSlugExists;
|
|
31730
|
+
exports.validateCreditSymbolExists = validateCreditSymbolExists;
|
|
31740
31731
|
exports.validateDateAttribute = validateDateAttribute;
|
|
31741
31732
|
exports.validateLocationBrazilData = validateLocationBrazilData;
|
|
31733
|
+
exports.validateRetirementReceiptRequirement = validateRetirementReceiptRequirement;
|
|
31742
31734
|
exports.validateSummaryListMatchesData = validateSummaryListMatchesData;
|
|
31743
31735
|
exports.validateTotalMatches = validateTotalMatches;
|
|
31744
31736
|
//# sourceMappingURL=index.cjs.map
|