@neus/sdk 1.0.4 → 1.0.6
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/README.md +21 -4
- package/SECURITY.md +11 -6
- package/cjs/client.cjs +132 -220
- package/cjs/gates.cjs +10 -33
- package/cjs/index.cjs +143 -252
- package/cjs/utils.cjs +0 -6
- package/cli/neus.mjs +589 -41
- package/client.js +1834 -1955
- package/errors.js +0 -34
- package/gates.js +73 -175
- package/index.js +0 -9
- package/package.json +5 -4
- package/types.d.ts +14 -459
- package/utils.js +1 -265
- package/widgets/README.md +45 -45
- package/widgets/index.js +0 -8
- package/widgets/verify-gate/dist/ProofBadge.js +0 -3
- package/widgets/verify-gate/dist/VerifyGate.js +58 -78
- package/widgets/verify-gate/index.js +0 -4
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@neus/sdk)
|
|
4
4
|
|
|
5
|
-
**Portable trust, shipped as APIs and widgets.** The JavaScript SDK runs NEUS verification, polling, and **`gateCheck`**. Store **`proofId
|
|
5
|
+
**Portable trust, shipped as APIs and widgets.** The JavaScript SDK runs NEUS verification, polling, and **`gateCheck`**. Store **`proofId`**, then reuse it. NEUS runs the checks; you do not fork verifier logic into your repo.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -16,7 +16,22 @@ npm install @neus/sdk
|
|
|
16
16
|
npx -y -p @neus/sdk neus init
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Configures supported MCP clients automatically. By default the command installs NEUS into user-level Claude Code, Cursor, and VS Code MCP config when those clients are detected.
|
|
20
|
+
|
|
21
|
+
## CLI
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Autopilot setup for detected clients
|
|
25
|
+
npx -y -p @neus/sdk neus init
|
|
26
|
+
|
|
27
|
+
# Enable personal account tools such as neus_me and private reads
|
|
28
|
+
npx -y -p @neus/sdk neus auth --access-key <npk_...>
|
|
29
|
+
|
|
30
|
+
# Inspect current NEUS MCP setup
|
|
31
|
+
npx -y -p @neus/sdk neus status --json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Use `neus init --project` when you want shared repo config instead of personal user-scope setup. Access keys stay user-scope only so secrets do not land in checked-in config.
|
|
20
35
|
|
|
21
36
|
## Minimal working example
|
|
22
37
|
|
|
@@ -51,10 +66,11 @@ const check = await client.gateCheck({
|
|
|
51
66
|
| `client.gateCheck()` | **Server eligibility** (use for real gates) |
|
|
52
67
|
| `client.checkGate()` | Local preview only |
|
|
53
68
|
| `getHostedCheckoutUrl()` | Hosted verify URL |
|
|
69
|
+
| `client.createWalletLinkData()` | Build advanced direct wallet-link payload |
|
|
54
70
|
|
|
55
71
|
## VerifyGate (React)
|
|
56
72
|
|
|
57
|
-
Defaults:
|
|
73
|
+
Defaults: private create (`privacyLevel: 'private'`, `publicDisplay: false`). Set `proofOptions` only when you intentionally need public visibility.
|
|
58
74
|
|
|
59
75
|
```jsx
|
|
60
76
|
import { VerifyGate } from '@neus/sdk/widgets';
|
|
@@ -79,8 +95,9 @@ const client = new NeusClient({
|
|
|
79
95
|
## Docs
|
|
80
96
|
|
|
81
97
|
- [Quickstart](https://docs.neus.network/quickstart)
|
|
98
|
+
- [Examples](https://docs.neus.network/examples) — start with the [trust receipts showcase](https://github.com/neus/network/tree/main/examples/trust-receipts-showcase) locally; [live demo](https://neus.network/demo) on the product site
|
|
82
99
|
- [SDK](https://docs.neus.network/sdks/javascript)
|
|
83
|
-
- [MCP](https://docs.neus.network/mcp/overview)
|
|
100
|
+
- [MCP](https://docs.neus.network/mcp/overview) for IDEs and assistants
|
|
84
101
|
- [Widgets](https://docs.neus.network/widgets/overview)
|
|
85
102
|
- [API](https://docs.neus.network/api/overview)
|
|
86
103
|
- [Hosted Verify](https://docs.neus.network/cookbook/auth-hosted-verify)
|
package/SECURITY.md
CHANGED
|
@@ -16,18 +16,23 @@ Treat **wallet signatures** and **API keys** as secrets. Do not log them, expose
|
|
|
16
16
|
|
|
17
17
|
## Privacy defaults
|
|
18
18
|
|
|
19
|
-
**`client.verify()`** defaults to **private
|
|
19
|
+
**`client.verify()`** defaults to **private**.
|
|
20
20
|
|
|
21
|
-
**`VerifyGate`** create mode defaults to **
|
|
21
|
+
**`VerifyGate`** create mode also defaults to **private**.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Use public visibility only when you intentionally need proof reuse without owner-authenticated access:
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
- unlisted public: `privacyLevel: 'public'`, `publicDisplay: false`
|
|
26
|
+
- listed public: `privacyLevel: 'public'`, `publicDisplay: true`
|
|
27
|
+
|
|
28
|
+
Do not treat unlisted public proofs as secret.
|
|
29
|
+
|
|
30
|
+
`storeOriginalContent` is an advanced storage control. Most integrations should leave the default as-is.
|
|
26
31
|
|
|
27
32
|
Controls:
|
|
28
33
|
|
|
29
|
-
- `privacyLevel` - private
|
|
34
|
+
- `privacyLevel` - private by default; switch to public only for intentional public reuse
|
|
30
35
|
- `publicDisplay` - discovery vs unlisted
|
|
31
|
-
- `storeOriginalContent` -
|
|
36
|
+
- `storeOriginalContent` - advanced content-storage control
|
|
32
37
|
|
|
33
38
|
Discoverable listings require **`privacyLevel: 'public'`** and **`publicDisplay: true`**.
|
package/cjs/client.cjs
CHANGED
|
@@ -364,9 +364,7 @@ async function signMessage({ provider, message, walletAddress, chain } = {}) {
|
|
|
364
364
|
throw new SDKError("Unable to sign message with provided wallet/provider", "SIGNER_UNAVAILABLE");
|
|
365
365
|
}
|
|
366
366
|
var NEUS_CONSTANTS = {
|
|
367
|
-
/** Default EVM chain id for NEUS protocol signing context (`HUB_CHAIN_ID` name kept for compatibility). */
|
|
368
367
|
HUB_CHAIN_ID: 84532,
|
|
369
|
-
// Supported target chains for cross-chain propagation
|
|
370
368
|
TESTNET_CHAINS: [
|
|
371
369
|
11155111,
|
|
372
370
|
// Ethereum Sepolia
|
|
@@ -377,15 +375,12 @@ var NEUS_CONSTANTS = {
|
|
|
377
375
|
80002
|
|
378
376
|
// Polygon Amoy
|
|
379
377
|
],
|
|
380
|
-
// API endpoints
|
|
381
378
|
API_BASE_URL: "https://api.neus.network",
|
|
382
379
|
API_VERSION: "v1",
|
|
383
|
-
// Timeouts and limits
|
|
384
380
|
SIGNATURE_MAX_AGE_MS: 5 * 60 * 1e3,
|
|
385
381
|
// 5 minutes
|
|
386
382
|
REQUEST_TIMEOUT_MS: 30 * 1e3,
|
|
387
383
|
// 30 seconds
|
|
388
|
-
// Default verifier set for quick starts
|
|
389
384
|
DEFAULT_VERIFIERS: [
|
|
390
385
|
"ownership-basic",
|
|
391
386
|
"nft-ownership",
|
|
@@ -411,6 +406,21 @@ var FALLBACK_PUBLIC_VERIFIER_CATALOG = {
|
|
|
411
406
|
"ai-content-moderation": { supportsDirectApi: true }
|
|
412
407
|
};
|
|
413
408
|
var EVM_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
|
|
409
|
+
var WALLET_LINK_RELATIONSHIP_TYPES = /* @__PURE__ */ new Set(["primary", "personal", "org", "affiliate", "agent", "linked"]);
|
|
410
|
+
function normalizeWalletLinkRelationshipType(value) {
|
|
411
|
+
const normalized = String(value || "").trim().toLowerCase();
|
|
412
|
+
return WALLET_LINK_RELATIONSHIP_TYPES.has(normalized) ? normalized : "linked";
|
|
413
|
+
}
|
|
414
|
+
function normalizeBrowserSignerString(raw) {
|
|
415
|
+
if (raw === null || raw === void 0) {
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
if (typeof raw === "string") {
|
|
419
|
+
const t = raw.trim();
|
|
420
|
+
return t.length > 0 ? t : null;
|
|
421
|
+
}
|
|
422
|
+
return null;
|
|
423
|
+
}
|
|
414
424
|
var validateVerifierData = (verifierId, data) => {
|
|
415
425
|
if (!data || typeof data !== "object") {
|
|
416
426
|
return { valid: false, error: "Data object is required" };
|
|
@@ -739,26 +749,49 @@ var NeusClient = class {
|
|
|
739
749
|
if (!wallet) {
|
|
740
750
|
throw new ConfigurationError("No wallet provider available");
|
|
741
751
|
}
|
|
742
|
-
if (wallet.address) {
|
|
743
|
-
|
|
752
|
+
if (wallet.address !== null && wallet.address !== void 0) {
|
|
753
|
+
const s = normalizeBrowserSignerString(
|
|
754
|
+
typeof wallet.address === "string" ? wallet.address : null
|
|
755
|
+
);
|
|
756
|
+
if (s) {
|
|
757
|
+
return { signerWalletAddress: s, provider: wallet };
|
|
758
|
+
}
|
|
744
759
|
}
|
|
745
760
|
if (wallet.publicKey && typeof wallet.publicKey.toBase58 === "function") {
|
|
746
|
-
|
|
761
|
+
const b58 = wallet.publicKey.toBase58();
|
|
762
|
+
const s = normalizeBrowserSignerString(typeof b58 === "string" ? b58 : null);
|
|
763
|
+
if (s) {
|
|
764
|
+
return { signerWalletAddress: s, provider: wallet };
|
|
765
|
+
}
|
|
747
766
|
}
|
|
748
767
|
if (typeof wallet.getAddress === "function") {
|
|
749
|
-
const
|
|
750
|
-
|
|
768
|
+
const got = await wallet.getAddress().catch(() => null);
|
|
769
|
+
const s = normalizeBrowserSignerString(
|
|
770
|
+
got === null || got === void 0 ? null : typeof got === "string" ? got : null
|
|
771
|
+
);
|
|
772
|
+
if (s) {
|
|
773
|
+
return { signerWalletAddress: s, provider: wallet };
|
|
774
|
+
}
|
|
751
775
|
}
|
|
752
776
|
if (wallet.selectedAddress || wallet.request) {
|
|
753
777
|
const provider = wallet;
|
|
754
778
|
if (wallet.selectedAddress) {
|
|
755
|
-
|
|
779
|
+
const s2 = normalizeBrowserSignerString(
|
|
780
|
+
typeof wallet.selectedAddress === "string" ? wallet.selectedAddress : null
|
|
781
|
+
);
|
|
782
|
+
if (s2) {
|
|
783
|
+
return { signerWalletAddress: s2, provider };
|
|
784
|
+
}
|
|
756
785
|
}
|
|
757
786
|
const accounts = await provider.request({ method: "eth_accounts" });
|
|
758
787
|
if (!accounts || accounts.length === 0) {
|
|
759
788
|
throw new ConfigurationError("No wallet accounts available");
|
|
760
789
|
}
|
|
761
|
-
|
|
790
|
+
const s = normalizeBrowserSignerString(accounts[0]);
|
|
791
|
+
if (!s) {
|
|
792
|
+
throw new ConfigurationError("No wallet accounts available");
|
|
793
|
+
}
|
|
794
|
+
return { signerWalletAddress: s, provider };
|
|
762
795
|
}
|
|
763
796
|
throw new ConfigurationError("Invalid wallet provider");
|
|
764
797
|
}
|
|
@@ -821,47 +854,74 @@ var NeusClient = class {
|
|
|
821
854
|
signatureMethod: params.signatureMethod
|
|
822
855
|
});
|
|
823
856
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
857
|
+
async createWalletLinkData(params = {}) {
|
|
858
|
+
const normalizedPrimary = this._normalizeIdentity(params.primaryWalletAddress);
|
|
859
|
+
const normalizedSecondary = this._normalizeIdentity(params.secondaryWalletAddress);
|
|
860
|
+
if (!EVM_ADDRESS_RE.test(normalizedPrimary)) {
|
|
861
|
+
throw new ValidationError("wallet-link requires a valid primaryWalletAddress");
|
|
862
|
+
}
|
|
863
|
+
if (!EVM_ADDRESS_RE.test(normalizedSecondary)) {
|
|
864
|
+
throw new ValidationError("wallet-link requires a valid secondaryWalletAddress");
|
|
865
|
+
}
|
|
866
|
+
if (normalizedPrimary === normalizedSecondary) {
|
|
867
|
+
throw new ValidationError("wallet-link secondaryWalletAddress must differ from primaryWalletAddress");
|
|
868
|
+
}
|
|
869
|
+
const providerWallet = params.wallet || this._getDefaultBrowserWallet();
|
|
870
|
+
const { signerWalletAddress, provider } = await this._resolveWalletSigner(providerWallet);
|
|
871
|
+
const normalizedSigner = this._normalizeIdentity(signerWalletAddress);
|
|
872
|
+
if (!EVM_ADDRESS_RE.test(normalizedSigner)) {
|
|
873
|
+
throw new ValidationError("wallet-link requires an EVM wallet/provider for the secondary wallet");
|
|
874
|
+
}
|
|
875
|
+
if (normalizedSigner !== normalizedSecondary) {
|
|
876
|
+
throw new ValidationError("wallet-link wallet/provider must be connected to secondaryWalletAddress");
|
|
877
|
+
}
|
|
878
|
+
const resolvedChain = (() => {
|
|
879
|
+
const raw = String(params.chain || "").trim();
|
|
880
|
+
if (!raw) return `eip155:${this._getHubChainId()}`;
|
|
881
|
+
if (!/^eip155:\d+$/.test(raw)) {
|
|
882
|
+
throw new ValidationError("wallet-link requires chain in the form eip155:<chainId>");
|
|
883
|
+
}
|
|
884
|
+
return raw;
|
|
885
|
+
})();
|
|
886
|
+
const signedTimestamp = Number.isFinite(Number(params.signedTimestamp)) && Number(params.signedTimestamp) > 0 ? Number(params.signedTimestamp) : Date.now();
|
|
887
|
+
const linkData = {
|
|
888
|
+
primaryAccountId: `${resolvedChain}:${normalizedPrimary}`,
|
|
889
|
+
secondaryAccountId: `${resolvedChain}:${normalizedSecondary}`,
|
|
890
|
+
primaryWalletAddress: normalizedPrimary,
|
|
891
|
+
secondaryWalletAddress: normalizedSecondary
|
|
892
|
+
};
|
|
893
|
+
const message = constructVerificationMessage({
|
|
894
|
+
walletAddress: normalizedSecondary,
|
|
895
|
+
signedTimestamp,
|
|
896
|
+
data: linkData,
|
|
897
|
+
verifierIds: ["wallet-link"],
|
|
898
|
+
chain: resolvedChain
|
|
899
|
+
});
|
|
900
|
+
let signature;
|
|
901
|
+
try {
|
|
902
|
+
signature = await signMessage({
|
|
903
|
+
provider,
|
|
904
|
+
message,
|
|
905
|
+
walletAddress: signerWalletAddress
|
|
906
|
+
});
|
|
907
|
+
} catch (error) {
|
|
908
|
+
if (error?.code === 4001) {
|
|
909
|
+
throw new ValidationError("User rejected wallet-link signature request");
|
|
910
|
+
}
|
|
911
|
+
throw new ValidationError(`Failed to sign wallet-link message: ${error?.message || String(error)}`);
|
|
912
|
+
}
|
|
913
|
+
const label = String(params.label || "").trim().slice(0, 64);
|
|
914
|
+
return {
|
|
915
|
+
primaryWalletAddress: normalizedPrimary,
|
|
916
|
+
secondaryWalletAddress: normalizedSecondary,
|
|
917
|
+
signature,
|
|
918
|
+
chain: resolvedChain,
|
|
919
|
+
signatureMethod: "eip191",
|
|
920
|
+
signedTimestamp,
|
|
921
|
+
relationshipType: normalizeWalletLinkRelationshipType(params.relationshipType),
|
|
922
|
+
...label ? { label } : {}
|
|
923
|
+
};
|
|
924
|
+
}
|
|
865
925
|
async verify(params) {
|
|
866
926
|
if ((!params?.signature || !params?.walletAddress) && (params?.verifier || params?.content || params?.data)) {
|
|
867
927
|
const { content, verifier = "ownership-basic", data: data2 = null, wallet = null, options: options2 = {} } = params;
|
|
@@ -903,11 +963,16 @@ var NeusClient = class {
|
|
|
903
963
|
}
|
|
904
964
|
let walletAddress2, provider;
|
|
905
965
|
if (wallet) {
|
|
906
|
-
walletAddress2 = wallet.address || wallet.selectedAddress || wallet.walletAddress || (typeof wallet.getAddress === "function" ? await wallet.getAddress() : null);
|
|
966
|
+
walletAddress2 = wallet.address || wallet.selectedAddress || wallet.walletAddress || (typeof wallet.getAddress === "function" ? await wallet.getAddress().catch(() => null) : null);
|
|
907
967
|
provider = wallet.provider || wallet;
|
|
908
968
|
if (!walletAddress2 && provider && typeof provider.request === "function") {
|
|
909
|
-
|
|
910
|
-
walletAddress2 = Array.isArray(accounts) ? accounts[0] : null;
|
|
969
|
+
let accounts = await provider.request({ method: "eth_accounts" });
|
|
970
|
+
walletAddress2 = Array.isArray(accounts) && accounts.length > 0 ? accounts[0] : null;
|
|
971
|
+
if (!walletAddress2) {
|
|
972
|
+
await provider.request({ method: "eth_requestAccounts" });
|
|
973
|
+
accounts = await provider.request({ method: "eth_accounts" });
|
|
974
|
+
walletAddress2 = Array.isArray(accounts) && accounts.length > 0 ? accounts[0] : null;
|
|
975
|
+
}
|
|
911
976
|
}
|
|
912
977
|
} else {
|
|
913
978
|
if (typeof window === "undefined" || !window.ethereum) {
|
|
@@ -918,6 +983,15 @@ var NeusClient = class {
|
|
|
918
983
|
const accounts = await provider.request({ method: "eth_accounts" });
|
|
919
984
|
walletAddress2 = accounts[0];
|
|
920
985
|
}
|
|
986
|
+
{
|
|
987
|
+
const normalized = normalizeBrowserSignerString(
|
|
988
|
+
typeof walletAddress2 === "string" ? walletAddress2 : null
|
|
989
|
+
);
|
|
990
|
+
if (!normalized) {
|
|
991
|
+
throw new ConfigurationError("No wallet accounts available. Connect a wallet to continue.");
|
|
992
|
+
}
|
|
993
|
+
walletAddress2 = normalized;
|
|
994
|
+
}
|
|
921
995
|
let verificationData;
|
|
922
996
|
if (verifier === "ownership-basic") {
|
|
923
997
|
if (data2 && typeof data2 === "object") {
|
|
@@ -1069,8 +1143,6 @@ var NeusClient = class {
|
|
|
1069
1143
|
verificationData = {
|
|
1070
1144
|
walletAddress: data2?.walletAddress || walletAddress2,
|
|
1071
1145
|
...data2?.provider && { provider: data2.provider },
|
|
1072
|
-
// Mainnet-first semantics: if caller doesn't provide chainId, default to Ethereum mainnet (1).
|
|
1073
|
-
// This avoids accidental testnet semantics for risk providers.
|
|
1074
1146
|
chainId: typeof data2?.chainId === "number" && Number.isFinite(data2.chainId) ? data2.chainId : 1,
|
|
1075
1147
|
...data2?.includeDetails !== void 0 && { includeDetails: data2.includeDetails }
|
|
1076
1148
|
};
|
|
@@ -1092,7 +1164,6 @@ var NeusClient = class {
|
|
|
1092
1164
|
data: verificationData,
|
|
1093
1165
|
verifierIds: verifierIds2,
|
|
1094
1166
|
chainId: this._getHubChainId()
|
|
1095
|
-
// Protocol-managed chain
|
|
1096
1167
|
});
|
|
1097
1168
|
let signature2;
|
|
1098
1169
|
try {
|
|
@@ -1128,6 +1199,7 @@ var NeusClient = class {
|
|
|
1128
1199
|
const hexMsg = toHexUtf82(message);
|
|
1129
1200
|
signature2 = await provider.request({ method: "personal_sign", params: [hexMsg, walletAddress2] });
|
|
1130
1201
|
} catch (e) {
|
|
1202
|
+
void e;
|
|
1131
1203
|
}
|
|
1132
1204
|
}
|
|
1133
1205
|
if (!signature2) {
|
|
@@ -1237,7 +1309,6 @@ ${bytes.length}`;
|
|
|
1237
1309
|
const optionsPayload = {
|
|
1238
1310
|
...options && typeof options === "object" ? options : {},
|
|
1239
1311
|
targetChains: Array.isArray(options?.targetChains) ? options.targetChains : [],
|
|
1240
|
-
// Privacy and storage options (defaults)
|
|
1241
1312
|
privacyLevel: options?.privacyLevel || "private",
|
|
1242
1313
|
publicDisplay: options?.publicDisplay || false,
|
|
1243
1314
|
storeOriginalContent: typeof options?.storeOriginalContent === "boolean" ? options.storeOriginalContent : true
|
|
@@ -1260,16 +1331,6 @@ ${bytes.length}`;
|
|
|
1260
1331
|
}
|
|
1261
1332
|
return this._formatResponse(response);
|
|
1262
1333
|
}
|
|
1263
|
-
/**
|
|
1264
|
-
* Get proof record by proof receipt id.
|
|
1265
|
-
*
|
|
1266
|
-
* @param {string} proofId - Proof receipt ID (0x + 64 hex).
|
|
1267
|
-
* @returns {Promise<Object>} Proof record and verification state
|
|
1268
|
-
*
|
|
1269
|
-
* @example
|
|
1270
|
-
* const result = await client.getProof('0x...');
|
|
1271
|
-
* console.log('Status:', result.status);
|
|
1272
|
-
*/
|
|
1273
1334
|
async getProof(proofId) {
|
|
1274
1335
|
if (!proofId || typeof proofId !== "string") {
|
|
1275
1336
|
throw new ValidationError("proofId is required");
|
|
@@ -1280,16 +1341,6 @@ ${bytes.length}`;
|
|
|
1280
1341
|
}
|
|
1281
1342
|
return this._formatResponse(response);
|
|
1282
1343
|
}
|
|
1283
|
-
/**
|
|
1284
|
-
* Get private proof record with wallet signature
|
|
1285
|
-
*
|
|
1286
|
-
* @param {string} proofId - Proof receipt ID.
|
|
1287
|
-
* @param {Object} wallet - Wallet provider (window.ethereum or ethers Wallet)
|
|
1288
|
-
* @returns {Promise<Object>} Private proof record and verification state
|
|
1289
|
-
*
|
|
1290
|
-
* @example
|
|
1291
|
-
* const privateData = await client.getPrivateProof(proofId, window.ethereum);
|
|
1292
|
-
*/
|
|
1293
1344
|
async getPrivateProof(proofId, wallet = null) {
|
|
1294
1345
|
if (!proofId || typeof proofId !== "string") {
|
|
1295
1346
|
throw new ValidationError("proofId is required");
|
|
@@ -1357,11 +1408,6 @@ ${bytes.length}`;
|
|
|
1357
1408
|
}
|
|
1358
1409
|
return this._formatResponse(response);
|
|
1359
1410
|
}
|
|
1360
|
-
/**
|
|
1361
|
-
* Check API health
|
|
1362
|
-
*
|
|
1363
|
-
* @returns {Promise<boolean>} True if API is healthy
|
|
1364
|
-
*/
|
|
1365
1411
|
async isHealthy() {
|
|
1366
1412
|
try {
|
|
1367
1413
|
const response = await this._makeRequest("GET", "/api/v1/health");
|
|
@@ -1370,19 +1416,10 @@ ${bytes.length}`;
|
|
|
1370
1416
|
return false;
|
|
1371
1417
|
}
|
|
1372
1418
|
}
|
|
1373
|
-
/**
|
|
1374
|
-
* List available verifiers
|
|
1375
|
-
*
|
|
1376
|
-
* @returns {Promise<string[]>} Array of verifier IDs
|
|
1377
|
-
*/
|
|
1378
1419
|
async getVerifiers() {
|
|
1379
1420
|
const catalog = await this.getVerifierCatalog();
|
|
1380
1421
|
return Array.isArray(catalog?.data) ? catalog.data : [];
|
|
1381
1422
|
}
|
|
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
1423
|
async getVerifierCatalog() {
|
|
1387
1424
|
const response = await this._makeRequest("GET", "/api/v1/verification/verifiers");
|
|
1388
1425
|
if (!response.success) {
|
|
@@ -1394,31 +1431,6 @@ ${bytes.length}`;
|
|
|
1394
1431
|
meta: response.meta && typeof response.meta === "object" && !Array.isArray(response.meta) ? response.meta : {}
|
|
1395
1432
|
};
|
|
1396
1433
|
}
|
|
1397
|
-
/**
|
|
1398
|
-
* POLL PROOF STATUS - Wait for verification completion
|
|
1399
|
-
*
|
|
1400
|
-
* Polls the verification status until it reaches a terminal state (completed or failed).
|
|
1401
|
-
* Useful for providing real-time feedback to users during verification.
|
|
1402
|
-
*
|
|
1403
|
-
* @param {string} proofId - Proof ID to poll.
|
|
1404
|
-
* @param {Object} [options] - Polling options
|
|
1405
|
-
* @param {number} [options.interval=5000] - Polling interval in ms
|
|
1406
|
-
* @param {number} [options.timeout=120000] - Total timeout in ms
|
|
1407
|
-
* @param {Function} [options.onProgress] - Progress callback function
|
|
1408
|
-
* @returns {Promise<Object>} Final verification status
|
|
1409
|
-
*
|
|
1410
|
-
* @example
|
|
1411
|
-
* const finalStatus = await client.pollProofStatus(proofId, {
|
|
1412
|
-
* interval: 3000,
|
|
1413
|
-
* timeout: 60000,
|
|
1414
|
-
* onProgress: (status) => {
|
|
1415
|
-
* console.log('Current status:', status.status);
|
|
1416
|
-
* if (status.crosschain) {
|
|
1417
|
-
* console.log(`Cross-chain: ${status.crosschain.finalized}/${status.crosschain.totalChains}`);
|
|
1418
|
-
* }
|
|
1419
|
-
* }
|
|
1420
|
-
* });
|
|
1421
|
-
*/
|
|
1422
1434
|
async pollProofStatus(proofId, options = {}) {
|
|
1423
1435
|
const {
|
|
1424
1436
|
interval = 5e3,
|
|
@@ -1463,11 +1475,6 @@ ${bytes.length}`;
|
|
|
1463
1475
|
}
|
|
1464
1476
|
throw new NetworkError(`Polling timeout after ${timeout}ms`, "POLLING_TIMEOUT");
|
|
1465
1477
|
}
|
|
1466
|
-
/**
|
|
1467
|
-
* DETECT CHAIN ID - Get current wallet chain
|
|
1468
|
-
*
|
|
1469
|
-
* @returns {Promise<number>} Current chain ID
|
|
1470
|
-
*/
|
|
1471
1478
|
async detectChainId() {
|
|
1472
1479
|
if (typeof window === "undefined" || !window.ethereum) {
|
|
1473
1480
|
throw new ConfigurationError("No Web3 wallet detected");
|
|
@@ -1479,7 +1486,6 @@ ${bytes.length}`;
|
|
|
1479
1486
|
throw new NetworkError(`Failed to detect chain ID: ${error.message}`);
|
|
1480
1487
|
}
|
|
1481
1488
|
}
|
|
1482
|
-
/** Revoke your own proof (owner-signed) */
|
|
1483
1489
|
async revokeOwnProof(proofId, wallet) {
|
|
1484
1490
|
if (!proofId || typeof proofId !== "string") {
|
|
1485
1491
|
throw new ValidationError("proofId is required");
|
|
@@ -1530,22 +1536,6 @@ ${bytes.length}`;
|
|
|
1530
1536
|
}
|
|
1531
1537
|
return true;
|
|
1532
1538
|
}
|
|
1533
|
-
/**
|
|
1534
|
-
* GET PROOFS BY WALLET - Fetch proofs for a wallet address
|
|
1535
|
-
*
|
|
1536
|
-
* @param {string} walletAddress - Wallet identity (EVM/Solana/DID)
|
|
1537
|
-
* @param {Object} [options] - Filter options
|
|
1538
|
-
* @param {number} [options.limit] - Max results (default: 50; higher limits require owner access)
|
|
1539
|
-
* @param {number} [options.offset] - Pagination offset (default: 0)
|
|
1540
|
-
* @param {string} [options.qHash] - Filter to single proof by qHash
|
|
1541
|
-
* @returns {Promise<Object>} Proofs result
|
|
1542
|
-
*
|
|
1543
|
-
* @example
|
|
1544
|
-
* const result = await client.getProofsByWallet('0x...', {
|
|
1545
|
-
* limit: 50,
|
|
1546
|
-
* offset: 0
|
|
1547
|
-
* });
|
|
1548
|
-
*/
|
|
1549
1539
|
async getProofsByWallet(walletAddress, options = {}) {
|
|
1550
1540
|
if (!walletAddress || typeof walletAddress !== "string") {
|
|
1551
1541
|
throw new ValidationError("walletAddress is required");
|
|
@@ -1573,18 +1563,6 @@ ${bytes.length}`;
|
|
|
1573
1563
|
nextOffset: response.data?.nextOffset ?? null
|
|
1574
1564
|
};
|
|
1575
1565
|
}
|
|
1576
|
-
/**
|
|
1577
|
-
* Get proofs by wallet (owner access)
|
|
1578
|
-
*
|
|
1579
|
-
* Signs an owner-access intent and requests private proofs via signature headers.
|
|
1580
|
-
*
|
|
1581
|
-
* @param {string} walletAddress - Wallet identity (EVM/Solana/DID)
|
|
1582
|
-
* @param {Object} [options]
|
|
1583
|
-
* @param {number} [options.limit] - Max results (server enforces caps)
|
|
1584
|
-
* @param {number} [options.offset] - Pagination offset
|
|
1585
|
-
* @param {string} [options.qHash] - Filter to single proof by qHash
|
|
1586
|
-
* @param {Object} [wallet] - Optional injected wallet/provider (MetaMask/ethers Wallet)
|
|
1587
|
-
*/
|
|
1588
1566
|
async getPrivateProofsByWallet(walletAddress, options = {}, wallet = null) {
|
|
1589
1567
|
if (!walletAddress || typeof walletAddress !== "string") {
|
|
1590
1568
|
throw new ValidationError("walletAddress is required");
|
|
@@ -1655,31 +1633,6 @@ ${bytes.length}`;
|
|
|
1655
1633
|
nextOffset: response.data?.nextOffset ?? null
|
|
1656
1634
|
};
|
|
1657
1635
|
}
|
|
1658
|
-
/**
|
|
1659
|
-
* Gate check (HTTP API) — minimal eligibility response.
|
|
1660
|
-
*
|
|
1661
|
-
* Calls the gate endpoint and returns a **minimal** yes/no response.
|
|
1662
|
-
* By default this checks **public + unlisted** proofs.
|
|
1663
|
-
*
|
|
1664
|
-
* When `includePrivate=true`, this can perform owner-signed private checks
|
|
1665
|
-
* (no full proof payloads returned) by providing a wallet/provider.
|
|
1666
|
-
*
|
|
1667
|
-
* Prefer this over `checkGate()` when you need the smallest, most stable
|
|
1668
|
-
* response shape and do not need full proof payloads.
|
|
1669
|
-
*
|
|
1670
|
-
* @param {Object} params - Gate check query params
|
|
1671
|
-
* @param {string} params.address - Wallet identity to check (EVM/Solana/DID)
|
|
1672
|
-
* @param {Array<string>|string} [params.verifierIds] - Verifier IDs to match (array or comma-separated)
|
|
1673
|
-
* @param {boolean} [params.requireAll] - Require all verifierIds on a single proof
|
|
1674
|
-
* @param {number} [params.minCount] - Minimum number of matching proofs
|
|
1675
|
-
* @param {number} [params.sinceDays] - Optional time window in days
|
|
1676
|
-
* @param {number} [params.since] - Optional unix timestamp in ms (lower bound)
|
|
1677
|
-
* @param {number} [params.limit] - Max rows to scan (server may clamp)
|
|
1678
|
-
* @param {boolean} [params.includePrivate] - Include private proofs for owner-authenticated requests
|
|
1679
|
-
* @param {boolean} [params.includeQHashes] - Include matched qHashes in response (minimal IDs only)
|
|
1680
|
-
* @param {Object} [params.wallet] - Optional wallet/provider used to sign includePrivate owner checks
|
|
1681
|
-
* @returns {Promise<Object>} API response ({ success, data })
|
|
1682
|
-
*/
|
|
1683
1636
|
async gateCheck(params = {}) {
|
|
1684
1637
|
const address = (params.address || "").toString();
|
|
1685
1638
|
if (!validateUniversalAddress(address, params.chain)) {
|
|
@@ -1751,8 +1704,7 @@ ${bytes.length}`;
|
|
|
1751
1704
|
});
|
|
1752
1705
|
}
|
|
1753
1706
|
}
|
|
1754
|
-
if (
|
|
1755
|
-
} else {
|
|
1707
|
+
if (auth) {
|
|
1756
1708
|
const normalizedAuthWallet = this._normalizeIdentity(auth.walletAddress);
|
|
1757
1709
|
const normalizedAddress = this._normalizeIdentity(address);
|
|
1758
1710
|
if (!normalizedAuthWallet || normalizedAuthWallet !== normalizedAddress) {
|
|
@@ -1775,45 +1727,6 @@ ${bytes.length}`;
|
|
|
1775
1727
|
}
|
|
1776
1728
|
return response;
|
|
1777
1729
|
}
|
|
1778
|
-
/**
|
|
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
|
-
*
|
|
1787
|
-
* Gate-first verification: checks if wallet has valid proofs satisfying requirements.
|
|
1788
|
-
* Returns which requirements are missing/expired.
|
|
1789
|
-
*
|
|
1790
|
-
* @param {Object} params - Gate check parameters
|
|
1791
|
-
* @param {string} params.walletAddress - Target wallet
|
|
1792
|
-
* @param {Array<Object>} params.requirements - Array of gate requirements
|
|
1793
|
-
* @param {string} params.requirements[].verifierId - Required verifier ID
|
|
1794
|
-
* @param {number} [params.requirements[].maxAgeMs] - Max proof age in ms (TTL)
|
|
1795
|
-
* @param {boolean} [params.requirements[].optional] - If true, not required for gate satisfaction
|
|
1796
|
-
* @param {number} [params.requirements[].minCount] - Minimum proofs needed (default: 1)
|
|
1797
|
-
* @param {Object} [params.requirements[].match] - Verifier data match criteria
|
|
1798
|
-
* Supports nested fields: 'reference.type', 'reference.id', 'content', 'contentHash', 'input.*', 'license.*'
|
|
1799
|
-
* Supports verifier-specific:
|
|
1800
|
-
* - NFT/Token: 'contractAddress', 'tokenId', 'chainId', 'ownerAddress', 'minBalance'
|
|
1801
|
-
* - DNS: 'domain', 'walletAddress'
|
|
1802
|
-
* - Wallet-link: 'primaryWalletAddress', 'secondaryWalletAddress', 'chain', 'signatureMethod'
|
|
1803
|
-
* - Contract-ownership: 'contractAddress', 'chainId', 'owner', 'verificationMethod'
|
|
1804
|
-
* Note: contentHash matching uses approximation in SDK; for exact SHA-256 matching, use backend API
|
|
1805
|
-
* @param {Array} [params.proofs] - Pre-fetched proofs (skip API call)
|
|
1806
|
-
* @returns {Promise<Object>} Gate result with satisfied, missing, existing
|
|
1807
|
-
*
|
|
1808
|
-
* @example
|
|
1809
|
-
* // Basic gate check
|
|
1810
|
-
* const result = await client.checkGate({
|
|
1811
|
-
* walletAddress: '0x...',
|
|
1812
|
-
* requirements: [
|
|
1813
|
-
* { verifierId: 'nft-ownership', match: { contractAddress: '0x...' } }
|
|
1814
|
-
* ]
|
|
1815
|
-
* });
|
|
1816
|
-
*/
|
|
1817
1730
|
async checkGate(params) {
|
|
1818
1731
|
const { walletAddress, requirements, proofs: preloadedProofs } = params;
|
|
1819
1732
|
if (!validateUniversalAddress(walletAddress)) {
|
|
@@ -2045,7 +1958,6 @@ ${bytes.length}`;
|
|
|
2045
1958
|
];
|
|
2046
1959
|
return typeof status === "string" && terminalStates.some((state) => status.includes(state));
|
|
2047
1960
|
}
|
|
2048
|
-
/** SDK logging (opt-in via config.enableLogging) */
|
|
2049
1961
|
_log(message, data = {}) {
|
|
2050
1962
|
if (this.config.enableLogging) {
|
|
2051
1963
|
try {
|