@neus/sdk 1.0.10 → 1.1.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ # Changelog
2
+
3
+ Release notes: [github.com/neus/network/blob/main/CHANGELOG.md](https://github.com/neus/network/blob/main/CHANGELOG.md)
package/README.md CHANGED
@@ -1,22 +1,50 @@
1
1
  # @neus/sdk
2
2
 
3
- Create, check, and reuse NEUS trust receipts from apps.
3
+ Create, check, and reuse NEUS trust receipts from apps and backends. The same package ships the **`neus`** CLI for hosted MCP setup and portable agent import.
4
4
 
5
- NEUS turns signed claims, ownership checks, account links, access rules, and verification results into portable receipts your app can store, display, and check later.
5
+ NEUS makes trust portable across apps, agents, and ecosystems before access, payment, or action.
6
6
 
7
- ## Install
7
+ **Status:** [Live and Operational for Production Apps](https://docs.neus.network/platform/status).
8
+
9
+ ## Install (library)
8
10
 
9
11
  ```bash
10
12
  npm install @neus/sdk
11
13
  ```
12
14
 
13
- ## What you can build
15
+ ## Bring Your Own Agent (BYOA) in 30 Seconds
16
+
17
+ Already have an agent setup? Use the CLI to instantly scan and import your local agent setups—including instructions, memories, rules, skills, and MCP servers from **OpenClaw, Cursor, Claude Code, and Claude Desktop**—straight into the NEUS trust network:
18
+
19
+ ```bash
20
+ npx -y -p @neus/sdk neus import
21
+ ```
22
+
23
+ This automatically prepares your portable NEUS agent manifest, maps your credentials, and secures a reusable trust receipt for your workflows.
24
+
25
+ *To check what will be imported without writing changes:*
26
+ ```bash
27
+ npx -y -p @neus/sdk neus import --dry-run
28
+ ```
29
+
30
+ ## Connect editors and assistants
31
+
32
+ | Topic | Link |
33
+ | --------------------------------- | ----------------------------------------------------------------------------- |
34
+ | Setup, JSON snippets, and headers | [MCP setup](https://docs.neus.network/mcp/setup) |
35
+ | Tools and session order | [MCP overview](https://docs.neus.network/mcp/overview) |
36
+ | Discovery URLs | [Discovery and endpoints](https://docs.neus.network/mcp/endpoints) |
37
+ | Claude Code skill bundle | [NEUS for Claude Code](https://docs.neus.network/mcp/claude-code-marketplace) |
38
+
39
+ Prefer `neus setup` over hand-editing config files so every host stays on **`https://mcp.neus.network/mcp`**.
14
40
 
15
- - Issue a proof that a user, wallet, org, app, file, release, profile, or result belongs to someone
16
- - Store the returned `qHash` as a durable trust receipt ID
17
- - Check receipts later for access, eligibility, provenance, or display
18
- - Add proof-gated UX with React widgets
19
- - Connect IDEs and agents through optional MCP
41
+ ## What you can ship
42
+
43
+ - Hosted verification flows that return a reusable receipt
44
+ - Server checks before access, rewards, payments, or actions
45
+ - React gates with `VerifyGate`
46
+ - Agent identity and scoped delegation
47
+ - MCP setup for assistants and agent tools
20
48
 
21
49
  ## Fastest path: Hosted Verify
22
50
 
@@ -27,19 +55,17 @@ import { getHostedCheckoutUrl } from '@neus/sdk';
27
55
 
28
56
  const url = getHostedCheckoutUrl({
29
57
  verifiers: ['ownership-basic'],
30
- returnUrl: 'https://yourapp.com/neus/callback'
58
+ returnUrl: 'https://yourapp.com/auth/callback'
31
59
  });
32
60
 
33
61
  window.location.assign(url);
34
62
  ```
35
63
 
36
- After completion, NEUS redirects back with a `qHash`.
37
-
38
- Store that `qHash` in your database next to your user, workspace, project, claim, listing, or record.
64
+ After completion, NEUS redirects back with a receipt ID. Store it with your user or record.
39
65
 
40
- ## Create a signed receipt directly
66
+ ## Create a receipt directly
41
67
 
42
- Use this when your app already controls the signing flow.
68
+ Use this when your app handles signing. This example is EVM. For non-EVM wallets, pass the provider explicitly and include `chain` as a CAIP-2 value.
43
69
 
44
70
  ```js
45
71
  import { NeusClient } from '@neus/sdk';
@@ -64,7 +90,7 @@ const proof = await client.verify({
64
90
  title: 'Source record'
65
91
  }
66
92
  },
67
- wallet: window.ethereum
93
+ wallet: window.ethereum // EVM provider
68
94
  });
69
95
 
70
96
  console.log(proof.qHash);
@@ -97,7 +123,7 @@ export function Page() {
97
123
  }
98
124
  }
99
125
  }}
100
- onVerified={(result) => {
126
+ onVerified={result => {
101
127
  console.log(result.qHash || result.qHashes);
102
128
  }}
103
129
  />
@@ -126,7 +152,7 @@ if (!result.data?.eligible) {
126
152
  }
127
153
  ```
128
154
 
129
- Access keys are only for trusted server, IDE, or agent environments. Never ship access keys in browser code.
155
+ Never ship access keys in browser code.
130
156
 
131
157
  ## Core methods
132
158
 
@@ -134,11 +160,11 @@ Access keys are only for trusted server, IDE, or agent environments. Never ship
134
160
  | ------------------------------- | ------------------------------------------- |
135
161
  | `getHostedCheckoutUrl()` | Send a user to Hosted Verify |
136
162
  | `client.verify()` | Create a proof |
137
- | `client.getProof()` | Fetch a proof by `qHash` |
163
+ | `client.getProof()` | Fetch a receipt by `qHash` |
138
164
  | `client.pollProofStatus()` | Wait for async completion |
139
165
  | `client.gateCheck()` | Server-side eligibility checks |
140
166
  | `client.checkGate()` | Local preview against already-loaded proofs |
141
- | `client.createWalletLinkData()` | Advanced wallet-link payloads |
167
+ | `client.createWalletLinkData()` | Wallet-link payloads |
142
168
 
143
169
  ## Configuration
144
170
 
@@ -153,20 +179,23 @@ const client = new NeusClient({
153
179
  `appId` is public attribution for your app.
154
180
  `apiKey` / `npk_*` is optional and server-side only.
155
181
 
156
- ## Optional MCP setup
157
-
158
- Use MCP when you want IDEs, assistants, or agents to inspect receipts, check proof state, or work with NEUS tools.
182
+ ## MCP step-by-step
159
183
 
160
184
  ```bash
161
- npx -y -p @neus/sdk neus init
185
+ npx -y -p @neus/sdk neus setup
186
+ npx -y -p @neus/sdk neus auth
187
+ npx -y -p @neus/sdk neus doctor --live
162
188
  ```
163
189
 
164
- Add account-aware/private access only when needed:
190
+ Re-sign in or rotate credentials:
165
191
 
166
192
  ```bash
167
- npx -y -p @neus/sdk neus auth --access-key <npk_...>
193
+ npx -y -p @neus/sdk neus auth
194
+ npx -y -p @neus/sdk neus auth --access-key <npk_...> # servers and CI only
168
195
  ```
169
196
 
197
+ Claude Code users can add the optional **`neus-mcp@neus`** skill bundle, then run **`neus setup`** and **`neus auth`**. See [NEUS for Claude Code](https://docs.neus.network/mcp/claude-code-marketplace).
198
+
170
199
  ## Docs
171
200
 
172
201
  - Quickstart: https://docs.neus.network/quickstart
package/SECURITY.md CHANGED
@@ -20,7 +20,7 @@ Treat **wallet signatures** and **API keys** as secrets. Do not log them, expose
20
20
 
21
21
  **`VerifyGate`** create mode also defaults to **private**.
22
22
 
23
- Use public visibility only when you intentionally need proof reuse without owner-authenticated access:
23
+ Use public visibility only when you need proof reuse without owner-authenticated access:
24
24
 
25
25
  - unlisted public: `privacyLevel: 'public'`, `publicDisplay: false`
26
26
  - listed public: `privacyLevel: 'public'`, `publicDisplay: true`
package/cjs/client.cjs CHANGED
@@ -421,6 +421,11 @@ function normalizeBrowserSignerString(raw) {
421
421
  }
422
422
  return null;
423
423
  }
424
+ function isPlaceholderNeusSignature(signature) {
425
+ const s = typeof signature === "string" ? signature.trim() : "";
426
+ if (!s) return true;
427
+ return /^0x0+$/i.test(s);
428
+ }
424
429
  var validateVerifierData = (verifierId, data) => {
425
430
  if (!data || typeof data !== "object") {
426
431
  return { valid: false, error: "Data object is required" };
@@ -594,6 +599,17 @@ var validateVerifierData = (verifierId, data) => {
594
599
  if (data.agentType && !["ai", "bot", "service", "automation", "agent"].includes(data.agentType)) {
595
600
  return { valid: false, error: "agentType must be one of: ai, bot, service, automation, agent" };
596
601
  }
602
+ if (data.defaultRuntime && typeof data.defaultRuntime === "object") {
603
+ if (data.defaultRuntime.provider && typeof data.defaultRuntime.provider === "string" && data.defaultRuntime.provider.length > 64) {
604
+ return { valid: false, error: "defaultRuntime.provider must be 64 chars or less" };
605
+ }
606
+ if (data.defaultRuntime.model && typeof data.defaultRuntime.model === "string" && data.defaultRuntime.model.length > 128) {
607
+ return { valid: false, error: "defaultRuntime.model must be 128 chars or less" };
608
+ }
609
+ if (data.defaultRuntime.mode && typeof data.defaultRuntime.mode === "string" && data.defaultRuntime.mode.length > 64) {
610
+ return { valid: false, error: "defaultRuntime.mode must be 64 chars or less" };
611
+ }
612
+ }
597
613
  break;
598
614
  case "agent-delegation":
599
615
  if (!data.controllerWallet || !validateWalletAddress(data.controllerWallet)) {
@@ -608,6 +624,18 @@ var validateVerifierData = (verifierId, data) => {
608
624
  if (data.expiresAt && (typeof data.expiresAt !== "number" || data.expiresAt < Date.now())) {
609
625
  return { valid: false, error: "expiresAt must be a future timestamp" };
610
626
  }
627
+ if (data.model && typeof data.model === "string" && data.model.length > 128) {
628
+ return { valid: false, error: "model must be 128 chars or less" };
629
+ }
630
+ if (data.provider && typeof data.provider === "string" && data.provider.length > 64) {
631
+ return { valid: false, error: "provider must be 64 chars or less" };
632
+ }
633
+ if (data.allowedActions && Array.isArray(data.allowedActions) && data.allowedActions.length > 32) {
634
+ return { valid: false, error: "allowedActions must have 32 items or less" };
635
+ }
636
+ if (data.deniedActions && Array.isArray(data.deniedActions) && data.deniedActions.length > 32) {
637
+ return { valid: false, error: "deniedActions must have 32 items or less" };
638
+ }
611
639
  break;
612
640
  case "ai-content-moderation":
613
641
  if (!data.content || typeof data.content !== "string") {
@@ -797,7 +825,7 @@ var NeusClient = class {
797
825
  }
798
826
  _getDefaultBrowserWallet() {
799
827
  if (typeof window === "undefined") return null;
800
- return window.ethereum || window.solana || window.phantom && window.phantom.solana || null;
828
+ return window.ethereum || null;
801
829
  }
802
830
  async _buildPrivateGateAuth({ address, wallet, chain, signatureMethod } = {}) {
803
831
  const providerWallet = wallet || this._getDefaultBrowserWallet();
@@ -922,8 +950,57 @@ var NeusClient = class {
922
950
  ...label ? { label } : {}
923
951
  };
924
952
  }
953
+ async verifyFromApp(params) {
954
+ if (!params || typeof params !== "object") {
955
+ throw new ValidationError("verifyFromApp requires a params object");
956
+ }
957
+ const {
958
+ user,
959
+ verifier = "ownership-basic",
960
+ content,
961
+ data: explicitData = null,
962
+ options = {}
963
+ } = params;
964
+ if (!user || typeof user !== "object") {
965
+ throw new ValidationError("verifyFromApp requires user object");
966
+ }
967
+ const walletAddress = user.walletAddress || user.address || user.identity;
968
+ if (!walletAddress || typeof walletAddress !== "string") {
969
+ throw new ValidationError("verifyFromApp requires user.walletAddress");
970
+ }
971
+ const delegationQHash = this.config.appLinkQHash || typeof process !== "undefined" && process.env && process.env.NEUS_APP_LINK_QHASH || null;
972
+ let data;
973
+ if (explicitData && typeof explicitData === "object") {
974
+ data = { owner: walletAddress, ...explicitData };
975
+ } else if (content && typeof content === "object") {
976
+ data = {
977
+ owner: walletAddress,
978
+ content: JSON.stringify(content),
979
+ contentType: typeof content.contentType === "string" ? content.contentType : "application/json",
980
+ reference: content.reference || { type: "other" }
981
+ };
982
+ } else if (typeof content === "string") {
983
+ data = {
984
+ owner: walletAddress,
985
+ content,
986
+ reference: { type: "other" }
987
+ };
988
+ } else {
989
+ data = { owner: walletAddress, reference: { type: "other" } };
990
+ }
991
+ const signedTimestamp = Date.now();
992
+ const verifierIds = [verifier];
993
+ return this.verify({
994
+ verifierIds,
995
+ data,
996
+ walletAddress,
997
+ signedTimestamp,
998
+ ...delegationQHash ? { delegationQHash } : {},
999
+ options
1000
+ });
1001
+ }
925
1002
  async verify(params) {
926
- if ((!params?.signature || !params?.walletAddress) && (params?.verifier || params?.content || params?.data)) {
1003
+ if ((isPlaceholderNeusSignature(params?.signature) || !params?.signature || !params?.walletAddress) && (params?.verifier || params?.content || params?.data)) {
927
1004
  const { content, verifier = "ownership-basic", data: data2 = null, wallet = null, options: options2 = {} } = params;
928
1005
  if (verifier === "ownership-basic" && !data2 && (!content || typeof content !== "string")) {
929
1006
  throw new ValidationError("content is required and must be a string (or use data param with owner + reference)");
@@ -976,7 +1053,7 @@ var NeusClient = class {
976
1053
  }
977
1054
  } else {
978
1055
  if (typeof window === "undefined" || !window.ethereum) {
979
- throw new ConfigurationError("No Web3 wallet detected. Please install MetaMask or provide wallet parameter.");
1056
+ throw new ConfigurationError("No EVM browser wallet detected. Provide wallet explicitly for non-EVM flows and include chain as a CAIP-2 value.");
980
1057
  }
981
1058
  await window.ethereum.request({ method: "eth_requestAccounts" });
982
1059
  provider = window.ethereum;
@@ -1092,9 +1169,13 @@ var NeusClient = class {
1092
1169
  verificationData = {
1093
1170
  agentId: data2.agentId,
1094
1171
  agentWallet: data2?.agentWallet || walletAddress2,
1172
+ ...data2?.agentChainRef && { agentChainRef: data2.agentChainRef },
1173
+ ...data2?.agentAccountId && { agentAccountId: data2.agentAccountId },
1095
1174
  ...data2?.agentLabel && { agentLabel: data2.agentLabel },
1096
1175
  ...data2?.agentType && { agentType: data2.agentType },
1176
+ ...data2?.avatar && { avatar: data2.avatar },
1097
1177
  ...data2?.description && { description: data2.description },
1178
+ ...data2?.defaultRuntime && { defaultRuntime: data2.defaultRuntime },
1098
1179
  ...data2?.capabilities && { capabilities: data2.capabilities },
1099
1180
  ...data2?.instructions && { instructions: data2.instructions },
1100
1181
  ...data2?.skills && { skills: data2.skills },
@@ -1106,7 +1187,11 @@ var NeusClient = class {
1106
1187
  }
1107
1188
  verificationData = {
1108
1189
  controllerWallet: data2?.controllerWallet || walletAddress2,
1190
+ ...data2?.controllerChainRef && { controllerChainRef: data2.controllerChainRef },
1109
1191
  agentWallet: data2.agentWallet,
1192
+ ...data2?.agentChainRef && { agentChainRef: data2.agentChainRef },
1193
+ ...data2?.controllerAccountId && { controllerAccountId: data2.controllerAccountId },
1194
+ ...data2?.agentAccountId && { agentAccountId: data2.agentAccountId },
1110
1195
  ...data2?.agentId && { agentId: data2.agentId },
1111
1196
  ...data2?.scope && { scope: data2.scope },
1112
1197
  ...data2?.permissions && { permissions: data2.permissions },
@@ -1115,7 +1200,13 @@ var NeusClient = class {
1115
1200
  ...data2?.receiptDisclosure && { receiptDisclosure: data2.receiptDisclosure },
1116
1201
  ...data2?.expiresAt && { expiresAt: data2.expiresAt },
1117
1202
  ...data2?.instructions && { instructions: data2.instructions },
1118
- ...data2?.skills && { skills: data2.skills }
1203
+ ...data2?.skills && { skills: data2.skills },
1204
+ ...data2?.model && { model: data2.model },
1205
+ ...data2?.provider && { provider: data2.provider },
1206
+ ...data2?.runtimePolicy && { runtimePolicy: data2.runtimePolicy },
1207
+ ...data2?.allowedActions && { allowedActions: data2.allowedActions },
1208
+ ...data2?.deniedActions && { deniedActions: data2.deniedActions },
1209
+ ...data2?.approvalPolicy && { approvalPolicy: data2.approvalPolicy }
1119
1210
  };
1120
1211
  } else if (verifier === "ai-content-moderation") {
1121
1212
  if (!data2?.content) {
@@ -1264,13 +1355,15 @@ ${bytes.length}`;
1264
1355
  verifierIds,
1265
1356
  data,
1266
1357
  walletAddress,
1267
- signature,
1358
+ signature: rawSignature,
1268
1359
  signedTimestamp,
1269
1360
  chainId,
1270
1361
  chain,
1271
1362
  signatureMethod,
1363
+ delegationQHash,
1272
1364
  options = {}
1273
1365
  } = params;
1366
+ const signature = isPlaceholderNeusSignature(rawSignature) ? void 0 : rawSignature;
1274
1367
  const resolvedChainId = chainId || (chain ? null : NEUS_CONSTANTS.HUB_CHAIN_ID);
1275
1368
  const normalizeVerifierId = (id) => {
1276
1369
  if (typeof id !== "string") return id;
@@ -1287,8 +1380,11 @@ ${bytes.length}`;
1287
1380
  if (!walletAddress || typeof walletAddress !== "string") {
1288
1381
  throw new ValidationError("walletAddress is required");
1289
1382
  }
1290
- if (!signature) {
1291
- throw new ValidationError("signature is required");
1383
+ const hasAppAttribution = typeof this.config.appId === "string" && this.config.appId.trim().length > 0;
1384
+ if (!signature && !delegationQHash && !hasAppAttribution) {
1385
+ throw new ValidationError(
1386
+ "signature, delegationQHash, or NeusClient config appId (sent as X-Neus-App) is required"
1387
+ );
1292
1388
  }
1293
1389
  if (!signedTimestamp || typeof signedTimestamp !== "number") {
1294
1390
  throw new ValidationError("signedTimestamp is required");
@@ -1314,11 +1410,12 @@ ${bytes.length}`;
1314
1410
  verifierIds: normalizedVerifierIds,
1315
1411
  data,
1316
1412
  walletAddress,
1317
- signature,
1413
+ ...signature ? { signature } : {},
1318
1414
  signedTimestamp,
1319
1415
  ...resolvedChainId !== null && { chainId: resolvedChainId },
1320
1416
  ...chain && { chain },
1321
1417
  ...signatureMethod && { signatureMethod },
1418
+ ...delegationQHash && { delegationQHash },
1322
1419
  options: optionsPayload
1323
1420
  };
1324
1421
  const response = await this._makeRequest("POST", "/api/v1/verification", requestData);
@@ -1328,19 +1425,17 @@ ${bytes.length}`;
1328
1425
  return this._formatResponse(response);
1329
1426
  }
1330
1427
  async getProof(qHash) {
1331
- const resolvedQHash = qHash;
1332
- if (!resolvedQHash || typeof resolvedQHash !== "string") {
1428
+ if (!qHash || typeof qHash !== "string") {
1333
1429
  throw new ValidationError("qHash is required");
1334
1430
  }
1335
- const response = await this._makeRequest("GET", `/api/v1/proofs/${resolvedQHash}`);
1431
+ const response = await this._makeRequest("GET", `/api/v1/proofs/${qHash}`);
1336
1432
  if (!response.success) {
1337
1433
  throw new ApiError(`Failed to get proof: ${response.error?.message || "Unknown error"}`, response.error);
1338
1434
  }
1339
1435
  return this._formatResponse(response);
1340
1436
  }
1341
1437
  async getPrivateProof(qHash, wallet = null) {
1342
- const resolvedQHash = qHash;
1343
- if (!resolvedQHash || typeof resolvedQHash !== "string") {
1438
+ if (!qHash || typeof qHash !== "string") {
1344
1439
  throw new ValidationError("qHash is required");
1345
1440
  }
1346
1441
  const isPreSignedAuth = wallet && typeof wallet === "object" && typeof wallet.walletAddress === "string" && typeof wallet.signature === "string" && typeof wallet.signedTimestamp === "number";
@@ -1353,7 +1448,7 @@ ${bytes.length}`;
1353
1448
  ...typeof auth.chain === "string" && auth.chain.trim() ? { "x-chain": auth.chain.trim() } : {},
1354
1449
  ...typeof auth.signatureMethod === "string" && auth.signatureMethod.trim() ? { "x-signature-method": auth.signatureMethod.trim() } : {}
1355
1450
  };
1356
- const response2 = await this._makeRequest("GET", `/api/v1/proofs/${resolvedQHash}`, null, headers);
1451
+ const response2 = await this._makeRequest("GET", `/api/v1/proofs/${qHash}`, null, headers);
1357
1452
  if (!response2.success) {
1358
1453
  throw new ApiError(
1359
1454
  `Failed to access private proof: ${response2.error?.message || "Unauthorized"}`,
@@ -1374,7 +1469,7 @@ ${bytes.length}`;
1374
1469
  const message = constructVerificationMessage({
1375
1470
  walletAddress,
1376
1471
  signedTimestamp,
1377
- data: { action: "access_private_proof", qHash: resolvedQHash },
1472
+ data: { action: "access_private_proof", qHash },
1378
1473
  verifierIds: ["ownership-basic"],
1379
1474
  ...signerIsEvm ? { chainId: this._getHubChainId() } : { chain }
1380
1475
  });
@@ -1392,7 +1487,7 @@ ${bytes.length}`;
1392
1487
  }
1393
1488
  throw new ValidationError(`Failed to sign message: ${error.message}`);
1394
1489
  }
1395
- const response = await this._makeRequest("GET", `/api/v1/proofs/${resolvedQHash}`, null, {
1490
+ const response = await this._makeRequest("GET", `/api/v1/proofs/${qHash}`, null, {
1396
1491
  "x-wallet-address": walletAddress,
1397
1492
  "x-signature": signature,
1398
1493
  "x-signed-timestamp": signedTimestamp.toString(),
@@ -1430,20 +1525,19 @@ ${bytes.length}`;
1430
1525
  };
1431
1526
  }
1432
1527
  async pollProofStatus(qHash, options = {}) {
1433
- const resolvedQHash = qHash;
1434
1528
  const {
1435
1529
  interval = 5e3,
1436
1530
  timeout = 12e4,
1437
1531
  onProgress
1438
1532
  } = options;
1439
- if (!resolvedQHash || typeof resolvedQHash !== "string") {
1533
+ if (!qHash || typeof qHash !== "string") {
1440
1534
  throw new ValidationError("qHash is required");
1441
1535
  }
1442
1536
  const startTime = Date.now();
1443
1537
  let consecutiveRateLimits = 0;
1444
1538
  while (Date.now() - startTime < timeout) {
1445
1539
  try {
1446
- const status = await this.getProof(resolvedQHash);
1540
+ const status = await this.getProof(qHash);
1447
1541
  consecutiveRateLimits = 0;
1448
1542
  if (onProgress && typeof onProgress === "function") {
1449
1543
  onProgress(status.data || status);
@@ -1486,8 +1580,7 @@ ${bytes.length}`;
1486
1580
  }
1487
1581
  }
1488
1582
  async revokeOwnProof(qHash, wallet) {
1489
- const resolvedQHash = qHash;
1490
- if (!resolvedQHash || typeof resolvedQHash !== "string") {
1583
+ if (!qHash || typeof qHash !== "string") {
1491
1584
  throw new ValidationError("qHash is required");
1492
1585
  }
1493
1586
  const providerWallet = wallet || this._getDefaultBrowserWallet();
@@ -1502,7 +1595,7 @@ ${bytes.length}`;
1502
1595
  const message = constructVerificationMessage({
1503
1596
  walletAddress: address,
1504
1597
  signedTimestamp,
1505
- data: { action: "revoke_proof", qHash: resolvedQHash },
1598
+ data: { action: "revoke_proof", qHash },
1506
1599
  verifierIds: ["ownership-basic"],
1507
1600
  ...signerIsEvm ? { chainId: this._getHubChainId() } : { chain }
1508
1601
  });
@@ -1520,7 +1613,7 @@ ${bytes.length}`;
1520
1613
  }
1521
1614
  throw new ValidationError(`Failed to sign revocation: ${error.message}`);
1522
1615
  }
1523
- const res = await this._makeRequest("POST", `/api/v1/proofs/revoke-self/${resolvedQHash}`, {
1616
+ const res = await this._makeRequest("POST", `/api/v1/proofs/revoke-self/${qHash}`, {
1524
1617
  walletAddress: address,
1525
1618
  signature,
1526
1619
  signedTimestamp,
@@ -1927,10 +2020,7 @@ ${bytes.length}`;
1927
2020
  }
1928
2021
  }
1929
2022
  _formatResponse(response) {
1930
- const qHash = response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || response?.data?.proofId || // Legacy input compatibility only. Do not expose or store proofId.
1931
- response?.proofId || // Legacy input compatibility only. Do not expose or store proofId.
1932
- response?.data?.resource?.proofId || // Legacy input compatibility only. Do not expose or store proofId.
1933
- response?.data?.id;
2023
+ const qHash = response?.data?.qHash || response?.qHash || response?.data?.resource?.qHash || response?.data?.id;
1934
2024
  const status = response?.data?.status || response?.status || response?.data?.resource?.status || (response?.success ? "completed" : "unknown");
1935
2025
  return {
1936
2026
  success: response.success,