@neus/sdk 1.0.2 → 1.0.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.
package/cjs/client.cjs CHANGED
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -128,6 +129,50 @@ var ConfigurationError = class extends SDKError {
128
129
  };
129
130
 
130
131
  // utils.js
132
+ var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
133
+ function encodeBase58Bytes(input) {
134
+ let source;
135
+ if (input instanceof Uint8Array) {
136
+ source = input;
137
+ } else if (input instanceof ArrayBuffer) {
138
+ source = new Uint8Array(input);
139
+ } else if (ArrayBuffer.isView(input)) {
140
+ source = new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
141
+ } else if (typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function" && Buffer.isBuffer(input)) {
142
+ source = new Uint8Array(input);
143
+ } else {
144
+ throw new SDKError("Unsupported non-EVM signature byte format", "INVALID_SIGNATURE_FORMAT");
145
+ }
146
+ if (source.length === 0)
147
+ return "";
148
+ let zeroes = 0;
149
+ while (zeroes < source.length && source[zeroes] === 0) {
150
+ zeroes++;
151
+ }
152
+ const iFactor = Math.log(256) / Math.log(58);
153
+ const size = (source.length - zeroes) * iFactor + 1 >>> 0;
154
+ const b58 = new Uint8Array(size);
155
+ let length = 0;
156
+ for (let i = zeroes; i < source.length; i++) {
157
+ let carry = source[i];
158
+ let j = 0;
159
+ for (let k = size - 1; (carry !== 0 || j < length) && k >= 0; k--, j++) {
160
+ carry += 256 * b58[k];
161
+ b58[k] = carry % 58;
162
+ carry = carry / 58 | 0;
163
+ }
164
+ length = j;
165
+ }
166
+ let it = size - length;
167
+ while (it < size && b58[it] === 0) {
168
+ it++;
169
+ }
170
+ let out = BASE58_ALPHABET[0].repeat(zeroes);
171
+ for (; it < size; it++) {
172
+ out += BASE58_ALPHABET[b58[it]];
173
+ }
174
+ return out;
175
+ }
131
176
  function deterministicStringify(obj) {
132
177
  if (obj === null || obj === void 0) {
133
178
  return JSON.stringify(obj);
@@ -186,6 +231,146 @@ function validateWalletAddress(address) {
186
231
  }
187
232
  return /^0x[a-fA-F0-9]{40}$/.test(address);
188
233
  }
234
+ function validateUniversalAddress(address, chain) {
235
+ if (!address || typeof address !== "string")
236
+ return false;
237
+ const value = address.trim();
238
+ if (!value)
239
+ return false;
240
+ const chainRef = typeof chain === "string" ? chain.trim().toLowerCase() : "";
241
+ const namespace = chainRef.includes(":") ? chainRef.split(":")[0] : "";
242
+ if (validateWalletAddress(value))
243
+ return true;
244
+ if (namespace === "eip155")
245
+ return false;
246
+ if (namespace === "solana") {
247
+ return /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(value);
248
+ }
249
+ if (namespace === "bip122") {
250
+ return /^(bc1|tb1|bcrt1)[a-z0-9]{11,87}$/.test(value.toLowerCase()) || /^[13mn2][a-km-zA-HJ-NP-Z1-9]{25,62}$/.test(value);
251
+ }
252
+ if (namespace === "near") {
253
+ return /^[a-z0-9._-]{2,64}$/.test(value);
254
+ }
255
+ return /^[A-Za-z0-9][A-Za-z0-9._:-]{1,127}$/.test(value);
256
+ }
257
+ function toHexUtf8(value) {
258
+ const input = typeof value === "string" ? value : String(value || "");
259
+ const bytes = new TextEncoder().encode(input);
260
+ return `0x${Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("")}`;
261
+ }
262
+ async function signMessage({ provider, message, walletAddress, chain } = {}) {
263
+ const msg = typeof message === "string" ? message : String(message || "");
264
+ if (!msg) {
265
+ throw new SDKError("signMessage: message is required", "INVALID_ARGUMENT");
266
+ }
267
+ const resolvedProvider = provider || (typeof window !== "undefined" && window?.ethereum ? window.ethereum : null);
268
+ if (!resolvedProvider) {
269
+ throw new SDKError("signMessage: provider is required", "SIGNER_UNAVAILABLE");
270
+ }
271
+ const chainStr = typeof chain === "string" && chain.trim().length > 0 ? chain.trim() : "eip155";
272
+ const namespace = chainStr.includes(":") ? chainStr.split(":")[0] || "eip155" : "eip155";
273
+ const resolveAddress = async () => {
274
+ if (typeof walletAddress === "string" && walletAddress.trim().length > 0)
275
+ return walletAddress;
276
+ if (namespace === "solana") {
277
+ if (resolvedProvider?.publicKey && typeof resolvedProvider.publicKey.toBase58 === "function") {
278
+ const pk = resolvedProvider.publicKey.toBase58();
279
+ if (typeof pk === "string" && pk)
280
+ return pk;
281
+ }
282
+ if (typeof resolvedProvider.getAddress === "function") {
283
+ const addr = await resolvedProvider.getAddress().catch(() => null);
284
+ if (typeof addr === "string" && addr)
285
+ return addr;
286
+ }
287
+ if (typeof resolvedProvider.address === "string" && resolvedProvider.address)
288
+ return resolvedProvider.address;
289
+ return null;
290
+ }
291
+ if (typeof resolvedProvider.address === "string" && resolvedProvider.address)
292
+ return resolvedProvider.address;
293
+ if (typeof resolvedProvider.getAddress === "function")
294
+ return await resolvedProvider.getAddress();
295
+ if (typeof resolvedProvider.request === "function") {
296
+ let accounts = await resolvedProvider.request({ method: "eth_accounts" }).catch(() => []);
297
+ if (!Array.isArray(accounts) || accounts.length === 0) {
298
+ accounts = await resolvedProvider.request({ method: "eth_requestAccounts" }).catch(() => []);
299
+ }
300
+ if (Array.isArray(accounts) && accounts[0])
301
+ return accounts[0];
302
+ }
303
+ return null;
304
+ };
305
+ if (namespace !== "eip155") {
306
+ if (typeof resolvedProvider.signMessage === "function") {
307
+ const encoded = typeof msg === "string" ? new TextEncoder().encode(msg) : msg;
308
+ 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);
319
+ }
320
+ throw new SDKError("Non-EVM signing requires provider.signMessage", "SIGNER_UNAVAILABLE");
321
+ }
322
+ const address = await resolveAddress();
323
+ if (typeof resolvedProvider.request === "function" && address) {
324
+ let firstPersonalSignError = null;
325
+ try {
326
+ const sig = await resolvedProvider.request({ method: "personal_sign", params: [msg, address] });
327
+ if (typeof sig === "string" && sig)
328
+ return sig;
329
+ } catch (error) {
330
+ firstPersonalSignError = error;
331
+ }
332
+ let secondPersonalSignError = null;
333
+ try {
334
+ const sig = await resolvedProvider.request({ method: "personal_sign", params: [address, msg] });
335
+ if (typeof sig === "string" && sig)
336
+ return sig;
337
+ } catch (error) {
338
+ secondPersonalSignError = error;
339
+ const signatureErrorMessage = String(
340
+ error?.message || error?.reason || firstPersonalSignError?.message || firstPersonalSignError?.reason || ""
341
+ ).toLowerCase();
342
+ const needsHex = /byte|bytes|invalid byte sequence|encoding|non-hex/i.test(signatureErrorMessage);
343
+ if (needsHex) {
344
+ try {
345
+ const hexMsg = toHexUtf8(msg);
346
+ const sig = await resolvedProvider.request({ method: "personal_sign", params: [hexMsg, address] });
347
+ if (typeof sig === "string" && sig)
348
+ return sig;
349
+ } catch {
350
+ }
351
+ }
352
+ }
353
+ try {
354
+ const sig = await resolvedProvider.request({ method: "eth_sign", params: [address, msg] });
355
+ if (typeof sig === "string" && sig)
356
+ return sig;
357
+ } catch {
358
+ }
359
+ if (secondPersonalSignError || firstPersonalSignError) {
360
+ const lastError = secondPersonalSignError || firstPersonalSignError;
361
+ const isUserRejection = [4001, "ACTION_REJECTED"].includes(lastError?.code);
362
+ if (isUserRejection) {
363
+ throw lastError;
364
+ }
365
+ }
366
+ }
367
+ if (typeof resolvedProvider.signMessage === "function") {
368
+ const result = await resolvedProvider.signMessage(msg);
369
+ if (typeof result === "string" && result)
370
+ return result;
371
+ }
372
+ throw new SDKError("Unable to sign message with provided wallet/provider", "SIGNER_UNAVAILABLE");
373
+ }
189
374
  var NEUS_CONSTANTS = {
190
375
  // Hub chain (where all verifications occur)
191
376
  HUB_CHAIN_ID: 84532,
@@ -217,18 +402,36 @@ var NEUS_CONSTANTS = {
217
402
  };
218
403
 
219
404
  // 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
+ ]);
426
+ var EVM_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
220
427
  var validateVerifierData = (verifierId, data) => {
221
428
  if (!data || typeof data !== "object") {
222
429
  return { valid: false, error: "Data object is required" };
223
430
  }
224
- const ownerField = verifierId === "nft-ownership" || verifierId === "token-holding" ? "ownerAddress" : "owner";
225
- if (data[ownerField] && !validateWalletAddress(data[ownerField])) {
226
- return { valid: false, error: `Invalid ${ownerField} address` };
227
- }
228
431
  switch (verifierId) {
229
432
  case "ownership-basic":
230
- if (!data.owner || !validateWalletAddress(data.owner)) {
231
- return { valid: false, error: "owner (wallet address) is required" };
433
+ if (!data.owner || !validateUniversalAddress(data.owner, typeof data.chain === "string" ? data.chain : void 0)) {
434
+ return { valid: false, error: "owner (universal wallet address) is required" };
232
435
  }
233
436
  if (data.content !== void 0 && data.content !== null) {
234
437
  if (typeof data.content !== "string") {
@@ -354,17 +557,20 @@ var validateVerifierData = (verifierId, data) => {
354
557
  }
355
558
  break;
356
559
  case "wallet-link":
357
- if (!data.primaryWalletAddress || !validateWalletAddress(data.primaryWalletAddress)) {
560
+ if (!data.primaryWalletAddress || !validateUniversalAddress(data.primaryWalletAddress, data.chain)) {
358
561
  return { valid: false, error: "primaryWalletAddress is required" };
359
562
  }
360
- if (!data.secondaryWalletAddress || !validateWalletAddress(data.secondaryWalletAddress)) {
563
+ if (!data.secondaryWalletAddress || !validateUniversalAddress(data.secondaryWalletAddress, data.chain)) {
361
564
  return { valid: false, error: "secondaryWalletAddress is required" };
362
565
  }
363
566
  if (!data.signature || typeof data.signature !== "string") {
364
567
  return { valid: false, error: "signature is required (signed by secondary wallet)" };
365
568
  }
366
- if (typeof data.chainId !== "number") {
367
- return { valid: false, error: "chainId is required" };
569
+ if (typeof data.chain !== "string" || !/^[a-z0-9]+:[^\s]+$/.test(data.chain)) {
570
+ return { valid: false, error: "chain is required (namespace:reference)" };
571
+ }
572
+ if (typeof data.signatureMethod !== "string" || !data.signatureMethod.trim()) {
573
+ return { valid: false, error: "signatureMethod is required" };
368
574
  }
369
575
  if (typeof data.signedTimestamp !== "number") {
370
576
  return { valid: false, error: "signedTimestamp is required" };
@@ -459,7 +665,7 @@ var validateVerifierData = (verifierId, data) => {
459
665
  }
460
666
  break;
461
667
  case "wallet-risk":
462
- if (data.walletAddress && !validateWalletAddress(data.walletAddress)) {
668
+ if (data.walletAddress && !validateUniversalAddress(data.walletAddress, data.chain)) {
463
669
  return { valid: false, error: "Invalid walletAddress" };
464
670
  }
465
671
  break;
@@ -491,6 +697,26 @@ var NeusClient = class {
491
697
  if (typeof this.config.apiKey === "string" && this.config.apiKey.trim().length > 0) {
492
698
  this.defaultHeaders["Authorization"] = `Bearer ${this.config.apiKey.trim()}`;
493
699
  }
700
+ if (typeof this.config.appId === "string" && this.config.appId.trim().length > 0) {
701
+ this.defaultHeaders["X-Neus-App"] = this.config.appId.trim();
702
+ }
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
+ if (typeof this.config.paymentSignature === "string" && this.config.paymentSignature.trim().length > 0) {
707
+ this.defaultHeaders["PAYMENT-SIGNATURE"] = this.config.paymentSignature.trim();
708
+ }
709
+ if (this.config.extraHeaders && typeof this.config.extraHeaders === "object") {
710
+ for (const [k, v] of Object.entries(this.config.extraHeaders)) {
711
+ if (!k || v === void 0 || v === null)
712
+ continue;
713
+ const key = String(k).trim();
714
+ const value = String(v).trim();
715
+ if (!key || !value)
716
+ continue;
717
+ this.defaultHeaders[key] = value;
718
+ }
719
+ }
494
720
  try {
495
721
  if (typeof window !== "undefined" && window.location && window.location.origin) {
496
722
  this.defaultHeaders["X-Client-Origin"] = window.location.origin;
@@ -498,6 +724,122 @@ var NeusClient = class {
498
724
  } catch {
499
725
  }
500
726
  }
727
+ _getHubChainId() {
728
+ const configured = Number(this.config?.hubChainId);
729
+ if (Number.isFinite(configured) && configured > 0)
730
+ return Math.floor(configured);
731
+ return NEUS_CONSTANTS.HUB_CHAIN_ID;
732
+ }
733
+ _normalizeIdentity(value) {
734
+ let raw = String(value || "").trim();
735
+ if (!raw)
736
+ return "";
737
+ const didMatch = raw.match(/^did:pkh:([^:]+):([^:]+):(.+)$/i);
738
+ if (didMatch && didMatch[3]) {
739
+ raw = String(didMatch[3]).trim();
740
+ }
741
+ return EVM_ADDRESS_RE.test(raw) ? raw.toLowerCase() : raw;
742
+ }
743
+ _inferChainForAddress(address, explicitChain) {
744
+ if (typeof explicitChain === "string" && explicitChain.includes(":"))
745
+ return explicitChain.trim();
746
+ const raw = String(address || "").trim();
747
+ const didMatch = raw.match(/^did:pkh:([^:]+):([^:]+):(.+)$/i);
748
+ if (didMatch && didMatch[1] && didMatch[2]) {
749
+ return `${didMatch[1]}:${didMatch[2]}`;
750
+ }
751
+ if (EVM_ADDRESS_RE.test(raw)) {
752
+ return `eip155:${this._getHubChainId()}`;
753
+ }
754
+ return "solana:mainnet";
755
+ }
756
+ async _resolveWalletSigner(wallet) {
757
+ if (!wallet) {
758
+ throw new ConfigurationError("No wallet provider available");
759
+ }
760
+ if (wallet.address) {
761
+ return { signerWalletAddress: wallet.address, provider: wallet };
762
+ }
763
+ if (wallet.publicKey && typeof wallet.publicKey.toBase58 === "function") {
764
+ return { signerWalletAddress: wallet.publicKey.toBase58(), provider: wallet };
765
+ }
766
+ if (typeof wallet.getAddress === "function") {
767
+ const signerWalletAddress = await wallet.getAddress().catch(() => null);
768
+ return { signerWalletAddress, provider: wallet };
769
+ }
770
+ if (wallet.selectedAddress || wallet.request) {
771
+ const provider = wallet;
772
+ if (wallet.selectedAddress) {
773
+ return { signerWalletAddress: wallet.selectedAddress, provider };
774
+ }
775
+ const accounts = await provider.request({ method: "eth_accounts" });
776
+ if (!accounts || accounts.length === 0) {
777
+ throw new ConfigurationError("No wallet accounts available");
778
+ }
779
+ return { signerWalletAddress: accounts[0], provider };
780
+ }
781
+ throw new ConfigurationError("Invalid wallet provider");
782
+ }
783
+ _getDefaultBrowserWallet() {
784
+ if (typeof window === "undefined")
785
+ return null;
786
+ return window.ethereum || window.solana || window.phantom && window.phantom.solana || null;
787
+ }
788
+ async _buildPrivateGateAuth({ address, wallet, chain, signatureMethod } = {}) {
789
+ const providerWallet = wallet || this._getDefaultBrowserWallet();
790
+ const { signerWalletAddress, provider } = await this._resolveWalletSigner(providerWallet);
791
+ if (!signerWalletAddress || typeof signerWalletAddress !== "string") {
792
+ throw new ConfigurationError("No wallet accounts available");
793
+ }
794
+ const normalizedSigner = this._normalizeIdentity(signerWalletAddress);
795
+ const normalizedAddress = this._normalizeIdentity(address);
796
+ if (!normalizedSigner || normalizedSigner !== normalizedAddress) {
797
+ throw new ValidationError("wallet must match address when includePrivate=true");
798
+ }
799
+ const signerIsEvm = EVM_ADDRESS_RE.test(normalizedSigner);
800
+ const resolvedChain = this._inferChainForAddress(normalizedSigner, chain);
801
+ const resolvedSignatureMethod = typeof signatureMethod === "string" && signatureMethod.trim() ? signatureMethod.trim() : signerIsEvm ? "eip191" : "ed25519";
802
+ const signedTimestamp = Date.now();
803
+ const message = constructVerificationMessage({
804
+ walletAddress: signerWalletAddress,
805
+ signedTimestamp,
806
+ data: { action: "gate_check_private_proofs", walletAddress: normalizedAddress },
807
+ verifierIds: ["ownership-basic"],
808
+ ...signerIsEvm ? { chainId: this._getHubChainId() } : { chain: resolvedChain }
809
+ });
810
+ let signature;
811
+ try {
812
+ signature = await signMessage({
813
+ provider,
814
+ message,
815
+ walletAddress: signerWalletAddress,
816
+ ...signerIsEvm ? {} : { chain: resolvedChain }
817
+ });
818
+ } catch (error) {
819
+ if (error.code === 4001) {
820
+ throw new ValidationError("User rejected signature request");
821
+ }
822
+ throw new ValidationError(`Failed to sign message: ${error.message}`);
823
+ }
824
+ return {
825
+ walletAddress: signerWalletAddress,
826
+ signature,
827
+ signedTimestamp,
828
+ ...signerIsEvm ? {} : { chain: resolvedChain, signatureMethod: resolvedSignatureMethod }
829
+ };
830
+ }
831
+ async createGatePrivateAuth(params = {}) {
832
+ const address = (params.address || "").toString();
833
+ if (!validateUniversalAddress(address, params.chain)) {
834
+ throw new ValidationError("Valid address is required");
835
+ }
836
+ return this._buildPrivateGateAuth({
837
+ address,
838
+ wallet: params.wallet,
839
+ chain: params.chain,
840
+ signatureMethod: params.signatureMethod
841
+ });
842
+ }
501
843
  // ============================================================================
502
844
  // CORE VERIFICATION METHODS
503
845
  // ============================================================================
@@ -519,7 +861,7 @@ var NeusClient = class {
519
861
  * @param {string} [params.verifier] - Verifier ID (auto path)
520
862
  * @param {string} [params.content] - Content/description (auto path)
521
863
  * @param {Object} [params.wallet] - Optional injected wallet/provider (auto path)
522
- * @returns {Promise<Object>} Verification result with qHash
864
+ * @returns {Promise<Object>} Verification result with proofId (qHash is a deprecated alias)
523
865
  *
524
866
  * @example
525
867
  * const proof = await client.verify({
@@ -544,7 +886,7 @@ var NeusClient = class {
544
886
  * @param {Object} [params.data] - Structured verification data
545
887
  * @param {Object} [params.wallet] - Wallet provider
546
888
  * @param {Object} [params.options] - Additional options
547
- * @returns {Promise<Object>} Verification result with qHash
889
+ * @returns {Promise<Object>} Verification result with proofId (qHash is a deprecated alias)
548
890
  *
549
891
  * @example
550
892
  * // Simple ownership proof
@@ -560,25 +902,23 @@ var NeusClient = class {
560
902
  if (verifier === "ownership-basic" && !data2 && (!content || typeof content !== "string")) {
561
903
  throw new ValidationError("content is required and must be a string (or use data param with owner + reference)");
562
904
  }
563
- const validVerifiers = [
564
- "ownership-basic",
565
- "ownership-pseudonym",
566
- // Pseudonymous identity (public)
567
- "nft-ownership",
568
- "token-holding",
569
- "ownership-dns-txt",
570
- "wallet-link",
571
- "contract-ownership",
572
- "wallet-risk",
573
- // Wallet risk assessment (public)
574
- // AI & Agent verifiers (ERC-8004 aligned)
575
- "agent-identity",
576
- "agent-delegation",
577
- "ai-content-moderation"
578
- ];
905
+ let validVerifiers = FALLBACK_PUBLIC_VERIFIERS;
906
+ try {
907
+ const discovered = await this.getVerifiers();
908
+ if (Array.isArray(discovered) && discovered.length > 0) {
909
+ validVerifiers = discovered;
910
+ }
911
+ } catch {
912
+ }
579
913
  if (!validVerifiers.includes(verifier)) {
580
914
  throw new ValidationError(`Invalid verifier '${verifier}'. Must be one of: ${validVerifiers.join(", ")}.`);
581
915
  }
916
+ if (INTERACTIVE_VERIFIERS.has(verifier)) {
917
+ const hostedCheckoutUrl = options2?.hostedCheckoutUrl || "https://neus.network/verify";
918
+ throw new ValidationError(
919
+ `${verifier} requires hosted interactive checkout. Use VerifyGate or redirect to ${hostedCheckoutUrl}.`
920
+ );
921
+ }
582
922
  const requiresDataParam = [
583
923
  "ownership-dns-txt",
584
924
  "wallet-link",
@@ -596,8 +936,12 @@ var NeusClient = class {
596
936
  }
597
937
  let walletAddress2, provider;
598
938
  if (wallet) {
599
- walletAddress2 = wallet.address || wallet.selectedAddress;
939
+ walletAddress2 = wallet.address || wallet.selectedAddress || wallet.walletAddress || (typeof wallet.getAddress === "function" ? await wallet.getAddress() : null);
600
940
  provider = wallet.provider || wallet;
941
+ if (!walletAddress2 && provider && typeof provider.request === "function") {
942
+ const accounts = await provider.request({ method: "eth_accounts" });
943
+ walletAddress2 = Array.isArray(accounts) ? accounts[0] : null;
944
+ }
601
945
  } else {
602
946
  if (typeof window === "undefined" || !window.ethereum) {
603
947
  throw new ConfigurationError("No Web3 wallet detected. Please install MetaMask or provide wallet parameter.");
@@ -673,14 +1017,18 @@ var NeusClient = class {
673
1017
  if (!data2?.signature) {
674
1018
  throw new ValidationError("wallet-link requires signature in data parameter (signed by secondary wallet)");
675
1019
  }
676
- if (typeof data2?.chainId !== "number") {
677
- throw new ValidationError("wallet-link requires chainId (number) in data parameter");
1020
+ if (typeof data2?.chain !== "string" || !/^[a-z0-9]+:[^\s]+$/.test(data2.chain)) {
1021
+ throw new ValidationError("wallet-link requires chain (namespace:reference) in data parameter");
1022
+ }
1023
+ if (typeof data2?.signatureMethod !== "string" || !data2.signatureMethod.trim()) {
1024
+ throw new ValidationError("wallet-link requires signatureMethod in data parameter");
678
1025
  }
679
1026
  verificationData = {
680
1027
  primaryWalletAddress: walletAddress2,
681
1028
  secondaryWalletAddress: data2.secondaryWalletAddress,
682
1029
  signature: data2.signature,
683
- chainId: data2.chainId,
1030
+ chain: data2.chain,
1031
+ signatureMethod: data2.signatureMethod,
684
1032
  signedTimestamp: data2?.signedTimestamp || Date.now()
685
1033
  };
686
1034
  } else if (verifier === "contract-ownership") {
@@ -769,12 +1117,12 @@ var NeusClient = class {
769
1117
  signedTimestamp: signedTimestamp2,
770
1118
  data: verificationData,
771
1119
  verifierIds: verifierIds2,
772
- chainId: NEUS_CONSTANTS.HUB_CHAIN_ID
1120
+ chainId: this._getHubChainId()
773
1121
  // Protocol-managed chain
774
1122
  });
775
1123
  let signature2;
776
1124
  try {
777
- const toHexUtf8 = (s) => {
1125
+ const toHexUtf82 = (s) => {
778
1126
  try {
779
1127
  const enc = new TextEncoder();
780
1128
  const bytes = enc.encode(s);
@@ -810,7 +1158,7 @@ var NeusClient = class {
810
1158
  })();
811
1159
  if (isFarcasterWallet) {
812
1160
  try {
813
- const hexMsg = toHexUtf8(message);
1161
+ const hexMsg = toHexUtf82(message);
814
1162
  signature2 = await provider.request({ method: "personal_sign", params: [hexMsg, walletAddress2] });
815
1163
  } catch (e) {
816
1164
  }
@@ -859,7 +1207,7 @@ ${bytes.length}`;
859
1207
  }
860
1208
  } else if (needsHex) {
861
1209
  this._log("Retrying personal_sign with hex-encoded message");
862
- const hexMsg = toHexUtf8(message);
1210
+ const hexMsg = toHexUtf82(message);
863
1211
  signature2 = await provider.request({ method: "personal_sign", params: [hexMsg, walletAddress2] });
864
1212
  } else {
865
1213
  throw e;
@@ -957,18 +1305,18 @@ ${bytes.length}`;
957
1305
  /**
958
1306
  * Get verification status
959
1307
  *
960
- * @param {string} qHash - Verification ID (qHash or proofId)
1308
+ * @param {string} proofId - Proof ID (standard). `qHash` is a deprecated alias (same value).
961
1309
  * @returns {Promise<Object>} Verification status and data
962
1310
  *
963
1311
  * @example
964
1312
  * const result = await client.getStatus('0x...');
965
1313
  * console.log('Status:', result.status);
966
1314
  */
967
- async getStatus(qHash) {
968
- if (!qHash || typeof qHash !== "string") {
969
- throw new ValidationError("qHash is required");
1315
+ async getStatus(proofId) {
1316
+ if (!proofId || typeof proofId !== "string") {
1317
+ throw new ValidationError("proofId is required");
970
1318
  }
971
- const response = await this._makeRequest("GET", `/api/v1/verification/status/${qHash}`);
1319
+ const response = await this._makeRequest("GET", `/api/v1/verification/status/${proofId}`);
972
1320
  if (!response.success) {
973
1321
  throw new ApiError(`Failed to get status: ${response.error?.message || "Unknown error"}`, response.error);
974
1322
  }
@@ -977,70 +1325,72 @@ ${bytes.length}`;
977
1325
  /**
978
1326
  * Get private proof status with wallet signature
979
1327
  *
980
- * @param {string} qHash - Verification ID
1328
+ * @param {string} proofId - Proof ID (standard). `qHash` is a deprecated alias (same value).
981
1329
  * @param {Object} wallet - Wallet provider (window.ethereum or ethers Wallet)
982
1330
  * @returns {Promise<Object>} Private verification status and data
983
1331
  *
984
1332
  * @example
985
1333
  * // Access private proof
986
- * const privateData = await client.getPrivateStatus(qHash, window.ethereum);
1334
+ * const privateData = await client.getPrivateStatus(proofId, window.ethereum);
987
1335
  */
988
- async getPrivateStatus(qHash, wallet = null) {
989
- if (!qHash || typeof qHash !== "string") {
990
- throw new ValidationError("qHash is required");
1336
+ async getPrivateStatus(proofId, wallet = null) {
1337
+ if (!proofId || typeof proofId !== "string") {
1338
+ throw new ValidationError("proofId is required");
991
1339
  }
992
- if (!wallet) {
993
- if (typeof window === "undefined" || !window.ethereum) {
994
- throw new ConfigurationError("No wallet provider available");
1340
+ const isPreSignedAuth = wallet && typeof wallet === "object" && typeof wallet.walletAddress === "string" && typeof wallet.signature === "string" && typeof wallet.signedTimestamp === "number";
1341
+ if (isPreSignedAuth) {
1342
+ const auth = wallet;
1343
+ const headers = {
1344
+ "x-wallet-address": String(auth.walletAddress),
1345
+ "x-signature": String(auth.signature),
1346
+ "x-signed-timestamp": String(auth.signedTimestamp),
1347
+ ...typeof auth.chain === "string" && auth.chain.trim() ? { "x-chain": auth.chain.trim() } : {},
1348
+ ...typeof auth.signatureMethod === "string" && auth.signatureMethod.trim() ? { "x-signature-method": auth.signatureMethod.trim() } : {}
1349
+ };
1350
+ const response2 = await this._makeRequest("GET", `/api/v1/verification/status/${proofId}`, null, headers);
1351
+ if (!response2.success) {
1352
+ throw new ApiError(
1353
+ `Failed to access private proof: ${response2.error?.message || "Unauthorized"}`,
1354
+ response2.error
1355
+ );
995
1356
  }
996
- wallet = window.ethereum;
1357
+ return this._formatResponse(response2);
997
1358
  }
998
- let walletAddress, provider;
999
- if (wallet.address) {
1000
- walletAddress = wallet.address;
1001
- provider = wallet;
1002
- } else if (wallet.selectedAddress || wallet.request) {
1003
- provider = wallet;
1004
- if (wallet.selectedAddress) {
1005
- walletAddress = wallet.selectedAddress;
1006
- } else {
1007
- const accounts = await provider.request({ method: "eth_accounts" });
1008
- if (!accounts || accounts.length === 0) {
1009
- throw new ConfigurationError("No wallet accounts available");
1010
- }
1011
- walletAddress = accounts[0];
1012
- }
1013
- } else {
1014
- throw new ConfigurationError("Invalid wallet provider");
1359
+ const providerWallet = wallet || this._getDefaultBrowserWallet();
1360
+ const { signerWalletAddress: walletAddress, provider } = await this._resolveWalletSigner(providerWallet);
1361
+ if (!walletAddress || typeof walletAddress !== "string") {
1362
+ throw new ConfigurationError("No wallet accounts available");
1015
1363
  }
1364
+ const signerIsEvm = EVM_ADDRESS_RE.test(this._normalizeIdentity(walletAddress));
1365
+ const chain = this._inferChainForAddress(walletAddress);
1366
+ const signatureMethod = signerIsEvm ? "eip191" : "ed25519";
1016
1367
  const signedTimestamp = Date.now();
1017
1368
  const message = constructVerificationMessage({
1018
1369
  walletAddress,
1019
1370
  signedTimestamp,
1020
- data: { action: "access_private_proof", qHash },
1371
+ data: { action: "access_private_proof", qHash: proofId },
1021
1372
  verifierIds: ["ownership-basic"],
1022
- chainId: NEUS_CONSTANTS.HUB_CHAIN_ID
1373
+ ...signerIsEvm ? { chainId: this._getHubChainId() } : { chain }
1023
1374
  });
1024
1375
  let signature;
1025
1376
  try {
1026
- if (provider.signMessage) {
1027
- signature = await provider.signMessage(message);
1028
- } else {
1029
- signature = await provider.request({
1030
- method: "personal_sign",
1031
- params: [message, walletAddress]
1032
- });
1033
- }
1377
+ signature = await signMessage({
1378
+ provider,
1379
+ message,
1380
+ walletAddress,
1381
+ ...signerIsEvm ? {} : { chain }
1382
+ });
1034
1383
  } catch (error) {
1035
1384
  if (error.code === 4001) {
1036
1385
  throw new ValidationError("User rejected signature request");
1037
1386
  }
1038
1387
  throw new ValidationError(`Failed to sign message: ${error.message}`);
1039
1388
  }
1040
- const response = await this._makeRequest("GET", `/api/v1/verification/status/${qHash}`, null, {
1389
+ const response = await this._makeRequest("GET", `/api/v1/verification/status/${proofId}`, null, {
1041
1390
  "x-wallet-address": walletAddress,
1042
1391
  "x-signature": signature,
1043
- "x-signed-timestamp": signedTimestamp.toString()
1392
+ "x-signed-timestamp": signedTimestamp.toString(),
1393
+ ...signerIsEvm ? {} : { "x-chain": chain, "x-signature-method": signatureMethod }
1044
1394
  });
1045
1395
  if (!response.success) {
1046
1396
  throw new ApiError(
@@ -1081,7 +1431,7 @@ ${bytes.length}`;
1081
1431
  * Polls the verification status until it reaches a terminal state (completed or failed).
1082
1432
  * Useful for providing real-time feedback to users during verification.
1083
1433
  *
1084
- * @param {string} qHash - Verification ID to poll
1434
+ * @param {string} proofId - Proof ID to poll (standard). `qHash` is a deprecated alias (same value).
1085
1435
  * @param {Object} [options] - Polling options
1086
1436
  * @param {number} [options.interval=5000] - Polling interval in ms
1087
1437
  * @param {number} [options.timeout=120000] - Total timeout in ms
@@ -1089,7 +1439,7 @@ ${bytes.length}`;
1089
1439
  * @returns {Promise<Object>} Final verification status
1090
1440
  *
1091
1441
  * @example
1092
- * const finalStatus = await client.pollProofStatus(qHash, {
1442
+ * const finalStatus = await client.pollProofStatus(proofId, {
1093
1443
  * interval: 3000,
1094
1444
  * timeout: 60000,
1095
1445
  * onProgress: (status) => {
@@ -1100,20 +1450,20 @@ ${bytes.length}`;
1100
1450
  * }
1101
1451
  * });
1102
1452
  */
1103
- async pollProofStatus(qHash, options = {}) {
1453
+ async pollProofStatus(proofId, options = {}) {
1104
1454
  const {
1105
1455
  interval = 5e3,
1106
1456
  timeout = 12e4,
1107
1457
  onProgress
1108
1458
  } = options;
1109
- if (!qHash || typeof qHash !== "string") {
1110
- throw new ValidationError("qHash is required");
1459
+ if (!proofId || typeof proofId !== "string") {
1460
+ throw new ValidationError("proofId is required");
1111
1461
  }
1112
1462
  const startTime = Date.now();
1113
1463
  let consecutiveRateLimits = 0;
1114
1464
  while (Date.now() - startTime < timeout) {
1115
1465
  try {
1116
- const status = await this.getStatus(qHash);
1466
+ const status = await this.getStatus(proofId);
1117
1467
  consecutiveRateLimits = 0;
1118
1468
  if (onProgress && typeof onProgress === "function") {
1119
1469
  onProgress(status.data || status);
@@ -1161,70 +1511,51 @@ ${bytes.length}`;
1161
1511
  }
1162
1512
  }
1163
1513
  /** Revoke your own proof (owner-signed) */
1164
- async revokeOwnProof(qHash, wallet) {
1165
- if (!qHash || typeof qHash !== "string") {
1166
- throw new ValidationError("qHash is required");
1514
+ async revokeOwnProof(proofId, wallet) {
1515
+ if (!proofId || typeof proofId !== "string") {
1516
+ throw new ValidationError("proofId is required");
1167
1517
  }
1168
- const address = wallet?.address || await this._getWalletAddress();
1518
+ const providerWallet = wallet || this._getDefaultBrowserWallet();
1519
+ const { signerWalletAddress: address, provider } = await this._resolveWalletSigner(providerWallet);
1520
+ if (!address || typeof address !== "string") {
1521
+ throw new ConfigurationError("No wallet accounts available");
1522
+ }
1523
+ const signerIsEvm = EVM_ADDRESS_RE.test(this._normalizeIdentity(address));
1524
+ const chain = this._inferChainForAddress(address);
1525
+ const signatureMethod = signerIsEvm ? "eip191" : "ed25519";
1169
1526
  const signedTimestamp = Date.now();
1170
- const hubChainId = NEUS_CONSTANTS.HUB_CHAIN_ID;
1171
1527
  const message = constructVerificationMessage({
1172
1528
  walletAddress: address,
1173
1529
  signedTimestamp,
1174
- data: { action: "revoke_proof", qHash },
1530
+ // Keep wire payload key `qHash` for backwards compatibility.
1531
+ data: { action: "revoke_proof", qHash: proofId },
1175
1532
  verifierIds: ["ownership-basic"],
1176
- chainId: hubChainId
1533
+ ...signerIsEvm ? { chainId: this._getHubChainId() } : { chain }
1177
1534
  });
1178
1535
  let signature;
1179
1536
  try {
1180
- const toHexUtf8 = (s) => {
1181
- const enc = new TextEncoder();
1182
- const bytes = enc.encode(s);
1183
- let hex = "0x";
1184
- for (let i = 0; i < bytes.length; i++)
1185
- hex += bytes[i].toString(16).padStart(2, "0");
1186
- return hex;
1187
- };
1188
- const isFarcasterWallet = (() => {
1189
- if (typeof window === "undefined")
1190
- return false;
1191
- try {
1192
- const w = window;
1193
- const fc = w.farcaster;
1194
- if (!fc || !fc.context)
1195
- return false;
1196
- const fcProvider = fc.provider || fc.walletProvider || fc.context && fc.context.walletProvider;
1197
- if (fcProvider === w.ethereum)
1198
- return true;
1199
- if (w.mini && w.mini.wallet === w.ethereum && fc && fc.context)
1200
- return true;
1201
- if (w.ethereum && fc && fc.context)
1202
- return true;
1203
- } catch {
1204
- }
1205
- return false;
1206
- })();
1207
- if (isFarcasterWallet) {
1208
- try {
1209
- const hexMsg = toHexUtf8(message);
1210
- signature = await window.ethereum.request({ method: "personal_sign", params: [hexMsg, address] });
1211
- } catch {
1212
- }
1213
- }
1214
- if (!signature) {
1215
- signature = await window.ethereum.request({ method: "personal_sign", params: [message, address] });
1216
- }
1537
+ signature = await signMessage({
1538
+ provider,
1539
+ message,
1540
+ walletAddress: address,
1541
+ ...signerIsEvm ? {} : { chain }
1542
+ });
1217
1543
  } catch (error) {
1218
1544
  if (error.code === 4001) {
1219
1545
  throw new ValidationError("User rejected revocation signature");
1220
1546
  }
1221
1547
  throw new ValidationError(`Failed to sign revocation: ${error.message}`);
1222
1548
  }
1223
- const res = await fetch(`${this.config.apiUrl}/api/v1/proofs/${qHash}/revoke-self`, {
1549
+ const res = await fetch(`${this.config.apiUrl}/api/v1/proofs/${proofId}/revoke-self`, {
1224
1550
  method: "POST",
1225
1551
  // SECURITY: Do not put proof signatures into Authorization headers.
1226
1552
  headers: { "Content-Type": "application/json" },
1227
- body: JSON.stringify({ walletAddress: address, signature, signedTimestamp })
1553
+ body: JSON.stringify({
1554
+ walletAddress: address,
1555
+ signature,
1556
+ signedTimestamp,
1557
+ ...signerIsEvm ? {} : { chain, signatureMethod }
1558
+ })
1228
1559
  });
1229
1560
  const json = await res.json();
1230
1561
  if (!json.success) {
@@ -1238,7 +1569,7 @@ ${bytes.length}`;
1238
1569
  /**
1239
1570
  * GET PROOFS BY WALLET - Fetch proofs for a wallet address
1240
1571
  *
1241
- * @param {string} walletAddress - Wallet address (0x...) or DID (did:pkh:...)
1572
+ * @param {string} walletAddress - Wallet identity (EVM/Solana/DID)
1242
1573
  * @param {Object} [options] - Filter options
1243
1574
  * @param {number} [options.limit] - Max results (default: 50; higher limits require owner access)
1244
1575
  * @param {number} [options.offset] - Pagination offset (default: 0)
@@ -1283,7 +1614,7 @@ ${bytes.length}`;
1283
1614
  *
1284
1615
  * Signs an owner-access intent and requests private proofs via signature headers.
1285
1616
  *
1286
- * @param {string} walletAddress - Wallet address (0x...) or DID (did:pkh:...)
1617
+ * @param {string} walletAddress - Wallet identity (EVM/Solana/DID)
1287
1618
  * @param {Object} [options]
1288
1619
  * @param {number} [options.limit] - Max results (server enforces caps)
1289
1620
  * @param {number} [options.offset] - Pagination offset
@@ -1295,48 +1626,41 @@ ${bytes.length}`;
1295
1626
  }
1296
1627
  const id = walletAddress.trim();
1297
1628
  const pathId = /^0x[a-fA-F0-9]{40}$/i.test(id) ? id.toLowerCase() : id;
1629
+ const requestedIdentity = this._normalizeIdentity(id);
1298
1630
  if (!wallet) {
1299
- if (typeof window === "undefined" || !window.ethereum) {
1631
+ const defaultWallet = this._getDefaultBrowserWallet();
1632
+ if (!defaultWallet) {
1300
1633
  throw new ConfigurationError("No wallet provider available");
1301
1634
  }
1302
- wallet = window.ethereum;
1635
+ wallet = defaultWallet;
1303
1636
  }
1304
- let signerWalletAddress, provider;
1305
- if (wallet.address) {
1306
- signerWalletAddress = wallet.address;
1307
- provider = wallet;
1308
- } else if (wallet.selectedAddress || wallet.request) {
1309
- provider = wallet;
1310
- if (wallet.selectedAddress) {
1311
- signerWalletAddress = wallet.selectedAddress;
1312
- } else {
1313
- const accounts = await provider.request({ method: "eth_accounts" });
1314
- if (!accounts || accounts.length === 0) {
1315
- throw new ConfigurationError("No wallet accounts available");
1316
- }
1317
- signerWalletAddress = accounts[0];
1318
- }
1319
- } else {
1320
- throw new ConfigurationError("Invalid wallet provider");
1637
+ const { signerWalletAddress, provider } = await this._resolveWalletSigner(wallet);
1638
+ if (!signerWalletAddress || typeof signerWalletAddress !== "string") {
1639
+ throw new ConfigurationError("No wallet accounts available");
1321
1640
  }
1641
+ const normalizedSigner = this._normalizeIdentity(signerWalletAddress);
1642
+ if (!normalizedSigner || normalizedSigner !== requestedIdentity) {
1643
+ throw new ValidationError("wallet must match walletAddress for private proof access");
1644
+ }
1645
+ const signerIsEvm = EVM_ADDRESS_RE.test(normalizedSigner);
1646
+ const chain = this._inferChainForAddress(normalizedSigner, options?.chain);
1647
+ const signatureMethod = typeof options?.signatureMethod === "string" && options.signatureMethod.trim() ? options.signatureMethod.trim() : signerIsEvm ? "eip191" : "ed25519";
1322
1648
  const signedTimestamp = Date.now();
1323
1649
  const message = constructVerificationMessage({
1324
1650
  walletAddress: signerWalletAddress,
1325
1651
  signedTimestamp,
1326
- data: { action: "access_private_proofs_by_wallet", walletAddress: signerWalletAddress.toLowerCase() },
1652
+ data: { action: "access_private_proofs_by_wallet", walletAddress: normalizedSigner },
1327
1653
  verifierIds: ["ownership-basic"],
1328
- chainId: NEUS_CONSTANTS.HUB_CHAIN_ID
1654
+ ...signerIsEvm ? { chainId: this._getHubChainId() } : { chain }
1329
1655
  });
1330
1656
  let signature;
1331
1657
  try {
1332
- if (provider.signMessage) {
1333
- signature = await provider.signMessage(message);
1334
- } else {
1335
- signature = await provider.request({
1336
- method: "personal_sign",
1337
- params: [message, signerWalletAddress]
1338
- });
1339
- }
1658
+ signature = await signMessage({
1659
+ provider,
1660
+ message,
1661
+ walletAddress: signerWalletAddress,
1662
+ ...signerIsEvm ? {} : { chain }
1663
+ });
1340
1664
  } catch (error) {
1341
1665
  if (error.code === 4001) {
1342
1666
  throw new ValidationError("User rejected signature request");
@@ -1352,7 +1676,8 @@ ${bytes.length}`;
1352
1676
  const response = await this._makeRequest("GET", `/api/v1/proofs/byWallet/${encodeURIComponent(pathId)}${query}`, null, {
1353
1677
  "x-wallet-address": signerWalletAddress,
1354
1678
  "x-signature": signature,
1355
- "x-signed-timestamp": signedTimestamp.toString()
1679
+ "x-signed-timestamp": signedTimestamp.toString(),
1680
+ ...signerIsEvm ? {} : { "x-chain": chain, "x-signature-method": signatureMethod }
1356
1681
  });
1357
1682
  if (!response.success) {
1358
1683
  throw new ApiError(`Failed to get proofs: ${response.error?.message || "Unauthorized"}`, response.error);
@@ -1369,25 +1694,31 @@ ${bytes.length}`;
1369
1694
  /**
1370
1695
  * GATE CHECK (API) - Minimal eligibility check
1371
1696
  *
1372
- * Calls the public gate endpoint and returns a **minimal** yes/no response
1373
- * against **public + discoverable** proofs only.
1697
+ * Calls the gate endpoint and returns a **minimal** yes/no response.
1698
+ * By default this checks **public + discoverable** proofs only.
1699
+ *
1700
+ * When `includePrivate=true`, this can perform owner-signed private checks
1701
+ * (no full proof payloads returned) by providing a wallet/provider.
1374
1702
  *
1375
- * Prefer this over `checkGate()` for server-side integrations that want the
1703
+ * Prefer this over `checkGate()` for integrations that want the
1376
1704
  * smallest, most stable surface area (and do NOT need full proof payloads).
1377
1705
  *
1378
1706
  * @param {Object} params - Gate check query params
1379
- * @param {string} params.address - Wallet address to check (0x...)
1707
+ * @param {string} params.address - Wallet identity to check (EVM/Solana/DID)
1380
1708
  * @param {Array<string>|string} [params.verifierIds] - Verifier IDs to match (array or comma-separated)
1381
1709
  * @param {boolean} [params.requireAll] - Require all verifierIds on a single proof
1382
1710
  * @param {number} [params.minCount] - Minimum number of matching proofs
1383
1711
  * @param {number} [params.sinceDays] - Optional time window in days
1384
1712
  * @param {number} [params.since] - Optional unix timestamp in ms (lower bound)
1385
1713
  * @param {number} [params.limit] - Max rows to scan (server may clamp)
1714
+ * @param {boolean} [params.includePrivate] - Include private proofs for owner-authenticated requests
1715
+ * @param {boolean} [params.includeQHashes] - Include matched qHashes in response (minimal IDs only)
1716
+ * @param {Object} [params.wallet] - Optional wallet/provider used to sign includePrivate owner checks
1386
1717
  * @returns {Promise<Object>} API response ({ success, data })
1387
1718
  */
1388
1719
  async gateCheck(params = {}) {
1389
1720
  const address = (params.address || "").toString();
1390
- if (!address || !/^0x[a-fA-F0-9]{40}$/i.test(address)) {
1721
+ if (!validateUniversalAddress(address, params.chain)) {
1391
1722
  throw new ValidationError("Valid address is required");
1392
1723
  }
1393
1724
  const qs = new URLSearchParams();
@@ -1422,6 +1753,8 @@ ${bytes.length}`;
1422
1753
  setIfPresent("sinceDays", params.sinceDays);
1423
1754
  setIfPresent("since", params.since);
1424
1755
  setIfPresent("limit", params.limit);
1756
+ setBoolIfPresent("includePrivate", params.includePrivate);
1757
+ setBoolIfPresent("includeQHashes", params.includeQHashes);
1425
1758
  setIfPresent("referenceType", params.referenceType);
1426
1759
  setIfPresent("referenceId", params.referenceId);
1427
1760
  setIfPresent("tag", params.tag);
@@ -1442,7 +1775,40 @@ ${bytes.length}`;
1442
1775
  setIfPresent("primaryWalletAddress", params.primaryWalletAddress);
1443
1776
  setIfPresent("secondaryWalletAddress", params.secondaryWalletAddress);
1444
1777
  setIfPresent("verificationMethod", params.verificationMethod);
1445
- const response = await this._makeRequest("GET", `/api/v1/proofs/gate/check?${qs.toString()}`);
1778
+ let headersOverride = null;
1779
+ if (params.includePrivate === true) {
1780
+ const provided = params.privateAuth && typeof params.privateAuth === "object" ? params.privateAuth : null;
1781
+ let auth = provided;
1782
+ if (!auth) {
1783
+ const walletCandidate = params.wallet || this._getDefaultBrowserWallet();
1784
+ if (walletCandidate) {
1785
+ auth = await this._buildPrivateGateAuth({
1786
+ address,
1787
+ wallet: walletCandidate,
1788
+ chain: params.chain,
1789
+ signatureMethod: params.signatureMethod
1790
+ });
1791
+ }
1792
+ }
1793
+ if (!auth) {
1794
+ } else {
1795
+ const normalizedAuthWallet = this._normalizeIdentity(auth.walletAddress);
1796
+ const normalizedAddress = this._normalizeIdentity(address);
1797
+ if (!normalizedAuthWallet || normalizedAuthWallet !== normalizedAddress) {
1798
+ throw new ValidationError("privateAuth.walletAddress must match address when includePrivate=true");
1799
+ }
1800
+ const authChain = typeof auth.chain === "string" && auth.chain.includes(":") ? auth.chain.trim() : null;
1801
+ const authSignatureMethod = typeof auth.signatureMethod === "string" && auth.signatureMethod.trim() ? auth.signatureMethod.trim() : null;
1802
+ headersOverride = {
1803
+ "x-wallet-address": String(auth.walletAddress),
1804
+ "x-signature": String(auth.signature),
1805
+ "x-signed-timestamp": String(auth.signedTimestamp),
1806
+ ...authChain ? { "x-chain": authChain } : {},
1807
+ ...authSignatureMethod ? { "x-signature-method": authSignatureMethod } : {}
1808
+ };
1809
+ }
1810
+ }
1811
+ const response = await this._makeRequest("GET", `/api/v1/proofs/check?${qs.toString()}`, null, headersOverride);
1446
1812
  if (!response.success) {
1447
1813
  throw new ApiError(`Gate check failed: ${response.error?.message || "Unknown error"}`, response.error);
1448
1814
  }
@@ -1466,7 +1832,7 @@ ${bytes.length}`;
1466
1832
  * Supports verifier-specific:
1467
1833
  * - NFT/Token: 'contractAddress', 'tokenId', 'chainId', 'ownerAddress', 'minBalance'
1468
1834
  * - DNS: 'domain', 'walletAddress'
1469
- * - Wallet-link: 'primaryWalletAddress', 'secondaryWalletAddress', 'chainId'
1835
+ * - Wallet-link: 'primaryWalletAddress', 'secondaryWalletAddress', 'chain', 'signatureMethod'
1470
1836
  * - Contract-ownership: 'contractAddress', 'chainId', 'owner', 'verificationMethod'
1471
1837
  * Note: contentHash matching uses approximation in SDK; for exact SHA-256 matching, use backend API
1472
1838
  * @param {Array} [params.proofs] - Pre-fetched proofs (skip API call)
@@ -1483,7 +1849,7 @@ ${bytes.length}`;
1483
1849
  */
1484
1850
  async checkGate(params) {
1485
1851
  const { walletAddress, requirements, proofs: preloadedProofs } = params;
1486
- if (!walletAddress || !/^0x[a-fA-F0-9]{40}$/i.test(walletAddress)) {
1852
+ if (!validateUniversalAddress(walletAddress)) {
1487
1853
  throw new ValidationError("Valid walletAddress is required");
1488
1854
  }
1489
1855
  if (!Array.isArray(requirements) || requirements.length === 0) {
@@ -1677,16 +2043,20 @@ ${bytes.length}`;
1677
2043
  * @private
1678
2044
  */
1679
2045
  _formatResponse(response) {
1680
- const qHash = response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || response?.data?.id;
2046
+ const proofId = response?.data?.proofId || response?.proofId || response?.data?.resource?.proofId || response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || response?.data?.id;
2047
+ const qHash = response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || proofId || response?.data?.id;
2048
+ const finalProofId = proofId || qHash || null;
2049
+ const finalQHash = qHash || proofId || finalProofId;
1681
2050
  const status = response?.data?.status || response?.status || response?.data?.resource?.status || (response?.success ? "completed" : "unknown");
1682
2051
  return {
1683
2052
  success: response.success,
1684
- qHash,
2053
+ proofId: finalProofId,
2054
+ qHash: finalQHash,
1685
2055
  status,
1686
2056
  data: response.data,
1687
2057
  message: response.message,
1688
2058
  timestamp: Date.now(),
1689
- statusUrl: qHash ? `${this.baseUrl}/api/v1/verification/status/${qHash}` : null
2059
+ statusUrl: finalProofId ? `${this.baseUrl}/api/v1/verification/status/${finalProofId}` : null
1690
2060
  };
1691
2061
  }
1692
2062
  /**