@sage-protocol/cli 0.3.9 → 0.3.10

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.
@@ -7,7 +7,7 @@
7
7
  "RPC_URL": "https://sepolia.base.org",
8
8
  "LIBRARY_REGISTRY_ADDRESS": "0x032F2E93549640a319163Ba600fc50bA1AFBE50F",
9
9
  "SUBDAO_FACTORY_ADDRESS": "0x6bb6A83149F84Df0584aC863e5fE3416AFb214aC",
10
- "SUBGRAPH_URL": "https://api.goldsky.com/api/public/project_cmhxp0fppsbdd01q56xp2gqw9/subgraphs/sxxx-protocol/1.0.0/gn",
10
+ "SUBGRAPH_URL": "https://api.goldsky.com/api/public/project_cmhxp0fppsbdd01q56xp2gqw9/subgraphs/sxxx-protocol/1.0.1/gn",
11
11
  "PINATA_JWT": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mb3JtYXRpb24iOnsiaWQiOiI4ODE2MWM1Ni05NTYzLTQyNTUtYTU4Ni0xMzBiMTUyMWIxNmIiLCJlbWFpbCI6InRlcnJlbmV0d2VsbHM0N0BnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwicGluX3BvbGljeSI6eyJyZWdpb25zIjpbeyJkZXNpcmVkUmVwbGljYXRpb25Db3VudCI6MSwiaWQiOiJGUkExIn0seyJkZXNpcmVkUmVwbGljYXRpb25Db3VudCI6MSwiaWQiOiJOWUMxIn1dLCJ2ZXJzaW9uIjoxfSwibWZhX2VuYWJsZWQiOmZhbHNlLCJzdGF0dXMiOiJBQ1RJVkUifSwiYXV0aGVudGljYXRpb25UeXBlIjoic2NvcGVkS2V5Iiwic2NvcGVkS2V5S2V5IjoiMDRjZWY4NzE5OTg1ODE1M2U5Y2IiLCJzY29wZWRLZXlTZWNyZXQiOiJmNDFjMDVhZTNjN2EzMTliOTAxZjhiNGI3YjMxMDljMThmNjgyZmRkZGY3OGU1ZmZkZjQ4MTM4OTQ0OWUyOGVjIiwiZXhwIjoxNzk1NTMzNTA4fQ.tQKFU7aZ3EKb7RkB99QTaWVduaaKaKjEa1nk43aeSlo"
12
12
  }
13
13
  }
@@ -7,6 +7,7 @@ const { formatJson } = require('../utils/format');
7
7
  const { getProvider, getWallet } = require('../utils/provider');
8
8
  const { loadAbi } = require('../utils/abi-loader');
9
9
  const { buildAccessControlConditions, receiptIdToHex } = require('../utils/personal-helpers');
10
+ const { buildNodeAuthSig } = require('../utils/lit');
10
11
  const ConfigManager = require('../config');
11
12
 
12
13
  if (ConfigManager && typeof ConfigManager.loadEnv === 'function') {
@@ -114,7 +115,7 @@ async function createAction(opts) {
114
115
  try { return contract.interface.parseLog(l); } catch (_) { return null; }
115
116
  }).find(Boolean);
116
117
  const out = {
117
- txHash: receipt.transactionHash,
118
+ txHash: receipt.hash,
118
119
  registry: evt && evt.args ? evt.args.registry : undefined,
119
120
  policy,
120
121
  };
@@ -140,7 +141,7 @@ async function setPriceAction(key, price, opts) {
140
141
  key,
141
142
  price,
142
143
  priceWei: priceWei.toString(),
143
- txHash: receipt.transactionHash,
144
+ txHash: receipt.hash,
144
145
  };
145
146
  if (opts && opts.json) {
146
147
  console.log(JSON.stringify(result, null, 2));
@@ -172,7 +173,7 @@ async function sellAction(key, price, opts = {}) {
172
173
  const tx = await facet.createPersonalRegistry(policy);
173
174
  const rcpt = await tx.wait();
174
175
  if (!opts.json) {
175
- console.log(`📚 Personal registry created (policy=${policy}) -> tx ${rcpt.transactionHash}`);
176
+ console.log(`📚 Personal registry created (policy=${policy}) -> tx ${rcpt.hash}`);
176
177
  }
177
178
  }
178
179
 
@@ -244,10 +245,12 @@ async function sellAction(key, price, opts = {}) {
244
245
  throw new Error('Lit encryption helpers not available. Ensure @lit-protocol/encryption is installed.');
245
246
  }
246
247
 
247
- const litNetwork = opts.litNetwork || process.env.LIT_NETWORK || 'serrano';
248
- const client = new LitNodeClient({ litNetwork });
248
+ const litNetwork = opts.litNetwork || process.env.LIT_NETWORK || 'datil-test';
249
+ const client = new LitNodeClient({ litNetwork, debug: false });
249
250
  await client.connect();
250
251
 
252
+ const litChain = await inferLitChain(provider, opts.chain);
253
+
251
254
  let sessionSigs = null;
252
255
  if (opts.session) {
253
256
  sessionSigs = loadJsonFile(opts.session, '--session');
@@ -261,13 +264,14 @@ async function sellAction(key, price, opts = {}) {
261
264
  authSig = loadJsonFile(opts.authSig, '--auth-sig');
262
265
  } else if (process.env.LIT_AUTH_SIG) {
263
266
  authSig = loadJsonFile(process.env.LIT_AUTH_SIG, 'LIT_AUTH_SIG');
264
- }
265
- if (!authSig) {
266
- throw new Error('Provide Lit session signatures (--session) or authSig (--auth-sig) for encryption.');
267
+ } else {
268
+ // Auto-generate authSig from connected wallet
269
+ if (!opts.json) {
270
+ console.log('🔐 Generating Lit auth signature from wallet...');
271
+ }
272
+ authSig = await buildNodeAuthSig(wallet, litChain);
267
273
  }
268
274
  }
269
-
270
- const litChain = await inferLitChain(provider, opts.chain);
271
275
  const accessConditions = buildAccessControlConditions(receiptAddress, receiptId, litChain);
272
276
 
273
277
  const encResp = await encryptUint8Array({
@@ -328,12 +332,12 @@ async function sellAction(key, price, opts = {}) {
328
332
  const marketplace = new Contract(marketplaceAddress, marketplaceAbi, wallet);
329
333
  const priceTx = await marketplace.setPrice(keyHash, priceWei);
330
334
  const priceReceipt = await priceTx.wait();
331
- result.txHash = priceReceipt.transactionHash;
335
+ result.txHash = priceReceipt.hash;
332
336
 
333
337
  if (opts.json) {
334
338
  console.log(JSON.stringify(result, null, 2));
335
339
  } else {
336
- console.log(`✅ Listed ${key} for ${price} SXXX (${priceReceipt.transactionHash})`);
340
+ console.log(`✅ Listed ${key} for ${price} SXXX (tx: ${priceReceipt.hash})`);
337
341
  if (result.encryptedCid) {
338
342
  console.log(`🔒 Encrypted CID: ${result.encryptedCid}`);
339
343
  console.log(`đŸ—ƒī¸ Manifest CID: ${result.manifestCid}`);
@@ -430,7 +434,48 @@ async function listAction(opts = {}) {
430
434
  let personalResourceMap = new Map();
431
435
 
432
436
  if (!explicitKeys.length && subgraphUrl) {
433
- const document = `
437
+ // First try to get all listings (PriceSet events)
438
+ const listingsQuery = `
439
+ query($creator: Bytes!, $first: Int!) {
440
+ personalListings(where: { creator: $creator, listed: true }, first: $first, orderBy: updatedAt, orderDirection: desc) {
441
+ id
442
+ creator
443
+ key
444
+ price
445
+ listed
446
+ createdAt
447
+ updatedAt
448
+ }
449
+ }
450
+ `;
451
+ try {
452
+ const listingsData = await subgraphQuery(subgraphUrl, listingsQuery, {
453
+ creator: creatorAddress.toLowerCase(),
454
+ first: limit,
455
+ });
456
+
457
+ for (const listing of listingsData?.personalListings || []) {
458
+ const keyHash = String(listing.key);
459
+ const idKey = `hash:${keyHash}`;
460
+ if (!entries.has(idKey)) {
461
+ entries.set(idKey, {
462
+ type: 'hash',
463
+ keyHash,
464
+ priceFromListing: listing.price ? BigInt(String(listing.price)) : null,
465
+ listedAt: listing.createdAt ? Number(listing.createdAt) : null,
466
+ updatedAt: listing.updatedAt ? Number(listing.updatedAt) : null,
467
+ });
468
+ }
469
+ }
470
+ } catch (listingError) {
471
+ // PersonalListing entity may not exist yet, fall back to purchases
472
+ if (!listingError.message?.includes('Cannot query field')) {
473
+ console.warn(`âš ī¸ Listings query: ${listingError.message}`);
474
+ }
475
+ }
476
+
477
+ // Also fetch purchases for additional metadata
478
+ const purchasesQuery = `
434
479
  query($creator: Bytes!, $first: Int!) {
435
480
  licensePurchases(where: { creator: $creator }, first: $first, orderBy: blockTimestamp, orderDirection: desc) {
436
481
  key
@@ -444,7 +489,7 @@ async function listAction(opts = {}) {
444
489
  }
445
490
  `;
446
491
  try {
447
- const data = await subgraphQuery(subgraphUrl, document, {
492
+ const data = await subgraphQuery(subgraphUrl, purchasesQuery, {
448
493
  creator: creatorAddress.toLowerCase(),
449
494
  first: limit,
450
495
  });
@@ -452,7 +497,15 @@ async function listAction(opts = {}) {
452
497
  for (const purchase of data?.licensePurchases || []) {
453
498
  const keyHash = String(purchase.key);
454
499
  const idKey = `hash:${keyHash}`;
455
- if (!entries.has(idKey)) {
500
+ const existing = entries.get(idKey);
501
+ if (existing) {
502
+ // Enrich existing listing with purchase data
503
+ existing.receiptId = purchase.receiptId ? BigInt(String(purchase.receiptId)) : existing.receiptId;
504
+ existing.lastBuyer = purchase.buyer ? getAddress(purchase.buyer) : existing.lastBuyer;
505
+ existing.lastPurchaseAt = purchase.blockTimestamp ? Number(purchase.blockTimestamp) : existing.lastPurchaseAt;
506
+ existing.encryptedCid = purchase.encryptedCid || existing.encryptedCid;
507
+ existing.metadata = purchase.metadata || existing.metadata;
508
+ } else {
456
509
  entries.set(idKey, {
457
510
  type: 'hash',
458
511
  keyHash,
@@ -501,7 +554,10 @@ async function listAction(opts = {}) {
501
554
  }
502
555
 
503
556
  if (!entries.size) {
504
- console.log('â„šī¸ No listings found. Provide --keys or ensure listings have been purchased/indexed.');
557
+ console.log('â„šī¸ No listings found.');
558
+ console.log(' Use --key <name> to check a specific listing by key.');
559
+ console.log(' Example: sage personal list --mine --key "my-prompt"');
560
+ console.log(' Note: Listings appear in subgraph after first purchase.');
505
561
  return [];
506
562
  }
507
563
 
@@ -751,7 +807,7 @@ async function buyAction(creator, key, expectedPriceArg, opts = {}) {
751
807
  const approveTx = await sxxx.approve(marketplaceAddress, approveAmount);
752
808
  const approveReceipt = await approveTx.wait();
753
809
  if (!opts.json) {
754
- console.log(`✅ SXXX approval tx ${approveReceipt.transactionHash}`);
810
+ console.log(`✅ SXXX approval tx ${approveReceipt.hash}`);
755
811
  }
756
812
  }
757
813
 
@@ -778,7 +834,7 @@ async function buyAction(creator, key, expectedPriceArg, opts = {}) {
778
834
  : sdk.personal.computeReceiptId(creatorAddress, key);
779
835
 
780
836
  const result = {
781
- txHash: receipt.transactionHash,
837
+ txHash: receipt.hash,
782
838
  creator: creatorAddress,
783
839
  buyer: buyerAddress,
784
840
  key,
@@ -879,10 +935,12 @@ async function accessAction(creator, key, opts) {
879
935
 
880
936
  if (!opts.skipDecrypt && payloadObject) {
881
937
  const { LitNodeClient } = requireLit();
882
- const litNetwork = opts.litNetwork || process.env.LIT_NETWORK || 'serrano';
883
- const client = new LitNodeClient({ litNetwork });
938
+ const litNetwork = opts.litNetwork || process.env.LIT_NETWORK || 'datil-test';
939
+ const client = new LitNodeClient({ litNetwork, debug: false });
884
940
  await client.connect();
885
941
 
942
+ const litChain = await inferLitChain(provider, opts.chain);
943
+
886
944
  let sessionSigs = null;
887
945
  if (opts.session) {
888
946
  sessionSigs = loadJsonFile(opts.session, '--session');
@@ -891,13 +949,20 @@ async function accessAction(creator, key, opts) {
891
949
  }
892
950
 
893
951
  let authSig = null;
894
- if (opts.authSig) {
895
- authSig = loadJsonFile(opts.authSig, '--auth-sig');
896
- } else if (process.env.LIT_AUTH_SIG) {
897
- authSig = loadJsonFile(process.env.LIT_AUTH_SIG, 'LIT_AUTH_SIG');
952
+ if (!sessionSigs) {
953
+ if (opts.authSig) {
954
+ authSig = loadJsonFile(opts.authSig, '--auth-sig');
955
+ } else if (process.env.LIT_AUTH_SIG) {
956
+ authSig = loadJsonFile(process.env.LIT_AUTH_SIG, 'LIT_AUTH_SIG');
957
+ } else {
958
+ // Auto-generate authSig from connected wallet
959
+ if (!opts.json) {
960
+ console.log('🔐 Generating Lit auth signature from wallet...');
961
+ }
962
+ authSig = await buildNodeAuthSig(wallet, litChain);
963
+ }
898
964
  }
899
965
 
900
- const litChain = await inferLitChain(provider, opts.chain);
901
966
  decrypted = await sdk.personal.decryptWithLit({
902
967
  encryptedCid: payloadObject,
903
968
  receiptId,
@@ -18,7 +18,7 @@ Create or update your `.env` file with the required configuration:
18
18
 
19
19
  ```bash
20
20
  # Subgraph (preferred) + Blockchain
21
- SUBGRAPH_URL=https://api.goldsky.com/api/public/project_cmhxp0fppsbdd01q56xp2gqw9/subgraphs/sxxx-protocol/1.0.0/gn
21
+ SUBGRAPH_URL=https://api.goldsky.com/api/public/project_cmhxp0fppsbdd01q56xp2gqw9/subgraphs/sxxx-protocol/1.0.1/gn
22
22
  RPC_URL=https://sepolia.base.org
23
23
  LIBRARY_REGISTRY_ADDRESS=0x032F2E93549640a319163Ba600fc50bA1AFBE50F
24
24
  SUBDAO_FACTORY_ADDRESS=0x6bb6A83149F84Df0584aC863e5fE3416AFb214aC
@@ -65,7 +65,7 @@ You should see a JSON response listing the available tools.
65
65
  "command": "node",
66
66
  "args": ["/absolute/path/to/sage-protocol/cli/mcp-server-stdio.js"],
67
67
  "env": {
68
- "SUBGRAPH_URL": "https://api.goldsky.com/api/public/project_cmhxp0fppsbdd01q56xp2gqw9/subgraphs/sxxx-protocol/1.0.0/gn",
68
+ "SUBGRAPH_URL": "https://api.goldsky.com/api/public/project_cmhxp0fppsbdd01q56xp2gqw9/subgraphs/sxxx-protocol/1.0.1/gn",
69
69
  "RPC_URL": "https://sepolia.base.org",
70
70
  "LIBRARY_REGISTRY_ADDRESS": "0x032F2E93549640a319163Ba600fc50bA1AFBE50F",
71
71
  "SUBDAO_FACTORY_ADDRESS": "0x6bb6A83149F84Df0584aC863e5fE3416AFb214aC"
@@ -44,7 +44,7 @@ function buildAccessControlConditions(receiptAddress, receiptId, chain) {
44
44
  type: 'function',
45
45
  },
46
46
  chain: litChain,
47
- returnValueTest: { comparator: '>', value: '0' },
47
+ returnValueTest: { key: '', comparator: '>', value: '0' },
48
48
  },
49
49
  ];
50
50
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sage-protocol/cli",
3
- "version": "0.3.9",
3
+ "version": "0.3.10",
4
4
  "description": "Sage Protocol CLI for managing AI prompt libraries",
5
5
  "bin": {
6
6
  "sage": "./bin/sage.js"