@neus/sdk 1.1.0 → 1.1.1

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/index.cjs CHANGED
@@ -167,6 +167,89 @@ var init_errors = __esm({
167
167
  }
168
168
  });
169
169
 
170
+ // sponsor.js
171
+ async function fetchSponsorGrant(params = {}) {
172
+ const {
173
+ apiUrl = "https://api.neus.network",
174
+ appId,
175
+ orgWallet,
176
+ verifierIds = [],
177
+ targetChains = [],
178
+ origin,
179
+ expiresInSeconds = 900,
180
+ fetchImpl = fetch
181
+ } = params;
182
+ const normalizedAppId = typeof appId === "string" ? appId.trim() : "";
183
+ const normalizedOrg = typeof orgWallet === "string" ? orgWallet.trim().toLowerCase() : "";
184
+ if (!normalizedAppId) {
185
+ throw new ValidationError("appId is required for sponsor grant");
186
+ }
187
+ if (!normalizedOrg || !/^0x[a-f0-9]{40}$/.test(normalizedOrg)) {
188
+ throw new ValidationError("orgWallet must be a valid EVM address");
189
+ }
190
+ let base = String(apiUrl || "https://api.neus.network").replace(/\/+$/, "");
191
+ try {
192
+ const url = new URL(base);
193
+ if (url.hostname.endsWith("neus.network") && url.protocol === "http:") {
194
+ url.protocol = "https:";
195
+ }
196
+ base = url.toString().replace(/\/+$/, "");
197
+ } catch {
198
+ }
199
+ const headers = {
200
+ "Content-Type": "application/json",
201
+ Accept: "application/json",
202
+ "X-Neus-App": normalizedAppId,
203
+ "X-Neus-Sdk": "js"
204
+ };
205
+ if (typeof origin === "string" && origin.trim()) {
206
+ headers.Origin = origin.trim();
207
+ }
208
+ const body = {
209
+ orgWallet: normalizedOrg,
210
+ scope: "sponsored-verification",
211
+ expiresInSeconds,
212
+ ...Array.isArray(verifierIds) && verifierIds.length > 0 ? { verifierIds: verifierIds.map((v) => String(v).trim()).filter(Boolean).slice(0, 25) } : {},
213
+ ...Array.isArray(targetChains) && targetChains.length > 0 ? { targetChains: targetChains.filter((n) => Number.isFinite(Number(n))).slice(0, 25) } : {}
214
+ };
215
+ let response;
216
+ try {
217
+ response = await fetchImpl(`${base}/api/v1/sponsor/grant`, {
218
+ method: "POST",
219
+ headers,
220
+ body: JSON.stringify(body)
221
+ });
222
+ } catch (error) {
223
+ throw new NetworkError(`Sponsor grant request failed: ${error?.message || String(error)}`);
224
+ }
225
+ let payload;
226
+ try {
227
+ payload = await response.json();
228
+ } catch {
229
+ payload = { success: false, error: { message: "Invalid JSON response" } };
230
+ }
231
+ if (!response.ok || payload?.success !== true) {
232
+ throw ApiError.fromResponse(response, payload);
233
+ }
234
+ const token = payload?.data?.sponsorGrant;
235
+ if (!token || typeof token !== "string") {
236
+ throw new ApiError("Sponsor grant response missing sponsorGrant token", payload?.error);
237
+ }
238
+ return {
239
+ sponsorGrant: token,
240
+ exp: payload?.data?.exp,
241
+ orgWallet: payload?.data?.orgWallet || normalizedOrg,
242
+ appId: payload?.data?.appId || normalizedAppId,
243
+ maxCredits: payload?.data?.maxCredits
244
+ };
245
+ }
246
+ var init_sponsor = __esm({
247
+ "sponsor.js"() {
248
+ "use strict";
249
+ init_errors();
250
+ }
251
+ });
252
+
170
253
  // utils.js
171
254
  function encodeBase58Bytes(input) {
172
255
  let source;
@@ -956,6 +1039,8 @@ function getHostedCheckoutUrl(opts = {}) {
956
1039
  if (opts.intent) params.set("intent", String(opts.intent));
957
1040
  if (opts.origin) params.set("origin", String(opts.origin));
958
1041
  if (opts.oauthProvider) params.set("oauthProvider", String(opts.oauthProvider));
1042
+ if (opts.appId) params.set("appId", String(opts.appId));
1043
+ if (opts.billingWallet) params.set("billingWallet", String(opts.billingWallet).trim().toLowerCase());
959
1044
  const qs = params.toString();
960
1045
  return qs ? `${base}?${qs}` : base;
961
1046
  }
@@ -1091,6 +1176,7 @@ var init_client = __esm({
1091
1176
  "client.js"() {
1092
1177
  "use strict";
1093
1178
  init_errors();
1179
+ init_sponsor();
1094
1180
  init_utils();
1095
1181
  FALLBACK_PUBLIC_VERIFIER_CATALOG = {
1096
1182
  "ownership-basic": { supportsDirectApi: true },
@@ -1430,6 +1516,54 @@ var init_client = __esm({
1430
1516
  }
1431
1517
  } catch {
1432
1518
  }
1519
+ this._sponsorGrantCache = null;
1520
+ }
1521
+ _getBillingWallet() {
1522
+ const raw = this.config.billingWallet || this.config.sponsorOrgWallet || this.config.orgWallet || null;
1523
+ if (typeof raw !== "string") return null;
1524
+ const trimmed = raw.trim().toLowerCase();
1525
+ return /^0x[a-f0-9]{40}$/.test(trimmed) ? trimmed : null;
1526
+ }
1527
+ _resolveIntegratorOrigin() {
1528
+ if (typeof this.config.appOrigin === "string" && this.config.appOrigin.trim()) {
1529
+ return this.config.appOrigin.trim();
1530
+ }
1531
+ try {
1532
+ if (typeof window !== "undefined" && window.location?.origin) {
1533
+ return window.location.origin;
1534
+ }
1535
+ } catch {
1536
+ }
1537
+ return null;
1538
+ }
1539
+ async _resolveSponsorGrantHeaders(verifierIds = []) {
1540
+ const appId = typeof this.config.appId === "string" ? this.config.appId.trim() : "";
1541
+ const orgWallet = this._getBillingWallet();
1542
+ if (!appId || !orgWallet) {
1543
+ return {};
1544
+ }
1545
+ const normalizedVerifierIds = Array.isArray(verifierIds) ? verifierIds.map((v) => String(v || "").trim()).filter(Boolean).slice(0, 25) : [];
1546
+ const cacheKey = `${appId}:${orgWallet}:${normalizedVerifierIds.join(",")}`;
1547
+ const now = Date.now();
1548
+ if (this._sponsorGrantCache && this._sponsorGrantCache.key === cacheKey && this._sponsorGrantCache.expMs > now + 3e4) {
1549
+ return { "X-Sponsor-Grant": this._sponsorGrantCache.token };
1550
+ }
1551
+ const origin = this._resolveIntegratorOrigin();
1552
+ const grant = await fetchSponsorGrant({
1553
+ apiUrl: this.baseUrl,
1554
+ appId,
1555
+ orgWallet,
1556
+ verifierIds: normalizedVerifierIds,
1557
+ origin
1558
+ });
1559
+ const expSeconds = Number(grant?.exp);
1560
+ const expMs = Number.isFinite(expSeconds) && expSeconds > 0 ? expSeconds * 1e3 : now + 15 * 60 * 1e3;
1561
+ this._sponsorGrantCache = {
1562
+ key: cacheKey,
1563
+ token: grant.sponsorGrant,
1564
+ expMs
1565
+ };
1566
+ return { "X-Sponsor-Grant": grant.sponsorGrant };
1433
1567
  }
1434
1568
  _getHubChainId() {
1435
1569
  const configured = Number(this.config?.hubChainId);
@@ -2102,7 +2236,8 @@ ${bytes.length}`;
2102
2236
  ...delegationQHash && { delegationQHash },
2103
2237
  options: optionsPayload
2104
2238
  };
2105
- const response = await this._makeRequest("POST", "/api/v1/verification", requestData);
2239
+ const sponsorHeaders = await this._resolveSponsorGrantHeaders(normalizedVerifierIds);
2240
+ const response = await this._makeRequest("POST", "/api/v1/verification", requestData, sponsorHeaders);
2106
2241
  if (!response.success) {
2107
2242
  throw new ApiError(`Verification failed: ${response.error?.message || "Unknown error"}`, response.error);
2108
2243
  }
@@ -2495,7 +2630,20 @@ ${bytes.length}`;
2495
2630
  };
2496
2631
  }
2497
2632
  }
2498
- const response = await this._makeRequest("GET", `/api/v1/proofs/check?${qs.toString()}`, null, headersOverride);
2633
+ let mergedHeaders = headersOverride;
2634
+ if (!mergedHeaders) {
2635
+ try {
2636
+ const sponsorHeaders = await this._resolveSponsorGrantHeaders(
2637
+ Array.isArray(params.verifierIds) ? params.verifierIds : params.verifierIds ? [params.verifierIds] : []
2638
+ );
2639
+ if (sponsorHeaders && Object.keys(sponsorHeaders).length > 0) {
2640
+ mergedHeaders = sponsorHeaders;
2641
+ }
2642
+ } catch (error) {
2643
+ this._log("Sponsor grant unavailable for gateCheck (continuing without)", error?.message || String(error));
2644
+ }
2645
+ }
2646
+ const response = await this._makeRequest("GET", `/api/v1/proofs/check?${qs.toString()}`, null, mergedHeaders);
2499
2647
  if (!response.success) {
2500
2648
  throw new ApiError(`Gate check failed: ${response.error?.message || "Unknown error"}`, response.error);
2501
2649
  }
@@ -2784,6 +2932,7 @@ __export(index_exports, {
2784
2932
  default: () => index_default,
2785
2933
  delay: () => delay,
2786
2934
  deriveDid: () => deriveDid,
2935
+ fetchSponsorGrant: () => fetchSponsorGrant,
2787
2936
  formatTimestamp: () => formatTimestamp,
2788
2937
  formatVerificationStatus: () => formatVerificationStatus,
2789
2938
  getHostedCheckoutUrl: () => getHostedCheckoutUrl,
@@ -2850,6 +2999,7 @@ function combineGates(...gates) {
2850
2999
  }
2851
3000
 
2852
3001
  // index.js
3002
+ init_sponsor();
2853
3003
  init_errors();
2854
3004
  var index_default = {
2855
3005
  NeusClient: () => Promise.resolve().then(() => (init_client(), client_exports)).then((m) => m.NeusClient),
@@ -2892,6 +3042,7 @@ var index_default = {
2892
3042
  createVerificationData,
2893
3043
  delay,
2894
3044
  deriveDid,
3045
+ fetchSponsorGrant,
2895
3046
  formatTimestamp,
2896
3047
  formatVerificationStatus,
2897
3048
  getHostedCheckoutUrl,
package/cjs/utils.cjs CHANGED
@@ -1012,6 +1012,8 @@ function getHostedCheckoutUrl(opts = {}) {
1012
1012
  if (opts.intent) params.set("intent", String(opts.intent));
1013
1013
  if (opts.origin) params.set("origin", String(opts.origin));
1014
1014
  if (opts.oauthProvider) params.set("oauthProvider", String(opts.oauthProvider));
1015
+ if (opts.appId) params.set("appId", String(opts.appId));
1016
+ if (opts.billingWallet) params.set("billingWallet", String(opts.billingWallet).trim().toLowerCase());
1015
1017
  const qs = params.toString();
1016
1018
  return qs ? `${base}?${qs}` : base;
1017
1019
  }
package/cli/neus.mjs CHANGED
@@ -496,14 +496,21 @@ function cursorConfigPath(scope, cwd) {
496
496
  }
497
497
 
498
498
  function vscodeConfigPath(scope, cwd) {
499
- return scope === 'user'
500
- ? path.join(
501
- process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'),
502
- 'Code',
503
- 'User',
504
- 'mcp.json'
505
- )
506
- : path.join(cwd, '.vscode', 'mcp.json');
499
+ if (scope !== 'user') {
500
+ return path.join(cwd, '.vscode', 'mcp.json');
501
+ }
502
+ if (process.platform === 'darwin') {
503
+ return path.join(os.homedir(), 'Library', 'Application Support', 'Code', 'User', 'mcp.json');
504
+ }
505
+ if (process.platform === 'win32') {
506
+ return path.join(
507
+ process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'),
508
+ 'Code',
509
+ 'User',
510
+ 'mcp.json'
511
+ );
512
+ }
513
+ return path.join(os.homedir(), '.config', 'Code', 'User', 'mcp.json');
507
514
  }
508
515
 
509
516
  function claudeProjectConfigPath(cwd) {
@@ -1255,9 +1262,10 @@ function printResultSummary(command, scope, results, accessKey) {
1255
1262
  );
1256
1263
  }
1257
1264
  if (command === 'init' || command === 'setup') {
1258
- lines.push('Claude Code skill bundle: https://docs.neus.network/mcp/claude-code-marketplace');
1265
+ lines.push('All hosts (Cursor, Codex, OpenClaw, Hermes, Windsurf, Gemini, …): https://docs.neus.network/mcp/ide-plugin');
1266
+ lines.push('Claude Code plugin: neus-trust@neus — same page');
1259
1267
  lines.push(
1260
- 'Cursor / VS Code: same command when those apps are detected (local MCP config) — https://docs.neus.network/mcp/setup'
1268
+ 'Auto-setup clients: claude, cursor, vscode re-run with --client to limit scope'
1261
1269
  );
1262
1270
  }
1263
1271
  if ((command === 'init' || command === 'auth') && accessKey) {
package/client.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { ApiError, ValidationError, NetworkError, ConfigurationError } from './errors.js';
2
+ import { fetchSponsorGrant } from './sponsor.js';
2
3
  import {
3
4
  PORTABLE_PROOF_SIGNER_HEADER,
4
5
  constructVerificationMessage,
@@ -396,6 +397,77 @@ export class NeusClient {
396
397
  } catch {
397
398
  void 0;
398
399
  }
400
+
401
+ /** @type {{ token: string, expMs: number, key: string } | null} */
402
+ this._sponsorGrantCache = null;
403
+ }
404
+
405
+ _getBillingWallet() {
406
+ const raw =
407
+ this.config.billingWallet ||
408
+ this.config.sponsorOrgWallet ||
409
+ this.config.orgWallet ||
410
+ null;
411
+ if (typeof raw !== 'string') return null;
412
+ const trimmed = raw.trim().toLowerCase();
413
+ return /^0x[a-f0-9]{40}$/.test(trimmed) ? trimmed : null;
414
+ }
415
+
416
+ _resolveIntegratorOrigin() {
417
+ if (typeof this.config.appOrigin === 'string' && this.config.appOrigin.trim()) {
418
+ return this.config.appOrigin.trim();
419
+ }
420
+ try {
421
+ if (typeof window !== 'undefined' && window.location?.origin) {
422
+ return window.location.origin;
423
+ }
424
+ } catch {
425
+ void 0;
426
+ }
427
+ return null;
428
+ }
429
+
430
+ async _resolveSponsorGrantHeaders(verifierIds = []) {
431
+ const appId = typeof this.config.appId === 'string' ? this.config.appId.trim() : '';
432
+ const orgWallet = this._getBillingWallet();
433
+ if (!appId || !orgWallet) {
434
+ return {};
435
+ }
436
+
437
+ const normalizedVerifierIds = Array.isArray(verifierIds)
438
+ ? verifierIds.map((v) => String(v || '').trim()).filter(Boolean).slice(0, 25)
439
+ : [];
440
+ const cacheKey = `${appId}:${orgWallet}:${normalizedVerifierIds.join(',')}`;
441
+ const now = Date.now();
442
+ if (
443
+ this._sponsorGrantCache &&
444
+ this._sponsorGrantCache.key === cacheKey &&
445
+ this._sponsorGrantCache.expMs > now + 30_000
446
+ ) {
447
+ return { 'X-Sponsor-Grant': this._sponsorGrantCache.token };
448
+ }
449
+
450
+ const origin = this._resolveIntegratorOrigin();
451
+ const grant = await fetchSponsorGrant({
452
+ apiUrl: this.baseUrl,
453
+ appId,
454
+ orgWallet,
455
+ verifierIds: normalizedVerifierIds,
456
+ origin
457
+ });
458
+
459
+ const expSeconds = Number(grant?.exp);
460
+ const expMs = Number.isFinite(expSeconds) && expSeconds > 0
461
+ ? expSeconds * 1000
462
+ : now + 15 * 60 * 1000;
463
+
464
+ this._sponsorGrantCache = {
465
+ key: cacheKey,
466
+ token: grant.sponsorGrant,
467
+ expMs
468
+ };
469
+
470
+ return { 'X-Sponsor-Grant': grant.sponsorGrant };
399
471
  }
400
472
 
401
473
  _getHubChainId() {
@@ -1147,7 +1219,8 @@ export class NeusClient {
1147
1219
  options: optionsPayload
1148
1220
  };
1149
1221
 
1150
- const response = await this._makeRequest('POST', '/api/v1/verification', requestData);
1222
+ const sponsorHeaders = await this._resolveSponsorGrantHeaders(normalizedVerifierIds);
1223
+ const response = await this._makeRequest('POST', '/api/v1/verification', requestData, sponsorHeaders);
1151
1224
 
1152
1225
  if (!response.success) {
1153
1226
  throw new ApiError(`Verification failed: ${response.error?.message || 'Unknown error'}`, response.error);
@@ -1619,7 +1692,23 @@ export class NeusClient {
1619
1692
  }
1620
1693
  }
1621
1694
 
1622
- const response = await this._makeRequest('GET', `/api/v1/proofs/check?${qs.toString()}`, null, headersOverride);
1695
+ let mergedHeaders = headersOverride;
1696
+ if (!mergedHeaders) {
1697
+ try {
1698
+ const sponsorHeaders = await this._resolveSponsorGrantHeaders(
1699
+ Array.isArray(params.verifierIds)
1700
+ ? params.verifierIds
1701
+ : (params.verifierIds ? [params.verifierIds] : [])
1702
+ );
1703
+ if (sponsorHeaders && Object.keys(sponsorHeaders).length > 0) {
1704
+ mergedHeaders = sponsorHeaders;
1705
+ }
1706
+ } catch (error) {
1707
+ this._log('Sponsor grant unavailable for gateCheck (continuing without)', error?.message || String(error));
1708
+ }
1709
+ }
1710
+
1711
+ const response = await this._makeRequest('GET', `/api/v1/proofs/check?${qs.toString()}`, null, mergedHeaders);
1623
1712
  if (!response.success) {
1624
1713
  throw new ApiError(`Gate check failed: ${response.error?.message || 'Unknown error'}`, response.error);
1625
1714
  }