@billionsnetwork/x402-human-proof 0.1.3

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 (43) hide show
  1. package/dist/node/cjs/declare.cjs +42 -0
  2. package/dist/node/cjs/declare.cjs.map +1 -0
  3. package/dist/node/cjs/hooks.cjs +198 -0
  4. package/dist/node/cjs/hooks.cjs.map +1 -0
  5. package/dist/node/cjs/index.cjs +493 -0
  6. package/dist/node/cjs/index.cjs.map +1 -0
  7. package/dist/node/cjs/server.cjs +469 -0
  8. package/dist/node/cjs/server.cjs.map +1 -0
  9. package/dist/node/cjs/types.cjs +19 -0
  10. package/dist/node/cjs/types.cjs.map +1 -0
  11. package/dist/node/cjs/utils.cjs +184 -0
  12. package/dist/node/cjs/utils.cjs.map +1 -0
  13. package/dist/node/cjs/verifier.cjs +102 -0
  14. package/dist/node/cjs/verifier.cjs.map +1 -0
  15. package/dist/node/esm/declare.js +15 -0
  16. package/dist/node/esm/declare.js.map +1 -0
  17. package/dist/node/esm/hooks.js +160 -0
  18. package/dist/node/esm/hooks.js.map +1 -0
  19. package/dist/node/esm/index.js +445 -0
  20. package/dist/node/esm/index.js.map +1 -0
  21. package/dist/node/esm/server.js +427 -0
  22. package/dist/node/esm/server.js.map +1 -0
  23. package/dist/node/esm/types.js +1 -0
  24. package/dist/node/esm/types.js.map +1 -0
  25. package/dist/node/esm/utils.js +145 -0
  26. package/dist/node/esm/utils.js.map +1 -0
  27. package/dist/node/esm/verifier.js +74 -0
  28. package/dist/node/esm/verifier.js.map +1 -0
  29. package/dist/types/declare.d.ts +17 -0
  30. package/dist/types/declare.d.ts.map +1 -0
  31. package/dist/types/hooks.d.ts +36 -0
  32. package/dist/types/hooks.d.ts.map +1 -0
  33. package/dist/types/index.d.ts +9 -0
  34. package/dist/types/index.d.ts.map +1 -0
  35. package/dist/types/server.d.ts +87 -0
  36. package/dist/types/server.d.ts.map +1 -0
  37. package/dist/types/types.d.ts +99 -0
  38. package/dist/types/types.d.ts.map +1 -0
  39. package/dist/types/utils.d.ts +40 -0
  40. package/dist/types/utils.d.ts.map +1 -0
  41. package/dist/types/verifier.d.ts +13 -0
  42. package/dist/types/verifier.d.ts.map +1 -0
  43. package/package.json +36 -0
@@ -0,0 +1,469 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/server.ts
31
+ var server_exports = {};
32
+ __export(server_exports, {
33
+ configureHumanProofServer: () => configureHumanProofServer,
34
+ createAfterVerifyFailureRollbackHook: () => createAfterVerifyFailureRollbackHook,
35
+ createHumanProofExtension: () => createHumanProofExtension,
36
+ createSettleFailureRollbackHook: () => createSettleFailureRollbackHook,
37
+ createVerifyFailureRollbackHook: () => createVerifyFailureRollbackHook,
38
+ createVerifyHumanProofHook: () => createVerifyHumanProofHook
39
+ });
40
+ module.exports = __toCommonJS(server_exports);
41
+
42
+ // src/utils.ts
43
+ var import_viem = require("viem");
44
+ var import_bs58 = __toESM(require("bs58"), 1);
45
+ var import_tweetnacl = __toESM(require("tweetnacl"), 1);
46
+ function formatResources(resources) {
47
+ if (!resources?.length) return "";
48
+ const lines = resources.map((resource) => `- ${resource}`).join("\n");
49
+ return `
50
+ Resources:
51
+ ${lines}`;
52
+ }
53
+ function formatSIWEMessage(payload) {
54
+ const statementBlock = payload.statement ? `
55
+ ${payload.statement}
56
+ ` : "\n";
57
+ const expirationLine = payload.expirationTime ? `
58
+ Expiration Time: ${payload.expirationTime}` : "";
59
+ return `${payload.domain} wants you to sign in with your Ethereum account:
60
+ ${payload.address}${statementBlock}
61
+ URI: ${payload.uri ?? ""}
62
+ Version: ${payload.version}
63
+ Chain ID: ${payload.chainId}
64
+ Nonce: ${payload.nonce}
65
+ Issued At: ${payload.issuedAt}${expirationLine}${formatResources(payload.resources)}`;
66
+ }
67
+ function formatSIWSMessage(payload) {
68
+ const statementBlock = payload.statement ? `
69
+ ${payload.statement}
70
+ ` : "\n";
71
+ const expirationLine = payload.expirationTime ? `
72
+ Expiration Time: ${payload.expirationTime}` : "";
73
+ return `${payload.domain} wants you to sign in with your Solana account:
74
+ ${payload.address}${statementBlock}
75
+ URI: ${payload.uri ?? ""}
76
+ Version: ${payload.version}
77
+ Chain ID: ${payload.chainId}
78
+ Nonce: ${payload.nonce}
79
+ Issued At: ${payload.issuedAt}${expirationLine}${formatResources(payload.resources)}`;
80
+ }
81
+ function decodeBase58(input) {
82
+ return import_bs58.default.decode(input);
83
+ }
84
+ function buildHumanProofSchema() {
85
+ return {
86
+ type: "object",
87
+ required: ["domain", "version", "nonce", "issuedAt", "chainId", "type", "address", "signature", "requiredAttestations"],
88
+ properties: {
89
+ domain: { type: "string" },
90
+ uri: { type: "string" },
91
+ version: { type: "string" },
92
+ nonce: { type: "string" },
93
+ issuedAt: { type: "string" },
94
+ expirationTime: { type: "string" },
95
+ statement: { type: "string" },
96
+ resources: { type: "array", items: { type: "string" } },
97
+ chainId: { type: "string" },
98
+ type: { enum: ["eip191", "ed25519"] },
99
+ address: { type: "string" },
100
+ signature: { type: "string" },
101
+ requiredAttestations: { type: "array", items: { type: "string" } }
102
+ },
103
+ additionalProperties: true
104
+ };
105
+ }
106
+ function parseHumanProofHeader(headerValue) {
107
+ const parsed = JSON.parse(headerValue);
108
+ if (!parsed || typeof parsed !== "object") {
109
+ throw new Error("Invalid header payload");
110
+ }
111
+ const payload = parsed;
112
+ if (!payload.address || !payload.signature || !payload.chainId || !payload.type) {
113
+ throw new Error("Missing required fields in header payload");
114
+ }
115
+ return payload;
116
+ }
117
+ async function validateHumanProofMessage(payload, resource) {
118
+ if (!payload.domain || !payload.version || !payload.nonce || !payload.issuedAt) {
119
+ return { valid: false, error: "invalid_message" };
120
+ }
121
+ if (!payload.uri || payload.uri !== resource) {
122
+ return { valid: false, error: "resource_mismatch" };
123
+ }
124
+ const issuedAtMillis = Date.parse(payload.issuedAt);
125
+ if (Number.isNaN(issuedAtMillis)) {
126
+ return { valid: false, error: "invalid_issued_at" };
127
+ }
128
+ if (payload.expirationTime) {
129
+ const expirationMillis = Date.parse(payload.expirationTime);
130
+ if (Number.isNaN(expirationMillis)) {
131
+ return { valid: false, error: "invalid_expiration_time" };
132
+ }
133
+ if (expirationMillis < Date.now()) {
134
+ return { valid: false, error: "message_expired" };
135
+ }
136
+ }
137
+ return { valid: true };
138
+ }
139
+ async function verifyHumanProofSignature(payload) {
140
+ if (payload.type === "eip191") {
141
+ if (!payload.signature.startsWith("0x")) {
142
+ return { valid: false, error: "invalid_signature" };
143
+ }
144
+ try {
145
+ const message = formatSIWEMessage(payload);
146
+ const signature = payload.signature;
147
+ const recovered = await (0, import_viem.recoverMessageAddress)({ message, signature });
148
+ if (recovered.toLowerCase() !== payload.address.toLowerCase()) {
149
+ return { valid: false, error: "invalid_signature" };
150
+ }
151
+ const publicKey = await (0, import_viem.recoverPublicKey)({ hash: (0, import_viem.hashMessage)(message), signature });
152
+ return { valid: true, address: payload.address, pubKey: publicKey };
153
+ } catch {
154
+ return { valid: false, error: "invalid_signature" };
155
+ }
156
+ }
157
+ if (payload.type === "ed25519") {
158
+ try {
159
+ const message = new TextEncoder().encode(formatSIWSMessage(payload));
160
+ const publicKey = decodeBase58(payload.address);
161
+ const signature = decodeBase58(payload.signature);
162
+ const valid = import_tweetnacl.default.sign.detached.verify(message, signature, publicKey);
163
+ if (!valid) return { valid: false, error: "invalid_signature" };
164
+ return { valid: true, address: payload.address, pubKey: import_bs58.default.encode(publicKey) };
165
+ } catch {
166
+ return { valid: false, error: "invalid_signature" };
167
+ }
168
+ }
169
+ return { valid: false, error: "invalid_signature_type" };
170
+ }
171
+
172
+ // src/server.ts
173
+ var import_crypto = require("crypto");
174
+
175
+ // src/declare.ts
176
+ var HUMAN_PROOF = "human-proof";
177
+ function getSignatureTypes(network) {
178
+ if (network.startsWith("solana:")) return ["ed25519"];
179
+ return ["eip191"];
180
+ }
181
+
182
+ // src/hooks.ts
183
+ var import_js_iden3_core = require("@iden3/js-iden3-core");
184
+ var import_js_sdk = require("@0xpolygonid/js-sdk");
185
+ async function verifyHumanProofRequest(verifier, context) {
186
+ const { resource, humanProofHeader, onEvent } = context;
187
+ if (!humanProofHeader) {
188
+ return { allowed: false, reason: "missing_header" };
189
+ }
190
+ let payload;
191
+ try {
192
+ payload = parseHumanProofHeader(humanProofHeader);
193
+ } catch {
194
+ return { allowed: false, reason: "invalid_header" };
195
+ }
196
+ const validation = await validateHumanProofMessage(payload, resource);
197
+ if (!validation.valid) {
198
+ return { allowed: false, reason: validation.error ?? "invalid_message" };
199
+ }
200
+ const sigResult = await verifyHumanProofSignature(payload);
201
+ if (!sigResult.valid || !sigResult.address) {
202
+ return { allowed: false, reason: sigResult.error ?? "invalid_signature" };
203
+ }
204
+ const didType = (0, import_js_iden3_core.buildDIDType)(import_js_iden3_core.DidMethod.Iden3, import_js_iden3_core.Blockchain.Billions, import_js_iden3_core.NetworkId.Main);
205
+ const didString = (0, import_js_sdk.buildDIDFromEthAddress)(didType, sigResult.address).string();
206
+ const resolution = await verifier.lookupHuman(didString, payload.chainId);
207
+ if (!resolution) {
208
+ await onEvent?.({
209
+ type: "human_not_registered",
210
+ resource,
211
+ did: didString
212
+ });
213
+ return { allowed: false, reason: "not_registered", did: didString };
214
+ }
215
+ await onEvent?.({
216
+ type: "human_verified",
217
+ resource,
218
+ humanId: resolution.humanId,
219
+ verifiedAt: resolution.verifiedAt,
220
+ attestationId: resolution.attestationId,
221
+ humanDid: resolution.humanDid,
222
+ humanAddress: resolution.humanAddress,
223
+ agentDid: resolution.agentDid,
224
+ agentAddress: resolution.agentAddress
225
+ });
226
+ return { allowed: true, resolution, did: didString, chainId: payload.chainId };
227
+ }
228
+
229
+ // src/verifier.ts
230
+ var DEFAULT_ATTESTATIONS_API_BASE_URL = "https://attestations-api.billions.network/api/v1/attestations";
231
+ var DEFAULT_NULLIFIER_API_BASE_URL = "https://attestations-api.billions.network/api/v1/nullifier";
232
+ var DEFAULT_AGENT_OWNERSHIP_SCHEMA = "0xca354bee6dc5eded165461d15ccb13aceb6f77ebbb1fd3fe45aca686097f2911";
233
+ async function fetchExplorerPage(baseUrl, schema, recipientDid) {
234
+ const url = new URL(baseUrl);
235
+ url.searchParams.set("schemaId", schema);
236
+ url.searchParams.set("recipientDid", recipientDid);
237
+ const response = await fetch(url.toString());
238
+ if (!response.ok) {
239
+ throw new Error(`Attestations explorer lookup failed (${response.status})`);
240
+ }
241
+ const json = await response.json();
242
+ return json;
243
+ }
244
+ async function fetchNullifier(nullifierBaseUrl, userId) {
245
+ const url = new URL(nullifierBaseUrl);
246
+ url.searchParams.set("userId", userId);
247
+ const response = await fetch(url.toString());
248
+ if (!response.ok) {
249
+ throw new Error(`Nullifier lookup failed (${response.status})`);
250
+ }
251
+ const json = await response.json();
252
+ return json.nullifier ?? null;
253
+ }
254
+ async function lookupHumanFromExplorer(did, options) {
255
+ const payload = await fetchExplorerPage(
256
+ options.baseUrl,
257
+ options.schema,
258
+ did
259
+ );
260
+ const sorted = (payload.data ?? []).sort((a, b) => (b.creationTime ?? 0) - (a.creationTime ?? 0));
261
+ const match = sorted[0];
262
+ if (match?.fromId) {
263
+ const nullifier = await fetchNullifier(options.nullifierBaseUrl, match.fromId);
264
+ if (nullifier) {
265
+ return {
266
+ humanId: nullifier,
267
+ verifiedAt: new Date(match.creationTime * 1e3).toISOString(),
268
+ attestationId: match.id,
269
+ humanDid: match.fromDid,
270
+ humanAddress: match.fromEthereumAddress,
271
+ agentDid: match.toDid,
272
+ agentAddress: match.toEthereumAddress
273
+ };
274
+ }
275
+ }
276
+ return null;
277
+ }
278
+ function createPoUVerifier(options = {}) {
279
+ const baseUrl = options.attestationsApiBaseUrl ?? DEFAULT_ATTESTATIONS_API_BASE_URL;
280
+ const nullifierBaseUrl = options.nullifierApiBaseUrl ?? DEFAULT_NULLIFIER_API_BASE_URL;
281
+ const ownershipSchema = options.agentOwnershipSchema ?? DEFAULT_AGENT_OWNERSHIP_SCHEMA;
282
+ return {
283
+ ownershipSchema,
284
+ async lookupHuman(did, _chainId) {
285
+ return lookupHumanFromExplorer(did, { baseUrl, schema: ownershipSchema, nullifierBaseUrl });
286
+ },
287
+ async hasAttestation(did, _chainId, schema) {
288
+ if (options.hasAttestation) {
289
+ return options.hasAttestation(did, _chainId, schema);
290
+ }
291
+ const payload = await fetchExplorerPage(baseUrl, schema, did);
292
+ return (payload.data ?? []).length > 0;
293
+ }
294
+ };
295
+ }
296
+
297
+ // src/server.ts
298
+ function createHumanProofExtension(options = {}) {
299
+ const ownershipSchema = options.agentOwnershipSchema ?? DEFAULT_AGENT_OWNERSHIP_SCHEMA;
300
+ return {
301
+ key: HUMAN_PROOF,
302
+ enrichPaymentRequiredResponse: async (declaration, context) => {
303
+ const decl = declaration;
304
+ const opts = decl._options ?? {};
305
+ const resourceUri = opts.resourceUri ?? context.resourceInfo.url;
306
+ let domain = opts.domain;
307
+ if (!domain) {
308
+ try {
309
+ domain = new URL(resourceUri).hostname;
310
+ } catch {
311
+ throw new Error(
312
+ `Cannot derive domain from resourceUri "${resourceUri}". Set opts.domain explicitly in declareHumanProofExtension.`
313
+ );
314
+ }
315
+ }
316
+ let networks;
317
+ if (opts.network) {
318
+ networks = Array.isArray(opts.network) ? opts.network : [opts.network];
319
+ } else {
320
+ networks = [...new Set(context.requirements.map((r) => r.network))];
321
+ }
322
+ const nonce = (0, import_crypto.randomBytes)(16).toString("hex");
323
+ const issuedAt = (/* @__PURE__ */ new Date()).toISOString();
324
+ const expirationSeconds = opts.expirationSeconds;
325
+ const expirationTime = expirationSeconds !== void 0 ? new Date(Date.now() + expirationSeconds * 1e3).toISOString() : void 0;
326
+ const requiredAttestations = [ownershipSchema];
327
+ const info = {
328
+ domain,
329
+ uri: resourceUri,
330
+ version: opts.version ?? "1",
331
+ nonce,
332
+ issuedAt,
333
+ requiredAttestations
334
+ };
335
+ if (resourceUri) info.resources = [resourceUri];
336
+ if (expirationTime) info.expirationTime = expirationTime;
337
+ if (opts.statement) info.statement = opts.statement;
338
+ const supportedChains = networks.filter((network) => network.startsWith("eip155:")).flatMap((network) => getSignatureTypes(network).map((type) => ({ chainId: network, type })));
339
+ const result = {
340
+ info,
341
+ supportedChains,
342
+ schema: buildHumanProofSchema()
343
+ };
344
+ return result;
345
+ }
346
+ };
347
+ }
348
+ function createVerifyHumanProofHook(options = {}) {
349
+ const { onEvent, storage } = options;
350
+ const verifier = options.verifier ?? createPoUVerifier(options.verifierOptions ?? {});
351
+ return async (context) => {
352
+ const humanProofHeader = context.paymentPayload.extensions?.[HUMAN_PROOF];
353
+ const resource = context.paymentPayload.resource?.url ?? "";
354
+ const requiredAttestations = context.requirements?.extra?.requiredAttestations;
355
+ if (!requiredAttestations?.length) {
356
+ return;
357
+ }
358
+ const result = await verifyHumanProofRequest(verifier, {
359
+ resource,
360
+ humanProofHeader: humanProofHeader ?? null,
361
+ ...onEvent ? { onEvent } : {}
362
+ });
363
+ if (!result.allowed) {
364
+ return { abort: true, reason: result.reason };
365
+ }
366
+ const extraSchemas = requiredAttestations?.filter((s) => s !== verifier.ownershipSchema);
367
+ if (extraSchemas?.length) {
368
+ if (!verifier.hasAttestation) {
369
+ return { abort: true, reason: "verifier_cannot_check_attestations" };
370
+ }
371
+ for (const schema of extraSchemas) {
372
+ const has = await verifier.hasAttestation(result.did, result.chainId, schema);
373
+ if (!has) {
374
+ return { abort: true, reason: "missing_required_attestation" };
375
+ }
376
+ }
377
+ }
378
+ const maxUseRaw = context.requirements?.extra?.maxUse;
379
+ if (maxUseRaw === void 0) return;
380
+ if (typeof maxUseRaw !== "number" || !Number.isFinite(maxUseRaw) || !Number.isInteger(maxUseRaw) || maxUseRaw < 1) {
381
+ return { abort: true, reason: "invalid_max_use_value" };
382
+ }
383
+ const maxUse = maxUseRaw;
384
+ if (!storage) {
385
+ return { abort: true, reason: "misconfigured_max_use_storage" };
386
+ }
387
+ const scopeRaw = context.requirements?.extra?.scope;
388
+ const scope = typeof scopeRaw === "string" && scopeRaw ? scopeRaw : resource;
389
+ const count = await storage.incrementIfBelow(result.resolution.humanId, maxUse, scope);
390
+ if (count === null) {
391
+ await onEvent?.({ type: "max_use_exceeded", resource, humanId: result.resolution.humanId, maxUse });
392
+ return { abort: true, reason: "max_use_exceeded" };
393
+ }
394
+ };
395
+ }
396
+ async function resolveUsageContext(context, verifier) {
397
+ const requiredAttestations = context.requirements?.extra?.requiredAttestations;
398
+ if (!requiredAttestations?.length) return null;
399
+ const maxUseRaw = context.requirements?.extra?.maxUse;
400
+ if (typeof maxUseRaw !== "number" || !Number.isFinite(maxUseRaw) || !Number.isInteger(maxUseRaw) || maxUseRaw < 1) {
401
+ return null;
402
+ }
403
+ const humanProofHeader = context.paymentPayload.extensions?.[HUMAN_PROOF];
404
+ const resource = context.paymentPayload.resource?.url ?? "";
405
+ const result = await verifyHumanProofRequest(verifier, {
406
+ resource,
407
+ humanProofHeader: humanProofHeader ?? null
408
+ });
409
+ if (!result.allowed) return null;
410
+ const scopeRaw = context.requirements?.extra?.scope;
411
+ const scope = typeof scopeRaw === "string" && scopeRaw ? scopeRaw : resource;
412
+ return { humanId: result.resolution.humanId, scope };
413
+ }
414
+ function createAfterVerifyFailureRollbackHook(options) {
415
+ const { storage, verifier } = options;
416
+ return async (context) => {
417
+ if (context.result.isValid !== false) return;
418
+ const resolved = await resolveUsageContext(context, verifier);
419
+ if (!resolved) return;
420
+ await storage.decrementIfAboveZero(resolved.humanId, resolved.scope);
421
+ };
422
+ }
423
+ function createVerifyFailureRollbackHook(options) {
424
+ const { storage, verifier } = options;
425
+ return async (context) => {
426
+ const resolved = await resolveUsageContext(context, verifier);
427
+ if (!resolved) return;
428
+ await storage.decrementIfAboveZero(resolved.humanId, resolved.scope);
429
+ };
430
+ }
431
+ function createSettleFailureRollbackHook(options) {
432
+ const { storage, verifier } = options;
433
+ return async (context) => {
434
+ const resolved = await resolveUsageContext(context, verifier);
435
+ if (!resolved) return;
436
+ await storage.decrementIfAboveZero(resolved.humanId, resolved.scope);
437
+ };
438
+ }
439
+ function configureHumanProofServer(server, options = {}) {
440
+ const {
441
+ extensionOptions,
442
+ verifier,
443
+ verifierOptions,
444
+ onEvent,
445
+ storage
446
+ } = options;
447
+ const resolvedVerifier = verifier ?? createPoUVerifier(verifierOptions ?? {});
448
+ server.registerExtension(createHumanProofExtension(extensionOptions));
449
+ server.onBeforeVerify(createVerifyHumanProofHook({
450
+ verifier: resolvedVerifier,
451
+ ...onEvent ? { onEvent } : {},
452
+ ...storage ? { storage } : {}
453
+ }));
454
+ if (storage) {
455
+ server.onAfterVerify(createAfterVerifyFailureRollbackHook({ storage, verifier: resolvedVerifier }));
456
+ server.onVerifyFailure(createVerifyFailureRollbackHook({ storage, verifier: resolvedVerifier }));
457
+ server.onSettleFailure(createSettleFailureRollbackHook({ storage, verifier: resolvedVerifier }));
458
+ }
459
+ }
460
+ // Annotate the CommonJS export names for ESM import in node:
461
+ 0 && (module.exports = {
462
+ configureHumanProofServer,
463
+ createAfterVerifyFailureRollbackHook,
464
+ createHumanProofExtension,
465
+ createSettleFailureRollbackHook,
466
+ createVerifyFailureRollbackHook,
467
+ createVerifyHumanProofHook
468
+ });
469
+ //# sourceMappingURL=server.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server.ts","../../../src/utils.ts","../../../src/declare.ts","../../../src/hooks.ts","../../../src/verifier.ts"],"sourcesContent":["import { buildHumanProofSchema } from './utils.js'\nimport { randomBytes } from 'crypto'\nimport { HUMAN_PROOF, getSignatureTypes } from './declare.js'\nimport { verifyHumanProofRequest } from './hooks.js'\nimport type { HumanProofDeclaration, HumanProofEvent, HumanUsageStorage, PoUVerifier, PoUVerifierOptions } from './types.js'\nimport type { ResourceServerExtension, PaymentRequiredContext } from '@x402/core/types'\nimport type { HumanProofExtensionInfo, SupportedChain } from './utils.js'\nimport { createPoUVerifier, DEFAULT_AGENT_OWNERSHIP_SCHEMA } from './verifier.js'\nimport type { x402ResourceServer } from '@x402/core/server'\n\nexport type CreateHumanProofExtensionOptions = {\n /** Must match the agentOwnershipSchema configured in your PoUVerifier, if customised. */\n agentOwnershipSchema?: string\n}\n\nexport function createHumanProofExtension(options: CreateHumanProofExtensionOptions = {}): ResourceServerExtension {\n const ownershipSchema = options.agentOwnershipSchema ?? DEFAULT_AGENT_OWNERSHIP_SCHEMA\n return {\n key: HUMAN_PROOF,\n enrichPaymentRequiredResponse: async (\n declaration: unknown,\n context: PaymentRequiredContext,\n ): Promise<unknown> => {\n const decl = declaration as HumanProofDeclaration\n const opts = decl._options ?? {}\n\n const resourceUri = opts.resourceUri ?? context.resourceInfo.url\n\n let domain = opts.domain\n if (!domain) {\n try {\n domain = new URL(resourceUri).hostname\n } catch {\n throw new Error(\n `Cannot derive domain from resourceUri \"${resourceUri}\". ` +\n `Set opts.domain explicitly in declareHumanProofExtension.`,\n )\n }\n }\n\n let networks: string[]\n if (opts.network) {\n networks = Array.isArray(opts.network) ? opts.network : [opts.network]\n } else {\n networks = [...new Set(context.requirements.map(r => r.network))]\n }\n\n const nonce = randomBytes(16).toString('hex')\n const issuedAt = new Date().toISOString()\n\n const expirationSeconds = opts.expirationSeconds\n const expirationTime =\n expirationSeconds !== undefined\n ? new Date(Date.now() + expirationSeconds * 1000).toISOString()\n : undefined\n\n const requiredAttestations: string[] = [ownershipSchema]\n\n const info: HumanProofExtensionInfo = {\n domain,\n uri: resourceUri,\n version: opts.version ?? '1',\n nonce,\n issuedAt,\n requiredAttestations,\n }\n\n if (resourceUri) info.resources = [resourceUri]\n if (expirationTime) info.expirationTime = expirationTime\n if (opts.statement) info.statement = opts.statement\n\n // Only eip155 networks support the CAIP-122 signing flow; Solana routes still\n // accept payment but are not listed as human-proof signing options.\n const supportedChains: SupportedChain[] = networks\n .filter(network => network.startsWith('eip155:'))\n .flatMap(network => getSignatureTypes(network).map(type => ({ chainId: network, type })))\n\n const result: Record<string, unknown> = {\n info,\n supportedChains,\n schema: buildHumanProofSchema(),\n }\n return result\n },\n }\n}\n\nexport type CreateVerifyHumanProofHookOptions = {\n verifier?: PoUVerifier\n verifierOptions?: PoUVerifierOptions\n onEvent?: (event: HumanProofEvent) => void | Promise<void>\n storage?: HumanUsageStorage\n}\n\nexport function createVerifyHumanProofHook(\n options: CreateVerifyHumanProofHookOptions = {},\n) {\n const { onEvent, storage } = options\n const verifier = options.verifier ?? createPoUVerifier(options.verifierOptions ?? {})\n\n return async (context: {\n paymentPayload: { extensions?: Record<string, unknown>; resource?: { url: string } }\n requirements?: { extra?: Record<string, unknown> }\n }): Promise<void | { abort: true; reason: string }> => {\n const humanProofHeader = context.paymentPayload.extensions?.[HUMAN_PROOF] as string | undefined\n const resource = context.paymentPayload.resource?.url ?? ''\n\n\n // if no extra attestation requirements are specified, we can skip the human proof verification\n const requiredAttestations = context.requirements?.extra?.requiredAttestations as string[] | undefined\n if (!requiredAttestations?.length) {\n return\n }\n const result = await verifyHumanProofRequest(verifier, {\n resource,\n humanProofHeader: humanProofHeader ?? null,\n ...(onEvent ? { onEvent } : {}),\n })\n\n if (!result.allowed) {\n return { abort: true, reason: result.reason }\n }\n\n const extraSchemas = requiredAttestations?.filter(s => s !== verifier.ownershipSchema)\n if (extraSchemas?.length) {\n if (!verifier.hasAttestation) {\n return { abort: true, reason: 'verifier_cannot_check_attestations' }\n }\n for (const schema of extraSchemas) {\n const has = await verifier.hasAttestation(result.did, result.chainId, schema)\n if (!has) {\n return { abort: true, reason: 'missing_required_attestation' }\n }\n }\n }\n\n const maxUseRaw = context.requirements?.extra?.maxUse\n if (maxUseRaw === undefined) return\n if (typeof maxUseRaw !== 'number' || !Number.isFinite(maxUseRaw) || !Number.isInteger(maxUseRaw) || maxUseRaw < 1) {\n return { abort: true, reason: 'invalid_max_use_value' }\n }\n const maxUse = maxUseRaw\n if (!storage) {\n return { abort: true, reason: 'misconfigured_max_use_storage' }\n }\n const scopeRaw = context.requirements?.extra?.scope\n const scope = typeof scopeRaw === 'string' && scopeRaw ? scopeRaw : resource\n const count = await storage.incrementIfBelow(result.resolution.humanId, maxUse, scope)\n if (count === null) {\n await onEvent?.({ type: 'max_use_exceeded', resource, humanId: result.resolution.humanId, maxUse })\n return { abort: true, reason: 'max_use_exceeded' }\n }\n }\n}\n\nasync function resolveUsageContext(\n context: {\n paymentPayload: { extensions?: Record<string, unknown>; resource?: { url: string } }\n requirements?: { extra?: Record<string, unknown> }\n },\n verifier: PoUVerifier,\n): Promise<{ humanId: string; scope: string } | null> {\n const requiredAttestations = context.requirements?.extra?.requiredAttestations as string[] | undefined\n if (!requiredAttestations?.length) return null\n\n const maxUseRaw = context.requirements?.extra?.maxUse\n if (typeof maxUseRaw !== 'number' || !Number.isFinite(maxUseRaw) || !Number.isInteger(maxUseRaw) || maxUseRaw < 1) {\n return null\n }\n\n const humanProofHeader = context.paymentPayload.extensions?.[HUMAN_PROOF] as string | undefined\n const resource = context.paymentPayload.resource?.url ?? ''\n\n const result = await verifyHumanProofRequest(verifier, {\n resource,\n humanProofHeader: humanProofHeader ?? null,\n })\n if (!result.allowed) return null\n\n const scopeRaw = context.requirements?.extra?.scope\n const scope = typeof scopeRaw === 'string' && scopeRaw ? scopeRaw : resource\n return { humanId: result.resolution.humanId, scope }\n}\n\nexport type CreateAfterVerifyFailureRollbackHookOptions = {\n storage: HumanUsageStorage\n verifier: PoUVerifier\n}\n\nexport function createAfterVerifyFailureRollbackHook(\n options: CreateAfterVerifyFailureRollbackHookOptions,\n) {\n const { storage, verifier } = options\n\n return async (context: {\n paymentPayload: { extensions?: Record<string, unknown>; resource?: { url: string } }\n requirements?: { extra?: Record<string, unknown> }\n result: { isValid?: boolean }\n }): Promise<void> => {\n if (context.result.isValid !== false) return\n const resolved = await resolveUsageContext(context, verifier)\n if (!resolved) return\n await storage.decrementIfAboveZero(resolved.humanId, resolved.scope)\n }\n}\n\nexport type CreateVerifyFailureRollbackHookOptions = {\n storage: HumanUsageStorage\n verifier: PoUVerifier\n}\n\nexport function createVerifyFailureRollbackHook(\n options: CreateVerifyFailureRollbackHookOptions,\n) {\n const { storage, verifier } = options\n\n return async (context: {\n paymentPayload: { extensions?: Record<string, unknown>; resource?: { url: string } }\n requirements?: { extra?: Record<string, unknown> }\n error?: Error\n }): Promise<void> => {\n const resolved = await resolveUsageContext(context, verifier)\n if (!resolved) return\n await storage.decrementIfAboveZero(resolved.humanId, resolved.scope)\n }\n}\n\nexport type CreateSettleFailureRollbackHookOptions = {\n storage: HumanUsageStorage\n verifier: PoUVerifier\n}\n\nexport function createSettleFailureRollbackHook(\n options: CreateSettleFailureRollbackHookOptions,\n) {\n const { storage, verifier } = options\n\n return async (context: {\n paymentPayload: { extensions?: Record<string, unknown>; resource?: { url: string } }\n requirements?: { extra?: Record<string, unknown> }\n error?: Error\n }): Promise<void> => {\n const resolved = await resolveUsageContext(context, verifier)\n if (!resolved) return\n await storage.decrementIfAboveZero(resolved.humanId, resolved.scope)\n }\n}\n\nexport type ConfigureHumanProofServerOptions = {\n extensionOptions?: CreateHumanProofExtensionOptions\n verifier?: PoUVerifier\n verifierOptions?: PoUVerifierOptions\n onEvent?: (event: HumanProofEvent) => void | Promise<void>\n storage?: HumanUsageStorage\n}\n\nexport function configureHumanProofServer(\n server: x402ResourceServer,\n options: ConfigureHumanProofServerOptions = {},\n): void {\n const {\n extensionOptions,\n verifier,\n verifierOptions,\n onEvent,\n storage,\n } = options\n\n const resolvedVerifier = verifier ?? createPoUVerifier(verifierOptions ?? {})\n\n server.registerExtension(createHumanProofExtension(extensionOptions))\n server.onBeforeVerify(createVerifyHumanProofHook({\n verifier: resolvedVerifier,\n ...(onEvent ? { onEvent } : {}),\n ...(storage ? { storage } : {}),\n }))\n\n if (storage) {\n server.onAfterVerify(createAfterVerifyFailureRollbackHook({ storage, verifier: resolvedVerifier }))\n server.onVerifyFailure(createVerifyFailureRollbackHook({ storage, verifier: resolvedVerifier }))\n server.onSettleFailure(createSettleFailureRollbackHook({ storage, verifier: resolvedVerifier }))\n }\n}\n","import { recoverPublicKey, hashMessage, recoverMessageAddress } from 'viem'\nimport bs58 from 'bs58'\nimport nacl from 'tweetnacl'\nimport type { PaywallProvider } from '@x402/core/server'\nimport type { PaymentRequired } from '@x402/core/types'\n\nexport type SignatureType = 'eip191' | 'ed25519'\n\nexport type SupportedChain = {\n chainId: string\n type: SignatureType\n}\n\nexport type HumanProofExtensionInfo = {\n domain: string\n uri?: string\n version: string\n nonce: string\n issuedAt: string\n expirationTime?: string\n statement?: string\n resources?: string[]\n requiredAttestations: string[]\n}\n\nexport type HumanProofExtensionPayload = HumanProofExtensionInfo & {\n chainId: string\n type: SignatureType\n address: string\n signature: string\n}\n\ntype ValidationResult = {\n valid: boolean\n error?: string\n}\n\ntype SignatureVerificationResult = {\n valid: boolean\n address?: string\n pubKey?: string\n error?: string\n}\n\nfunction formatResources(resources?: string[]): string {\n if (!resources?.length) return ''\n const lines = resources.map(resource => `- ${resource}`).join('\\n')\n return `\\nResources:\\n${lines}`\n}\n\nfunction formatSIWEMessage(payload: HumanProofExtensionPayload): string {\n const statementBlock = payload.statement ? `\\n${payload.statement}\\n` : '\\n'\n const expirationLine = payload.expirationTime ? `\\nExpiration Time: ${payload.expirationTime}` : ''\n\n return (\n `${payload.domain} wants you to sign in with your Ethereum account:\\n` +\n `${payload.address}${statementBlock}\\n` +\n `URI: ${payload.uri ?? ''}\\n` +\n `Version: ${payload.version}\\n` +\n `Chain ID: ${payload.chainId}\\n` +\n `Nonce: ${payload.nonce}\\n` +\n `Issued At: ${payload.issuedAt}` +\n `${expirationLine}` +\n `${formatResources(payload.resources)}`\n )\n}\n\nfunction formatSIWSMessage(payload: HumanProofExtensionPayload): string {\n const statementBlock = payload.statement ? `\\n${payload.statement}\\n` : '\\n'\n const expirationLine = payload.expirationTime ? `\\nExpiration Time: ${payload.expirationTime}` : ''\n\n return (\n `${payload.domain} wants you to sign in with your Solana account:\\n` +\n `${payload.address}${statementBlock}\\n` +\n `URI: ${payload.uri ?? ''}\\n` +\n `Version: ${payload.version}\\n` +\n `Chain ID: ${payload.chainId}\\n` +\n `Nonce: ${payload.nonce}\\n` +\n `Issued At: ${payload.issuedAt}` +\n `${expirationLine}` +\n `${formatResources(payload.resources)}`\n )\n}\n\nfunction decodeBase58(input: string): Uint8Array {\n return bs58.decode(input)\n}\n\nexport function buildHumanProofSchema(): Record<string, unknown> {\n return {\n type: 'object',\n required: ['domain', 'version', 'nonce', 'issuedAt', 'chainId', 'type', 'address', 'signature', 'requiredAttestations'],\n properties: {\n domain: { type: 'string' },\n uri: { type: 'string' },\n version: { type: 'string' },\n nonce: { type: 'string' },\n issuedAt: { type: 'string' },\n expirationTime: { type: 'string' },\n statement: { type: 'string' },\n resources: { type: 'array', items: { type: 'string' } },\n chainId: { type: 'string' },\n type: { enum: ['eip191', 'ed25519'] },\n address: { type: 'string' },\n signature: { type: 'string' },\n requiredAttestations: { type: 'array', items: { type: 'string' }},\n },\n additionalProperties: true,\n }\n}\n\nexport function parseHumanProofHeader(headerValue: string): HumanProofExtensionPayload {\n const parsed = JSON.parse(headerValue) as unknown\n if (!parsed || typeof parsed !== 'object') {\n throw new Error('Invalid header payload')\n }\n\n const payload = parsed as Partial<HumanProofExtensionPayload>\n if (!payload.address || !payload.signature || !payload.chainId || !payload.type) {\n throw new Error('Missing required fields in header payload')\n }\n\n return payload as HumanProofExtensionPayload\n}\n\nexport async function validateHumanProofMessage(\n payload: HumanProofExtensionPayload,\n resource: string,\n): Promise<ValidationResult> {\n if (!payload.domain || !payload.version || !payload.nonce || !payload.issuedAt) {\n return { valid: false, error: 'invalid_message' }\n }\n\n if (!payload.uri || payload.uri !== resource) {\n return { valid: false, error: 'resource_mismatch' }\n }\n\n const issuedAtMillis = Date.parse(payload.issuedAt)\n if (Number.isNaN(issuedAtMillis)) {\n return { valid: false, error: 'invalid_issued_at' }\n }\n\n if (payload.expirationTime) {\n const expirationMillis = Date.parse(payload.expirationTime)\n if (Number.isNaN(expirationMillis)) {\n return { valid: false, error: 'invalid_expiration_time' }\n }\n if (expirationMillis < Date.now()) {\n return { valid: false, error: 'message_expired' }\n }\n }\n\n return { valid: true }\n}\n\nexport async function verifyHumanProofSignature(\n payload: HumanProofExtensionPayload,\n): Promise<SignatureVerificationResult> {\n if (payload.type === 'eip191') {\n if (!payload.signature.startsWith('0x')) {\n return { valid: false, error: 'invalid_signature' }\n }\n try {\n const message = formatSIWEMessage(payload)\n const signature = payload.signature as `0x${string}`\n\n const recovered = await recoverMessageAddress({ message, signature })\n if (recovered.toLowerCase() !== payload.address.toLowerCase()) {\n return { valid: false, error: 'invalid_signature' }\n }\n\n const publicKey = await recoverPublicKey({ hash: hashMessage(message), signature })\n return { valid: true, address: payload.address, pubKey: publicKey }\n } catch {\n return { valid: false, error: 'invalid_signature' }\n }\n }\n\n if (payload.type === 'ed25519') {\n try {\n const message = new TextEncoder().encode(formatSIWSMessage(payload))\n const publicKey = decodeBase58(payload.address)\n const signature = decodeBase58(payload.signature)\n\n const valid = nacl.sign.detached.verify(message, signature, publicKey)\n if (!valid) return { valid: false, error: 'invalid_signature' }\n return { valid: true, address: payload.address, pubKey: bs58.encode(publicKey) }\n } catch {\n return { valid: false, error: 'invalid_signature' }\n }\n }\n\n return { valid: false, error: 'invalid_signature_type' }\n}\n\nconst DEFAULT_PAYWALL_HTML =\n \"<html><body>\" +\n \"<h1>Payment Required</h1>\" +\n \"<p>Please complete the payment to access this resource.</p>\" +\n \"<p>The payment depends on verified-agent-identity plugin. \" +\n \"That can be downloaded from: \" +\n '<a href=\"https://clawhub.ai/obrezhniev/verified-agent-identity\">clawhub.ai</a> ' +\n '<a href=\"https://skills.sh/billionsnetwork/verified-agent-identity/verified-agent-identity\">skills.sh</a>' +\n \"</p></body></html>\"\n\nexport function paywallInstructions(html?: string): PaywallProvider {\n return new (class implements PaywallProvider {\n public generateHtml(_: PaymentRequired): string {\n return html ?? DEFAULT_PAYWALL_HTML\n }\n })()\n}\n","import type { SignatureType } from './utils.js'\nimport type { DeclareHumanProofOptions, HumanProofDeclaration } from './types.js'\n\nexport const HUMAN_PROOF = 'human-proof'\n\n/**\n *\n * @example\n * extensions: declareHumanProofExtension({\n * statement: 'Verify your agent is backed by a verified human',\n * })\n */\nexport function declareHumanProofExtension(options: DeclareHumanProofOptions): HumanProofDeclaration {\n return { _options: options, _type: 'human-proof' }\n}\n\n/**\n * Returns the supported signature types for a given CAIP-2 network.\n * Solana uses ed25519 (SIWS); all EVM networks use eip191 (SIWE).\n */\nexport function getSignatureTypes(network: string): SignatureType[] {\n if (network.startsWith('solana:')) return ['ed25519']\n return ['eip191']\n}\n","import {\n parseHumanProofHeader,\n validateHumanProofMessage,\n verifyHumanProofSignature,\n} from './utils.js'\nimport type { HumanResolution, HumanProofEvent, PoUVerifier } from './types.js'\nimport { Blockchain, buildDIDType, DidMethod, NetworkId } from '@iden3/js-iden3-core'\nimport { buildDIDFromEthAddress } from '@0xpolygonid/js-sdk'\n\nexport const HUMAN_PROOF_HEADER = 'HUMAN-PROOF'\n\nexport type HumanProofRequestContext = {\n /** The resource URI being accessed (used to validate the CAIP-122 message). */\n resource: string\n /** Value of the HUMAN-PROOF request header, or null if absent. */\n humanProofHeader: string | null\n /** Optional callback fired on human_verified and human_not_registered events. */\n onEvent?: (event: HumanProofEvent) => void | Promise<void>\n}\n\nexport type HumanProofRequestResult =\n | { allowed: true; resolution: HumanResolution; did: string; chainId: string }\n | {\n allowed: false\n reason:\n | 'missing_header'\n | 'invalid_header'\n | 'invalid_message'\n | 'invalid_signature'\n | 'not_registered'\n | string\n did?: string\n humanId?: string\n }\n\n/**\n * Verify a HUMAN-PROOF request header against the PoU registry.\n *\n * Call this inside a request hook (BeforeVerifyHook or framework middleware)\n * to gate access based on human verification.\n *\n * Flow:\n * 1. Parse the CAIP-122 signed payload from the HUMAN-PROOF header\n * 2. Validate message fields (resource URI, nonce expiry)\n * 3. Verify the cryptographic signature (EVM eip191 or Solana ed25519)\n * 4. Resolve the wallet address to a HumanResolution via the on-chain registry\n * 5. Fire hook events\n */\nexport async function verifyHumanProofRequest(\n verifier: PoUVerifier,\n context: HumanProofRequestContext,\n): Promise<HumanProofRequestResult> {\n const { resource, humanProofHeader, onEvent } = context\n\n if (!humanProofHeader) {\n return { allowed: false, reason: 'missing_header' }\n }\n\n let payload\n try {\n payload = parseHumanProofHeader(humanProofHeader)\n } catch {\n return { allowed: false, reason: 'invalid_header' }\n }\n\n // Validate CAIP-122 message fields (URI match, nonce, expiry)\n const validation = await validateHumanProofMessage(payload, resource)\n if (!validation.valid) {\n return { allowed: false, reason: validation.error ?? 'invalid_message' }\n }\n\n // Verify cryptographic signature — handles both eip191 (SIWE) and ed25519 (SIWS)\n const sigResult = await verifyHumanProofSignature(payload)\n if (!sigResult.valid || !sigResult.address) {\n return { allowed: false, reason: sigResult.error ?? 'invalid_signature' }\n }\n\n const didType = buildDIDType(DidMethod.Iden3!, Blockchain.Billions!, NetworkId.Main!)\n const didString = buildDIDFromEthAddress(didType, sigResult.address!).string()\n // Resolve did → human via resolver\n const resolution = await verifier.lookupHuman(didString, payload.chainId)\n if (!resolution) {\n await onEvent?.({\n type: 'human_not_registered',\n resource,\n did: didString,\n })\n\n return { allowed: false, reason: 'not_registered', did: didString }\n }\n\n await onEvent?.({\n type: 'human_verified',\n resource,\n humanId: resolution.humanId,\n verifiedAt: resolution.verifiedAt,\n attestationId: resolution.attestationId,\n humanDid: resolution.humanDid,\n humanAddress: resolution.humanAddress,\n agentDid: resolution.agentDid,\n agentAddress: resolution.agentAddress, \n })\n\n return { allowed: true, resolution, did: didString, chainId: payload.chainId }\n}\n","import type {\n HumanResolution,\n PoUVerifier,\n PoUVerifierOptions,\n} from './types.js'\n\nexport const DEFAULT_ATTESTATIONS_API_BASE_URL =\n 'https://attestations-api.billions.network/api/v1/attestations'\n\nexport const DEFAULT_NULLIFIER_API_BASE_URL =\n 'https://attestations-api.billions.network/api/v1/nullifier'\n\nexport const DEFAULT_AGENT_OWNERSHIP_SCHEMA =\n '0xca354bee6dc5eded165461d15ccb13aceb6f77ebbb1fd3fe45aca686097f2911'\n\ntype ExplorerAttestationItem = {\n creationTime: number\n time?: number\n id: string\n schemaId: string\n fromId?: string\n recipientEthereumAddress?: string\n attesterEthereumAddress?: string\n toDid: string\n toEthereumAddress: string\n fromDid: string\n fromEthereumAddress: string\n}\n\ntype ExplorerAttestationsResponse = {\n data?: ExplorerAttestationItem[]\n nextPage?: number | null\n}\n\nasync function fetchExplorerPage(\n baseUrl: string,\n schema: string,\n recipientDid: string,\n): Promise<ExplorerAttestationsResponse> {\n const url = new URL(baseUrl)\n\n url.searchParams.set('schemaId', schema)\n url.searchParams.set('recipientDid', recipientDid)\n\n const response = await fetch(url.toString())\n if (!response.ok) {\n throw new Error(`Attestations explorer lookup failed (${response.status})`)\n }\n\n const json = (await response.json()) as ExplorerAttestationsResponse\n return json\n}\n\nasync function fetchNullifier(nullifierBaseUrl: string, userId: string): Promise<string | null> {\n const url = new URL(nullifierBaseUrl)\n url.searchParams.set('userId', userId)\n\n const response = await fetch(url.toString())\n if (!response.ok) {\n throw new Error(`Nullifier lookup failed (${response.status})`)\n }\n\n const json = (await response.json()) as { userId: string; nullifier: string }\n return json.nullifier ?? null\n}\n\nasync function lookupHumanFromExplorer(\n did: string,\n options: {\n baseUrl: string\n schema: string\n nullifierBaseUrl: string\n },\n): Promise<HumanResolution | null> {\n const payload = await fetchExplorerPage(\n options.baseUrl,\n options.schema,\n did,\n )\n\n const sorted = (payload.data ?? []).sort((a, b) => (b.creationTime ?? 0) - (a.creationTime ?? 0))\n const match = sorted[0]\n\n if (match?.fromId) {\n const nullifier = await fetchNullifier(options.nullifierBaseUrl, match.fromId)\n if (nullifier) {\n return {\n humanId: nullifier,\n verifiedAt: new Date(match.creationTime * 1000).toISOString(),\n attestationId: match.id,\n humanDid: match.fromDid,\n humanAddress: match.fromEthereumAddress,\n agentDid: match.toDid,\n agentAddress: match.toEthereumAddress,\n }\n }\n }\n\n return null\n}\n\n/**\n * Creates a PoU (Proof of Uniqueness) verifier that resolves a DID\n * to a HumanResolution.\n * @example\n * const verifier = createPoUVerifier()\n * const resolution = await verifier.lookupHuman('did:iden3:...', 'eip155:137')\n */\nexport function createPoUVerifier(options: PoUVerifierOptions = {}): PoUVerifier {\n const baseUrl = options.attestationsApiBaseUrl ?? DEFAULT_ATTESTATIONS_API_BASE_URL\n const nullifierBaseUrl = options.nullifierApiBaseUrl ?? DEFAULT_NULLIFIER_API_BASE_URL\n const ownershipSchema = options.agentOwnershipSchema ?? DEFAULT_AGENT_OWNERSHIP_SCHEMA\n\n return {\n ownershipSchema,\n\n async lookupHuman(did: string, _chainId: string): Promise<HumanResolution | null> {\n return lookupHumanFromExplorer(did, { baseUrl, schema: ownershipSchema, nullifierBaseUrl })\n },\n\n async hasAttestation(did: string, _chainId: string, schema: string): Promise<boolean> {\n if (options.hasAttestation) {\n return options.hasAttestation(did, _chainId, schema)\n }\n const payload = await fetchExplorerPage(baseUrl, schema, did)\n return (payload.data ?? []).length > 0\n },\n }\n}\n"],"mappings":"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","names":["bs58","nacl"]}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+
16
+ // src/types.ts
17
+ var types_exports = {};
18
+ module.exports = __toCommonJS(types_exports);
19
+ //# sourceMappingURL=types.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/types.ts"],"sourcesContent":["export type HumanResolution = {\n humanId: string\n verifiedAt: string // ISO 8601\n attestationId: string\n humanDid: string\n humanAddress: string\n agentDid: string\n agentAddress: string\n}\n\nexport type DeclareHumanProofOptions = {\n statement?: string\n resourceUri?: string\n domain?: string\n version?: string\n expirationSeconds?: number\n network?: string | string[]\n}\n\nexport type HumanProofDeclaration = {\n _options: DeclareHumanProofOptions\n _type: 'human-proof'\n}\n\nexport type HumanVerifiedEvent = {\n type: 'human_verified'\n resource: string\n humanId: string\n verifiedAt: string\n attestationId: string\n humanDid: string\n humanAddress: string\n agentDid: string\n agentAddress: string\n}\n\nexport type HumanNotRegisteredEvent = {\n type: 'human_not_registered'\n resource: string\n did: string\n}\n\nexport type MaxUseExceededEvent = {\n type: 'max_use_exceeded'\n resource: string\n humanId: string\n maxUse: number\n}\n\nexport type HumanProofEvent = HumanVerifiedEvent | HumanNotRegisteredEvent | MaxUseExceededEvent\n\n\nexport type PoUVerifierOptions = {\n /**\n * Optional override for the attestation check implementation.\n * If not provided, queries the Billions Network explorer API.\n * For full customisation (including human lookup), implement the PoUVerifier\n * interface directly and pass it via CreateVerifyHumanProofHookOptions.verifier.\n */\n hasAttestation?: (did: string, chainId: string, schema: string) => Promise<boolean>\n /** Override the attestations API base URL. Defaults to the Billions Network explorer. */\n attestationsApiBaseUrl?: string\n /** Override the agent-ownership schema ID used for human registry lookups. */\n agentOwnershipSchema?: string\n /** Override the nullifier API base URL. Defaults to the Billions Network nullifier endpoint. */\n nullifierApiBaseUrl?: string\n}\n\nexport interface HumanUsageStorage {\n /**\n * Atomically increments the usage count for (humanId, scope) only if the\n * current count is strictly below maxUse, and returns the new count.\n * Returns null if the limit was already reached (no increment is performed).\n *\n * `scope` isolates counters per resource so that a limit on one route does\n * not consume quota for another. Typically the resource URL, but callers may\n * supply any stable key (e.g. a route ID or accept-option identifier).\n *\n * Implementations must be a single atomic operation so concurrent requests\n * cannot both pass the limit check:\n * - Redis: Lua script (GET + conditional INCR), key = `${humanId}:${scope}`\n * - SQL: UPDATE human_usage SET count = count + 1 WHERE human_id = ? AND scope = ? AND count < ? RETURNING count\n */\n incrementIfBelow(humanId: string, maxUse: number, scope: string): Promise<number | null>\n\n /**\n * Decrements usage for (humanId, scope) if current value is above zero.\n * Returns the new count, or null if no decrement was performed.\n */\n decrementIfAboveZero(humanId: string, scope: string): Promise<number | null>\n}\n\nexport interface PoUVerifier {\n /**\n * The schema ID used to determine human registration (checked by lookupHuman).\n * Used by hooks to skip redundant hasAttestation calls for this schema.\n */\n ownershipSchema: string\n /**\n * Resolve an agent DID to its verified human record.\n * Returns null if the DID is not registered in the PoU registry.\n */\n lookupHuman(did: string, chainId: string): Promise<HumanResolution | null>\n /**\n * Check whether a DID holds a specific attestation schema.\n * Returns true if the attestation exists, false otherwise.\n */\n hasAttestation?(did: string, chainId: string, schema: string): Promise<boolean>\n}"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}