@obscura-fhe/sdk 1.0.1 → 1.0.4

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 CHANGED
@@ -2,6 +2,35 @@
2
2
 
3
3
  All notable changes to `@obscura-fhe/sdk` are documented in this file.
4
4
 
5
+ ## [1.0.4] - 2026-05-30
6
+
7
+ ### Added
8
+
9
+ - **AgentModule** — create, list, revoke, and regenerate agent tokens via Obscura API
10
+ - **`agentToken` config** — `Authorization: Bearer` on wallet-scoped API reads
11
+ - **`getAuthenticatedSummary()`** / **`listAuthenticated()`** — `/agent/reputation` and `/agent/activity`
12
+ - **`buildAgentTokenMessage()`** — EIP-191 message helper for token issuance
13
+
14
+ ### Changed
15
+
16
+ - **HttpClient** sends Bearer header when `agentToken` is set
17
+ - **ReputationModule** / **ActivityModule** route authenticated reads to `/agent/*` when token configured
18
+
19
+ ## [1.0.3] - 2026-05-30
20
+
21
+ ### Changed
22
+
23
+ - **Activity module:** reads via `GET /activity/:wallet` on Obscura API — no Supabase credentials required
24
+ - **Breaking:** `ActivityModule` constructor now takes `HttpClient` only; `supabaseUrl` / `supabaseAnonKey` config deprecated
25
+
26
+ ## [1.0.2] - 2026-05-30
27
+
28
+ ### Added
29
+
30
+ - **Credit module:** `getMarketUtilization()` — public pool aggregates (`utilizationBps`, `totalSupplyAssets`, `totalBorrowAssets`)
31
+ - **Credit module:** `getPositionHandles()` — encrypted position handles as opaque hex; optional plaintext shadows with explicit warning
32
+ - Exported types: `CreditMarketUtilization`, `CreditPositionHandles`
33
+
5
34
  ## [1.0.1] - 2026-05-29
6
35
 
7
36
  ### Fixed
package/dist/index.cjs CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  var viem = require('viem');
4
4
  var chains = require('viem/chains');
5
- var supabaseJs = require('@supabase/supabase-js');
6
5
 
7
6
  // src/config/defaults.ts
8
7
  var ARBITRUM_SEPOLIA_CHAIN_ID = 421614;
@@ -68,18 +67,30 @@ function stripTrailingSlash(url) {
68
67
 
69
68
  // src/core/http.ts
70
69
  var HttpClient = class {
71
- constructor(baseUrl) {
70
+ constructor(baseUrl, agentToken) {
72
71
  this.baseUrl = baseUrl;
72
+ this.agentToken = agentToken;
73
73
  }
74
74
  baseUrl;
75
+ agentToken;
75
76
  get url() {
76
77
  return stripTrailingSlash(this.baseUrl);
77
78
  }
79
+ hasAgentToken() {
80
+ return Boolean(this.agentToken);
81
+ }
82
+ authHeaders(extra) {
83
+ return {
84
+ Accept: "application/json",
85
+ ...this.agentToken ? { Authorization: `Bearer ${this.agentToken}` } : {},
86
+ ...extra
87
+ };
88
+ }
78
89
  async get(path, init) {
79
90
  const response = await fetch(`${this.url}${path}`, {
80
91
  ...init,
81
92
  method: "GET",
82
- headers: { Accept: "application/json", ...init?.headers }
93
+ headers: this.authHeaders(init?.headers)
83
94
  });
84
95
  if (!response.ok) {
85
96
  const body = await response.text().catch(() => "");
@@ -92,8 +103,9 @@ var HttpClient = class {
92
103
  ...init,
93
104
  method: "POST",
94
105
  headers: {
95
- Accept: "application/json",
96
- "Content-Type": "application/json",
106
+ ...this.authHeaders({
107
+ "Content-Type": "application/json"
108
+ }),
97
109
  ...init?.headers
98
110
  },
99
111
  body: JSON.stringify(body)
@@ -109,8 +121,9 @@ var HttpClient = class {
109
121
  ...init,
110
122
  method: "DELETE",
111
123
  headers: {
112
- Accept: "application/json",
113
- "Content-Type": "application/json",
124
+ ...this.authHeaders({
125
+ "Content-Type": "application/json"
126
+ }),
114
127
  ...init?.headers
115
128
  },
116
129
  body: body !== void 0 ? JSON.stringify(body) : void 0
@@ -221,54 +234,115 @@ var ACTIVITY_EVENT_FILTERS = {
221
234
  // src/modules/activity.ts
222
235
  var DEFAULT_PAGE_SIZE = 20;
223
236
  var ActivityModule = class {
224
- client;
225
- supabaseUrl;
226
- supabaseAnonKey;
227
- constructor(supabaseUrl, supabaseAnonKey) {
228
- this.supabaseUrl = supabaseUrl;
229
- this.supabaseAnonKey = supabaseAnonKey;
230
- this.client = supabaseUrl && supabaseAnonKey ? supabaseJs.createClient(supabaseUrl, supabaseAnonKey) : null;
231
- }
232
- /** True when both Supabase URL and anon key were supplied at SDK init. */
237
+ constructor(http2) {
238
+ this.http = http2;
239
+ }
240
+ http;
241
+ /** True when API-backed activity reads are available (always when SDK has default apiUrl). */
233
242
  isConfigured() {
234
- return this.client !== null;
243
+ return Boolean(this.http.url);
244
+ }
245
+ hasAgentToken() {
246
+ return this.http.hasAgentToken();
235
247
  }
236
248
  getEventFilters() {
237
249
  return ACTIVITY_EVENT_FILTERS;
238
250
  }
251
+ /** Authenticated activity for the agent token wallet */
252
+ async listAuthenticated(options = {}) {
253
+ if (!this.http.hasAgentToken()) {
254
+ throw new Error("agentToken required \u2014 create one at /docs/agents");
255
+ }
256
+ return this.listWithPath("/agent/activity", options);
257
+ }
239
258
  async listForWallet(wallet, options = {}) {
240
- if (!this.client) {
241
- throw new Error(
242
- [
243
- "Activity module requires Supabase credentials.",
244
- `Pass supabaseAnonKey (and optionally supabaseUrl) to ObscuraSDK.create().`,
245
- `Default URL: ${DEFAULT_SUPABASE_URL}`,
246
- "Get the anon key from your Supabase project \u2192 Settings \u2192 API \u2192 anon public.",
247
- "Reputation and notifications work without Supabase; activity does not."
248
- ].join(" ")
249
- );
259
+ if (this.http.hasAgentToken()) {
260
+ return this.listAuthenticated(options);
250
261
  }
251
262
  const normalized = normalizeWallet(wallet);
252
263
  if (!normalized) throw new Error("Invalid wallet address");
264
+ return this.listWithPath(`/activity/${normalized}`, options);
265
+ }
266
+ async listWithPath(basePath, options) {
253
267
  const filter = options.filter ?? "all";
254
268
  const page = options.page ?? 0;
255
269
  const pageSize = options.pageSize ?? DEFAULT_PAGE_SIZE;
256
- let query = this.client.from("obscura_activity").select("*").contains("participants", [normalized]).order("block_number", { ascending: false }).range(page * pageSize, page * pageSize + pageSize - 1);
257
- const allowed = ACTIVITY_EVENT_FILTERS[filter];
258
- if (allowed.length > 0) {
259
- query = query.in("event_name", [...allowed]);
270
+ const params = new URLSearchParams();
271
+ if (filter !== "all") params.set("filter", filter);
272
+ if (page > 0) params.set("page", String(page));
273
+ if (pageSize !== DEFAULT_PAGE_SIZE) params.set("pageSize", String(pageSize));
274
+ const qs = params.toString();
275
+ const path = `${basePath}${qs ? `?${qs}` : ""}`;
276
+ return this.http.get(path);
277
+ }
278
+ };
279
+
280
+ // src/modules/agent.ts
281
+ var AgentModule = class {
282
+ constructor(http2) {
283
+ this.http = http2;
284
+ }
285
+ http;
286
+ async validateToken(token) {
287
+ return this.http.post("/agent/validate", { token });
288
+ }
289
+ async getIdentity() {
290
+ if (!this.http.hasAgentToken()) {
291
+ throw new Error("agentToken required");
260
292
  }
261
- const { data, error } = await query;
262
- if (error) throw new Error(error.message);
263
- const items = data ?? [];
264
- return {
265
- items,
266
- page,
267
- pageSize,
268
- hasMore: items.length === pageSize
269
- };
293
+ return this.http.get("/agent/me");
294
+ }
295
+ async createToken(params) {
296
+ const wallet = normalizeWallet(params.wallet);
297
+ if (!wallet) throw new Error("Invalid wallet address");
298
+ return this.http.post("/agent-tokens", {
299
+ wallet,
300
+ signature: params.signature,
301
+ timestamp: params.timestamp,
302
+ label: params.label,
303
+ permissions: params.permissions
304
+ });
305
+ }
306
+ async listTokens(params) {
307
+ const wallet = normalizeWallet(params.wallet);
308
+ if (!wallet) throw new Error("Invalid wallet address");
309
+ const qs = new URLSearchParams({
310
+ wallet,
311
+ signature: params.signature,
312
+ timestamp: String(params.timestamp)
313
+ });
314
+ return this.http.get(`/agent-tokens?${qs.toString()}`);
315
+ }
316
+ async revokeToken(params) {
317
+ const wallet = normalizeWallet(params.wallet);
318
+ if (!wallet) throw new Error("Invalid wallet address");
319
+ return this.http.delete(`/agent-tokens/${params.tokenId}`, {
320
+ wallet,
321
+ signature: params.signature,
322
+ timestamp: params.timestamp
323
+ });
324
+ }
325
+ async regenerateToken(params) {
326
+ const wallet = normalizeWallet(params.wallet);
327
+ if (!wallet) throw new Error("Invalid wallet address");
328
+ return this.http.post(`/agent-tokens/${params.tokenId}/regenerate`, {
329
+ wallet,
330
+ signature: params.signature,
331
+ timestamp: params.timestamp,
332
+ label: params.label
333
+ });
270
334
  }
271
335
  };
336
+ function buildAgentTokenMessage(wallet, timestamp, action, tokenId) {
337
+ const lines = [
338
+ "Obscura Agent Token Request",
339
+ `Wallet: ${wallet.toLowerCase()}`,
340
+ `Timestamp: ${timestamp}`,
341
+ `Action: ${action}`
342
+ ];
343
+ if (tokenId) lines.push(`TokenId: ${tokenId}`);
344
+ return lines.join("\n");
345
+ }
272
346
 
273
347
  // src/abis/index.ts
274
348
  var IN_EUINT64_COMPONENTS = [
@@ -317,6 +391,53 @@ var OC_USDC_PAY_ABI = [
317
391
  }
318
392
  ];
319
393
  var CREDIT_MARKET_ABI = [
394
+ {
395
+ name: "utilizationBps",
396
+ type: "function",
397
+ stateMutability: "view",
398
+ inputs: [],
399
+ outputs: [{ name: "", type: "uint256" }]
400
+ },
401
+ {
402
+ name: "totalSupplyAssets",
403
+ type: "function",
404
+ stateMutability: "view",
405
+ inputs: [],
406
+ outputs: [{ name: "", type: "uint128" }]
407
+ },
408
+ {
409
+ name: "totalBorrowAssets",
410
+ type: "function",
411
+ stateMutability: "view",
412
+ inputs: [],
413
+ outputs: [{ name: "", type: "uint128" }]
414
+ },
415
+ {
416
+ name: "getPosition",
417
+ type: "function",
418
+ stateMutability: "view",
419
+ inputs: [{ name: "user", type: "address" }],
420
+ outputs: [
421
+ { name: "encSupplyShares", type: "uint256" },
422
+ { name: "borrowShares", type: "uint256" },
423
+ { name: "collateral", type: "uint256" },
424
+ { name: "disburseTo", type: "uint256" }
425
+ ]
426
+ },
427
+ {
428
+ name: "getPlainCollateral",
429
+ type: "function",
430
+ stateMutability: "view",
431
+ inputs: [{ name: "user", type: "address" }],
432
+ outputs: [{ name: "", type: "uint128" }]
433
+ },
434
+ {
435
+ name: "getPlainBorrow",
436
+ type: "function",
437
+ stateMutability: "view",
438
+ inputs: [{ name: "user", type: "address" }],
439
+ outputs: [{ name: "", type: "uint128" }]
440
+ },
320
441
  {
321
442
  name: "supplyCollateral",
322
443
  type: "function",
@@ -389,6 +510,11 @@ var OBSCURA_VOTE_ABI = [
389
510
  ];
390
511
 
391
512
  // src/modules/credit.ts
513
+ var PLAINTEXT_SHADOW_WARNING = "Plaintext shadows are public testnet UI hints only \u2014 not encrypted balances. Do not treat as private position size. Omit on mainnet strict privacy mode.";
514
+ function bigintToHandleHex(value) {
515
+ const hex = value.toString(16).padStart(64, "0");
516
+ return `0x${hex}`;
517
+ }
392
518
  var CreditModule = class {
393
519
  constructor(deps) {
394
520
  this.deps = deps;
@@ -397,6 +523,75 @@ var CreditModule = class {
397
523
  getMarketAddress(override) {
398
524
  return override ?? this.deps.addresses.CreditCanonicalPayOcUSDCMarket;
399
525
  }
526
+ /** Public pool aggregates — no wallet required */
527
+ async getMarketUtilization(marketAddress) {
528
+ const market = this.getMarketAddress(marketAddress);
529
+ const [utilizationBps, totalSupplyAssets, totalBorrowAssets] = await Promise.all([
530
+ this.deps.publicClient.readContract({
531
+ address: market,
532
+ abi: CREDIT_MARKET_ABI,
533
+ functionName: "utilizationBps"
534
+ }),
535
+ this.deps.publicClient.readContract({
536
+ address: market,
537
+ abi: CREDIT_MARKET_ABI,
538
+ functionName: "totalSupplyAssets"
539
+ }),
540
+ this.deps.publicClient.readContract({
541
+ address: market,
542
+ abi: CREDIT_MARKET_ABI,
543
+ functionName: "totalBorrowAssets"
544
+ })
545
+ ]);
546
+ return {
547
+ marketAddress: market,
548
+ utilizationBps,
549
+ totalSupplyAssets,
550
+ totalBorrowAssets
551
+ };
552
+ }
553
+ /**
554
+ * Returns encrypted position handles as opaque hex strings.
555
+ * Plaintext shadows are optional and labeled with an explicit warning.
556
+ */
557
+ async getPositionHandles(wallet, options = {}) {
558
+ const normalized = normalizeWallet(wallet);
559
+ if (!normalized) throw new Error("Invalid wallet address");
560
+ const market = this.getMarketAddress(options.marketAddress);
561
+ const position = await this.deps.publicClient.readContract({
562
+ address: market,
563
+ abi: CREDIT_MARKET_ABI,
564
+ functionName: "getPosition",
565
+ args: [normalized]
566
+ });
567
+ const result = {
568
+ marketAddress: market,
569
+ wallet: normalized,
570
+ encryptedSupplySharesHandle: bigintToHandleHex(position[0]),
571
+ encryptedBorrowSharesHandle: bigintToHandleHex(position[1]),
572
+ encryptedCollateralHandle: bigintToHandleHex(position[2])
573
+ };
574
+ if (options.includePlaintextShadows) {
575
+ const [plainCollateral, plainBorrow] = await Promise.all([
576
+ this.deps.publicClient.readContract({
577
+ address: market,
578
+ abi: CREDIT_MARKET_ABI,
579
+ functionName: "getPlainCollateral",
580
+ args: [normalized]
581
+ }),
582
+ this.deps.publicClient.readContract({
583
+ address: market,
584
+ abi: CREDIT_MARKET_ABI,
585
+ functionName: "getPlainBorrow",
586
+ args: [normalized]
587
+ })
588
+ ]);
589
+ result.plaintextShadowWarning = PLAINTEXT_SHADOW_WARNING;
590
+ result.plainCollateral = plainCollateral;
591
+ result.plainBorrow = plainBorrow;
592
+ }
593
+ return result;
594
+ }
400
595
  async buildSupplyCollateral(amount, encryptedAmount, marketAddress) {
401
596
  const market = this.getMarketAddress(marketAddress);
402
597
  const enc = await resolveInEuint64(amount, market, this.deps.fhe, encryptedAmount);
@@ -532,7 +727,24 @@ var ReputationModule = class {
532
727
  this.http = http2;
533
728
  }
534
729
  http;
730
+ /** True when an agent token is configured for authenticated reads */
731
+ hasAgentToken() {
732
+ return this.http.hasAgentToken();
733
+ }
734
+ /** Authenticated reputation for the agent token wallet */
735
+ async getAuthenticatedSummary() {
736
+ if (!this.http.hasAgentToken()) {
737
+ throw new Error("agentToken required \u2014 create one at /docs/agents");
738
+ }
739
+ return this.http.get("/agent/reputation");
740
+ }
535
741
  async getSummary(wallet) {
742
+ if (this.http.hasAgentToken()) {
743
+ return this.getAuthenticatedSummary();
744
+ }
745
+ if (!wallet) {
746
+ throw new Error("Invalid wallet address");
747
+ }
536
748
  const normalized = normalizeWallet(wallet);
537
749
  if (!normalized) {
538
750
  throw new Error("Invalid wallet address");
@@ -614,6 +826,7 @@ var ObscuraSDK = class _ObscuraSDK {
614
826
  vote;
615
827
  reputation;
616
828
  activity;
829
+ agent;
617
830
  notifications;
618
831
  walletClient;
619
832
  constructor(config) {
@@ -624,7 +837,7 @@ var ObscuraSDK = class _ObscuraSDK {
624
837
  const rpcUrl = config.rpcUrl ?? DEFAULT_RPC_URL;
625
838
  this.publicClient = config.publicClient ?? createDefaultPublicClient(rpcUrl, this.chainId);
626
839
  const apiUrl = config.apiUrl ?? DEFAULT_API_URL;
627
- const http2 = new HttpClient(apiUrl);
840
+ const http2 = new HttpClient(apiUrl, config.agentToken);
628
841
  const moduleDeps = {
629
842
  chainId: this.chainId,
630
843
  addresses: this.addresses,
@@ -635,15 +848,14 @@ var ObscuraSDK = class _ObscuraSDK {
635
848
  this.credit = new CreditModule({
636
849
  chainId: this.chainId,
637
850
  addresses: this.addresses,
851
+ publicClient: this.publicClient,
638
852
  fhe: this.fhe
639
853
  });
640
854
  this.vote = new VoteModule(moduleDeps);
641
855
  this.reputation = new ReputationModule(http2);
856
+ this.agent = new AgentModule(http2);
642
857
  this.notifications = new NotificationsModule(http2);
643
- this.activity = new ActivityModule(
644
- config.supabaseUrl ?? DEFAULT_SUPABASE_URL,
645
- config.supabaseAnonKey
646
- );
858
+ this.activity = new ActivityModule(http2);
647
859
  }
648
860
  static create(config = {}) {
649
861
  return new _ObscuraSDK(config);
@@ -662,6 +874,7 @@ var ObscuraSDK = class _ObscuraSDK {
662
874
  exports.ACTIVITY_EVENT_FILTERS = ACTIVITY_EVENT_FILTERS;
663
875
  exports.ARBITRUM_SEPOLIA_CHAIN_ID = ARBITRUM_SEPOLIA_CHAIN_ID;
664
876
  exports.ActivityModule = ActivityModule;
877
+ exports.AgentModule = AgentModule;
665
878
  exports.CREDIT_MARKET_ABI = CREDIT_MARKET_ABI;
666
879
  exports.CreditModule = CreditModule;
667
880
  exports.DEFAULT_ADDRESSES = DEFAULT_ADDRESSES;
@@ -677,6 +890,7 @@ exports.ObscuraSDK = ObscuraSDK;
677
890
  exports.PayModule = PayModule;
678
891
  exports.ReputationModule = ReputationModule;
679
892
  exports.VoteModule = VoteModule;
893
+ exports.buildAgentTokenMessage = buildAgentTokenMessage;
680
894
  exports.createDefaultPublicClient = createDefaultPublicClient;
681
895
  exports.encodeCall = encodeCall;
682
896
  exports.normalizeWallet = normalizeWallet;