@neus/sdk 1.0.1 → 1.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neus/sdk",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "NEUS SDK - Create and verify cryptographic proofs with simple, clean API",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/types.d.ts CHANGED
@@ -3,6 +3,20 @@
3
3
  */
4
4
 
5
5
  declare module '@neus/sdk' {
6
+ /**
7
+ * Minimal EIP-1193 provider interface (browser wallets like MetaMask).
8
+ * The SDK also supports other wallet objects; use this for typing in integrations.
9
+ */
10
+ export interface Eip1193Provider {
11
+ request(args: { method: string; params?: unknown[] | Record<string, unknown> }): Promise<unknown>;
12
+ }
13
+
14
+ /**
15
+ * Wallet/provider object accepted by SDK methods that require signing.
16
+ * Prefer passing an EIP-1193 provider in browser environments.
17
+ */
18
+ export type WalletLike = Eip1193Provider | { address?: string } | { getAddress?: () => Promise<string> } | { signMessage?: (message: string) => Promise<string> };
19
+
6
20
  /**
7
21
  * Main NEUS SDK client for creating and verifying proofs
8
22
  */
@@ -28,7 +42,7 @@ declare module '@neus/sdk' {
28
42
  * @param qHash - Proof ID (wire field: qHash)
29
43
  * @param wallet - Optional injected wallet/provider (MetaMask/ethers Wallet)
30
44
  */
31
- getPrivateStatus(qHash: string, wallet?: any): Promise<StatusResult>;
45
+ getPrivateStatus(qHash: string, wallet?: WalletLike): Promise<StatusResult>;
32
46
 
33
47
  /**
34
48
  * Check API health
@@ -58,7 +72,7 @@ declare module '@neus/sdk' {
58
72
  revokeOwnProof(qHash: string, wallet?: { address: string }): Promise<boolean>;
59
73
 
60
74
  // ═══════════════════════════════════════════════════════════════
61
- // GATE & LOOKUP METHODS
75
+ // PROOFS & GATING METHODS
62
76
  // ═══════════════════════════════════════════════════════════════
63
77
 
64
78
  /**
@@ -73,7 +87,7 @@ declare module '@neus/sdk' {
73
87
  * Get proofs by wallet or DID (owner access)
74
88
  * Requests private proofs using owner signature headers.
75
89
  */
76
- getPrivateProofsByWallet(walletAddress: string, options?: GetProofsOptions, wallet?: any): Promise<ProofsResult>;
90
+ getPrivateProofsByWallet(walletAddress: string, options?: GetProofsOptions, wallet?: WalletLike): Promise<ProofsResult>;
77
91
 
78
92
  /**
79
93
  * Minimal eligibility check against public + discoverable proofs only (API-backed).
@@ -81,12 +95,6 @@ declare module '@neus/sdk' {
81
95
  */
82
96
  gateCheck(params: GateCheckApiParams): Promise<GateCheckApiResponse>;
83
97
 
84
- /**
85
- * Non-persistent lookup mode (API-backed, server-side only).
86
- * Requires Premium API key and does NOT mint/store proofs.
87
- */
88
- lookup(params: LookupParams): Promise<LookupApiResponse>;
89
-
90
98
  /**
91
99
  * Evaluate gate requirements against existing proofs
92
100
  * Returns whether wallet satisfies all requirements, with missing items listed
@@ -117,7 +125,7 @@ declare module '@neus/sdk' {
117
125
  export interface NeusClientConfig {
118
126
  /** API endpoint URL (defaults to hosted public API) */
119
127
  apiUrl?: string;
120
- /** Optional premium API key (server-side only; do not embed in browser apps) */
128
+ /** Optional deployment API key (server-side only; do not embed in browser apps) */
121
129
  apiKey?: string;
122
130
  /** Request timeout in milliseconds */
123
131
  timeout?: number;
@@ -168,12 +176,12 @@ declare module '@neus/sdk' {
168
176
  signedTimestamp?: number;
169
177
  /** Advanced/manual path: chain ID for verification context; optional, managed by protocol */
170
178
  chainId?: number;
171
- /** Reserved (preview): non-EVM chain context as "namespace:reference" (not part of the stable public path) */
179
+ /** CAIP-2 chain reference for universal mode (e.g. eip155:1, solana:mainnet) */
172
180
  chain?: string;
173
- /** Reserved (preview): signature method hint (not part of the stable public path) */
181
+ /** Signature method hint for universal mode (eip191, ed25519, ...) */
174
182
  signatureMethod?: string;
175
183
  /** Auto path: optional wallet instance (browser/provider) */
176
- wallet?: any;
184
+ wallet?: WalletLike;
177
185
  }
178
186
 
179
187
  /**
@@ -548,7 +556,7 @@ declare module '@neus/sdk' {
548
556
 
549
557
 
550
558
  // ============================================================================
551
- // GATE & LOOKUP TYPES
559
+ // PROOFS & GATING TYPES
552
560
  // ============================================================================
553
561
 
554
562
  /**
@@ -650,9 +658,9 @@ declare module '@neus/sdk' {
650
658
  domain?: string;
651
659
  minBalance?: string;
652
660
 
653
- // Social / wallet filters
661
+ // Wallet filters
662
+ /** Risk assessment provider hint. Known value: webacy. */
654
663
  provider?: string;
655
- handle?: string;
656
664
  ownerAddress?: string;
657
665
  riskLevel?: string;
658
666
  sanctioned?: boolean;
@@ -660,12 +668,6 @@ declare module '@neus/sdk' {
660
668
  primaryWalletAddress?: string;
661
669
  secondaryWalletAddress?: string;
662
670
  verificationMethod?: string;
663
-
664
- // Trait checks + projections
665
- traitPath?: string;
666
- traitGte?: number;
667
- /** Comma-separated projection fields (handle,provider,profileUrl,traits.<key>) */
668
- select?: string[] | string;
669
671
  }
670
672
 
671
673
  export interface GateCheckApiResponse {
@@ -681,38 +683,6 @@ declare module '@neus/sdk' {
681
683
  error?: any;
682
684
  }
683
685
 
684
- /**
685
- * Parameters for lookup() (API-backed).
686
- * Mirrors `POST /api/v1/verification/lookup` body.
687
- */
688
- export interface LookupParams {
689
- /** Premium API key (sk_live_... or sk_test_...) */
690
- apiKey: string;
691
- /** Verifiers to run (external_lookup only) */
692
- verifierIds: string[];
693
- /** Wallet to evaluate */
694
- targetWalletAddress: string;
695
- /** Verifier input data (e.g., contractAddress/tokenId/chainId) */
696
- data?: Record<string, any>;
697
- }
698
-
699
- export interface LookupApiResponse {
700
- success: boolean;
701
- data?: {
702
- mode: 'lookup';
703
- requestId: string;
704
- targetWalletAddress: string;
705
- payerWallet: string;
706
- verifierIds: string[];
707
- verified: boolean;
708
- results: any[];
709
- timing?: {
710
- startedAt: number;
711
- durationMs: number;
712
- };
713
- };
714
- error?: any;
715
- }
716
686
 
717
687
  export interface ApiResponse<T = any> {
718
688
  success: boolean;
@@ -778,12 +748,27 @@ declare module '@neus/sdk' {
778
748
  // SUPPORTING TYPES
779
749
  // ============================================================================
780
750
 
781
- interface VerificationData {
782
- content?: string;
751
+ type OwnershipBasicData = {
783
752
  owner: string;
753
+ content?: string;
754
+ contentHash?: string;
755
+ contentType?: string;
784
756
  reference?: {
785
- type: string;
786
- /** Optional reference identifier (required only for reference-only proofs). */
757
+ type:
758
+ | 'ipfs'
759
+ | 'ipfs-hash'
760
+ | 'url'
761
+ | 'license-nft'
762
+ | 'contract'
763
+ | 'qhash'
764
+ | 'ethereum-tx'
765
+ | 'on-chain-tx'
766
+ | 'tx'
767
+ | 'file'
768
+ | 'doc'
769
+ | 'media'
770
+ | 'username-claim'
771
+ | 'other';
787
772
  id?: string;
788
773
  title?: string;
789
774
  description?: string;
@@ -791,8 +776,135 @@ declare module '@neus/sdk' {
791
776
  name?: string;
792
777
  size?: number;
793
778
  };
779
+ provenance?: {
780
+ declaredKind?: 'human' | 'ai' | 'mixed' | 'unknown';
781
+ aiContext?: {
782
+ generatorType?: 'local' | 'saas' | 'agent';
783
+ provider?: string;
784
+ model?: string;
785
+ runId?: string;
786
+ };
787
+ };
794
788
  [key: string]: any;
795
- }
789
+ };
790
+
791
+ type OwnershipPseudonymData = {
792
+ pseudonymId: string;
793
+ namespace?: string;
794
+ displayName?: string;
795
+ metadata?: Record<string, any>;
796
+ [key: string]: any;
797
+ };
798
+
799
+ type OwnershipDnsTxtData = {
800
+ domain: string;
801
+ walletAddress?: string;
802
+ [key: string]: any;
803
+ };
804
+
805
+ type ContractOwnershipData = {
806
+ contractAddress: string;
807
+ chainId: number;
808
+ walletAddress?: string;
809
+ method?: 'owner' | 'admin' | 'accessControl';
810
+ [key: string]: any;
811
+ };
812
+
813
+ type NftOwnershipData = {
814
+ ownerAddress?: string;
815
+ contractAddress: string;
816
+ tokenId: string;
817
+ tokenType?: 'erc721' | 'erc1155';
818
+ chainId: number;
819
+ blockNumber?: number;
820
+ [key: string]: any;
821
+ };
822
+
823
+ type TokenHoldingData = {
824
+ ownerAddress?: string;
825
+ contractAddress: string;
826
+ minBalance: string;
827
+ chainId: number;
828
+ blockNumber?: number;
829
+ [key: string]: any;
830
+ };
831
+
832
+ type WalletRiskData = {
833
+ /** Risk assessment provider hint. Known value: webacy. */
834
+ provider?: string;
835
+ walletAddress?: string;
836
+ chainId?: number;
837
+ includeDetails?: boolean;
838
+ [key: string]: any;
839
+ };
840
+
841
+ type WalletLinkData = {
842
+ primaryWalletAddress: string;
843
+ secondaryWalletAddress: string;
844
+ signature: string;
845
+ chainId: number;
846
+ signedTimestamp: number;
847
+ relationshipType?: 'primary' | 'personal' | 'org' | 'affiliate' | 'agent' | 'linked';
848
+ label?: string;
849
+ [key: string]: any;
850
+ };
851
+
852
+ type AiContentModerationData = {
853
+ content: string;
854
+ contentType:
855
+ | 'image/jpeg'
856
+ | 'image/png'
857
+ | 'image/webp'
858
+ | 'image/gif'
859
+ | 'text/plain'
860
+ | 'text/markdown'
861
+ | 'text/x-markdown'
862
+ | 'application/json'
863
+ | 'application/xml';
864
+ provider?: 'google-vision' | 'google-perspective';
865
+ [key: string]: any;
866
+ };
867
+
868
+ type AgentIdentityData = {
869
+ agentId: string;
870
+ agentWallet: string;
871
+ agentLabel?: string;
872
+ agentType?: 'ai' | 'bot' | 'service' | 'automation' | 'agent';
873
+ description?: string;
874
+ capabilities?: any[];
875
+ [key: string]: any;
876
+ };
877
+
878
+ type AgentDelegationData = {
879
+ controllerWallet: string;
880
+ agentWallet: string;
881
+ agentId?: string;
882
+ scope?: string;
883
+ permissions?: any[];
884
+ maxSpend?: string;
885
+ allowedPaymentTypes?: string[];
886
+ receiptDisclosure?: 'none' | 'summary' | 'full';
887
+ expiresAt?: number;
888
+ [key: string]: any;
889
+ };
890
+
891
+ type CoreVerificationData =
892
+ | OwnershipBasicData
893
+ | OwnershipPseudonymData
894
+ | OwnershipDnsTxtData
895
+ | ContractOwnershipData
896
+ | NftOwnershipData
897
+ | TokenHoldingData
898
+ | WalletRiskData
899
+ | WalletLinkData
900
+ | AiContentModerationData
901
+ | AgentIdentityData
902
+ | AgentDelegationData;
903
+
904
+ type VerificationData =
905
+ | CoreVerificationData
906
+ | Record<string, CoreVerificationData>
907
+ | Record<string, any>;
796
908
 
797
909
 
798
910
 
package/utils.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Core utility functions for proof creation and verification
4
4
  */
5
5
 
6
- import { SDKError } from './errors.js';
6
+ import { SDKError, ApiError, ValidationError } from './errors.js';
7
7
 
8
8
  /**
9
9
  * Deterministic JSON stringification for consistent serialization
@@ -58,11 +58,11 @@ export function constructVerificationMessage({ walletAddress, signedTimestamp, d
58
58
  throw new SDKError('verifierIds is required and must be a non-empty array', 'INVALID_VERIFIER_IDS');
59
59
  }
60
60
 
61
- // Chain context: prefer explicit `chain` when provided (reserved/preview for non-EVM),
61
+ // Chain context: prefer explicit `chain` when provided (e.g. "solana:mainnet"),
62
62
  // otherwise use numeric `chainId` (EVM-first public surface).
63
63
  const chainContext = (typeof chain === 'string' && chain.length > 0) ? chain : chainId;
64
64
  if (!chainContext) {
65
- throw new SDKError('chainId is required (or provide chain for preview mode)', 'INVALID_CHAIN_CONTEXT');
65
+ throw new SDKError('chainId is required (or provide chain for universal mode)', 'INVALID_CHAIN_CONTEXT');
66
66
  }
67
67
  if (chainContext === chainId && typeof chainId !== 'number') {
68
68
  throw new SDKError('chainId must be a number when provided', 'INVALID_CHAIN_ID');
@@ -442,10 +442,28 @@ export class StatusPoller {
442
442
  setTimeout(pollAttempt, this.currentInterval);
443
443
 
444
444
  } catch (error) {
445
- reject(new SDKError(
446
- `Polling failed: ${error.message}`,
447
- 'POLLING_ERROR'
448
- ));
445
+ if (error instanceof ValidationError) {
446
+ reject(error);
447
+ return;
448
+ }
449
+
450
+ if ((error instanceof ApiError && error.statusCode === 429) || error?.isRetryable === true) {
451
+ if (this.options.exponentialBackoff) {
452
+ const next = Math.min(this.currentInterval * 2, this.options.maxInterval);
453
+ const jitter = next * (0.5 + Math.random() * 0.5);
454
+ this.currentInterval = Math.max(250, Math.floor(jitter));
455
+ }
456
+
457
+ if (this.attempt >= this.options.maxAttempts) {
458
+ reject(new SDKError('Verification polling timeout', 'POLLING_TIMEOUT'));
459
+ return;
460
+ }
461
+
462
+ setTimeout(pollAttempt, this.currentInterval);
463
+ return;
464
+ }
465
+
466
+ reject(new SDKError(`Polling failed: ${error.message}`, 'POLLING_ERROR'));
449
467
  }
450
468
  };
451
469
 
@@ -564,9 +582,17 @@ export function validateVerifierPayload(verifierId, data) {
564
582
  result.warnings.push('ownerAddress omitted (most deployments default to the signed walletAddress)');
565
583
  }
566
584
  } else if (id === 'ownership-basic') {
567
- ['content'].forEach((key) => {
568
- if (!(key in data)) result.missing.push(key);
569
- });
585
+ // ownership-basic requires an owner, and needs at least one binding:
586
+ // - content (inline), or
587
+ // - contentHash (recommended for large content), or
588
+ // - reference.id (reference-only proofs)
589
+ if (!('owner' in data)) result.missing.push('owner');
590
+ const hasContent = typeof data.content === 'string' && data.content.length > 0;
591
+ const hasContentHash = typeof data.contentHash === 'string' && data.contentHash.length > 0;
592
+ const hasRefId = typeof data.reference?.id === 'string' && data.reference.id.length > 0;
593
+ if (!hasContent && !hasContentHash && !hasRefId) {
594
+ result.missing.push('content (or contentHash or reference.id)');
595
+ }
570
596
  }
571
597
 
572
598
  if (result.missing.length > 0) {
@@ -336,7 +336,7 @@ function VerifyGate({
336
336
  const dataForVerifier = buildDataForVerifier(verifierId);
337
337
  const params = verifierId === "ownership-basic" && dataForVerifier === null ? {
338
338
  verifier: "ownership-basic",
339
- content: verifierData?.["ownership-basic"]?.content || `NEUS verification (${verifierId})`,
339
+ content: (typeof verifierData?.["ownership-basic"] === "string" ? verifierData["ownership-basic"] : verifierData?.["ownership-basic"]?.content) || `NEUS verification (${verifierId})`,
340
340
  options: resolvedProofOptions
341
341
  } : {
342
342
  verifier: verifierId,