@neus/sdk 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cjs/client.cjs CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var client_exports = {};
22
22
  __export(client_exports, {
23
23
  NeusClient: () => NeusClient,
24
+ PORTABLE_PROOF_SIGNER_HEADER: () => PORTABLE_PROOF_SIGNER_HEADER,
24
25
  constructVerificationMessage: () => constructVerificationMessage
25
26
  });
26
27
  module.exports = __toCommonJS(client_exports);
@@ -129,6 +130,7 @@ var ConfigurationError = class extends SDKError {
129
130
  };
130
131
 
131
132
  // utils.js
133
+ var PORTABLE_PROOF_SIGNER_HEADER = "Portable Proof Verification Request";
132
134
  var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
133
135
  function encodeBase58Bytes(input) {
134
136
  let source;
@@ -143,8 +145,7 @@ function encodeBase58Bytes(input) {
143
145
  } else {
144
146
  throw new SDKError("Unsupported non-EVM signature byte format", "INVALID_SIGNATURE_FORMAT");
145
147
  }
146
- if (source.length === 0)
147
- return "";
148
+ if (source.length === 0) return "";
148
149
  let zeroes = 0;
149
150
  while (zeroes < source.length && source[zeroes] === 0) {
150
151
  zeroes++;
@@ -178,16 +179,28 @@ function deterministicStringify(obj) {
178
179
  return JSON.stringify(obj);
179
180
  }
180
181
  if (typeof obj !== "object") {
182
+ if (typeof obj === "string") return JSON.stringify(obj.normalize("NFC"));
181
183
  return JSON.stringify(obj);
182
184
  }
183
185
  if (Array.isArray(obj)) {
184
- return "[" + obj.map((item) => deterministicStringify(item)).join(",") + "]";
186
+ return `[${obj.map((item) => item === void 0 ? "null" : deterministicStringify(item)).join(",")}]`;
185
187
  }
186
- const sortedKeys = Object.keys(obj).sort();
188
+ const sortedKeys = Object.keys(obj).filter((k) => obj[k] !== void 0).sort();
187
189
  const pairs = sortedKeys.map(
188
- (key) => JSON.stringify(key) + ":" + deterministicStringify(obj[key])
190
+ (key) => `${JSON.stringify(key)}:${deterministicStringify(obj[key])}`
189
191
  );
190
- return "{" + pairs.join(",") + "}";
192
+ return `{${pairs.join(",")}}`;
193
+ }
194
+ function chainLineForPortableProofSigner(chain, chainId) {
195
+ if (typeof chain === "string" && chain.length > 0) {
196
+ const m = chain.match(/^eip155:(\d+)$/);
197
+ if (m) return Number(m[1]);
198
+ return chain;
199
+ }
200
+ if (typeof chainId === "number" && Number.isFinite(chainId) && chainId > 0) {
201
+ return chainId;
202
+ }
203
+ throw new SDKError("chainId is required (or provide chain for universal mode)", "INVALID_CHAIN_CONTEXT");
191
204
  }
192
205
  function constructVerificationMessage({ walletAddress, signedTimestamp, data, verifierIds, chainId, chain }) {
193
206
  if (!walletAddress || typeof walletAddress !== "string") {
@@ -202,28 +215,28 @@ function constructVerificationMessage({ walletAddress, signedTimestamp, data, ve
202
215
  if (!Array.isArray(verifierIds) || verifierIds.length === 0) {
203
216
  throw new SDKError("verifierIds is required and must be a non-empty array", "INVALID_VERIFIER_IDS");
204
217
  }
205
- const chainContext = typeof chain === "string" && chain.length > 0 ? chain : chainId;
206
- if (!chainContext) {
218
+ if ((typeof chain !== "string" || !chain.length) && !(typeof chainId === "number" && chainId > 0)) {
207
219
  throw new SDKError("chainId is required (or provide chain for universal mode)", "INVALID_CHAIN_CONTEXT");
208
220
  }
209
- if (chainContext === chainId && typeof chainId !== "number") {
210
- throw new SDKError("chainId must be a number when provided", "INVALID_CHAIN_ID");
211
- }
212
- if (chainContext === chain && (typeof chain !== "string" || !chain.includes(":"))) {
221
+ if (typeof chain === "string" && chain.length > 0 && !chain.includes(":")) {
213
222
  throw new SDKError('chain must be a "namespace:reference" string', "INVALID_CHAIN");
214
223
  }
224
+ if ((!chain || !chain.length) && typeof chainId !== "number") {
225
+ throw new SDKError("chainId must be a number when provided", "INVALID_CHAIN_ID");
226
+ }
227
+ const chainLine = chainLineForPortableProofSigner(chain, chainId);
215
228
  const namespace = typeof chain === "string" && chain.includes(":") ? chain.split(":")[0] : "eip155";
216
229
  const normalizedWalletAddress = namespace === "eip155" ? walletAddress.toLowerCase() : walletAddress;
217
230
  const dataString = deterministicStringify(data);
218
231
  const messageComponents = [
219
- "NEUS Verification Request",
232
+ PORTABLE_PROOF_SIGNER_HEADER,
220
233
  `Wallet: ${normalizedWalletAddress}`,
221
- `Chain: ${chainContext}`,
234
+ `Chain: ${chainLine}`,
222
235
  `Verifiers: ${verifierIds.join(",")}`,
223
236
  `Data: ${dataString}`,
224
237
  `Timestamp: ${signedTimestamp}`
225
238
  ];
226
- return messageComponents.join("\n");
239
+ return messageComponents.join("\n").normalize("NFC");
227
240
  }
228
241
  function validateWalletAddress(address) {
229
242
  if (!address || typeof address !== "string") {
@@ -232,17 +245,13 @@ function validateWalletAddress(address) {
232
245
  return /^0x[a-fA-F0-9]{40}$/.test(address);
233
246
  }
234
247
  function validateUniversalAddress(address, chain) {
235
- if (!address || typeof address !== "string")
236
- return false;
248
+ if (!address || typeof address !== "string") return false;
237
249
  const value = address.trim();
238
- if (!value)
239
- return false;
250
+ if (!value) return false;
240
251
  const chainRef = typeof chain === "string" ? chain.trim().toLowerCase() : "";
241
252
  const namespace = chainRef.includes(":") ? chainRef.split(":")[0] : "";
242
- if (validateWalletAddress(value))
243
- return true;
244
- if (namespace === "eip155")
245
- return false;
253
+ if (validateWalletAddress(value)) return true;
254
+ if (namespace === "eip155") return false;
246
255
  if (namespace === "solana") {
247
256
  return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(value);
248
257
  }
@@ -271,34 +280,27 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
271
280
  const chainStr = typeof chain === "string" && chain.trim().length > 0 ? chain.trim() : "eip155";
272
281
  const namespace = chainStr.includes(":") ? chainStr.split(":")[0] || "eip155" : "eip155";
273
282
  const resolveAddress = async () => {
274
- if (typeof walletAddress === "string" && walletAddress.trim().length > 0)
275
- return walletAddress;
283
+ if (typeof walletAddress === "string" && walletAddress.trim().length > 0) return walletAddress;
276
284
  if (namespace === "solana") {
277
285
  if (resolvedProvider?.publicKey && typeof resolvedProvider.publicKey.toBase58 === "function") {
278
286
  const pk = resolvedProvider.publicKey.toBase58();
279
- if (typeof pk === "string" && pk)
280
- return pk;
287
+ if (typeof pk === "string" && pk) return pk;
281
288
  }
282
289
  if (typeof resolvedProvider.getAddress === "function") {
283
290
  const addr = await resolvedProvider.getAddress().catch(() => null);
284
- if (typeof addr === "string" && addr)
285
- return addr;
291
+ if (typeof addr === "string" && addr) return addr;
286
292
  }
287
- if (typeof resolvedProvider.address === "string" && resolvedProvider.address)
288
- return resolvedProvider.address;
293
+ if (typeof resolvedProvider.address === "string" && resolvedProvider.address) return resolvedProvider.address;
289
294
  return null;
290
295
  }
291
- if (typeof resolvedProvider.address === "string" && resolvedProvider.address)
292
- return resolvedProvider.address;
293
- if (typeof resolvedProvider.getAddress === "function")
294
- return await resolvedProvider.getAddress();
296
+ if (typeof resolvedProvider.address === "string" && resolvedProvider.address) return resolvedProvider.address;
297
+ if (typeof resolvedProvider.getAddress === "function") return resolvedProvider.getAddress();
295
298
  if (typeof resolvedProvider.request === "function") {
296
299
  let accounts = await resolvedProvider.request({ method: "eth_accounts" }).catch(() => []);
297
300
  if (!Array.isArray(accounts) || accounts.length === 0) {
298
301
  accounts = await resolvedProvider.request({ method: "eth_requestAccounts" }).catch(() => []);
299
302
  }
300
- if (Array.isArray(accounts) && accounts[0])
301
- return accounts[0];
303
+ if (Array.isArray(accounts) && accounts[0]) return accounts[0];
302
304
  }
303
305
  return null;
304
306
  };
@@ -306,16 +308,11 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
306
308
  if (typeof resolvedProvider.signMessage === "function") {
307
309
  const encoded = typeof msg === "string" ? new TextEncoder().encode(msg) : msg;
308
310
  const result = await resolvedProvider.signMessage(encoded);
309
- if (typeof result === "string" && result)
310
- return result;
311
- if (result instanceof Uint8Array)
312
- return encodeBase58Bytes(result);
313
- if (result instanceof ArrayBuffer)
314
- return encodeBase58Bytes(new Uint8Array(result));
315
- if (ArrayBuffer.isView(result))
316
- return encodeBase58Bytes(result);
317
- if (typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function" && Buffer.isBuffer(result))
318
- return encodeBase58Bytes(result);
311
+ if (typeof result === "string" && result) return result;
312
+ if (result instanceof Uint8Array) return encodeBase58Bytes(result);
313
+ if (result instanceof ArrayBuffer) return encodeBase58Bytes(new Uint8Array(result));
314
+ if (ArrayBuffer.isView(result)) return encodeBase58Bytes(result);
315
+ if (typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function" && Buffer.isBuffer(result)) return encodeBase58Bytes(result);
319
316
  }
320
317
  throw new SDKError("Non-EVM signing requires provider.signMessage", "SIGNER_UNAVAILABLE");
321
318
  }
@@ -324,16 +321,14 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
324
321
  let firstPersonalSignError = null;
325
322
  try {
326
323
  const sig = await resolvedProvider.request({ method: "personal_sign", params: [msg, address] });
327
- if (typeof sig === "string" && sig)
328
- return sig;
324
+ if (typeof sig === "string" && sig) return sig;
329
325
  } catch (error) {
330
326
  firstPersonalSignError = error;
331
327
  }
332
328
  let secondPersonalSignError = null;
333
329
  try {
334
330
  const sig = await resolvedProvider.request({ method: "personal_sign", params: [address, msg] });
335
- if (typeof sig === "string" && sig)
336
- return sig;
331
+ if (typeof sig === "string" && sig) return sig;
337
332
  } catch (error) {
338
333
  secondPersonalSignError = error;
339
334
  const signatureErrorMessage = String(
@@ -344,16 +339,14 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
344
339
  try {
345
340
  const hexMsg = toHexUtf8(msg);
346
341
  const sig = await resolvedProvider.request({ method: "personal_sign", params: [hexMsg, address] });
347
- if (typeof sig === "string" && sig)
348
- return sig;
342
+ if (typeof sig === "string" && sig) return sig;
349
343
  } catch {
350
344
  }
351
345
  }
352
346
  }
353
347
  try {
354
348
  const sig = await resolvedProvider.request({ method: "eth_sign", params: [address, msg] });
355
- if (typeof sig === "string" && sig)
356
- return sig;
349
+ if (typeof sig === "string" && sig) return sig;
357
350
  } catch {
358
351
  }
359
352
  if (secondPersonalSignError || firstPersonalSignError) {
@@ -366,13 +359,12 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
366
359
  }
367
360
  if (typeof resolvedProvider.signMessage === "function") {
368
361
  const result = await resolvedProvider.signMessage(msg);
369
- if (typeof result === "string" && result)
370
- return result;
362
+ if (typeof result === "string" && result) return result;
371
363
  }
372
364
  throw new SDKError("Unable to sign message with provided wallet/provider", "SIGNER_UNAVAILABLE");
373
365
  }
374
366
  var NEUS_CONSTANTS = {
375
- // Hub chain (where all verifications occur)
367
+ /** Default EVM chain id for NEUS protocol signing context (`HUB_CHAIN_ID` name kept for compatibility). */
376
368
  HUB_CHAIN_ID: 84532,
377
369
  // Supported target chains for cross-chain propagation
378
370
  TESTNET_CHAINS: [
@@ -402,27 +394,22 @@ var NEUS_CONSTANTS = {
402
394
  };
403
395
 
404
396
  // client.js
405
- var FALLBACK_PUBLIC_VERIFIERS = [
406
- "ownership-basic",
407
- "ownership-pseudonym",
408
- "ownership-dns-txt",
409
- "ownership-social",
410
- "ownership-org-oauth",
411
- "contract-ownership",
412
- "nft-ownership",
413
- "token-holding",
414
- "wallet-link",
415
- "wallet-risk",
416
- "proof-of-human",
417
- "agent-identity",
418
- "agent-delegation",
419
- "ai-content-moderation"
420
- ];
421
- var INTERACTIVE_VERIFIERS = /* @__PURE__ */ new Set([
422
- "ownership-social",
423
- "ownership-org-oauth",
424
- "proof-of-human"
425
- ]);
397
+ var FALLBACK_PUBLIC_VERIFIER_CATALOG = {
398
+ "ownership-basic": { supportsDirectApi: true },
399
+ "ownership-pseudonym": { supportsDirectApi: true },
400
+ "ownership-dns-txt": { supportsDirectApi: true },
401
+ "ownership-social": { supportsDirectApi: false },
402
+ "ownership-org-oauth": { supportsDirectApi: false },
403
+ "contract-ownership": { supportsDirectApi: true },
404
+ "nft-ownership": { supportsDirectApi: true },
405
+ "token-holding": { supportsDirectApi: true },
406
+ "wallet-link": { supportsDirectApi: true },
407
+ "wallet-risk": { supportsDirectApi: true },
408
+ "proof-of-human": { supportsDirectApi: false },
409
+ "agent-identity": { supportsDirectApi: true },
410
+ "agent-delegation": { supportsDirectApi: true },
411
+ "ai-content-moderation": { supportsDirectApi: true }
412
+ };
426
413
  var EVM_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
427
414
  var validateVerifierData = (verifierId, data) => {
428
415
  if (!data || typeof data !== "object") {
@@ -641,7 +628,10 @@ var validateVerifierData = (verifierId, data) => {
641
628
  const maxBytes = 50 * 1024;
642
629
  const bytes = typeof TextEncoder !== "undefined" ? new TextEncoder().encode(data.content).length : String(data.content).length;
643
630
  if (bytes > maxBytes) {
644
- return { valid: false, error: `content exceeds ${maxBytes} bytes limit for ai-content-moderation verifier (text)` };
631
+ return {
632
+ valid: false,
633
+ error: `content exceeds ${maxBytes} bytes limit for ai-content-moderation verifier (text)`
634
+ };
645
635
  }
646
636
  } catch {
647
637
  }
@@ -700,20 +690,15 @@ var NeusClient = class {
700
690
  if (typeof this.config.appId === "string" && this.config.appId.trim().length > 0) {
701
691
  this.defaultHeaders["X-Neus-App"] = this.config.appId.trim();
702
692
  }
703
- if (typeof this.config.sponsorGrant === "string" && this.config.sponsorGrant.trim().length > 0) {
704
- this.defaultHeaders["X-Sponsor-Grant"] = this.config.sponsorGrant.trim();
705
- }
706
693
  if (typeof this.config.paymentSignature === "string" && this.config.paymentSignature.trim().length > 0) {
707
694
  this.defaultHeaders["PAYMENT-SIGNATURE"] = this.config.paymentSignature.trim();
708
695
  }
709
696
  if (this.config.extraHeaders && typeof this.config.extraHeaders === "object") {
710
697
  for (const [k, v] of Object.entries(this.config.extraHeaders)) {
711
- if (!k || v === void 0 || v === null)
712
- continue;
698
+ if (!k || v === void 0 || v === null) continue;
713
699
  const key = String(k).trim();
714
700
  const value = String(v).trim();
715
- if (!key || !value)
716
- continue;
701
+ if (!key || !value) continue;
717
702
  this.defaultHeaders[key] = value;
718
703
  }
719
704
  }
@@ -726,14 +711,12 @@ var NeusClient = class {
726
711
  }
727
712
  _getHubChainId() {
728
713
  const configured = Number(this.config?.hubChainId);
729
- if (Number.isFinite(configured) && configured > 0)
730
- return Math.floor(configured);
714
+ if (Number.isFinite(configured) && configured > 0) return Math.floor(configured);
731
715
  return NEUS_CONSTANTS.HUB_CHAIN_ID;
732
716
  }
733
717
  _normalizeIdentity(value) {
734
718
  let raw = String(value || "").trim();
735
- if (!raw)
736
- return "";
719
+ if (!raw) return "";
737
720
  const didMatch = raw.match(/^did:pkh:([^:]+):([^:]+):(.+)$/i);
738
721
  if (didMatch && didMatch[3]) {
739
722
  raw = String(didMatch[3]).trim();
@@ -741,8 +724,7 @@ var NeusClient = class {
741
724
  return EVM_ADDRESS_RE.test(raw) ? raw.toLowerCase() : raw;
742
725
  }
743
726
  _inferChainForAddress(address, explicitChain) {
744
- if (typeof explicitChain === "string" && explicitChain.includes(":"))
745
- return explicitChain.trim();
727
+ if (typeof explicitChain === "string" && explicitChain.includes(":")) return explicitChain.trim();
746
728
  const raw = String(address || "").trim();
747
729
  const didMatch = raw.match(/^did:pkh:([^:]+):([^:]+):(.+)$/i);
748
730
  if (didMatch && didMatch[1] && didMatch[2]) {
@@ -781,8 +763,7 @@ var NeusClient = class {
781
763
  throw new ConfigurationError("Invalid wallet provider");
782
764
  }
783
765
  _getDefaultBrowserWallet() {
784
- if (typeof window === "undefined")
785
- return null;
766
+ if (typeof window === "undefined") return null;
786
767
  return window.ethereum || window.solana || window.phantom && window.phantom.solana || null;
787
768
  }
788
769
  async _buildPrivateGateAuth({ address, wallet, chain, signatureMethod } = {}) {
@@ -840,80 +821,66 @@ var NeusClient = class {
840
821
  signatureMethod: params.signatureMethod
841
822
  });
842
823
  }
843
- // ============================================================================
844
- // CORE VERIFICATION METHODS
845
- // ============================================================================
846
824
  /**
847
- * VERIFY - Standard verification (auto or manual)
848
- *
849
- * Create proofs with complete control over the verification process.
850
- * If signature and walletAddress are omitted but verifier/content are provided,
851
- * this method performs the wallet flow inline (no aliases, no secondary methods).
852
- *
825
+ * Create a verification proof.
826
+ *
827
+ * Supports two paths:
828
+ * - **Auto:** Supply `verifier`, `content`, and/or `data` with an optional
829
+ * `wallet` provider. The SDK performs signing in the client.
830
+ * - **Manual:** Supply pre-signed `verifierIds`, `data`, `walletAddress`,
831
+ * `signature`, and `signedTimestamp`.
832
+ *
853
833
  * @param {Object} params - Verification parameters
834
+ * @param {string} [params.verifier] - Verifier ID (auto path, e.g. 'ownership-basic')
835
+ * @param {string} [params.content] - Content to verify (auto path)
836
+ * @param {Object} [params.data] - Structured verification data
837
+ * @param {Object} [params.wallet] - Wallet provider (auto path)
838
+ * @param {Object} [params.options] - Additional options
854
839
  * @param {Array<string>} [params.verifierIds] - Array of verifier IDs (manual path)
855
- * @param {Object} [params.data] - Verification data object (manual path)
856
840
  * @param {string} [params.walletAddress] - Wallet address that signed the request (manual path)
857
841
  * @param {string} [params.signature] - EIP-191 signature (manual path)
858
842
  * @param {number} [params.signedTimestamp] - Unix timestamp when signature was created (manual path)
859
- * @param {number} [params.chainId] - Chain ID for verification context (optional, managed by protocol)
860
- * @param {Object} [params.options] - Additional options
861
- * @param {string} [params.verifier] - Verifier ID (auto path)
862
- * @param {string} [params.content] - Content/description (auto path)
863
- * @param {Object} [params.wallet] - Optional injected wallet/provider (auto path)
864
- * @returns {Promise<Object>} Verification result with proofId (qHash is a deprecated alias)
865
- *
843
+ * @param {number} [params.chainId] - EVM signing-context hint; when omitted, resolved to the NEUS protocol primary chain for signing
844
+ * @returns {Promise<Object>} Verification result with proofId
845
+ *
846
+ * @example
847
+ * // Auto path
848
+ * const proof = await client.verify({
849
+ * verifier: 'ownership-basic',
850
+ * content: 'Hello World',
851
+ * wallet: window.ethereum
852
+ * });
853
+ *
866
854
  * @example
855
+ * // Manual path
867
856
  * const proof = await client.verify({
868
857
  * verifierIds: ['ownership-basic'],
869
- * data: {
870
- * content: "My content",
871
- * owner: walletAddress, // or ownerAddress for nft-ownership/token-holding
872
- * reference: { type: 'other', id: 'my-unique-identifier' }
873
- * },
858
+ * data: { content: "My content", owner: walletAddress },
874
859
  * walletAddress: '0x...',
875
860
  * signature: '0x...',
876
861
  * signedTimestamp: Date.now(),
877
862
  * options: { targetChains: [421614, 11155111] }
878
863
  * });
879
864
  */
880
- /**
881
- * Create a verification proof
882
- *
883
- * @param {Object} params - Verification parameters
884
- * @param {string} [params.verifier] - Verifier ID (e.g., 'ownership-basic')
885
- * @param {string} [params.content] - Content to verify
886
- * @param {Object} [params.data] - Structured verification data
887
- * @param {Object} [params.wallet] - Wallet provider
888
- * @param {Object} [params.options] - Additional options
889
- * @returns {Promise<Object>} Verification result with proofId (qHash is a deprecated alias)
890
- *
891
- * @example
892
- * // Simple ownership proof
893
- * const proof = await client.verify({
894
- * verifier: 'ownership-basic',
895
- * content: 'Hello World',
896
- * wallet: window.ethereum
897
- * });
898
- */
899
865
  async verify(params) {
900
866
  if ((!params?.signature || !params?.walletAddress) && (params?.verifier || params?.content || params?.data)) {
901
867
  const { content, verifier = "ownership-basic", data: data2 = null, wallet = null, options: options2 = {} } = params;
902
868
  if (verifier === "ownership-basic" && !data2 && (!content || typeof content !== "string")) {
903
869
  throw new ValidationError("content is required and must be a string (or use data param with owner + reference)");
904
870
  }
905
- let validVerifiers = FALLBACK_PUBLIC_VERIFIERS;
871
+ let verifierCatalog = FALLBACK_PUBLIC_VERIFIER_CATALOG;
906
872
  try {
907
- const discovered = await this.getVerifiers();
908
- if (Array.isArray(discovered) && discovered.length > 0) {
909
- validVerifiers = discovered;
873
+ const discovered = await this.getVerifierCatalog();
874
+ if (discovered && discovered.metadata && Object.keys(discovered.metadata).length > 0) {
875
+ verifierCatalog = discovered.metadata;
910
876
  }
911
877
  } catch {
912
878
  }
879
+ const validVerifiers = Object.keys(verifierCatalog);
913
880
  if (!validVerifiers.includes(verifier)) {
914
881
  throw new ValidationError(`Invalid verifier '${verifier}'. Must be one of: ${validVerifiers.join(", ")}.`);
915
882
  }
916
- if (INTERACTIVE_VERIFIERS.has(verifier)) {
883
+ if (verifierCatalog?.[verifier]?.supportsDirectApi === false) {
917
884
  const hostedCheckoutUrl = options2?.hostedCheckoutUrl || "https://neus.network/verify";
918
885
  throw new ValidationError(
919
886
  `${verifier} requires hosted interactive checkout. Use VerifyGate or redirect to ${hostedCheckoutUrl}.`
@@ -1054,7 +1021,10 @@ var NeusClient = class {
1054
1021
  ...data2?.agentLabel && { agentLabel: data2.agentLabel },
1055
1022
  ...data2?.agentType && { agentType: data2.agentType },
1056
1023
  ...data2?.description && { description: data2.description },
1057
- ...data2?.capabilities && { capabilities: data2.capabilities }
1024
+ ...data2?.capabilities && { capabilities: data2.capabilities },
1025
+ ...data2?.instructions && { instructions: data2.instructions },
1026
+ ...data2?.skills && { skills: data2.skills },
1027
+ ...data2?.services && { services: data2.services }
1058
1028
  };
1059
1029
  } else if (verifier === "agent-delegation") {
1060
1030
  if (!data2?.agentWallet) {
@@ -1067,7 +1037,11 @@ var NeusClient = class {
1067
1037
  ...data2?.scope && { scope: data2.scope },
1068
1038
  ...data2?.permissions && { permissions: data2.permissions },
1069
1039
  ...data2?.maxSpend && { maxSpend: data2.maxSpend },
1070
- ...data2?.expiresAt && { expiresAt: data2.expiresAt }
1040
+ ...data2?.allowedPaymentTypes && { allowedPaymentTypes: data2.allowedPaymentTypes },
1041
+ ...data2?.receiptDisclosure && { receiptDisclosure: data2.receiptDisclosure },
1042
+ ...data2?.expiresAt && { expiresAt: data2.expiresAt },
1043
+ ...data2?.instructions && { instructions: data2.instructions },
1044
+ ...data2?.skills && { skills: data2.skills }
1071
1045
  };
1072
1046
  } else if (verifier === "ai-content-moderation") {
1073
1047
  if (!data2?.content) {
@@ -1127,31 +1101,24 @@ var NeusClient = class {
1127
1101
  const enc = new TextEncoder();
1128
1102
  const bytes = enc.encode(s);
1129
1103
  let hex = "0x";
1130
- for (let i = 0; i < bytes.length; i++)
1131
- hex += bytes[i].toString(16).padStart(2, "0");
1104
+ for (let i = 0; i < bytes.length; i++) hex += bytes[i].toString(16).padStart(2, "0");
1132
1105
  return hex;
1133
1106
  } catch {
1134
1107
  let hex = "0x";
1135
- for (let i = 0; i < s.length; i++)
1136
- hex += s.charCodeAt(i).toString(16).padStart(2, "0");
1108
+ for (let i = 0; i < s.length; i++) hex += s.charCodeAt(i).toString(16).padStart(2, "0");
1137
1109
  return hex;
1138
1110
  }
1139
1111
  };
1140
1112
  const isFarcasterWallet = (() => {
1141
- if (typeof window === "undefined")
1142
- return false;
1113
+ if (typeof window === "undefined") return false;
1143
1114
  try {
1144
1115
  const w = window;
1145
1116
  const fc = w.farcaster;
1146
- if (!fc || !fc.context)
1147
- return false;
1117
+ if (!fc || !fc.context) return false;
1148
1118
  const fcProvider = fc.provider || fc.walletProvider || fc.context && fc.context.walletProvider;
1149
- if (fcProvider === provider)
1150
- return true;
1151
- if (w.mini && w.mini.wallet === provider && fc && fc.context)
1152
- return true;
1153
- if (w.ethereum === provider && fc && fc.context)
1154
- return true;
1119
+ if (fcProvider === provider) return true;
1120
+ if (w.mini && w.mini.wallet === provider && fc && fc.context) return true;
1121
+ if (w.ethereum === provider && fc && fc.context) return true;
1155
1122
  } catch {
1156
1123
  }
1157
1124
  return false;
@@ -1170,7 +1137,8 @@ var NeusClient = class {
1170
1137
  const msg = String(e && (e.message || e.reason) || e || "").toLowerCase();
1171
1138
  const errCode = e && (e.code || e.error && e.error.code) || null;
1172
1139
  const needsHex = /byte|bytes|invalid byte sequence|encoding|non-hex/i.test(msg);
1173
- const methodUnsupported = /method.*not.*supported|unsupported|not implemented|method not found|unknown method|does not support/i.test(msg) || errCode === -32601 || errCode === 4200 || msg.includes("personal_sign") && msg.includes("not") || msg.includes("request method") && msg.includes("not supported");
1140
+ const unsupportedRe = /method.*not.*supported|unsupported|not implemented|method not found|unknown method|does not support/i;
1141
+ const methodUnsupported = unsupportedRe.test(msg) || errCode === -32601 || errCode === 4200 || msg.includes("personal_sign") && msg.includes("not") || msg.includes("request method") && msg.includes("not supported");
1174
1142
  if (methodUnsupported) {
1175
1143
  this._log("personal_sign not supported; attempting eth_sign fallback");
1176
1144
  try {
@@ -1179,28 +1147,23 @@ var NeusClient = class {
1179
1147
  const prefix = `Ethereum Signed Message:
1180
1148
  ${bytes.length}`;
1181
1149
  const full = new Uint8Array(prefix.length + bytes.length);
1182
- for (let i = 0; i < prefix.length; i++)
1183
- full[i] = prefix.charCodeAt(i);
1150
+ for (let i = 0; i < prefix.length; i++) full[i] = prefix.charCodeAt(i);
1184
1151
  full.set(bytes, prefix.length);
1185
1152
  let payloadHex = "0x";
1186
- for (let i = 0; i < full.length; i++)
1187
- payloadHex += full[i].toString(16).padStart(2, "0");
1153
+ for (let i = 0; i < full.length; i++) payloadHex += full[i].toString(16).padStart(2, "0");
1188
1154
  try {
1189
- if (typeof window !== "undefined")
1190
- window.__NEUS_ALLOW_ETH_SIGN__ = true;
1155
+ if (typeof window !== "undefined") window.__NEUS_ALLOW_ETH_SIGN__ = true;
1191
1156
  } catch {
1192
1157
  }
1193
1158
  signature2 = await provider.request({ method: "eth_sign", params: [walletAddress2, payloadHex], neusAllowEthSign: true });
1194
1159
  try {
1195
- if (typeof window !== "undefined")
1196
- delete window.__NEUS_ALLOW_ETH_SIGN__;
1160
+ if (typeof window !== "undefined") delete window.__NEUS_ALLOW_ETH_SIGN__;
1197
1161
  } catch {
1198
1162
  }
1199
1163
  } catch (fallbackErr) {
1200
1164
  this._log("eth_sign fallback failed", { message: fallbackErr?.message || String(fallbackErr) });
1201
1165
  try {
1202
- if (typeof window !== "undefined")
1203
- delete window.__NEUS_ALLOW_ETH_SIGN__;
1166
+ if (typeof window !== "undefined") delete window.__NEUS_ALLOW_ETH_SIGN__;
1204
1167
  } catch {
1205
1168
  }
1206
1169
  throw e;
@@ -1242,8 +1205,7 @@ ${bytes.length}`;
1242
1205
  } = params;
1243
1206
  const resolvedChainId = chainId || (chain ? null : NEUS_CONSTANTS.HUB_CHAIN_ID);
1244
1207
  const normalizeVerifierId = (id) => {
1245
- if (typeof id !== "string")
1246
- return id;
1208
+ if (typeof id !== "string") return id;
1247
1209
  const match = id.match(/^(.*)@\d+$/);
1248
1210
  return match ? match[1] : id;
1249
1211
  };
@@ -1278,10 +1240,9 @@ ${bytes.length}`;
1278
1240
  // Privacy and storage options (defaults)
1279
1241
  privacyLevel: options?.privacyLevel || "private",
1280
1242
  publicDisplay: options?.publicDisplay || false,
1281
- storeOriginalContent: options?.storeOriginalContent || false
1243
+ storeOriginalContent: typeof options?.storeOriginalContent === "boolean" ? options.storeOriginalContent : true
1282
1244
  };
1283
- if (typeof options?.enableIpfs === "boolean")
1284
- optionsPayload.enableIpfs = options.enableIpfs;
1245
+ if (typeof options?.enableIpfs === "boolean") optionsPayload.enableIpfs = options.enableIpfs;
1285
1246
  const requestData = {
1286
1247
  verifierIds: normalizedVerifierIds,
1287
1248
  data,
@@ -1299,41 +1260,37 @@ ${bytes.length}`;
1299
1260
  }
1300
1261
  return this._formatResponse(response);
1301
1262
  }
1302
- // ============================================================================
1303
- // STATUS AND UTILITY METHODS
1304
- // ============================================================================
1305
1263
  /**
1306
- * Get verification status
1264
+ * Get proof record by proof receipt id.
1307
1265
  *
1308
- * @param {string} proofId - Proof ID (standard). `qHash` is a deprecated alias (same value).
1309
- * @returns {Promise<Object>} Verification status and data
1266
+ * @param {string} proofId - Proof receipt ID (0x + 64 hex).
1267
+ * @returns {Promise<Object>} Proof record and verification state
1310
1268
  *
1311
1269
  * @example
1312
- * const result = await client.getStatus('0x...');
1270
+ * const result = await client.getProof('0x...');
1313
1271
  * console.log('Status:', result.status);
1314
1272
  */
1315
- async getStatus(proofId) {
1273
+ async getProof(proofId) {
1316
1274
  if (!proofId || typeof proofId !== "string") {
1317
1275
  throw new ValidationError("proofId is required");
1318
1276
  }
1319
- const response = await this._makeRequest("GET", `/api/v1/verification/status/${proofId}`);
1277
+ const response = await this._makeRequest("GET", `/api/v1/proofs/${proofId}`);
1320
1278
  if (!response.success) {
1321
- throw new ApiError(`Failed to get status: ${response.error?.message || "Unknown error"}`, response.error);
1279
+ throw new ApiError(`Failed to get proof: ${response.error?.message || "Unknown error"}`, response.error);
1322
1280
  }
1323
1281
  return this._formatResponse(response);
1324
1282
  }
1325
1283
  /**
1326
- * Get private proof status with wallet signature
1284
+ * Get private proof record with wallet signature
1327
1285
  *
1328
- * @param {string} proofId - Proof ID (standard). `qHash` is a deprecated alias (same value).
1286
+ * @param {string} proofId - Proof receipt ID.
1329
1287
  * @param {Object} wallet - Wallet provider (window.ethereum or ethers Wallet)
1330
- * @returns {Promise<Object>} Private verification status and data
1288
+ * @returns {Promise<Object>} Private proof record and verification state
1331
1289
  *
1332
1290
  * @example
1333
- * // Access private proof
1334
- * const privateData = await client.getPrivateStatus(proofId, window.ethereum);
1291
+ * const privateData = await client.getPrivateProof(proofId, window.ethereum);
1335
1292
  */
1336
- async getPrivateStatus(proofId, wallet = null) {
1293
+ async getPrivateProof(proofId, wallet = null) {
1337
1294
  if (!proofId || typeof proofId !== "string") {
1338
1295
  throw new ValidationError("proofId is required");
1339
1296
  }
@@ -1347,7 +1304,7 @@ ${bytes.length}`;
1347
1304
  ...typeof auth.chain === "string" && auth.chain.trim() ? { "x-chain": auth.chain.trim() } : {},
1348
1305
  ...typeof auth.signatureMethod === "string" && auth.signatureMethod.trim() ? { "x-signature-method": auth.signatureMethod.trim() } : {}
1349
1306
  };
1350
- const response2 = await this._makeRequest("GET", `/api/v1/verification/status/${proofId}`, null, headers);
1307
+ const response2 = await this._makeRequest("GET", `/api/v1/proofs/${proofId}`, null, headers);
1351
1308
  if (!response2.success) {
1352
1309
  throw new ApiError(
1353
1310
  `Failed to access private proof: ${response2.error?.message || "Unauthorized"}`,
@@ -1386,7 +1343,7 @@ ${bytes.length}`;
1386
1343
  }
1387
1344
  throw new ValidationError(`Failed to sign message: ${error.message}`);
1388
1345
  }
1389
- const response = await this._makeRequest("GET", `/api/v1/verification/status/${proofId}`, null, {
1346
+ const response = await this._makeRequest("GET", `/api/v1/proofs/${proofId}`, null, {
1390
1347
  "x-wallet-address": walletAddress,
1391
1348
  "x-signature": signature,
1392
1349
  "x-signed-timestamp": signedTimestamp.toString(),
@@ -1419,25 +1376,37 @@ ${bytes.length}`;
1419
1376
  * @returns {Promise<string[]>} Array of verifier IDs
1420
1377
  */
1421
1378
  async getVerifiers() {
1379
+ const catalog = await this.getVerifierCatalog();
1380
+ return Array.isArray(catalog?.data) ? catalog.data : [];
1381
+ }
1382
+ /**
1383
+ * Get the public verifier catalog with per-verifier capabilities.
1384
+ * @returns {Promise<{data: string[], metadata: Record<string, { supportsDirectApi?: boolean }>, meta?: object}>}
1385
+ */
1386
+ async getVerifierCatalog() {
1422
1387
  const response = await this._makeRequest("GET", "/api/v1/verification/verifiers");
1423
1388
  if (!response.success) {
1424
1389
  throw new ApiError(`Failed to get verifiers: ${response.error?.message || "Unknown error"}`, response.error);
1425
1390
  }
1426
- return Array.isArray(response.data) ? response.data : [];
1391
+ return {
1392
+ data: Array.isArray(response.data) ? response.data : [],
1393
+ metadata: response.metadata && typeof response.metadata === "object" && !Array.isArray(response.metadata) ? response.metadata : {},
1394
+ meta: response.meta && typeof response.meta === "object" && !Array.isArray(response.meta) ? response.meta : {}
1395
+ };
1427
1396
  }
1428
1397
  /**
1429
1398
  * POLL PROOF STATUS - Wait for verification completion
1430
- *
1399
+ *
1431
1400
  * Polls the verification status until it reaches a terminal state (completed or failed).
1432
1401
  * Useful for providing real-time feedback to users during verification.
1433
- *
1434
- * @param {string} proofId - Proof ID to poll (standard). `qHash` is a deprecated alias (same value).
1402
+ *
1403
+ * @param {string} proofId - Proof ID to poll.
1435
1404
  * @param {Object} [options] - Polling options
1436
1405
  * @param {number} [options.interval=5000] - Polling interval in ms
1437
1406
  * @param {number} [options.timeout=120000] - Total timeout in ms
1438
1407
  * @param {Function} [options.onProgress] - Progress callback function
1439
1408
  * @returns {Promise<Object>} Final verification status
1440
- *
1409
+ *
1441
1410
  * @example
1442
1411
  * const finalStatus = await client.pollProofStatus(proofId, {
1443
1412
  * interval: 3000,
@@ -1463,7 +1432,7 @@ ${bytes.length}`;
1463
1432
  let consecutiveRateLimits = 0;
1464
1433
  while (Date.now() - startTime < timeout) {
1465
1434
  try {
1466
- const status = await this.getStatus(proofId);
1435
+ const status = await this.getProof(proofId);
1467
1436
  consecutiveRateLimits = 0;
1468
1437
  if (onProgress && typeof onProgress === "function") {
1469
1438
  onProgress(status.data || status);
@@ -1496,7 +1465,7 @@ ${bytes.length}`;
1496
1465
  }
1497
1466
  /**
1498
1467
  * DETECT CHAIN ID - Get current wallet chain
1499
- *
1468
+ *
1500
1469
  * @returns {Promise<number>} Current chain ID
1501
1470
  */
1502
1471
  async detectChainId() {
@@ -1527,7 +1496,6 @@ ${bytes.length}`;
1527
1496
  const message = constructVerificationMessage({
1528
1497
  walletAddress: address,
1529
1498
  signedTimestamp,
1530
- // Keep wire payload key `qHash` for backwards compatibility.
1531
1499
  data: { action: "revoke_proof", qHash: proofId },
1532
1500
  verifierIds: ["ownership-basic"],
1533
1501
  ...signerIsEvm ? { chainId: this._getHubChainId() } : { chain }
@@ -1546,9 +1514,8 @@ ${bytes.length}`;
1546
1514
  }
1547
1515
  throw new ValidationError(`Failed to sign revocation: ${error.message}`);
1548
1516
  }
1549
- const res = await fetch(`${this.config.apiUrl}/api/v1/proofs/${proofId}/revoke-self`, {
1517
+ const res = await fetch(`${this.config.apiUrl}/api/v1/proofs/revoke-self/${proofId}`, {
1550
1518
  method: "POST",
1551
- // SECURITY: Do not put proof signatures into Authorization headers.
1552
1519
  headers: { "Content-Type": "application/json" },
1553
1520
  body: JSON.stringify({
1554
1521
  walletAddress: address,
@@ -1563,18 +1530,16 @@ ${bytes.length}`;
1563
1530
  }
1564
1531
  return true;
1565
1532
  }
1566
- // ============================================================================
1567
- // PROOFS & GATING METHODS
1568
- // ============================================================================
1569
1533
  /**
1570
1534
  * GET PROOFS BY WALLET - Fetch proofs for a wallet address
1571
- *
1535
+ *
1572
1536
  * @param {string} walletAddress - Wallet identity (EVM/Solana/DID)
1573
1537
  * @param {Object} [options] - Filter options
1574
1538
  * @param {number} [options.limit] - Max results (default: 50; higher limits require owner access)
1575
1539
  * @param {number} [options.offset] - Pagination offset (default: 0)
1540
+ * @param {string} [options.qHash] - Filter to single proof by qHash
1576
1541
  * @returns {Promise<Object>} Proofs result
1577
- *
1542
+ *
1578
1543
  * @example
1579
1544
  * const result = await client.getProofsByWallet('0x...', {
1580
1545
  * limit: 50,
@@ -1588,14 +1553,13 @@ ${bytes.length}`;
1588
1553
  const id = walletAddress.trim();
1589
1554
  const pathId = /^0x[a-fA-F0-9]{40}$/i.test(id) ? id.toLowerCase() : id;
1590
1555
  const qs = [];
1591
- if (options.limit)
1592
- qs.push(`limit=${encodeURIComponent(String(options.limit))}`);
1593
- if (options.offset)
1594
- qs.push(`offset=${encodeURIComponent(String(options.offset))}`);
1556
+ if (options.limit) qs.push(`limit=${encodeURIComponent(String(options.limit))}`);
1557
+ if (options.offset) qs.push(`offset=${encodeURIComponent(String(options.offset))}`);
1558
+ if (options.qHash) qs.push(`qHash=${encodeURIComponent(options.qHash.toLowerCase())}`);
1595
1559
  const query = qs.length ? `?${qs.join("&")}` : "";
1596
1560
  const response = await this._makeRequest(
1597
1561
  "GET",
1598
- `/api/v1/proofs/byWallet/${encodeURIComponent(pathId)}${query}`
1562
+ `/api/v1/proofs/by-wallet/${encodeURIComponent(pathId)}${query}`
1599
1563
  );
1600
1564
  if (!response.success) {
1601
1565
  throw new ApiError(`Failed to get proofs: ${response.error?.message || "Unknown error"}`, response.error);
@@ -1618,6 +1582,7 @@ ${bytes.length}`;
1618
1582
  * @param {Object} [options]
1619
1583
  * @param {number} [options.limit] - Max results (server enforces caps)
1620
1584
  * @param {number} [options.offset] - Pagination offset
1585
+ * @param {string} [options.qHash] - Filter to single proof by qHash
1621
1586
  * @param {Object} [wallet] - Optional injected wallet/provider (MetaMask/ethers Wallet)
1622
1587
  */
1623
1588
  async getPrivateProofsByWallet(walletAddress, options = {}, wallet = null) {
@@ -1668,12 +1633,11 @@ ${bytes.length}`;
1668
1633
  throw new ValidationError(`Failed to sign message: ${error.message}`);
1669
1634
  }
1670
1635
  const qs = [];
1671
- if (options.limit)
1672
- qs.push(`limit=${encodeURIComponent(String(options.limit))}`);
1673
- if (options.offset)
1674
- qs.push(`offset=${encodeURIComponent(String(options.offset))}`);
1636
+ if (options.limit) qs.push(`limit=${encodeURIComponent(String(options.limit))}`);
1637
+ if (options.offset) qs.push(`offset=${encodeURIComponent(String(options.offset))}`);
1638
+ if (options.qHash) qs.push(`qHash=${encodeURIComponent(options.qHash.toLowerCase())}`);
1675
1639
  const query = qs.length ? `?${qs.join("&")}` : "";
1676
- const response = await this._makeRequest("GET", `/api/v1/proofs/byWallet/${encodeURIComponent(pathId)}${query}`, null, {
1640
+ const response = await this._makeRequest("GET", `/api/v1/proofs/by-wallet/${encodeURIComponent(pathId)}${query}`, null, {
1677
1641
  "x-wallet-address": signerWalletAddress,
1678
1642
  "x-signature": signature,
1679
1643
  "x-signed-timestamp": signedTimestamp.toString(),
@@ -1692,16 +1656,16 @@ ${bytes.length}`;
1692
1656
  };
1693
1657
  }
1694
1658
  /**
1695
- * GATE CHECK (API) - Minimal eligibility check
1659
+ * Gate check (HTTP API) minimal eligibility response.
1696
1660
  *
1697
1661
  * Calls the gate endpoint and returns a **minimal** yes/no response.
1698
- * By default this checks **public + discoverable** proofs only.
1662
+ * By default this checks **public + unlisted** proofs.
1699
1663
  *
1700
1664
  * When `includePrivate=true`, this can perform owner-signed private checks
1701
1665
  * (no full proof payloads returned) by providing a wallet/provider.
1702
1666
  *
1703
- * Prefer this over `checkGate()` for integrations that want the
1704
- * smallest, most stable surface area (and do NOT need full proof payloads).
1667
+ * Prefer this over `checkGate()` when you need the smallest, most stable
1668
+ * response shape and do not need full proof payloads.
1705
1669
  *
1706
1670
  * @param {Object} params - Gate check query params
1707
1671
  * @param {string} params.address - Wallet identity to check (EVM/Solana/DID)
@@ -1724,25 +1688,20 @@ ${bytes.length}`;
1724
1688
  const qs = new URLSearchParams();
1725
1689
  qs.set("address", address);
1726
1690
  const setIfPresent = (key, value) => {
1727
- if (value === void 0 || value === null)
1728
- return;
1691
+ if (value === void 0 || value === null) return;
1729
1692
  const str = typeof value === "string" ? value : String(value);
1730
- if (str.length === 0)
1731
- return;
1693
+ if (str.length === 0) return;
1732
1694
  qs.set(key, str);
1733
1695
  };
1734
1696
  const setBoolIfPresent = (key, value) => {
1735
- if (value === void 0 || value === null)
1736
- return;
1697
+ if (value === void 0 || value === null) return;
1737
1698
  qs.set(key, value ? "true" : "false");
1738
1699
  };
1739
1700
  const setCsvIfPresent = (key, value) => {
1740
- if (value === void 0 || value === null)
1741
- return;
1701
+ if (value === void 0 || value === null) return;
1742
1702
  if (Array.isArray(value)) {
1743
1703
  const items = value.map((v) => String(v).trim()).filter(Boolean);
1744
- if (items.length)
1745
- qs.set(key, items.join(","));
1704
+ if (items.length) qs.set(key, items.join(","));
1746
1705
  return;
1747
1706
  }
1748
1707
  setIfPresent(key, value);
@@ -1768,6 +1727,8 @@ ${bytes.length}`;
1768
1727
  setIfPresent("domain", params.domain);
1769
1728
  setIfPresent("minBalance", params.minBalance);
1770
1729
  setIfPresent("provider", params.provider);
1730
+ setIfPresent("handle", params.handle);
1731
+ setIfPresent("namespace", params.namespace);
1771
1732
  setIfPresent("ownerAddress", params.ownerAddress);
1772
1733
  setIfPresent("riskLevel", params.riskLevel);
1773
1734
  setBoolIfPresent("sanctioned", params.sanctioned);
@@ -1815,11 +1776,17 @@ ${bytes.length}`;
1815
1776
  return response;
1816
1777
  }
1817
1778
  /**
1818
- * CHECK GATE - Evaluate requirements against existing proofs
1819
- *
1779
+ * CHECK GATE Local preview against proofs you already have in memory or from `getProofsByWallet`.
1780
+ *
1781
+ * **Not authoritative for access control.** For production allow/deny, use {@link NeusClient#gateCheck}
1782
+ * (`GET /api/v1/proofs/check`), which applies the same rules as the NEUS API. This method is useful for
1783
+ * UI previews, offline-ish flows, or when you already fetched proofs and want a quick match without
1784
+ * another round trip — but it can disagree with the server (e.g. `contentHash` matching uses a local
1785
+ * approximation when proof data only has inline `content`; the API uses the standard server-side hash).
1786
+ *
1820
1787
  * Gate-first verification: checks if wallet has valid proofs satisfying requirements.
1821
1788
  * Returns which requirements are missing/expired.
1822
- *
1789
+ *
1823
1790
  * @param {Object} params - Gate check parameters
1824
1791
  * @param {string} params.walletAddress - Target wallet
1825
1792
  * @param {Array<Object>} params.requirements - Array of gate requirements
@@ -1837,7 +1804,7 @@ ${bytes.length}`;
1837
1804
  * Note: contentHash matching uses approximation in SDK; for exact SHA-256 matching, use backend API
1838
1805
  * @param {Array} [params.proofs] - Pre-fetched proofs (skip API call)
1839
1806
  * @returns {Promise<Object>} Gate result with satisfied, missing, existing
1840
- *
1807
+ *
1841
1808
  * @example
1842
1809
  * // Basic gate check
1843
1810
  * const result = await client.checkGate({
@@ -1870,20 +1837,20 @@ ${bytes.length}`;
1870
1837
  const verifier = verifiedVerifiers.find(
1871
1838
  (v) => v.verifierId === verifierId && v.verified === true
1872
1839
  );
1873
- if (!verifier)
1874
- return false;
1875
- if (proof.revokedAt)
1876
- return false;
1840
+ if (!verifier) return false;
1841
+ if (proof.revokedAt) return false;
1877
1842
  if (maxAgeMs) {
1878
1843
  const proofTimestamp = proof.createdAt || proof.signedTimestamp || 0;
1879
1844
  const proofAge = now - proofTimestamp;
1880
- if (proofAge > maxAgeMs)
1881
- return false;
1845
+ if (proofAge > maxAgeMs) return false;
1882
1846
  }
1883
1847
  if (match && typeof match === "object") {
1884
1848
  const data = verifier.data || {};
1885
1849
  const input = data.input || {};
1886
- for (const [key, expected] of Object.entries(match)) {
1850
+ const matchObj = Array.isArray(match) ? Object.fromEntries(
1851
+ match.filter((m) => m && m.path && String(m.value ?? "").trim() !== "").map((m) => [String(m.path).trim(), m.value])
1852
+ ) : match;
1853
+ for (const [key, expected] of Object.entries(matchObj)) {
1887
1854
  let actualValue = null;
1888
1855
  if (key.includes(".")) {
1889
1856
  const parts = key.split(".");
@@ -1908,6 +1875,7 @@ ${bytes.length}`;
1908
1875
  actualValue = data.reference?.id || data.content;
1909
1876
  }
1910
1877
  if (actualValue === void 0) {
1878
+ const claims = data.claims || {};
1911
1879
  if (key === "contractAddress") {
1912
1880
  actualValue = input.contractAddress || data.contractAddress;
1913
1881
  } else if (key === "tokenId") {
@@ -1926,6 +1894,22 @@ ${bytes.length}`;
1926
1894
  actualValue = data.verificationMethod;
1927
1895
  } else if (key === "domain") {
1928
1896
  actualValue = data.domain;
1897
+ } else if (key === "handle") {
1898
+ actualValue = data.handle || data.pseudonymId;
1899
+ } else if (key === "namespace") {
1900
+ actualValue = data.namespace !== void 0 && data.namespace !== null && data.namespace !== "" ? data.namespace : "neus";
1901
+ } else if (key === "claims.sanctions_passed") {
1902
+ actualValue = claims.sanctions_passed ?? claims.sanctionsPassed;
1903
+ } else if (key === "claims.age_min") {
1904
+ actualValue = claims.age_min ?? claims.ageMin;
1905
+ } else if (key === "neusPersonhoodId") {
1906
+ actualValue = data.neusPersonhoodId;
1907
+ } else if (key === "riskLevel") {
1908
+ actualValue = data.riskLevel;
1909
+ } else if (key === "sanctioned") {
1910
+ actualValue = data.sanctioned;
1911
+ } else if (key === "poisoned") {
1912
+ actualValue = data.poisoned;
1929
1913
  }
1930
1914
  }
1931
1915
  if (key === "contentHash" && actualValue === void 0 && data.content) {
@@ -1937,7 +1921,7 @@ ${bytes.length}`;
1937
1921
  hash = (hash << 5) - hash + char;
1938
1922
  hash = hash & hash;
1939
1923
  }
1940
- actualValue = "0x" + Math.abs(hash).toString(16).padStart(64, "0").substring(0, 66);
1924
+ actualValue = `0x${Math.abs(hash).toString(16).padStart(64, "0").substring(0, 66)}`;
1941
1925
  } catch {
1942
1926
  actualValue = String(data.content);
1943
1927
  }
@@ -1947,11 +1931,16 @@ ${bytes.length}`;
1947
1931
  if (actualValue === void 0 || actualValue === null) {
1948
1932
  return false;
1949
1933
  }
1934
+ if (typeof actualValue === "boolean" || key && (key.includes("sanctions") || key.includes("sanctioned") || key.includes("poisoned"))) {
1935
+ const bActual = Boolean(actualValue);
1936
+ const bExpected = expected === true || expected === "true" || String(expected).toLowerCase() === "true";
1937
+ if (bActual !== bExpected) return false;
1938
+ continue;
1939
+ }
1950
1940
  if (key === "chainId" || key === "tokenId" && (typeof actualValue === "number" || !isNaN(Number(actualValue)))) {
1951
1941
  normalizedActual = Number(actualValue);
1952
1942
  normalizedExpected = Number(expected);
1953
- if (isNaN(normalizedActual) || isNaN(normalizedExpected))
1954
- return false;
1943
+ if (isNaN(normalizedActual) || isNaN(normalizedExpected)) return false;
1955
1944
  } else if (typeof actualValue === "string" && (actualValue.startsWith("0x") || actualValue.length > 20)) {
1956
1945
  normalizedActual = actualValue.toLowerCase();
1957
1946
  normalizedExpected = typeof expected === "string" ? String(expected).toLowerCase() : expected;
@@ -1980,13 +1969,6 @@ ${bytes.length}`;
1980
1969
  allProofs: proofs
1981
1970
  };
1982
1971
  }
1983
- // ============================================================================
1984
- // PRIVATE UTILITY METHODS
1985
- // ============================================================================
1986
- /**
1987
- * Get connected wallet address
1988
- * @private
1989
- */
1990
1972
  async _getWalletAddress() {
1991
1973
  if (typeof window === "undefined" || !window.ethereum) {
1992
1974
  throw new ConfigurationError("No Web3 wallet detected");
@@ -1997,10 +1979,6 @@ ${bytes.length}`;
1997
1979
  }
1998
1980
  return accounts[0];
1999
1981
  }
2000
- /**
2001
- * Make HTTP request to API
2002
- * @private
2003
- */
2004
1982
  async _makeRequest(method, endpoint, data = null, headersOverride = null) {
2005
1983
  const url = `${this.baseUrl}${endpoint}`;
2006
1984
  const controller = new AbortController();
@@ -2038,10 +2016,6 @@ ${bytes.length}`;
2038
2016
  throw new NetworkError(`Network error: ${error.message}`);
2039
2017
  }
2040
2018
  }
2041
- /**
2042
- * Format API response for consistent structure
2043
- * @private
2044
- */
2045
2019
  _formatResponse(response) {
2046
2020
  const proofId = response?.data?.proofId || response?.proofId || response?.data?.resource?.proofId || response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || response?.data?.id;
2047
2021
  const qHash = response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || proofId || response?.data?.id;
@@ -2056,13 +2030,9 @@ ${bytes.length}`;
2056
2030
  data: response.data,
2057
2031
  message: response.message,
2058
2032
  timestamp: Date.now(),
2059
- statusUrl: finalProofId ? `${this.baseUrl}/api/v1/verification/status/${finalProofId}` : null
2033
+ proofUrl: finalProofId ? `${this.baseUrl}/api/v1/proofs/${finalProofId}` : null
2060
2034
  };
2061
2035
  }
2062
- /**
2063
- * Check if status is terminal (completed or failed)
2064
- * @private
2065
- */
2066
2036
  _isTerminalStatus(status) {
2067
2037
  const terminalStates = [
2068
2038
  "verified",
@@ -2093,5 +2063,6 @@ ${bytes.length}`;
2093
2063
  // Annotate the CommonJS export names for ESM import in node:
2094
2064
  0 && (module.exports = {
2095
2065
  NeusClient,
2066
+ PORTABLE_PROOF_SIGNER_HEADER,
2096
2067
  constructVerificationMessage
2097
2068
  });