chit402-verify 0.3.4 → 0.4.0

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.
Files changed (108) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +270 -82
  3. package/dist/anchor-trust.d.ts +144 -0
  4. package/dist/anchor-trust.d.ts.map +1 -0
  5. package/dist/anchor-trust.js +441 -0
  6. package/dist/anchor-trust.js.map +1 -0
  7. package/dist/anchor-witness.d.ts +265 -0
  8. package/dist/anchor-witness.d.ts.map +1 -0
  9. package/dist/anchor-witness.js +833 -0
  10. package/dist/anchor-witness.js.map +1 -0
  11. package/dist/base-payer.d.ts +65 -0
  12. package/dist/base-payer.d.ts.map +1 -0
  13. package/dist/base-payer.js +222 -0
  14. package/dist/base-payer.js.map +1 -0
  15. package/dist/binding.d.ts +52 -0
  16. package/dist/binding.d.ts.map +1 -0
  17. package/dist/binding.js +80 -0
  18. package/dist/binding.js.map +1 -0
  19. package/dist/canonical-preimage.d.ts +9 -0
  20. package/dist/canonical-preimage.d.ts.map +1 -0
  21. package/dist/canonical-preimage.js +25 -0
  22. package/dist/canonical-preimage.js.map +1 -0
  23. package/dist/carry-forward.d.ts +79 -0
  24. package/dist/carry-forward.d.ts.map +1 -0
  25. package/dist/carry-forward.js +184 -0
  26. package/dist/carry-forward.js.map +1 -0
  27. package/dist/cli.d.ts +18 -0
  28. package/dist/cli.d.ts.map +1 -0
  29. package/dist/cli.js +2090 -0
  30. package/dist/cli.js.map +1 -0
  31. package/dist/epoch.d.ts +143 -0
  32. package/dist/epoch.d.ts.map +1 -0
  33. package/dist/epoch.js +352 -0
  34. package/dist/epoch.js.map +1 -0
  35. package/dist/head-binding.d.ts +24 -0
  36. package/dist/head-binding.d.ts.map +1 -0
  37. package/dist/head-binding.js +61 -0
  38. package/dist/head-binding.js.map +1 -0
  39. package/dist/index.d.ts +585 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +1648 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/issuer-history.d.ts +151 -0
  44. package/dist/issuer-history.d.ts.map +1 -0
  45. package/dist/issuer-history.js +595 -0
  46. package/dist/issuer-history.js.map +1 -0
  47. package/dist/issuer-pin.d.ts +126 -0
  48. package/dist/issuer-pin.d.ts.map +1 -0
  49. package/dist/issuer-pin.js +567 -0
  50. package/dist/issuer-pin.js.map +1 -0
  51. package/dist/jcs.d.ts +8 -0
  52. package/dist/jcs.d.ts.map +1 -0
  53. package/dist/jcs.js +64 -0
  54. package/dist/jcs.js.map +1 -0
  55. package/dist/jws.d.ts +46 -0
  56. package/dist/jws.d.ts.map +1 -0
  57. package/dist/jws.js +129 -0
  58. package/dist/jws.js.map +1 -0
  59. package/dist/payer.d.ts +65 -0
  60. package/dist/payer.d.ts.map +1 -0
  61. package/dist/payer.js +148 -0
  62. package/dist/payer.js.map +1 -0
  63. package/dist/preimage.d.ts +78 -0
  64. package/dist/preimage.d.ts.map +1 -0
  65. package/dist/preimage.js +363 -0
  66. package/dist/preimage.js.map +1 -0
  67. package/dist/receipt-lane.d.ts +235 -0
  68. package/dist/receipt-lane.d.ts.map +1 -0
  69. package/dist/receipt-lane.js +446 -0
  70. package/dist/receipt-lane.js.map +1 -0
  71. package/dist/receipt-version.d.ts +98 -0
  72. package/dist/receipt-version.d.ts.map +1 -0
  73. package/dist/receipt-version.js +364 -0
  74. package/dist/receipt-version.js.map +1 -0
  75. package/dist/refusal.d.ts +93 -0
  76. package/dist/refusal.d.ts.map +1 -0
  77. package/dist/refusal.js +249 -0
  78. package/dist/refusal.js.map +1 -0
  79. package/dist/request-binding.d.ts +7 -0
  80. package/dist/request-binding.d.ts.map +1 -0
  81. package/dist/request-binding.js +26 -0
  82. package/dist/request-binding.js.map +1 -0
  83. package/dist/row-hash.d.ts +22 -0
  84. package/dist/row-hash.d.ts.map +1 -0
  85. package/dist/row-hash.js +26 -0
  86. package/dist/row-hash.js.map +1 -0
  87. package/dist/shell.d.ts +65 -0
  88. package/dist/shell.d.ts.map +1 -0
  89. package/dist/shell.js +268 -0
  90. package/dist/shell.js.map +1 -0
  91. package/dist/solana-payer.d.ts +99 -0
  92. package/dist/solana-payer.d.ts.map +1 -0
  93. package/dist/solana-payer.js +258 -0
  94. package/dist/solana-payer.js.map +1 -0
  95. package/dist/v11-receipt.d.ts +23 -0
  96. package/dist/v11-receipt.d.ts.map +1 -0
  97. package/dist/v11-receipt.js +368 -0
  98. package/dist/v11-receipt.js.map +1 -0
  99. package/dist/verdict.d.ts +94 -0
  100. package/dist/verdict.d.ts.map +1 -0
  101. package/dist/verdict.js +381 -0
  102. package/dist/verdict.js.map +1 -0
  103. package/issuer-history.snapshot.json +1 -0
  104. package/package.json +70 -59
  105. package/cli.js +0 -27
  106. package/index.cjs +0 -8
  107. package/index.d.ts +0 -5
  108. package/index.js +0 -7
package/dist/index.js ADDED
@@ -0,0 +1,1648 @@
1
+ "use strict";
2
+ /**
3
+ * @xfuel/verify — Offline verification for Chit402 receipts.
4
+ *
5
+ * Verify payment binding and output commitment WITHOUT calling the Chit402 API.
6
+ * Third parties use this to confirm:
7
+ * 1. The receipt's payment binding matches on-chain settlement
8
+ * 2. The output hash commitment is correct
9
+ * 3. The issuer signature is valid (ES256/JWKS)
10
+ * 4. (Optional) The SP1 nullifier is anchored on-chain
11
+ *
12
+ * See docs/specs/RECEIPT_V2_SEMANTICS.md for the verification algorithm.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.REFUSAL_SCHEMA = exports.verifyRefusal = exports.isRefusalDocument = exports.HEAD_BINDING_PAYLOAD_VERSION = exports.outerHeadDisagrees = exports.signedHeadBinding = exports.headBindingVerdict = exports.RECEIPT_LANE_BOUNDARY = exports.RECEIPT_LANE_ORDERING = exports.RECEIPT_LANE_RULE = exports.RECEIPT_LANE_SCHEMA = exports.anchorChangedSinceBinding = exports.deriveSettled = exports.deriveSettledBy = exports.receiptLaneDecision = exports.receiptLaneFromVerification = exports.buildReceiptLane = exports.jwksHostAllowed = exports.isPinnedTrustedJwk = exports.jwkThumbprint = exports.KEY_UNTRUSTED = exports.DEFAULT_TRUSTED_JWKS_HOSTS = exports.DEFAULT_TRUSTED_ISSUER_KIDS = exports.verifyIssuerJws = exports.resolvePinnedIssuerJwk = exports.canonicalSignedPayload = exports.BASE_SEPOLIA_RPC_URL = exports.ZK_VERIFIER_ADDRESS = exports.decodeJwsPayload = exports.receiptPayerClaimsFromEnvelope = exports.verifyPayerBinding = exports.SOLANA_USDC_MINT_DEVNET = exports.SOLANA_USDC_MINT_MAINNET = exports.SOLANA_RPC_URL = exports.fetchSolanaTransaction = exports.inferUsdcOutflowFromBalances = exports.extractUsdcTransfersFromTx = exports.isSolanaBase58Pubkey = exports.parseSolanaPaymentRef = exports.verifySolanaPayer = exports.BASE_RPC_URL = exports.ERC20_TRANSFER_TOPIC = exports.USDC_ADDRESSES = exports.fetchBaseTransactionReceipt = exports.sumUsdcTransfersFromPayer = exports.isEvmAddress = exports.parseBasePaymentRef = exports.verifyBasePayer = exports.computeInferenceBinding = exports.computePaymentCommitment = void 0;
16
+ exports.ISSUER_ROTATION_CONTEXT = exports.ISSUER_REGISTRATION_CONTEXT = exports.canonicalPublicKey = exports.verifyRegistrationSignature = exports.verifyCitizenRotation = exports.serializeIssuerPin = exports.rotationStatement = exports.registrationPreimage = exports.readIssuerPinClaim = exports.loadIssuerPinBytes = exports.issuerPinFileHash = exports.issuerPinContentUrl = exports.assessIssuerPin = exports.BASE_MAINNET_CHAIN_ID = exports.SOLANA_GENESIS = exports.ANCHOR_DOES_NOT_PROVE = exports.ANCHOR_PROVES = exports.leafHash = exports.parseAnchorMemo = exports.extractMemos = exports.verifyMerkleInclusion = exports.verifyAnchoredRoot = exports.CARRY_FORWARD_STATUS = exports.PINNED_ANCHOR_EPOCHS = exports.verifyCarryForward = exports.EPOCH2_OPENING_ROOT = exports.matchEpoch1Prefix = exports.epoch1PrefixRoot = exports.EPOCH1_SIZE2_ROOT = exports.EPOCH1_SIZE1_ROOT = exports.EPOCH1_GENESIS_DIGEST = exports.EPOCH1_FINAL_SIZE = exports.EPOCH1_FINAL_ROOT = exports.TREE_HEAD_SCHEMA_V2 = exports.TREE_HEAD_SCHEMA_V1 = exports.canonicalUnloggedRows = exports.unloggedReasonForTask = exports.unloggedIdCommitment = exports.verifyUnloggedCommitment = exports.verifyUnloggedSection = exports.verifyEpochInclusion = exports.verifyEpochRecord = exports.verifyEpochLink = exports.acceptTreeHeadSchema = exports.requestDigestOfPreimage = exports.verifyRequestDigest = exports.REFUSAL_DOES_NOT_PROVE = exports.REFUSAL_PROVES = exports.REFUSAL_PAYLOAD_VERSION = exports.REFUSAL_SCHEMA_V2 = void 0;
17
+ exports.decodeShellJwsPayload = exports.openV11Commitment = exports.shellHolderVerdict = exports.holderDocumentFromOwnerView = exports.compareShellToJws = exports.shellFromHolder = exports.isReceiptShell = exports.issuerHistoryDocumentHash = exports.readIssuerHistoryPin = exports.isJsonInteger = exports.refusalPayloadVersion = exports.readSignedClaims = exports.formatSupportedReceiptVersions = exports.signedClaimsOnAllowlist = exports.classifyShellDocument = exports.legacyIdentityErrors = exports.classifySignedClaims = exports.classifyReceiptDocument = exports.VERSION_MISMATCH = exports.UNSUPPORTED_VERSION = exports.VERIFIER_MIN = exports.REFUSAL_EXACT_VERSIONS = exports.LEGACY_PAYLOAD_VERSIONS = exports.SUPPORTED_RECEIPT_VERSIONS = exports.CANONICAL_PAYLOAD_VERSION = exports.verifyCanonicalPreimageBytes = exports.compileAnchorWallets = exports.verifyAnchorWalletDocument = exports.verifyTreeHeadTrust = exports.headTrustedFromInclusion = exports.headOmitsPinnedSigner = exports.HEAD_TRUST_MESSAGES = exports.LEGACY_HEAD_UNPINNED_SIGNER = exports.ANCHOR_WALLET_SOURCES_NOT_CONSULTED = exports.PINNED_SOLANA_ANCHOR_FEE_PAYER = exports.PINNED_BASE_ANCHOR_WALLET = exports.ISSUER_PIN_CHAIN_REFUSED = exports.ISSUER_ROTATION_UNCONTROLLED = exports.ISSUER_PIN_MUTABLE_REF = exports.ISSUER_PIN_DOWNGRADE = exports.ISSUER_SELF_SIG_INVALID = exports.ISSUER_PIN_HASH_MISMATCH = exports.ISSUER_PIN_MISMATCH = exports.CITIZEN_FREEZE_PURPOSE = exports.CITIZEN_FREEZE_SCHEMA = exports.PUBLISHED_ISSUER_PIN_KID = exports.ISSUER_PIN_CHAIN_ID = exports.ISSUER_PIN_PATH = exports.ISSUER_PIN_SCHEMA = exports.ISSUER_PIN_VERSION = void 0;
18
+ exports.INCLUDED_SHELL_LINE = exports.SHELL_SCHEMA = void 0;
19
+ exports.canonicalPayloadVersion = canonicalPayloadVersion;
20
+ exports.canonicalIssuerPayload = canonicalIssuerPayload;
21
+ exports.sumUsdcTransfersToPayee = sumUsdcTransfersToPayee;
22
+ exports.reconcileSettledTransfer = reconcileSettledTransfer;
23
+ exports.verifyIssuerSignature = verifyIssuerSignature;
24
+ exports.verifyIssuerSignatureWithJwks = verifyIssuerSignatureWithJwks;
25
+ exports.verifyBinding = verifyBinding;
26
+ exports.verifyNullifier = verifyNullifier;
27
+ exports.hashCanonicalPayload = hashCanonicalPayload;
28
+ exports.claimIdVerdict = claimIdVerdict;
29
+ exports.diffOuterClaims = diffOuterClaims;
30
+ exports.unsignedOuterFields = unsignedOuterFields;
31
+ exports.loadIssuerJwks = loadIssuerJwks;
32
+ exports.fetchIssuerJwks = fetchIssuerJwks;
33
+ exports.receiptPayerClaims = receiptPayerClaims;
34
+ exports.verifyReceiptUpToV10 = verifyReceiptUpToV10;
35
+ exports.verifyReceipt = verifyReceipt;
36
+ const ethers_1 = require("ethers");
37
+ const anchor_witness_js_1 = require("./anchor-witness.js");
38
+ const row_hash_js_1 = require("./row-hash.js");
39
+ const carry_forward_js_1 = require("./carry-forward.js");
40
+ const node_crypto_1 = require("node:crypto");
41
+ const binding_js_1 = require("./binding.js");
42
+ Object.defineProperty(exports, "computePaymentCommitment", { enumerable: true, get: function () { return binding_js_1.computePaymentCommitment; } });
43
+ Object.defineProperty(exports, "computeInferenceBinding", { enumerable: true, get: function () { return binding_js_1.computeInferenceBinding; } });
44
+ const base_payer_js_1 = require("./base-payer.js");
45
+ Object.defineProperty(exports, "verifyBasePayer", { enumerable: true, get: function () { return base_payer_js_1.verifyBasePayer; } });
46
+ Object.defineProperty(exports, "parseBasePaymentRef", { enumerable: true, get: function () { return base_payer_js_1.parseBasePaymentRef; } });
47
+ Object.defineProperty(exports, "isEvmAddress", { enumerable: true, get: function () { return base_payer_js_1.isEvmAddress; } });
48
+ Object.defineProperty(exports, "sumUsdcTransfersFromPayer", { enumerable: true, get: function () { return base_payer_js_1.sumUsdcTransfersFromPayer; } });
49
+ Object.defineProperty(exports, "fetchBaseTransactionReceipt", { enumerable: true, get: function () { return base_payer_js_1.fetchBaseTransactionReceipt; } });
50
+ Object.defineProperty(exports, "USDC_ADDRESSES", { enumerable: true, get: function () { return base_payer_js_1.USDC_ADDRESSES; } });
51
+ Object.defineProperty(exports, "ERC20_TRANSFER_TOPIC", { enumerable: true, get: function () { return base_payer_js_1.ERC20_TRANSFER_TOPIC; } });
52
+ Object.defineProperty(exports, "BASE_RPC_URL", { enumerable: true, get: function () { return base_payer_js_1.BASE_RPC_URL; } });
53
+ const solana_payer_js_1 = require("./solana-payer.js");
54
+ Object.defineProperty(exports, "verifySolanaPayer", { enumerable: true, get: function () { return solana_payer_js_1.verifySolanaPayer; } });
55
+ Object.defineProperty(exports, "parseSolanaPaymentRef", { enumerable: true, get: function () { return solana_payer_js_1.parseSolanaPaymentRef; } });
56
+ Object.defineProperty(exports, "isSolanaBase58Pubkey", { enumerable: true, get: function () { return solana_payer_js_1.isSolanaBase58Pubkey; } });
57
+ Object.defineProperty(exports, "extractUsdcTransfersFromTx", { enumerable: true, get: function () { return solana_payer_js_1.extractUsdcTransfersFromTx; } });
58
+ Object.defineProperty(exports, "inferUsdcOutflowFromBalances", { enumerable: true, get: function () { return solana_payer_js_1.inferUsdcOutflowFromBalances; } });
59
+ Object.defineProperty(exports, "fetchSolanaTransaction", { enumerable: true, get: function () { return solana_payer_js_1.fetchSolanaTransaction; } });
60
+ Object.defineProperty(exports, "SOLANA_RPC_URL", { enumerable: true, get: function () { return solana_payer_js_1.SOLANA_RPC_URL; } });
61
+ Object.defineProperty(exports, "SOLANA_USDC_MINT_MAINNET", { enumerable: true, get: function () { return solana_payer_js_1.SOLANA_USDC_MINT_MAINNET; } });
62
+ Object.defineProperty(exports, "SOLANA_USDC_MINT_DEVNET", { enumerable: true, get: function () { return solana_payer_js_1.SOLANA_USDC_MINT_DEVNET; } });
63
+ const payer_js_1 = require("./payer.js");
64
+ Object.defineProperty(exports, "verifyPayerBinding", { enumerable: true, get: function () { return payer_js_1.verifyPayerBinding; } });
65
+ Object.defineProperty(exports, "receiptPayerClaimsFromEnvelope", { enumerable: true, get: function () { return payer_js_1.receiptPayerClaimsFromEnvelope; } });
66
+ Object.defineProperty(exports, "decodeJwsPayload", { enumerable: true, get: function () { return payer_js_1.decodeJwsPayload; } });
67
+ const v11_receipt_js_1 = require("./v11-receipt.js");
68
+ const receipt_version_js_1 = require("./receipt-version.js");
69
+ const jws_js_1 = require("./jws.js");
70
+ const head_binding_js_1 = require("./head-binding.js");
71
+ const receipt_lane_js_1 = require("./receipt-lane.js");
72
+ const refusal_js_1 = require("./refusal.js");
73
+ const preimage_js_1 = require("./preimage.js");
74
+ const issuer_history_js_1 = require("./issuer-history.js");
75
+ const canonical_preimage_js_1 = require("./canonical-preimage.js");
76
+ const anchor_trust_js_1 = require("./anchor-trust.js");
77
+ /** ZKVerifierSP1 contract on Base mainnet. */
78
+ exports.ZK_VERIFIER_ADDRESS = '0x9373499645292715a2275A78eD65B14215C41c06';
79
+ /** Base Sepolia testnet RPC. */
80
+ exports.BASE_SEPOLIA_RPC_URL = 'https://sepolia.base.org';
81
+ /** Minimal ABI for nullifier check. */
82
+ const ZK_VERIFIER_ABI = [
83
+ 'function usedNullifiers(bytes32) view returns (bool)',
84
+ ];
85
+ /**
86
+ * HMAC payload version.
87
+ * Versions <= 7 keep the historical net/fee field list.
88
+ * Version 8 signs settled_amount plus the internal accounting breakdown.
89
+ * Lockstep with `canonicalPayloadVersion` in services/gateway/src/receipt.js
90
+ * for the v8 list (the v7 list here is the historical 15-field public formula).
91
+ */
92
+ function canonicalPayloadVersion(receipt) {
93
+ const stamped = receipt.hmac_attestation?.payload_version
94
+ ?? receipt.signature?.payload_version;
95
+ if (stamped != null)
96
+ return Number(stamped);
97
+ const issuerV = receipt.issuer_signature?.payload_version;
98
+ if (issuerV != null)
99
+ return Number(issuerV);
100
+ const payment = receipt.payment;
101
+ if (payment?.accounting || (payment && Object.prototype.hasOwnProperty.call(payment, 'settled_amount'))) {
102
+ return 8;
103
+ }
104
+ return 7;
105
+ }
106
+ function canonicalFieldsV7(receipt) {
107
+ return [
108
+ receipt.task_id ?? null,
109
+ receipt.payment?.rail ?? null,
110
+ receipt.payment?.ref ?? null,
111
+ receipt.payment?.gross_amount ?? null,
112
+ receipt.payment?.net_amount ?? null,
113
+ receipt.payment?.fee_amount ?? null,
114
+ receipt.payment?.protocol_fee_bps ?? receipt.payment?.fee_bps ?? null,
115
+ receipt.payment?.platform_fee ?? null,
116
+ receipt.payment?.platform_fee_bps ?? null,
117
+ receipt.provider_cogs?.actual ?? null,
118
+ receipt.route?.model ?? null,
119
+ receipt.route?.model_commitment?.commitment ?? null,
120
+ receipt.route?.provider ?? null,
121
+ receipt.output?.hash ?? null,
122
+ receipt.binding?.expected_commitment ?? null,
123
+ ];
124
+ }
125
+ function canonicalFieldsV8(receipt) {
126
+ const breakdown = receipt.payment?.accounting?.internal_breakdown;
127
+ const caller = receipt.caller_binding;
128
+ return [
129
+ receipt.task_id ?? null,
130
+ receipt.payment?.rail ?? null,
131
+ receipt.payment?.ref ?? null,
132
+ receipt.payment?.gross_amount ?? null,
133
+ receipt.payment?.settled_amount ?? null,
134
+ breakdown?.route_margin_bps ?? null,
135
+ breakdown?.route_margin_amount ?? null,
136
+ breakdown?.receipt_floor_amount ?? null,
137
+ breakdown?.provider_cogs_amount ?? null,
138
+ breakdown?.tier2_proof_amount ?? null,
139
+ receipt.provider_cogs?.actual ?? null,
140
+ receipt.route?.model ?? null,
141
+ receipt.route?.model_commitment?.commitment ?? null,
142
+ receipt.route?.provider ?? null,
143
+ receipt.output?.hash ?? null,
144
+ receipt.binding?.expected_commitment ?? null,
145
+ caller?.payer_wallet ?? null,
146
+ caller?.agent_pubkey ?? null,
147
+ caller?.api_key_hash ?? null,
148
+ ];
149
+ }
150
+ /**
151
+ * Canonical, order-stable payload an HMAC issuer signature covers.
152
+ * v8 matches `canonicalSignedPayload` in services/gateway/src/receipt.js.
153
+ * v7 and earlier stay on the historical 15-field list so old signatures verify.
154
+ */
155
+ function canonicalIssuerPayload(receipt) {
156
+ const fields = canonicalPayloadVersion(receipt) >= 8
157
+ ? canonicalFieldsV8(receipt)
158
+ : canonicalFieldsV7(receipt);
159
+ return JSON.stringify(fields);
160
+ }
161
+ function topicAddress(topic) {
162
+ const hex = topic.toLowerCase().replace(/^0x/, '');
163
+ return `0x${hex.slice(-40)}`;
164
+ }
165
+ /**
166
+ * Sum USDC Transfer values to `payee` in a transaction's logs.
167
+ * Non-Transfer logs are ignored. When `usdcAddress` is set, other contracts are ignored.
168
+ */
169
+ function sumUsdcTransfersToPayee(logs, payee, usdcAddress) {
170
+ if (!payee || !(0, base_payer_js_1.isEvmAddress)(payee))
171
+ return null;
172
+ const payeeLower = payee.toLowerCase();
173
+ const usdcLower = usdcAddress?.toLowerCase();
174
+ let total = 0n;
175
+ let found = false;
176
+ for (const log of logs || []) {
177
+ if (usdcLower && log.address?.toLowerCase() !== usdcLower)
178
+ continue;
179
+ const topics = log.topics || [];
180
+ if (topics[0]?.toLowerCase() !== base_payer_js_1.ERC20_TRANSFER_TOPIC)
181
+ continue;
182
+ if (topics.length < 3 || !topics[2])
183
+ continue;
184
+ if (topicAddress(topics[2]) !== payeeLower)
185
+ continue;
186
+ found = true;
187
+ total += BigInt(log.data || '0x0');
188
+ }
189
+ return found ? total : null;
190
+ }
191
+ /**
192
+ * Payment facts for on-chain reconciliation.
193
+ * A JWS is used only after `verifyIssuerSignatureWithJwks` accepts the key.
194
+ * An untrusted or invalid JWS is not decoded into the comparison, and the
195
+ * unsigned outer `payment` copy is not a fallback for those claims.
196
+ * Receipts with no JWS still use the outer payment (legacy envelopes).
197
+ */
198
+ function trustedPaymentForReconcile(receipt, options) {
199
+ const outerVersion = Number(receipt.issuer_signature?.payload_version ?? canonicalPayloadVersion(receipt));
200
+ const jws = receipt.issuer_signature?.jws;
201
+ if (!jws) {
202
+ return { ok: true, version: outerVersion, payment: receipt.payment || {} };
203
+ }
204
+ const verification = verifyIssuerSignatureWithJwks(receipt, options.jwks, {
205
+ trustedKids: options.trustedKids,
206
+ });
207
+ if (!verification.valid || verification.key_trusted === false) {
208
+ return {
209
+ ok: false,
210
+ version: 0,
211
+ reason: verification.reason || jws_js_1.KEY_UNTRUSTED,
212
+ };
213
+ }
214
+ const claims = verification.payload;
215
+ const claimPayment = (claims?.payment && typeof claims.payment === 'object')
216
+ ? claims.payment
217
+ : null;
218
+ if (!claimPayment) {
219
+ return { ok: false, version: 0, reason: 'no_signed_amount' };
220
+ }
221
+ // The signed payload is the version. The outer copy is not a fallback.
222
+ const signed = (0, receipt_version_js_1.classifySignedClaims)(claims && typeof claims === 'object' ? claims : null, null);
223
+ if (!signed.ok || signed.family !== 'legacy') {
224
+ return { ok: false, version: 0, reason: 'unsupported_version' };
225
+ }
226
+ return { ok: true, version: signed.version, payment: claimPayment };
227
+ }
228
+ /**
229
+ * Optional on-chain reconciliation. Given a tx receipt's logs, the signed
230
+ * amount the payee was supposed to receive must equal the USDC Transfer to payee.
231
+ *
232
+ * The amount and payee come from JWS claims only after a key-trust check
233
+ * (JWKS by kid, or an embedded key whose thumbprint is a pinned kid). An
234
+ * untrusted signature does not contribute those facts.
235
+ *
236
+ * v8 compares `settled_amount` (falling back to `gross_amount`): that is the
237
+ * on-chain transfer. v7 and earlier compare `net_amount`, which those receipts
238
+ * defined as "amount after fees". A single direct transfer of gross will not
239
+ * match a net that subtracts a fee that never moved on chain.
240
+ */
241
+ function reconcileSettledTransfer(receipt, logs, options = {}) {
242
+ const trusted = trustedPaymentForReconcile(receipt, options);
243
+ if (!trusted.ok) {
244
+ return {
245
+ checked: false,
246
+ matches: false,
247
+ payload_version: trusted.version,
248
+ signed_field: null,
249
+ signed_amount: null,
250
+ transfer_amount: null,
251
+ payee: null,
252
+ reason: trusted.reason,
253
+ };
254
+ }
255
+ const { version, payment } = trusted;
256
+ const payee = payment.payee ?? null;
257
+ let signed_field = null;
258
+ let signed_amount = null;
259
+ if (version >= 8) {
260
+ if (payment.settled_amount != null && payment.settled_amount !== '') {
261
+ signed_field = 'settled_amount';
262
+ signed_amount = String(payment.settled_amount);
263
+ }
264
+ else if (payment.gross_amount != null && payment.gross_amount !== '') {
265
+ signed_field = 'gross_amount';
266
+ signed_amount = String(payment.gross_amount);
267
+ }
268
+ }
269
+ else {
270
+ signed_field = 'net_amount';
271
+ signed_amount = payment.net_amount != null ? String(payment.net_amount) : null;
272
+ }
273
+ if (!payee || !(0, base_payer_js_1.isEvmAddress)(payee)) {
274
+ return {
275
+ checked: false,
276
+ matches: false,
277
+ payload_version: version,
278
+ signed_field,
279
+ signed_amount,
280
+ transfer_amount: null,
281
+ payee,
282
+ reason: 'no_payee',
283
+ };
284
+ }
285
+ if (signed_amount == null) {
286
+ return {
287
+ checked: false,
288
+ matches: false,
289
+ payload_version: version,
290
+ signed_field,
291
+ signed_amount,
292
+ transfer_amount: null,
293
+ payee,
294
+ reason: 'no_signed_amount',
295
+ };
296
+ }
297
+ const transfer = sumUsdcTransfersToPayee(logs, payee, options.usdcAddress);
298
+ if (transfer == null) {
299
+ return {
300
+ checked: true,
301
+ matches: false,
302
+ payload_version: version,
303
+ signed_field,
304
+ signed_amount,
305
+ transfer_amount: null,
306
+ payee,
307
+ reason: 'no_transfer_to_payee',
308
+ };
309
+ }
310
+ const matches = BigInt(signed_amount) === transfer;
311
+ return {
312
+ checked: true,
313
+ matches,
314
+ payload_version: version,
315
+ signed_field,
316
+ signed_amount,
317
+ transfer_amount: transfer.toString(),
318
+ payee,
319
+ reason: matches
320
+ ? undefined
321
+ : `amount_mismatch: signed ${signed_field} ${signed_amount} !== transfer ${transfer.toString()}`,
322
+ };
323
+ }
324
+ /**
325
+ * Verify a receipt's ES256 issuer signature against a JWK (public key).
326
+ * This is the public-key verification path — no shared secret required.
327
+ *
328
+ * Verification steps:
329
+ * 1. GET /receipt/:taskId?format=json → receipt.issuer_signature
330
+ * 2. GET /.well-known/jwks.json → find key matching issuer_signature.kid
331
+ * 3. ES256 verify canonicalIssuerPayload(receipt) against the signature
332
+ *
333
+ * @param receipt - Receipt JSON with issuer_signature
334
+ * @param jwk - JWK public key { kty: 'EC', crv: 'P-256', x, y }
335
+ */
336
+ function verifyIssuerSignature(receipt, jwk) {
337
+ const sig = receipt.issuer_signature;
338
+ if (!sig || !sig.value) {
339
+ return { checked: false, valid: false, reason: 'no_issuer_signature' };
340
+ }
341
+ if (sig.alg !== 'ES256') {
342
+ return { checked: false, valid: false, reason: `unsupported_alg: ${sig.alg}` };
343
+ }
344
+ if (!jwk || jwk.kty !== 'EC' || jwk.crv !== 'P-256') {
345
+ return { checked: false, valid: false, reason: 'invalid_jwk' };
346
+ }
347
+ if (sig.kid && jwk.kid && sig.kid !== jwk.kid) {
348
+ return { checked: false, valid: false, reason: 'kid_mismatch' };
349
+ }
350
+ try {
351
+ const jwkInput = { kty: jwk.kty, crv: jwk.crv, x: jwk.x, y: jwk.y };
352
+ const publicKey = (0, node_crypto_1.createPublicKey)({ key: jwkInput, format: 'jwk' });
353
+ const signature = Buffer.from(sig.value, 'base64url');
354
+ const payload = canonicalIssuerPayload(receipt);
355
+ const valid = (0, node_crypto_1.verify)('sha256', Buffer.from(payload, 'utf8'), {
356
+ key: publicKey,
357
+ dsaEncoding: 'ieee-p1363',
358
+ }, signature);
359
+ return { checked: true, valid, kid: sig.kid };
360
+ }
361
+ catch (err) {
362
+ return { checked: true, valid: false, kid: sig.kid, reason: `verify_error: ${err.message}` };
363
+ }
364
+ }
365
+ /**
366
+ * Verify a receipt's ES256 issuer signature against a JWKS (key set).
367
+ * Finds the matching key by kid and verifies.
368
+ *
369
+ * @param receipt - Receipt JSON with issuer_signature
370
+ * @param jwks - JWKS with keys array
371
+ */
372
+ function jwksCandidates(jwks, kid) {
373
+ const keys = jwks?.keys || [];
374
+ const es256 = keys.filter((k) => (0, jws_js_1.isEs256PublicJwk)(k) && (k.alg == null || k.alg === 'ES256'));
375
+ if (!kid)
376
+ return es256;
377
+ return es256.filter((k) => k.kid === kid);
378
+ }
379
+ /**
380
+ * Verify an issuer signature against trusted keys only.
381
+ *
382
+ * Trust, in order:
383
+ * 1. A JWKS entry matched by `kid` (supplied file or fetched issuer JWKS).
384
+ * 2. An embedded `issuer_jwk` whose RFC 7638 thumbprint equals a pinned trusted kid.
385
+ *
386
+ * An embedded key that merely verifies the bytes is `key untrusted`.
387
+ */
388
+ function verifyIssuerSignatureWithJwks(receipt, jwks, options = {}) {
389
+ const sig = receipt.issuer_signature;
390
+ if (!sig) {
391
+ return { checked: false, valid: false, key_trusted: false, reason: 'no_issuer_signature' };
392
+ }
393
+ const trustedKids = options.trustedKids ?? jws_js_1.DEFAULT_TRUSTED_ISSUER_KIDS;
394
+ const header = sig.jws ? (0, jws_js_1.readJwsHeader)(sig.jws) : null;
395
+ const kid = header?.kid || sig.kid;
396
+ const embedded = (0, jws_js_1.resolvePinnedIssuerJwk)(receipt);
397
+ const pinned = !!(embedded && (0, jws_js_1.isPinnedTrustedJwk)(embedded, trustedKids));
398
+ if (sig.jws) {
399
+ const fromJwks = jwksCandidates(jwks, kid);
400
+ for (const jwk of fromJwks) {
401
+ const jwsResult = (0, jws_js_1.verifyIssuerJws)(sig.jws, jwk);
402
+ if (jwsResult.valid) {
403
+ return {
404
+ checked: true,
405
+ valid: true,
406
+ key_trusted: true,
407
+ trust: 'jwks',
408
+ kid: jwk.kid || kid,
409
+ payload: jwsResult.payload,
410
+ };
411
+ }
412
+ }
413
+ if (pinned && embedded) {
414
+ const pinResult = (0, jws_js_1.verifyIssuerJws)(sig.jws, embedded);
415
+ if (pinResult.valid) {
416
+ return {
417
+ checked: true,
418
+ valid: true,
419
+ key_trusted: true,
420
+ trust: 'pinned_kid',
421
+ kid: embedded.kid || (0, jws_js_1.jwkThumbprint)(embedded),
422
+ payload: pinResult.payload,
423
+ };
424
+ }
425
+ return {
426
+ checked: true,
427
+ valid: false,
428
+ key_trusted: true,
429
+ kid: kid || embedded.kid,
430
+ reason: pinResult.reason || 'signature_invalid',
431
+ };
432
+ }
433
+ if (embedded && (0, jws_js_1.verifyIssuerJws)(sig.jws, embedded).valid) {
434
+ return {
435
+ checked: true,
436
+ valid: false,
437
+ key_trusted: false,
438
+ kid: embedded.kid || kid,
439
+ reason: jws_js_1.KEY_UNTRUSTED,
440
+ };
441
+ }
442
+ if (fromJwks.length === 0 && !pinned) {
443
+ return {
444
+ checked: true,
445
+ valid: false,
446
+ key_trusted: false,
447
+ kid,
448
+ reason: jws_js_1.KEY_UNTRUSTED,
449
+ };
450
+ }
451
+ return {
452
+ checked: true,
453
+ valid: false,
454
+ key_trusted: fromJwks.length > 0 || pinned,
455
+ kid,
456
+ reason: 'signature_invalid',
457
+ };
458
+ }
459
+ if (!sig.value) {
460
+ return { checked: false, valid: false, key_trusted: false, reason: 'no_issuer_signature' };
461
+ }
462
+ if (!jwks || !Array.isArray(jwks.keys)) {
463
+ return {
464
+ checked: false,
465
+ valid: false,
466
+ key_trusted: false,
467
+ kid: sig.kid,
468
+ reason: 'JWKS not provided — pass jwks option to verify issuer signature',
469
+ };
470
+ }
471
+ if (jwks.keys.length === 0) {
472
+ return { checked: false, valid: false, key_trusted: false, kid: sig.kid, reason: 'empty_jwks' };
473
+ }
474
+ // Find matching key by kid, or try all ES256 keys if no kid on signature
475
+ const candidates = sig.kid
476
+ ? jwks.keys.filter(k => k.kid === sig.kid && k.alg === 'ES256')
477
+ : jwks.keys.filter(k => k.alg === 'ES256');
478
+ if (candidates.length === 0) {
479
+ return { checked: false, valid: false, key_trusted: false, kid: sig.kid, reason: 'no_matching_key' };
480
+ }
481
+ for (const jwk of candidates) {
482
+ const result = verifyIssuerSignature(receipt, jwk);
483
+ if (result.valid) {
484
+ return { ...result, key_trusted: true, trust: 'jwks', kid: jwk.kid || sig.kid };
485
+ }
486
+ }
487
+ return { checked: true, valid: false, key_trusted: true, kid: sig.kid, reason: 'signature_invalid' };
488
+ }
489
+ /**
490
+ * Verify a receipt's payment binding locally (no network required).
491
+ *
492
+ * This recomputes the commitment from the receipt's fields and compares
493
+ * it to the stored `binding.expected_commitment`.
494
+ */
495
+ function noCommitmentReason(rail) {
496
+ if (rail === 'unmetered' || rail === 'tfuel') {
497
+ return 'No binding present on receipt (unmetered or TFUEL rail)';
498
+ }
499
+ if (rail === 'usdc' || rail === 'reported') {
500
+ return 'No payment-binding commitment (expected_commitment is null)';
501
+ }
502
+ return 'No binding present on receipt (may be unmetered or TFUEL rail)';
503
+ }
504
+ function verifyBinding(receipt) {
505
+ const binding = receipt.binding;
506
+ const railHint = binding?.rail || receipt.payment?.rail || null;
507
+ if (!binding) {
508
+ return {
509
+ verified: false,
510
+ expected: null,
511
+ recomputed: null,
512
+ matches: false,
513
+ covers: [],
514
+ reason: noCommitmentReason(railHint),
515
+ };
516
+ }
517
+ if (binding.expected_commitment == null || binding.expected_commitment === '') {
518
+ return {
519
+ verified: false,
520
+ expected: null,
521
+ recomputed: null,
522
+ matches: false,
523
+ covers: binding.covers || [],
524
+ reason: noCommitmentReason(railHint),
525
+ };
526
+ }
527
+ const paymentRef = receipt.payment?.ref ?? null;
528
+ const taskId = receipt.task_id;
529
+ const rail = (binding.rail || receipt.payment?.rail || 'usdc');
530
+ const amount = binding.amount || receipt.payment?.net_amount || '0';
531
+ const covers = binding.covers || ['payment', 'settlement'];
532
+ // Determine if this is a PBR (includes model + output)
533
+ const bindsInference = covers.includes('inference') ||
534
+ !!(binding.model_commitment && binding.output_hash);
535
+ let recomputed;
536
+ try {
537
+ if (bindsInference) {
538
+ const result = (0, binding_js_1.computeInferenceBinding)({
539
+ paymentRef,
540
+ taskId,
541
+ rail,
542
+ amount,
543
+ modelCommitment: binding.model_commitment,
544
+ outputHash: binding.output_hash,
545
+ });
546
+ recomputed = result.commitment;
547
+ }
548
+ else {
549
+ const result = (0, binding_js_1.computePaymentCommitment)({
550
+ paymentRef,
551
+ taskId,
552
+ rail,
553
+ amount,
554
+ });
555
+ recomputed = result.commitment;
556
+ }
557
+ }
558
+ catch (err) {
559
+ return {
560
+ verified: false,
561
+ expected: binding.expected_commitment || null,
562
+ recomputed: null,
563
+ matches: false,
564
+ covers,
565
+ reason: `Failed to recompute commitment: ${err instanceof Error ? err.message : String(err)}`,
566
+ };
567
+ }
568
+ const expected = binding.expected_commitment || null;
569
+ const matches = !!(expected &&
570
+ recomputed &&
571
+ expected.toLowerCase() === recomputed.toLowerCase());
572
+ return {
573
+ verified: true,
574
+ expected,
575
+ recomputed,
576
+ matches,
577
+ covers,
578
+ reason: matches ? undefined : 'Commitment mismatch — receipt may be tampered',
579
+ };
580
+ }
581
+ /**
582
+ * Verify a receipt's nullifier is anchored on-chain.
583
+ *
584
+ * Requires network access to the Base RPC.
585
+ */
586
+ async function verifyNullifier(receipt, options = {}) {
587
+ const nullifier = receipt.proof?.nullifier ?? null;
588
+ if (!nullifier) {
589
+ return {
590
+ verified: false,
591
+ nullifier: null,
592
+ anchored: null,
593
+ reason: 'No nullifier present (Tier-1 receipt or proof pending)',
594
+ };
595
+ }
596
+ if (!/^0x[0-9a-fA-F]{64}$/.test(nullifier)) {
597
+ return {
598
+ verified: false,
599
+ nullifier,
600
+ anchored: null,
601
+ reason: 'Invalid nullifier format',
602
+ };
603
+ }
604
+ const rpcUrl = options.rpcUrl || base_payer_js_1.BASE_RPC_URL;
605
+ const verifierAddress = options.verifierAddress || exports.ZK_VERIFIER_ADDRESS;
606
+ try {
607
+ const provider = new ethers_1.JsonRpcProvider(rpcUrl);
608
+ const contract = new ethers_1.Contract(verifierAddress, ZK_VERIFIER_ABI, provider);
609
+ const isUsed = await contract.usedNullifiers(nullifier);
610
+ return {
611
+ verified: true,
612
+ nullifier,
613
+ anchored: isUsed,
614
+ reason: isUsed ? undefined : 'Nullifier not found on-chain (proof may not be submitted yet)',
615
+ };
616
+ }
617
+ catch (err) {
618
+ return {
619
+ verified: false,
620
+ nullifier,
621
+ anchored: null,
622
+ reason: `Chain query failed: ${err instanceof Error ? err.message : String(err)}`,
623
+ };
624
+ }
625
+ }
626
+ /**
627
+ * Canonical signed payload for HMAC verification.
628
+ * Alias of canonicalIssuerPayload — both must produce identical bytes.
629
+ */
630
+ exports.canonicalSignedPayload = canonicalIssuerPayload;
631
+ /**
632
+ * Hash the canonical payload (for ERC-8004 response_hash).
633
+ */
634
+ function hashCanonicalPayload(receipt) {
635
+ return (0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)((0, exports.canonicalSignedPayload)(receipt)));
636
+ }
637
+ /**
638
+ * claim_id-era receipts include the key even when the value is null.
639
+ * Older payloads omit the key and stay valid.
640
+ */
641
+ function claimIdVerdict(claims) {
642
+ if (!claims || !Object.prototype.hasOwnProperty.call(claims, 'claim_id')) {
643
+ return 'not_present_legacy';
644
+ }
645
+ const payment = asRecord(claims.payment);
646
+ const ref = payment?.ref;
647
+ const hasRef = ref != null && String(ref) !== '';
648
+ const id = claims.claim_id;
649
+ const missing = id == null || id === '';
650
+ if (hasRef && missing)
651
+ return 'refused';
652
+ return 'ok';
653
+ }
654
+ function claimString(value) {
655
+ if (value == null || value === '')
656
+ return null;
657
+ return String(value);
658
+ }
659
+ function asRecord(value) {
660
+ if (!value || typeof value !== 'object' || Array.isArray(value))
661
+ return null;
662
+ return value;
663
+ }
664
+ function isPlain(value) {
665
+ return !!value && typeof value === 'object' && !Array.isArray(value);
666
+ }
667
+ function formatClaim(value) {
668
+ if (value == null)
669
+ return null;
670
+ if (typeof value === 'string')
671
+ return value;
672
+ if (typeof value === 'number' || typeof value === 'boolean')
673
+ return String(value);
674
+ return JSON.stringify(value);
675
+ }
676
+ /** 0x hex is compared case-insensitively. Checksum case is not a different claim. */
677
+ function sameLeaf(signed, outer) {
678
+ if (Array.isArray(signed) || Array.isArray(outer)) {
679
+ return JSON.stringify(signed) === JSON.stringify(outer);
680
+ }
681
+ if (typeof signed === 'string' && typeof outer === 'string') {
682
+ if (/^0x[0-9a-fA-F]+$/.test(signed) && /^0x[0-9a-fA-F]+$/.test(outer)) {
683
+ return signed.toLowerCase() === outer.toLowerCase();
684
+ }
685
+ return signed === outer;
686
+ }
687
+ if (signed == null || outer == null)
688
+ return signed == null && outer == null;
689
+ return Object.is(signed, outer);
690
+ }
691
+ /**
692
+ * The outer receipt `schema` (`xfuel.receipt.v3`) is the document type.
693
+ * The JWS `schema` (`chit402.foreign_payout.v1`) is the payload type.
694
+ * They share a name and are not copies of each other.
695
+ */
696
+ function schemaIsNotACopy(path) {
697
+ return path === 'schema';
698
+ }
699
+ function compareSignedNode(signed, outer, prefix, mismatches) {
700
+ if (!isPlain(signed))
701
+ return;
702
+ if (!isPlain(outer)) {
703
+ mismatches.push({
704
+ field: prefix || '$',
705
+ outer: formatClaim(outer),
706
+ signed: formatClaim(signed),
707
+ });
708
+ return;
709
+ }
710
+ for (const key of Object.keys(signed)) {
711
+ const path = prefix ? `${prefix}.${key}` : key;
712
+ if (schemaIsNotACopy(path))
713
+ continue;
714
+ if (!Object.prototype.hasOwnProperty.call(outer, key))
715
+ continue;
716
+ const sv = signed[key];
717
+ const ov = outer[key];
718
+ if (isPlain(sv) && isPlain(ov)) {
719
+ compareSignedNode(sv, ov, path, mismatches);
720
+ continue;
721
+ }
722
+ if (!sameLeaf(sv, ov)) {
723
+ mismatches.push({ field: path, outer: formatClaim(ov), signed: formatClaim(sv) });
724
+ }
725
+ }
726
+ }
727
+ /**
728
+ * Walk every signed claim. When the outer receipt has the same path, the
729
+ * values must match, including null against a filled-in outer copy. A path
730
+ * the outer receipt omits is not a copy, so it is not a mismatch.
731
+ */
732
+ function diffOuterClaims(receipt, claims) {
733
+ if (!claims)
734
+ return [];
735
+ const mismatches = [];
736
+ compareSignedNode(claims, receipt, '', mismatches);
737
+ return mismatches;
738
+ }
739
+ function pushUnsignedLeaves(value, path, paths) {
740
+ if (isPlain(value)) {
741
+ const keys = Object.keys(value).sort();
742
+ if (keys.length === 0) {
743
+ paths.push(path);
744
+ return;
745
+ }
746
+ for (const key of keys)
747
+ pushUnsignedLeaves(value[key], `${path}.${key}`, paths);
748
+ return;
749
+ }
750
+ paths.push(path);
751
+ }
752
+ function collectUnsigned(outer, signed, prefix, paths) {
753
+ if (!isPlain(outer))
754
+ return;
755
+ const signedObj = isPlain(signed) ? signed : null;
756
+ for (const key of Object.keys(outer).sort()) {
757
+ const path = prefix ? `${prefix}.${key}` : key;
758
+ // The signature container is the credential that was checked, not an unsigned claim.
759
+ if (!prefix && key === 'issuer_signature')
760
+ continue;
761
+ const signedHas = !!signedObj && Object.prototype.hasOwnProperty.call(signedObj, key);
762
+ if (!signedHas || schemaIsNotACopy(path)) {
763
+ pushUnsignedLeaves(outer[key], path, paths);
764
+ continue;
765
+ }
766
+ const sv = signedObj[key];
767
+ if (isPlain(outer[key]) && isPlain(sv))
768
+ collectUnsigned(outer[key], sv, path, paths);
769
+ }
770
+ }
771
+ /** Outer paths the signed claims do not cover. Sorted. Not a failure by themselves. */
772
+ function unsignedOuterFields(receipt, claims) {
773
+ const paths = [];
774
+ collectUnsigned(receipt, claims, '', paths);
775
+ return paths;
776
+ }
777
+ function receiptViewFromClaims(receipt, claims) {
778
+ const payment = asRecord(claims.payment);
779
+ const binding = asRecord(claims.binding);
780
+ const route = asRecord(claims.route);
781
+ const output = asRecord(claims.output);
782
+ const caller = asRecord(claims.caller_binding);
783
+ const modelCommitment = claimString(route?.model_commitment);
784
+ return {
785
+ ...receipt,
786
+ task_id: claimString(claims.task_id) || receipt.task_id,
787
+ payment: {
788
+ rail: claimString(payment?.rail) ?? undefined,
789
+ ref: claimString(payment?.ref),
790
+ gross_amount: claimString(payment?.gross_amount),
791
+ settled_amount: claimString(payment?.settled_amount),
792
+ net_amount: claimString(payment?.net_amount),
793
+ asset: claimString(payment?.asset),
794
+ payee: claimString(payment?.payee),
795
+ fee_amount: claimString(payment?.fee_amount),
796
+ protocol_fee_bps: typeof payment?.protocol_fee_bps === 'number' ? payment.protocol_fee_bps : null,
797
+ platform_fee: claimString(payment?.platform_fee),
798
+ platform_fee_bps: typeof payment?.platform_fee_bps === 'number' ? payment.platform_fee_bps : null,
799
+ },
800
+ route: {
801
+ model: claimString(route?.model) ?? undefined,
802
+ provider: claimString(route?.provider) ?? undefined,
803
+ model_commitment: modelCommitment ? { commitment: modelCommitment } : null,
804
+ },
805
+ output: output?.hash ? { hash: claimString(output.hash) ?? undefined } : null,
806
+ caller_binding: caller
807
+ ? {
808
+ payer_wallet: claimString(caller.payer_wallet),
809
+ agent_pubkey: claimString(caller.agent_pubkey),
810
+ api_key_hash: claimString(caller.api_key_hash),
811
+ }
812
+ : null,
813
+ provider_cogs: asRecord(claims.provider_cogs)?.actual != null
814
+ ? { actual: claimString(asRecord(claims.provider_cogs)?.actual) ?? undefined }
815
+ : receipt.provider_cogs,
816
+ binding: {
817
+ expected_commitment: binding && 'expected_commitment' in binding
818
+ ? (claimString(binding.expected_commitment) ?? undefined)
819
+ : undefined,
820
+ amount: claimString(binding?.amount)
821
+ || claimString(payment?.net_amount)
822
+ || claimString(payment?.gross_amount)
823
+ || '0',
824
+ rail: claimString(binding?.rail) || claimString(payment?.rail) || undefined,
825
+ covers: Array.isArray(binding?.covers) ? binding.covers : ['payment', 'settlement'],
826
+ model_commitment: claimString(binding?.model_commitment) || modelCommitment,
827
+ output_hash: claimString(binding?.output_hash) || claimString(output?.hash),
828
+ },
829
+ };
830
+ }
831
+ function payerClaimsFromPayload(payload) {
832
+ const payment = asRecord(payload.payment);
833
+ const caller = asRecord(payload.caller_binding);
834
+ return {
835
+ payment: {
836
+ ref: claimString(payment?.ref),
837
+ gross_amount: claimString(payment?.gross_amount),
838
+ payee: claimString(payment?.payee),
839
+ asset: claimString(payment?.asset),
840
+ rail: claimString(payment?.rail),
841
+ },
842
+ caller_binding: caller ? { payer_wallet: claimString(caller.payer_wallet) } : null,
843
+ };
844
+ }
845
+ function factsFromClaims(claims) {
846
+ if (!claims) {
847
+ return { hub: null, model: null, amount_usdc: null, tx: null, output_hash: null };
848
+ }
849
+ const payment = asRecord(claims.payment);
850
+ const route = asRecord(claims.route);
851
+ const output = asRecord(claims.output);
852
+ return {
853
+ hub: claimString(route?.provider),
854
+ model: claimString(route?.model),
855
+ amount_usdc: claimString(payment?.gross_amount),
856
+ tx: claimString(payment?.ref),
857
+ output_hash: claimString(output?.hash),
858
+ };
859
+ }
860
+ function issuerJwksUri(receipt) {
861
+ const fromVerification = receipt?.verification?.jwks_uri;
862
+ if (typeof fromVerification === 'string' && fromVerification.startsWith('https://'))
863
+ return fromVerification;
864
+ const jws = receipt?.issuer_signature?.jws;
865
+ const header = jws ? (0, jws_js_1.readJwsHeader)(jws) : null;
866
+ if (header?.jku && header.jku.startsWith('https://'))
867
+ return header.jku;
868
+ return null;
869
+ }
870
+ function httpsUrl(uri) {
871
+ try {
872
+ return new URL(uri).protocol === 'https:';
873
+ }
874
+ catch {
875
+ return false;
876
+ }
877
+ }
878
+ function mergeJwks(primary, extra) {
879
+ const keys = [...(primary?.keys || []), ...(extra?.keys || [])];
880
+ if (keys.length === 0)
881
+ return undefined;
882
+ const seen = new Set();
883
+ const deduped = [];
884
+ for (const key of keys) {
885
+ const id = `${key.kid || ''}:${key.x || ''}:${key.y || ''}`;
886
+ if (seen.has(id))
887
+ continue;
888
+ seen.add(id);
889
+ deduped.push(key);
890
+ }
891
+ return { keys: deduped };
892
+ }
893
+ /**
894
+ * Key sources shared by receipt verification and the epoch-record check:
895
+ * a caller-supplied JWKS, `--jwks-url` (any https URL), and `--fetch-jwks`
896
+ * from an allowlisted host. A failed fetch is an error. It does not add a key.
897
+ */
898
+ async function loadIssuerJwks(source, options = {}) {
899
+ const errors = [];
900
+ let jwks = options.jwks;
901
+ const trustedHosts = options.trustedJwksHosts ?? jws_js_1.DEFAULT_TRUSTED_JWKS_HOSTS;
902
+ if (options.jwksUri || options.fetchJwks) {
903
+ const uri = options.jwksUri || issuerJwksUri(source);
904
+ const allowed = !!uri && (options.jwksUri ? httpsUrl(uri) : (0, jws_js_1.jwksHostAllowed)(uri, trustedHosts));
905
+ if (uri && allowed) {
906
+ try {
907
+ const fetched = await fetchIssuerJwks(uri, options.fetchImpl);
908
+ jwks = mergeJwks(jwks, fetched);
909
+ }
910
+ catch (err) {
911
+ errors.push(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
912
+ }
913
+ }
914
+ else if (options.jwksUri) {
915
+ errors.push('JWKS URI rejected — only https URLs are fetched');
916
+ }
917
+ else if (options.fetchJwks && uri) {
918
+ errors.push(`JWKS host untrusted: ${uri}`);
919
+ }
920
+ }
921
+ return { jwks, errors };
922
+ }
923
+ /** Fetch a JWKS document. Caller decides whether the URL is a trust root. */
924
+ async function fetchIssuerJwks(uri, fetchImpl = globalThis.fetch) {
925
+ if (!httpsUrl(uri))
926
+ throw new Error('jwks_uri must be https');
927
+ const res = await fetchImpl(uri);
928
+ if (!res.ok)
929
+ throw new Error(`jwks_fetch_failed: ${res.status}`);
930
+ const body = await res.json();
931
+ if (!body || !Array.isArray(body.keys))
932
+ throw new Error('jwks_malformed');
933
+ return body;
934
+ }
935
+ /**
936
+ * Full receipt verification — trusted issuer signature, signed-claim facts,
937
+ * optional on-chain payer and nullifier checks.
938
+ *
939
+ * Facts (amount, payer, payee, asset, tx, model) are taken only from a JWS
940
+ * that verified under a trusted key. The embedded `issuer_jwk` is not trusted
941
+ * unless its RFC 7638 thumbprint is a pinned kid, or the same key is in a JWKS.
942
+ */
943
+ /** Extract JWS claims for payer binding. Prefers the JWS payload over the outer copy. */
944
+ function receiptPayerClaims(receipt) {
945
+ return (0, payer_js_1.receiptPayerClaimsFromEnvelope)(receipt);
946
+ }
947
+ function normalizeBoundRoot(root) {
948
+ if (root == null || root === '')
949
+ return null;
950
+ const hex = String(root).replace(/^0x/i, '').toLowerCase();
951
+ return /^[0-9a-f]{64}$/.test(hex) ? hex : null;
952
+ }
953
+ /**
954
+ * Row hash for an offline leaf. Null and `''` are missing: do not hash `task_id|`.
955
+ */
956
+ function inclusionRow(receipt, inclusion) {
957
+ const bound = (0, row_hash_js_1.boundRowHash)(receipt, inclusion);
958
+ if (!bound.ok)
959
+ return bound;
960
+ if (bound.row == null || bound.row === '')
961
+ return { ok: false, reason: 'no_leaf' };
962
+ return { ok: true, row: bound.row };
963
+ }
964
+ /**
965
+ * Bind a supplied inclusion proof to its leaf index and tree size.
966
+ * The head's size, when present, has to be the inclusion's size.
967
+ */
968
+ function offlineInclusionBound(receipt, head, inclusion) {
969
+ const index = inclusion.leaf_index;
970
+ const size = inclusion.tree_size ?? head?.tree_size;
971
+ if (head?.tree_size != null && inclusion.tree_size != null
972
+ && Number(head.tree_size) !== Number(inclusion.tree_size)) {
973
+ return { ok: false, reason: 'tree_size_mismatch' };
974
+ }
975
+ if (index == null || size == null || !Array.isArray(inclusion.proof)) {
976
+ return { ok: false, reason: 'inclusion_failed' };
977
+ }
978
+ const root = normalizeBoundRoot(head?.root) || normalizeBoundRoot(inclusion.root);
979
+ if (!root)
980
+ return { ok: false, reason: 'bad_root' };
981
+ if (receipt.task_id == null)
982
+ return { ok: false, reason: 'missing_task_id' };
983
+ const bound = inclusionRow(receipt, inclusion);
984
+ if (!bound.ok)
985
+ return bound;
986
+ const leaf = (0, anchor_witness_js_1.leafHash)(Buffer.from(`${receipt.task_id}|${bound.row}`));
987
+ if (typeof inclusion.leaf === 'string' && /^[0-9a-fA-F]{64}$/.test(inclusion.leaf)
988
+ && inclusion.leaf.toLowerCase() !== leaf.toString('hex')) {
989
+ return { ok: false, reason: 'leaf_mismatch' };
990
+ }
991
+ const included = (0, anchor_witness_js_1.verifyMerkleInclusion)(leaf, Number(index), Number(size), root, inclusion.proof);
992
+ return included ? { ok: true } : { ok: false, reason: 'inclusion_failed' };
993
+ }
994
+ /**
995
+ * `{ root }` and `{ root, tree_size }` only compare a signed tree_head_hash.
996
+ * Any other supplied head is an offline tree-head witness and needs a signature.
997
+ */
998
+ function offlineHeadNeedsSignature(head) {
999
+ if (!head || typeof head !== 'object')
1000
+ return false;
1001
+ return Object.keys(head).some((key) => key !== 'root' && key !== 'tree_size');
1002
+ }
1003
+ function suppliedHeadCovers(receipt, signedRoot, head, inclusion) {
1004
+ const signed = normalizeBoundRoot(signedRoot);
1005
+ const supplied = normalizeBoundRoot(head?.root);
1006
+ if (!signed || !supplied)
1007
+ return false;
1008
+ if (signed === supplied)
1009
+ return true;
1010
+ if (!inclusion || !Array.isArray(inclusion.proof) || inclusion.leaf_index == null)
1011
+ return true;
1012
+ if (receipt.task_id == null)
1013
+ return false;
1014
+ const bound = inclusionRow(receipt, inclusion);
1015
+ if (!bound.ok)
1016
+ return false;
1017
+ const leaf = (0, anchor_witness_js_1.leafHash)(Buffer.from(`${receipt.task_id}|${bound.row}`));
1018
+ if (typeof inclusion.leaf === 'string' && /^[0-9a-fA-F]{64}$/.test(inclusion.leaf)
1019
+ && inclusion.leaf.toLowerCase() !== leaf.toString('hex')) {
1020
+ return false;
1021
+ }
1022
+ const size = inclusion.tree_size ?? head.tree_size;
1023
+ if (size == null || !Number.isInteger(Number(size)))
1024
+ return false;
1025
+ return (0, anchor_witness_js_1.verifyMerkleInclusion)(leaf, Number(inclusion.leaf_index), Number(size), supplied, inclusion.proof);
1026
+ }
1027
+ /** v1–v10 verifier. A v11 payload is `unsupported_version` and is not checked as v10. */
1028
+ async function verifyReceiptUpToV10(receipt, options = {}) {
1029
+ return (0, v11_receipt_js_1.verifyReceiptUpToV10)(receipt, options, verifyReceipt);
1030
+ }
1031
+ async function verifyReceipt(receipt, options = {}) {
1032
+ let gate;
1033
+ try {
1034
+ gate = (0, receipt_version_js_1.classifyReceiptDocument)(receipt);
1035
+ }
1036
+ catch {
1037
+ return (0, v11_receipt_js_1.rejectReceiptVersion)(receipt, ['unsupported_version'], 'unsupported_version');
1038
+ }
1039
+ const identityErrors = (0, receipt_version_js_1.legacyIdentityErrors)(receipt);
1040
+ if (identityErrors.length) {
1041
+ return (0, v11_receipt_js_1.rejectReceiptVersion)(receipt, identityErrors, identityErrors[0]);
1042
+ }
1043
+ if (!gate.ok) {
1044
+ return (0, v11_receipt_js_1.rejectReceiptVersion)(receipt, gate.errors, gate.reason);
1045
+ }
1046
+ if (gate.family === 'v11') {
1047
+ const v11 = await (0, v11_receipt_js_1.verifyV11Receipt)(receipt, options);
1048
+ return Object.assign(v11, { receipt_version: 11, version_source: 'signed' });
1049
+ }
1050
+ const versionStamp = gate.family === 'legacy'
1051
+ ? { receipt_version: gate.version, version_source: gate.version_source }
1052
+ : {};
1053
+ const errors = [];
1054
+ const trustedKids = options.trustedKids ?? jws_js_1.DEFAULT_TRUSTED_ISSUER_KIDS;
1055
+ const trustedHosts = options.trustedJwksHosts ?? jws_js_1.DEFAULT_TRUSTED_JWKS_HOSTS;
1056
+ const loadedKeys = await loadIssuerJwks(receipt, {
1057
+ jwks: options.jwks,
1058
+ jwksUri: options.jwksUri,
1059
+ fetchJwks: options.fetchJwks,
1060
+ trustedJwksHosts: trustedHosts,
1061
+ fetchImpl: options.fetchImpl,
1062
+ });
1063
+ const jwks = loadedKeys.jwks;
1064
+ errors.push(...loadedKeys.errors);
1065
+ let issuer_signature;
1066
+ if (receipt.issuer_signature?.jws || receipt.issuer_signature?.value) {
1067
+ issuer_signature = verifyIssuerSignatureWithJwks(receipt, jwks, { trustedKids });
1068
+ if (issuer_signature.checked && !issuer_signature.valid) {
1069
+ errors.push(issuer_signature.reason === jws_js_1.KEY_UNTRUSTED
1070
+ ? jws_js_1.KEY_UNTRUSTED
1071
+ : `Issuer signature invalid: ${issuer_signature.reason}`);
1072
+ }
1073
+ }
1074
+ else if (receipt.issuer_signature) {
1075
+ issuer_signature = {
1076
+ checked: false,
1077
+ valid: false,
1078
+ key_trusted: false,
1079
+ kid: receipt.issuer_signature.kid,
1080
+ reason: 'JWKS not provided — pass jwks option to verify issuer signature',
1081
+ };
1082
+ }
1083
+ else {
1084
+ issuer_signature = {
1085
+ checked: false,
1086
+ valid: false,
1087
+ key_trusted: false,
1088
+ reason: 'No issuer signature present on receipt',
1089
+ };
1090
+ }
1091
+ const decoded = receipt.issuer_signature?.jws
1092
+ ? (0, payer_js_1.decodeJwsPayload)(receipt.issuer_signature.jws)
1093
+ : null;
1094
+ const claim_mismatches = diffOuterClaims(receipt, decoded);
1095
+ const unsigned_fields = unsignedOuterFields(receipt, decoded);
1096
+ for (const mismatch of claim_mismatches) {
1097
+ errors.push(`outer/signed mismatch: ${mismatch.field} (outer ${mismatch.outer}, signed ${mismatch.signed})`);
1098
+ }
1099
+ const verifiedClaims = issuer_signature.valid ? issuer_signature.payload : undefined;
1100
+ const claim_id = claimIdVerdict(issuer_signature.valid ? verifiedClaims : decoded);
1101
+ if (issuer_signature.valid && claim_id === 'refused') {
1102
+ errors.push('payment.ref is set and claim_id is null');
1103
+ }
1104
+ const headVerdict = (0, head_binding_js_1.headBindingVerdict)(issuer_signature.valid ? verifiedClaims : null);
1105
+ const headMissing = headVerdict === 'missing';
1106
+ if (headMissing) {
1107
+ errors.push('payload v9 requires tree_head_hash and tolerance inside signed claims');
1108
+ }
1109
+ const signedBinding = headVerdict === 'ok' ? (0, head_binding_js_1.signedHeadBinding)(verifiedClaims) : null;
1110
+ // A published head may differ from the signed prefix. That is not a failure.
1111
+ // An inclusion proof, when one is supplied, must be for this receipt's leaf
1112
+ // (`task_id|row_hash`), not an arbitrary hash already in the tree.
1113
+ // A head inside the inclusion is a summary. It counts only when its JWS
1114
+ // verifies under JWKS or a pinned kid. A key carried beside that JWS is
1115
+ // not a trust root. A caller-supplied head wins.
1116
+ const witnessHead = (options.head
1117
+ ?? (0, anchor_trust_js_1.headTrustedFromInclusion)(options.inclusion, { jwks, trustedKids })
1118
+ ?? null);
1119
+ let headMismatch = false;
1120
+ let sizeMismatch = false;
1121
+ if (witnessHead && options.inclusion
1122
+ && witnessHead.tree_size != null
1123
+ && options.inclusion.tree_size != null
1124
+ && Number(witnessHead.tree_size) !== Number(options.inclusion.tree_size)) {
1125
+ sizeMismatch = true;
1126
+ errors.push('tree_size_mismatch');
1127
+ }
1128
+ else if (signedBinding?.tree_head_hash && witnessHead?.root && options.inclusion) {
1129
+ if (!suppliedHeadCovers(receipt, signedBinding.tree_head_hash, witnessHead, options.inclusion)) {
1130
+ headMismatch = true;
1131
+ errors.push('tree_head_mismatch');
1132
+ }
1133
+ }
1134
+ const issuedAt = (verifiedClaims && 'iat' in verifiedClaims ? verifiedClaims.iat : null)
1135
+ ?? decoded?.iat
1136
+ ?? receipt.created_at
1137
+ ?? null;
1138
+ const historyPin = (0, issuer_history_js_1.readIssuerHistoryPin)(verifiedClaims);
1139
+ const payloadVersion = Number(verifiedClaims?.payload_version);
1140
+ // Payload v10 signs the history pin. A missing pin fails even when the
1141
+ // caller did not pass a history file or ask for a fetch.
1142
+ const pinRequired = !options.skipIssuerHistory
1143
+ && Number.isFinite(payloadVersion)
1144
+ && payloadVersion >= canonical_preimage_js_1.CANONICAL_PAYLOAD_VERSION;
1145
+ const historyAsked = pinRequired || (!options.skipIssuerHistory && !!(options.issuerHistory
1146
+ || options.issuerHistoryBytes
1147
+ || options.fetchIssuerHistory
1148
+ || options.strictIssuerHistory
1149
+ || options.issuerHistoryUrl
1150
+ || historyPin));
1151
+ const issuer_history = historyAsked
1152
+ ? await (0, issuer_history_js_1.checkReceiptIssuerHistory)(receipt, {
1153
+ document: options.issuerHistory ?? null,
1154
+ documentBytes: options.issuerHistoryBytes ?? null,
1155
+ fetchHistory: options.fetchIssuerHistory === true || options.strictIssuerHistory === true,
1156
+ strict: options.strictIssuerHistory === true,
1157
+ historyUrl: options.issuerHistoryUrl ?? null,
1158
+ jwks,
1159
+ trustedKids,
1160
+ fetchImpl: options.fetchImpl,
1161
+ trustedHosts,
1162
+ issuedAt,
1163
+ kid: issuer_signature.kid ?? receipt.issuer_signature?.kid ?? null,
1164
+ pin: historyPin,
1165
+ requirePin: pinRequired,
1166
+ })
1167
+ : {
1168
+ checked: false,
1169
+ ok: true,
1170
+ unreachable: false,
1171
+ warning: null,
1172
+ reason: null,
1173
+ kid: issuer_signature.kid ?? receipt.issuer_signature?.kid ?? null,
1174
+ document: null,
1175
+ loaded: false,
1176
+ };
1177
+ // Offline: a tree-head witness is trusted only when its ES256 signature
1178
+ // covers the outer size, root, and the other fields anchor mode already
1179
+ // compares. A missing signature is head_signature_missing. The history
1180
+ // body loaded above is the one this check trusts. Chain RPC is not used.
1181
+ let headTrustFailed = false;
1182
+ const suppliedHead = witnessHead;
1183
+ if (offlineHeadNeedsSignature(suppliedHead)) {
1184
+ const trust = (0, anchor_trust_js_1.verifyTreeHeadTrust)(suppliedHead, {
1185
+ jwks,
1186
+ trustedKids,
1187
+ issuerHistory: issuer_history.document,
1188
+ strictIssuerHistory: options.strictIssuerHistory === true,
1189
+ });
1190
+ if (!trust.ok) {
1191
+ headTrustFailed = true;
1192
+ errors.push(trust.reason || 'head_signature_invalid');
1193
+ }
1194
+ else if (issuer_history.loaded && !issuer_history.document) {
1195
+ headTrustFailed = true;
1196
+ errors.push('issuer_history_invalid');
1197
+ }
1198
+ }
1199
+ let inclusionFailed = false;
1200
+ if (!sizeMismatch && options.inclusion && (options.inclusion.proof || options.inclusion.leaf_index != null)) {
1201
+ const bound = offlineInclusionBound(receipt, witnessHead, options.inclusion);
1202
+ if (!bound.ok) {
1203
+ inclusionFailed = true;
1204
+ errors.push(bound.reason);
1205
+ }
1206
+ }
1207
+ let binding;
1208
+ if (receipt.issuer_signature?.jws) {
1209
+ if (verifiedClaims) {
1210
+ binding = verifyBinding(receiptViewFromClaims(receipt, verifiedClaims));
1211
+ }
1212
+ else {
1213
+ binding = {
1214
+ verified: false,
1215
+ expected: null,
1216
+ recomputed: null,
1217
+ matches: false,
1218
+ covers: [],
1219
+ reason: issuer_signature.reason === jws_js_1.KEY_UNTRUSTED
1220
+ ? 'Binding not checked — issuer key untrusted'
1221
+ : 'Binding not checked — issuer signature not verified',
1222
+ };
1223
+ }
1224
+ }
1225
+ else {
1226
+ binding = verifyBinding(receipt);
1227
+ }
1228
+ if (!binding.matches && binding.expected) {
1229
+ errors.push('Payment binding mismatch');
1230
+ }
1231
+ const signedPayerClaims = verifiedClaims ? payerClaimsFromPayload(verifiedClaims) : null;
1232
+ let payer;
1233
+ if (options.checkPayer) {
1234
+ if (!signedPayerClaims) {
1235
+ payer = {
1236
+ checked: false,
1237
+ valid: false,
1238
+ reason: 'Payer facts come from verified signed claims — issuer signature is not trusted',
1239
+ };
1240
+ }
1241
+ else {
1242
+ const payerResult = await (0, payer_js_1.verifyPayerBinding)(signedPayerClaims, {
1243
+ rpcUrl: options.rpcUrl,
1244
+ solanaRpcUrl: options.solanaRpcUrl,
1245
+ fetchSolanaTransaction: options.fetchSolanaTransaction,
1246
+ fetchBaseReceipt: options.fetchBaseReceipt,
1247
+ });
1248
+ payer = {
1249
+ checked: payerResult.checked,
1250
+ valid: payerResult.valid,
1251
+ rail: payerResult.rail,
1252
+ reason: payerResult.reason,
1253
+ payer_wallet: payerResult.payerWallet ?? signedPayerClaims.caller_binding?.payer_wallet ?? null,
1254
+ payee: signedPayerClaims.payment?.payee ?? null,
1255
+ asset: signedPayerClaims.payment?.asset ?? null,
1256
+ amount: payerResult.expectedAmount ?? signedPayerClaims.payment?.gross_amount ?? null,
1257
+ };
1258
+ if (payerResult.checked && !payerResult.valid) {
1259
+ errors.push(`Payer binding mismatch: ${payerResult.reason}`);
1260
+ }
1261
+ }
1262
+ }
1263
+ else if (signedPayerClaims?.caller_binding?.payer_wallet && signedPayerClaims.payment?.ref) {
1264
+ payer = {
1265
+ checked: false,
1266
+ valid: false,
1267
+ payer_wallet: signedPayerClaims.caller_binding.payer_wallet,
1268
+ payee: signedPayerClaims.payment.payee ?? null,
1269
+ asset: signedPayerClaims.payment.asset ?? null,
1270
+ amount: signedPayerClaims.payment.gross_amount ?? null,
1271
+ reason: 'On-chain payer check not requested — pass checkPayer: true',
1272
+ };
1273
+ }
1274
+ else if (!receipt.issuer_signature?.jws && receipt.caller_binding?.payer_wallet && receipt.payment?.ref) {
1275
+ payer = {
1276
+ checked: false,
1277
+ valid: false,
1278
+ reason: 'On-chain payer check not requested — pass checkPayer: true',
1279
+ };
1280
+ }
1281
+ else if (receipt.issuer_signature?.jws && !issuer_signature.valid) {
1282
+ payer = {
1283
+ checked: false,
1284
+ valid: false,
1285
+ reason: 'Payer facts come from verified signed claims — issuer signature is not trusted',
1286
+ };
1287
+ }
1288
+ else {
1289
+ payer = {
1290
+ checked: false,
1291
+ valid: false,
1292
+ reason: 'No payer_wallet or payment.ref to verify',
1293
+ };
1294
+ }
1295
+ let nullifier;
1296
+ if (options.checkNullifier && receipt.proof?.nullifier) {
1297
+ nullifier = await verifyNullifier(receipt, {
1298
+ rpcUrl: options.rpcUrl,
1299
+ verifierAddress: options.verifierAddress,
1300
+ });
1301
+ if (nullifier.verified && nullifier.anchored === false) {
1302
+ errors.push('Nullifier not anchored on-chain');
1303
+ }
1304
+ }
1305
+ else {
1306
+ nullifier = {
1307
+ verified: false,
1308
+ nullifier: receipt.proof?.nullifier ?? null,
1309
+ anchored: null,
1310
+ reason: options.checkNullifier
1311
+ ? 'No nullifier present'
1312
+ : 'On-chain check not requested',
1313
+ };
1314
+ }
1315
+ const facts = factsFromClaims(verifiedClaims);
1316
+ const warnings = [];
1317
+ const preimages = await (0, preimage_js_1.verifyPublishedPreimages)(receipt, {
1318
+ requirePreimages: options.requirePreimages === true,
1319
+ fetchImpl: options.fetchImpl,
1320
+ trustedHosts,
1321
+ });
1322
+ if (!preimages.ok)
1323
+ errors.push(...preimages.errors);
1324
+ const signedPayloadHash = verifiedClaims && 'payload_hash' in verifiedClaims
1325
+ ? verifiedClaims.payload_hash
1326
+ : null;
1327
+ const storedPreimage = typeof receipt.issuer_signature?.canonical_preimage === 'string'
1328
+ ? receipt.issuer_signature.canonical_preimage
1329
+ : null;
1330
+ let canonicalPreimageFailed = false;
1331
+ if (storedPreimage != null) {
1332
+ const storedCheck = (0, canonical_preimage_js_1.verifyCanonicalPreimageBytes)(storedPreimage, signedPayloadHash);
1333
+ if (!storedCheck.ok) {
1334
+ canonicalPreimageFailed = true;
1335
+ if (storedCheck.reason)
1336
+ errors.push(`canonical preimage: ${storedCheck.reason}`);
1337
+ }
1338
+ }
1339
+ if (typeof options.canonicalPreimage === 'string') {
1340
+ const fileCheck = (0, canonical_preimage_js_1.verifyCanonicalPreimageBytes)(options.canonicalPreimage, signedPayloadHash);
1341
+ if (!fileCheck.ok) {
1342
+ canonicalPreimageFailed = true;
1343
+ if (fileCheck.reason)
1344
+ errors.push(`canonical preimage: ${fileCheck.reason}`);
1345
+ }
1346
+ }
1347
+ if (issuer_history.warning)
1348
+ warnings.push(issuer_history.warning);
1349
+ if (issuer_history.checked && !issuer_history.ok && issuer_history.reason) {
1350
+ errors.push(`issuer history: ${issuer_history.reason}`);
1351
+ }
1352
+ const hasIssuerSig = !!receipt.issuer_signature;
1353
+ const jwksWasSupplied = !!(options.jwks || options.jwksUri || (options.fetchJwks && jwks));
1354
+ const claimRefused = issuer_signature.valid && claim_id === 'refused';
1355
+ const signatureFailed = hasIssuerSig && !issuer_signature.valid && (!!issuer_signature.checked
1356
+ || jwksWasSupplied
1357
+ || issuer_signature.reason === jws_js_1.KEY_UNTRUSTED
1358
+ || issuer_signature.reason === 'no_matching_key'
1359
+ || issuer_signature.reason === 'empty_jwks');
1360
+ const mismatchFailed = claim_mismatches.length > 0;
1361
+ const bindingFailed = !!(binding.expected && !binding.matches);
1362
+ const payerFailed = !!(options.checkPayer && payer.checked && !payer.valid);
1363
+ const nullifierFailed = !!(options.checkNullifier
1364
+ && receipt.proof?.nullifier
1365
+ && nullifier.anchored === false);
1366
+ const signatureUnchecked = hasIssuerSig && !issuer_signature.checked;
1367
+ let overall;
1368
+ const preimageFailed = !preimages.ok;
1369
+ const historyFailed = issuer_history.checked && !issuer_history.ok;
1370
+ if (signatureFailed || mismatchFailed || bindingFailed || payerFailed || nullifierFailed || claimRefused || headMissing || headMismatch || sizeMismatch || headTrustFailed || inclusionFailed || preimageFailed || historyFailed || canonicalPreimageFailed) {
1371
+ overall = 'failed';
1372
+ }
1373
+ else if (signatureUnchecked) {
1374
+ overall = 'partial';
1375
+ }
1376
+ else if (!binding.expected && !hasIssuerSig && !options.checkPayer) {
1377
+ overall = 'partial';
1378
+ }
1379
+ else if ((binding.matches || !binding.expected)
1380
+ && (!options.checkPayer || payer.valid)
1381
+ && (!options.checkNullifier || !receipt.proof?.nullifier || nullifier.anchored === true)
1382
+ && (issuer_signature.valid || !hasIssuerSig)) {
1383
+ overall = 'verified';
1384
+ }
1385
+ else {
1386
+ overall = 'partial';
1387
+ }
1388
+ // A refusal is a different document. Recognition uses the signed JWS
1389
+ // schema, not only the unsigned outer schema. A valid issuer signature
1390
+ // here must not be reported as a verified payment.
1391
+ const verifiedSchema = typeof verifiedClaims?.schema === 'string' ? verifiedClaims.schema : null;
1392
+ if (verifiedSchema === refusal_js_1.REFUSAL_SCHEMA || (0, refusal_js_1.isRefusalDocument)(receipt)) {
1393
+ errors.push('refusal document is not a payment receipt');
1394
+ overall = 'failed';
1395
+ }
1396
+ let carry_forward;
1397
+ if (options.carry) {
1398
+ const bound = (0, row_hash_js_1.boundRowHash)(receipt, { row_hash: options.carry.row_hash });
1399
+ const leaf = !bound.ok || bound.row == null || bound.row === '' || receipt.task_id == null
1400
+ ? null
1401
+ : (0, anchor_witness_js_1.leafHash)(Buffer.from(`${receipt.task_id}|${bound.row}`));
1402
+ const verdict = !bound.ok
1403
+ ? { applicable: true, ok: false, status: null, reason: bound.reason }
1404
+ : (bound.row == null || bound.row === '')
1405
+ ? { applicable: true, ok: false, status: null, reason: 'row_hash_missing' }
1406
+ : leaf
1407
+ ? (0, carry_forward_js_1.verifyCarryForward)({
1408
+ leaf,
1409
+ oldHead: options.carry.oldHead,
1410
+ oldInclusion: options.carry.oldInclusion,
1411
+ currentHead: options.carry.currentHead,
1412
+ currentInclusions: options.carry.currentInclusions,
1413
+ trustedKids,
1414
+ jwks,
1415
+ })
1416
+ : { applicable: true, ok: false, status: null, reason: 'not_in_tree' };
1417
+ if (verdict.applicable && !verdict.ok) {
1418
+ errors.push(verdict.reason);
1419
+ overall = 'failed';
1420
+ }
1421
+ else if (verdict.applicable && verdict.ok && overall === 'verified') {
1422
+ overall = 'verified_carried_forward';
1423
+ carry_forward = {
1424
+ status: verdict.status,
1425
+ issued_at: verdict.issued_at,
1426
+ issued_epoch: verdict.issued_epoch,
1427
+ logged_at: verdict.logged_at,
1428
+ logged_epoch: verdict.logged_epoch,
1429
+ leaf_index: verdict.leaf_index,
1430
+ };
1431
+ }
1432
+ }
1433
+ const signedPayment = asRecord(verifiedClaims?.payment);
1434
+ const signedSettlement = asRecord(verifiedClaims?.settlement);
1435
+ const receipt_lane = (0, receipt_lane_js_1.receiptLaneFromVerification)({
1436
+ receipt,
1437
+ claims: {
1438
+ schema: verifiedSchema,
1439
+ payment: signedPayment ? {
1440
+ ref: typeof signedPayment.ref === 'string' ? signedPayment.ref : null,
1441
+ rail: typeof signedPayment.rail === 'string' ? signedPayment.rail : null,
1442
+ collected: typeof signedPayment.collected === 'boolean' ? signedPayment.collected : null,
1443
+ } : null,
1444
+ settlement: signedSettlement ? {
1445
+ kind: typeof signedSettlement.kind === 'string' ? signedSettlement.kind : null,
1446
+ } : null,
1447
+ },
1448
+ issuerValid: issuer_signature.valid === true,
1449
+ payer: { checked: payer.checked, valid: payer.valid },
1450
+ head: options.head ?? null,
1451
+ });
1452
+ return {
1453
+ receipt_id: receipt.task_id,
1454
+ binding,
1455
+ issuer_signature,
1456
+ payer,
1457
+ nullifier,
1458
+ output_hash: facts.output_hash,
1459
+ hub: facts.hub,
1460
+ model: facts.model,
1461
+ amount_usdc: facts.amount_usdc,
1462
+ tx: facts.tx,
1463
+ claim_mismatches,
1464
+ unsigned_fields,
1465
+ verified_scope: 'signed_claims',
1466
+ claim_id,
1467
+ head_binding: signedBinding
1468
+ ? { tree_head_hash: signedBinding.tree_head_hash, tolerance: signedBinding.tolerance }
1469
+ : null,
1470
+ receipt_lane,
1471
+ preimages,
1472
+ issuer_history,
1473
+ warnings,
1474
+ ...(carry_forward ? { carry_forward } : {}),
1475
+ ...versionStamp,
1476
+ overall,
1477
+ errors,
1478
+ };
1479
+ }
1480
+ var jws_js_2 = require("./jws.js");
1481
+ Object.defineProperty(exports, "resolvePinnedIssuerJwk", { enumerable: true, get: function () { return jws_js_2.resolvePinnedIssuerJwk; } });
1482
+ Object.defineProperty(exports, "verifyIssuerJws", { enumerable: true, get: function () { return jws_js_2.verifyIssuerJws; } });
1483
+ Object.defineProperty(exports, "DEFAULT_TRUSTED_ISSUER_KIDS", { enumerable: true, get: function () { return jws_js_2.DEFAULT_TRUSTED_ISSUER_KIDS; } });
1484
+ Object.defineProperty(exports, "DEFAULT_TRUSTED_JWKS_HOSTS", { enumerable: true, get: function () { return jws_js_2.DEFAULT_TRUSTED_JWKS_HOSTS; } });
1485
+ Object.defineProperty(exports, "KEY_UNTRUSTED", { enumerable: true, get: function () { return jws_js_2.KEY_UNTRUSTED; } });
1486
+ Object.defineProperty(exports, "jwkThumbprint", { enumerable: true, get: function () { return jws_js_2.jwkThumbprint; } });
1487
+ Object.defineProperty(exports, "isPinnedTrustedJwk", { enumerable: true, get: function () { return jws_js_2.isPinnedTrustedJwk; } });
1488
+ Object.defineProperty(exports, "jwksHostAllowed", { enumerable: true, get: function () { return jws_js_2.jwksHostAllowed; } });
1489
+ var receipt_lane_js_2 = require("./receipt-lane.js");
1490
+ Object.defineProperty(exports, "buildReceiptLane", { enumerable: true, get: function () { return receipt_lane_js_2.buildReceiptLane; } });
1491
+ Object.defineProperty(exports, "receiptLaneFromVerification", { enumerable: true, get: function () { return receipt_lane_js_2.receiptLaneFromVerification; } });
1492
+ Object.defineProperty(exports, "receiptLaneDecision", { enumerable: true, get: function () { return receipt_lane_js_2.receiptLaneDecision; } });
1493
+ Object.defineProperty(exports, "deriveSettledBy", { enumerable: true, get: function () { return receipt_lane_js_2.deriveSettledBy; } });
1494
+ Object.defineProperty(exports, "deriveSettled", { enumerable: true, get: function () { return receipt_lane_js_2.deriveSettled; } });
1495
+ Object.defineProperty(exports, "anchorChangedSinceBinding", { enumerable: true, get: function () { return receipt_lane_js_2.anchorChangedSinceBinding; } });
1496
+ Object.defineProperty(exports, "RECEIPT_LANE_SCHEMA", { enumerable: true, get: function () { return receipt_lane_js_2.RECEIPT_LANE_SCHEMA; } });
1497
+ Object.defineProperty(exports, "RECEIPT_LANE_RULE", { enumerable: true, get: function () { return receipt_lane_js_2.RECEIPT_LANE_RULE; } });
1498
+ Object.defineProperty(exports, "RECEIPT_LANE_ORDERING", { enumerable: true, get: function () { return receipt_lane_js_2.RECEIPT_LANE_ORDERING; } });
1499
+ Object.defineProperty(exports, "RECEIPT_LANE_BOUNDARY", { enumerable: true, get: function () { return receipt_lane_js_2.RECEIPT_LANE_BOUNDARY; } });
1500
+ var head_binding_js_2 = require("./head-binding.js");
1501
+ Object.defineProperty(exports, "headBindingVerdict", { enumerable: true, get: function () { return head_binding_js_2.headBindingVerdict; } });
1502
+ Object.defineProperty(exports, "signedHeadBinding", { enumerable: true, get: function () { return head_binding_js_2.signedHeadBinding; } });
1503
+ Object.defineProperty(exports, "outerHeadDisagrees", { enumerable: true, get: function () { return head_binding_js_2.outerHeadDisagrees; } });
1504
+ Object.defineProperty(exports, "HEAD_BINDING_PAYLOAD_VERSION", { enumerable: true, get: function () { return head_binding_js_2.HEAD_BINDING_PAYLOAD_VERSION; } });
1505
+ var refusal_js_2 = require("./refusal.js");
1506
+ Object.defineProperty(exports, "isRefusalDocument", { enumerable: true, get: function () { return refusal_js_2.isRefusalDocument; } });
1507
+ Object.defineProperty(exports, "verifyRefusal", { enumerable: true, get: function () { return refusal_js_2.verifyRefusal; } });
1508
+ Object.defineProperty(exports, "REFUSAL_SCHEMA", { enumerable: true, get: function () { return refusal_js_2.REFUSAL_SCHEMA; } });
1509
+ Object.defineProperty(exports, "REFUSAL_SCHEMA_V2", { enumerable: true, get: function () { return refusal_js_2.REFUSAL_SCHEMA_V2; } });
1510
+ Object.defineProperty(exports, "REFUSAL_PAYLOAD_VERSION", { enumerable: true, get: function () { return refusal_js_2.REFUSAL_PAYLOAD_VERSION; } });
1511
+ Object.defineProperty(exports, "REFUSAL_PROVES", { enumerable: true, get: function () { return refusal_js_2.REFUSAL_PROVES; } });
1512
+ Object.defineProperty(exports, "REFUSAL_DOES_NOT_PROVE", { enumerable: true, get: function () { return refusal_js_2.REFUSAL_DOES_NOT_PROVE; } });
1513
+ var request_binding_js_1 = require("./request-binding.js");
1514
+ Object.defineProperty(exports, "verifyRequestDigest", { enumerable: true, get: function () { return request_binding_js_1.verifyRequestDigest; } });
1515
+ Object.defineProperty(exports, "requestDigestOfPreimage", { enumerable: true, get: function () { return request_binding_js_1.requestDigestOfPreimage; } });
1516
+ var epoch_js_1 = require("./epoch.js");
1517
+ Object.defineProperty(exports, "acceptTreeHeadSchema", { enumerable: true, get: function () { return epoch_js_1.acceptTreeHeadSchema; } });
1518
+ Object.defineProperty(exports, "verifyEpochLink", { enumerable: true, get: function () { return epoch_js_1.verifyEpochLink; } });
1519
+ Object.defineProperty(exports, "verifyEpochRecord", { enumerable: true, get: function () { return epoch_js_1.verifyEpochRecord; } });
1520
+ Object.defineProperty(exports, "verifyEpochInclusion", { enumerable: true, get: function () { return epoch_js_1.verifyEpochInclusion; } });
1521
+ Object.defineProperty(exports, "verifyUnloggedSection", { enumerable: true, get: function () { return epoch_js_1.verifyUnloggedSection; } });
1522
+ Object.defineProperty(exports, "verifyUnloggedCommitment", { enumerable: true, get: function () { return epoch_js_1.verifyUnloggedCommitment; } });
1523
+ Object.defineProperty(exports, "unloggedIdCommitment", { enumerable: true, get: function () { return epoch_js_1.unloggedIdCommitment; } });
1524
+ Object.defineProperty(exports, "unloggedReasonForTask", { enumerable: true, get: function () { return epoch_js_1.unloggedReasonForTask; } });
1525
+ Object.defineProperty(exports, "canonicalUnloggedRows", { enumerable: true, get: function () { return epoch_js_1.canonicalUnloggedRows; } });
1526
+ Object.defineProperty(exports, "TREE_HEAD_SCHEMA_V1", { enumerable: true, get: function () { return epoch_js_1.TREE_HEAD_SCHEMA_V1; } });
1527
+ Object.defineProperty(exports, "TREE_HEAD_SCHEMA_V2", { enumerable: true, get: function () { return epoch_js_1.TREE_HEAD_SCHEMA_V2; } });
1528
+ Object.defineProperty(exports, "EPOCH1_FINAL_ROOT", { enumerable: true, get: function () { return epoch_js_1.EPOCH1_FINAL_ROOT; } });
1529
+ Object.defineProperty(exports, "EPOCH1_FINAL_SIZE", { enumerable: true, get: function () { return epoch_js_1.EPOCH1_FINAL_SIZE; } });
1530
+ Object.defineProperty(exports, "EPOCH1_GENESIS_DIGEST", { enumerable: true, get: function () { return epoch_js_1.EPOCH1_GENESIS_DIGEST; } });
1531
+ Object.defineProperty(exports, "EPOCH1_SIZE1_ROOT", { enumerable: true, get: function () { return epoch_js_1.EPOCH1_SIZE1_ROOT; } });
1532
+ Object.defineProperty(exports, "EPOCH1_SIZE2_ROOT", { enumerable: true, get: function () { return epoch_js_1.EPOCH1_SIZE2_ROOT; } });
1533
+ Object.defineProperty(exports, "epoch1PrefixRoot", { enumerable: true, get: function () { return epoch_js_1.epoch1PrefixRoot; } });
1534
+ Object.defineProperty(exports, "matchEpoch1Prefix", { enumerable: true, get: function () { return epoch_js_1.matchEpoch1Prefix; } });
1535
+ Object.defineProperty(exports, "EPOCH2_OPENING_ROOT", { enumerable: true, get: function () { return epoch_js_1.EPOCH2_OPENING_ROOT; } });
1536
+ var carry_forward_js_2 = require("./carry-forward.js");
1537
+ Object.defineProperty(exports, "verifyCarryForward", { enumerable: true, get: function () { return carry_forward_js_2.verifyCarryForward; } });
1538
+ Object.defineProperty(exports, "PINNED_ANCHOR_EPOCHS", { enumerable: true, get: function () { return carry_forward_js_2.PINNED_ANCHOR_EPOCHS; } });
1539
+ Object.defineProperty(exports, "CARRY_FORWARD_STATUS", { enumerable: true, get: function () { return carry_forward_js_2.CARRY_FORWARD_STATUS; } });
1540
+ var anchor_witness_js_2 = require("./anchor-witness.js");
1541
+ Object.defineProperty(exports, "verifyAnchoredRoot", { enumerable: true, get: function () { return anchor_witness_js_2.verifyAnchoredRoot; } });
1542
+ Object.defineProperty(exports, "verifyMerkleInclusion", { enumerable: true, get: function () { return anchor_witness_js_2.verifyMerkleInclusion; } });
1543
+ Object.defineProperty(exports, "extractMemos", { enumerable: true, get: function () { return anchor_witness_js_2.extractMemos; } });
1544
+ Object.defineProperty(exports, "parseAnchorMemo", { enumerable: true, get: function () { return anchor_witness_js_2.parseAnchorMemo; } });
1545
+ Object.defineProperty(exports, "leafHash", { enumerable: true, get: function () { return anchor_witness_js_2.leafHash; } });
1546
+ Object.defineProperty(exports, "ANCHOR_PROVES", { enumerable: true, get: function () { return anchor_witness_js_2.ANCHOR_PROVES; } });
1547
+ Object.defineProperty(exports, "ANCHOR_DOES_NOT_PROVE", { enumerable: true, get: function () { return anchor_witness_js_2.ANCHOR_DOES_NOT_PROVE; } });
1548
+ Object.defineProperty(exports, "SOLANA_GENESIS", { enumerable: true, get: function () { return anchor_witness_js_2.SOLANA_GENESIS; } });
1549
+ Object.defineProperty(exports, "BASE_MAINNET_CHAIN_ID", { enumerable: true, get: function () { return anchor_witness_js_2.BASE_MAINNET_CHAIN_ID; } });
1550
+ var issuer_pin_js_1 = require("./issuer-pin.js");
1551
+ Object.defineProperty(exports, "assessIssuerPin", { enumerable: true, get: function () { return issuer_pin_js_1.assessIssuerPin; } });
1552
+ Object.defineProperty(exports, "issuerPinContentUrl", { enumerable: true, get: function () { return issuer_pin_js_1.issuerPinContentUrl; } });
1553
+ Object.defineProperty(exports, "issuerPinFileHash", { enumerable: true, get: function () { return issuer_pin_js_1.issuerPinFileHash; } });
1554
+ Object.defineProperty(exports, "loadIssuerPinBytes", { enumerable: true, get: function () { return issuer_pin_js_1.loadIssuerPinBytes; } });
1555
+ Object.defineProperty(exports, "readIssuerPinClaim", { enumerable: true, get: function () { return issuer_pin_js_1.readIssuerPinClaim; } });
1556
+ Object.defineProperty(exports, "registrationPreimage", { enumerable: true, get: function () { return issuer_pin_js_1.registrationPreimage; } });
1557
+ Object.defineProperty(exports, "rotationStatement", { enumerable: true, get: function () { return issuer_pin_js_1.rotationStatement; } });
1558
+ Object.defineProperty(exports, "serializeIssuerPin", { enumerable: true, get: function () { return issuer_pin_js_1.serializeIssuerPin; } });
1559
+ Object.defineProperty(exports, "verifyCitizenRotation", { enumerable: true, get: function () { return issuer_pin_js_1.verifyCitizenRotation; } });
1560
+ Object.defineProperty(exports, "verifyRegistrationSignature", { enumerable: true, get: function () { return issuer_pin_js_1.verifyRegistrationSignature; } });
1561
+ Object.defineProperty(exports, "canonicalPublicKey", { enumerable: true, get: function () { return issuer_pin_js_1.canonicalPublicKey; } });
1562
+ Object.defineProperty(exports, "ISSUER_REGISTRATION_CONTEXT", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_REGISTRATION_CONTEXT; } });
1563
+ Object.defineProperty(exports, "ISSUER_ROTATION_CONTEXT", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_ROTATION_CONTEXT; } });
1564
+ Object.defineProperty(exports, "ISSUER_PIN_VERSION", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_PIN_VERSION; } });
1565
+ Object.defineProperty(exports, "ISSUER_PIN_SCHEMA", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_PIN_SCHEMA; } });
1566
+ Object.defineProperty(exports, "ISSUER_PIN_PATH", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_PIN_PATH; } });
1567
+ Object.defineProperty(exports, "ISSUER_PIN_CHAIN_ID", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_PIN_CHAIN_ID; } });
1568
+ Object.defineProperty(exports, "PUBLISHED_ISSUER_PIN_KID", { enumerable: true, get: function () { return issuer_pin_js_1.PUBLISHED_ISSUER_PIN_KID; } });
1569
+ Object.defineProperty(exports, "CITIZEN_FREEZE_SCHEMA", { enumerable: true, get: function () { return issuer_pin_js_1.CITIZEN_FREEZE_SCHEMA; } });
1570
+ Object.defineProperty(exports, "CITIZEN_FREEZE_PURPOSE", { enumerable: true, get: function () { return issuer_pin_js_1.CITIZEN_FREEZE_PURPOSE; } });
1571
+ Object.defineProperty(exports, "ISSUER_PIN_MISMATCH", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_PIN_MISMATCH; } });
1572
+ Object.defineProperty(exports, "ISSUER_PIN_HASH_MISMATCH", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_PIN_HASH_MISMATCH; } });
1573
+ Object.defineProperty(exports, "ISSUER_SELF_SIG_INVALID", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_SELF_SIG_INVALID; } });
1574
+ Object.defineProperty(exports, "ISSUER_PIN_DOWNGRADE", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_PIN_DOWNGRADE; } });
1575
+ Object.defineProperty(exports, "ISSUER_PIN_MUTABLE_REF", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_PIN_MUTABLE_REF; } });
1576
+ Object.defineProperty(exports, "ISSUER_ROTATION_UNCONTROLLED", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_ROTATION_UNCONTROLLED; } });
1577
+ Object.defineProperty(exports, "ISSUER_PIN_CHAIN_REFUSED", { enumerable: true, get: function () { return issuer_pin_js_1.ISSUER_PIN_CHAIN_REFUSED; } });
1578
+ var anchor_trust_js_2 = require("./anchor-trust.js");
1579
+ Object.defineProperty(exports, "PINNED_BASE_ANCHOR_WALLET", { enumerable: true, get: function () { return anchor_trust_js_2.PINNED_BASE_ANCHOR_WALLET; } });
1580
+ Object.defineProperty(exports, "PINNED_SOLANA_ANCHOR_FEE_PAYER", { enumerable: true, get: function () { return anchor_trust_js_2.PINNED_SOLANA_ANCHOR_FEE_PAYER; } });
1581
+ Object.defineProperty(exports, "ANCHOR_WALLET_SOURCES_NOT_CONSULTED", { enumerable: true, get: function () { return anchor_trust_js_2.ANCHOR_WALLET_SOURCES_NOT_CONSULTED; } });
1582
+ Object.defineProperty(exports, "LEGACY_HEAD_UNPINNED_SIGNER", { enumerable: true, get: function () { return anchor_trust_js_2.LEGACY_HEAD_UNPINNED_SIGNER; } });
1583
+ Object.defineProperty(exports, "HEAD_TRUST_MESSAGES", { enumerable: true, get: function () { return anchor_trust_js_2.HEAD_TRUST_MESSAGES; } });
1584
+ Object.defineProperty(exports, "headOmitsPinnedSigner", { enumerable: true, get: function () { return anchor_trust_js_2.headOmitsPinnedSigner; } });
1585
+ Object.defineProperty(exports, "headTrustedFromInclusion", { enumerable: true, get: function () { return anchor_trust_js_2.headTrustedFromInclusion; } });
1586
+ Object.defineProperty(exports, "verifyTreeHeadTrust", { enumerable: true, get: function () { return anchor_trust_js_2.verifyTreeHeadTrust; } });
1587
+ Object.defineProperty(exports, "verifyAnchorWalletDocument", { enumerable: true, get: function () { return anchor_trust_js_2.verifyAnchorWalletDocument; } });
1588
+ Object.defineProperty(exports, "compileAnchorWallets", { enumerable: true, get: function () { return anchor_trust_js_2.compileAnchorWallets; } });
1589
+ var canonical_preimage_js_2 = require("./canonical-preimage.js");
1590
+ Object.defineProperty(exports, "verifyCanonicalPreimageBytes", { enumerable: true, get: function () { return canonical_preimage_js_2.verifyCanonicalPreimageBytes; } });
1591
+ Object.defineProperty(exports, "CANONICAL_PAYLOAD_VERSION", { enumerable: true, get: function () { return canonical_preimage_js_2.CANONICAL_PAYLOAD_VERSION; } });
1592
+ var receipt_version_js_2 = require("./receipt-version.js");
1593
+ Object.defineProperty(exports, "SUPPORTED_RECEIPT_VERSIONS", { enumerable: true, get: function () { return receipt_version_js_2.SUPPORTED_RECEIPT_VERSIONS; } });
1594
+ Object.defineProperty(exports, "LEGACY_PAYLOAD_VERSIONS", { enumerable: true, get: function () { return receipt_version_js_2.LEGACY_PAYLOAD_VERSIONS; } });
1595
+ Object.defineProperty(exports, "REFUSAL_EXACT_VERSIONS", { enumerable: true, get: function () { return receipt_version_js_2.REFUSAL_EXACT_VERSIONS; } });
1596
+ Object.defineProperty(exports, "VERIFIER_MIN", { enumerable: true, get: function () { return receipt_version_js_2.VERIFIER_MIN; } });
1597
+ Object.defineProperty(exports, "UNSUPPORTED_VERSION", { enumerable: true, get: function () { return receipt_version_js_2.UNSUPPORTED_VERSION; } });
1598
+ Object.defineProperty(exports, "VERSION_MISMATCH", { enumerable: true, get: function () { return receipt_version_js_2.VERSION_MISMATCH; } });
1599
+ Object.defineProperty(exports, "classifyReceiptDocument", { enumerable: true, get: function () { return receipt_version_js_2.classifyReceiptDocument; } });
1600
+ Object.defineProperty(exports, "classifySignedClaims", { enumerable: true, get: function () { return receipt_version_js_2.classifySignedClaims; } });
1601
+ Object.defineProperty(exports, "legacyIdentityErrors", { enumerable: true, get: function () { return receipt_version_js_2.legacyIdentityErrors; } });
1602
+ Object.defineProperty(exports, "classifyShellDocument", { enumerable: true, get: function () { return receipt_version_js_2.classifyShellDocument; } });
1603
+ Object.defineProperty(exports, "signedClaimsOnAllowlist", { enumerable: true, get: function () { return receipt_version_js_2.signedClaimsOnAllowlist; } });
1604
+ Object.defineProperty(exports, "formatSupportedReceiptVersions", { enumerable: true, get: function () { return receipt_version_js_2.formatSupportedReceiptVersions; } });
1605
+ Object.defineProperty(exports, "readSignedClaims", { enumerable: true, get: function () { return receipt_version_js_2.readSignedClaims; } });
1606
+ Object.defineProperty(exports, "refusalPayloadVersion", { enumerable: true, get: function () { return receipt_version_js_2.refusalPayloadVersion; } });
1607
+ Object.defineProperty(exports, "isJsonInteger", { enumerable: true, get: function () { return receipt_version_js_2.isJsonInteger; } });
1608
+ var issuer_history_js_2 = require("./issuer-history.js");
1609
+ Object.defineProperty(exports, "readIssuerHistoryPin", { enumerable: true, get: function () { return issuer_history_js_2.readIssuerHistoryPin; } });
1610
+ Object.defineProperty(exports, "issuerHistoryDocumentHash", { enumerable: true, get: function () { return issuer_history_js_2.issuerHistoryDocumentHash; } });
1611
+ var shell_js_1 = require("./shell.js");
1612
+ Object.defineProperty(exports, "isReceiptShell", { enumerable: true, get: function () { return shell_js_1.isReceiptShell; } });
1613
+ Object.defineProperty(exports, "shellFromHolder", { enumerable: true, get: function () { return shell_js_1.shellFromHolder; } });
1614
+ Object.defineProperty(exports, "compareShellToJws", { enumerable: true, get: function () { return shell_js_1.compareShellToJws; } });
1615
+ Object.defineProperty(exports, "holderDocumentFromOwnerView", { enumerable: true, get: function () { return shell_js_1.holderDocumentFromOwnerView; } });
1616
+ Object.defineProperty(exports, "shellHolderVerdict", { enumerable: true, get: function () { return shell_js_1.shellHolderVerdict; } });
1617
+ Object.defineProperty(exports, "openV11Commitment", { enumerable: true, get: function () { return shell_js_1.openV11Commitment; } });
1618
+ Object.defineProperty(exports, "decodeShellJwsPayload", { enumerable: true, get: function () { return shell_js_1.decodeJwsPayload; } });
1619
+ Object.defineProperty(exports, "SHELL_SCHEMA", { enumerable: true, get: function () { return shell_js_1.SHELL_SCHEMA; } });
1620
+ Object.defineProperty(exports, "INCLUDED_SHELL_LINE", { enumerable: true, get: function () { return shell_js_1.INCLUDED_SHELL_LINE; } });
1621
+ exports.default = {
1622
+ verifyBinding,
1623
+ verifyIssuerSignature,
1624
+ verifyIssuerSignatureWithJwks,
1625
+ verifyIssuerJws: jws_js_1.verifyIssuerJws,
1626
+ resolvePinnedIssuerJwk: jws_js_1.resolvePinnedIssuerJwk,
1627
+ verifyNullifier,
1628
+ verifyPayerBinding: payer_js_1.verifyPayerBinding,
1629
+ verifySolanaPayer: solana_payer_js_1.verifySolanaPayer,
1630
+ verifyBasePayer: base_payer_js_1.verifyBasePayer,
1631
+ verifyReceipt,
1632
+ receiptPayerClaims,
1633
+ receiptPayerClaimsFromEnvelope: payer_js_1.receiptPayerClaimsFromEnvelope,
1634
+ decodeJwsPayload: payer_js_1.decodeJwsPayload,
1635
+ computePaymentCommitment: binding_js_1.computePaymentCommitment,
1636
+ computeInferenceBinding: binding_js_1.computeInferenceBinding,
1637
+ canonicalIssuerPayload,
1638
+ canonicalPayloadVersion,
1639
+ canonicalSignedPayload: exports.canonicalSignedPayload,
1640
+ reconcileSettledTransfer,
1641
+ sumUsdcTransfersToPayee,
1642
+ hashCanonicalPayload,
1643
+ ZK_VERIFIER_ADDRESS: exports.ZK_VERIFIER_ADDRESS,
1644
+ BASE_RPC_URL: base_payer_js_1.BASE_RPC_URL,
1645
+ BASE_SEPOLIA_RPC_URL: exports.BASE_SEPOLIA_RPC_URL,
1646
+ SOLANA_RPC_URL: solana_payer_js_1.SOLANA_RPC_URL,
1647
+ };
1648
+ //# sourceMappingURL=index.js.map