@sage-protocol/cli 0.3.7 → 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,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') {
@@ -100,9 +101,6 @@ function resolveSubgraphUrl(override) {
100
101
  }
101
102
 
102
103
  async function createAction(opts) {
103
- if (process.env.SAGE_ENABLE_PERSONAL !== '1') {
104
- throw new Error('Personal libraries are disabled. Set SAGE_ENABLE_PERSONAL=1 to enable experimental commands.');
105
- }
106
104
  const provider = await getProvider();
107
105
  const wallet = await getWallet(provider);
108
106
  const diamond = getConfigAddress('SUBDAO_FACTORY_ADDRESS');
@@ -117,7 +115,7 @@ async function createAction(opts) {
117
115
  try { return contract.interface.parseLog(l); } catch (_) { return null; }
118
116
  }).find(Boolean);
119
117
  const out = {
120
- txHash: receipt.transactionHash,
118
+ txHash: receipt.hash,
121
119
  registry: evt && evt.args ? evt.args.registry : undefined,
122
120
  policy,
123
121
  };
@@ -129,9 +127,6 @@ async function createAction(opts) {
129
127
  }
130
128
 
131
129
  async function setPriceAction(key, price, opts) {
132
- if (process.env.SAGE_ENABLE_PERSONAL !== '1') {
133
- throw new Error('Personal libraries are disabled. Set SAGE_ENABLE_PERSONAL=1 to enable experimental commands.');
134
- }
135
130
  const provider = await getProvider();
136
131
  const wallet = await getWallet(provider);
137
132
  const mkt = getConfigAddress('PERSONAL_MARKETPLACE_ADDRESS');
@@ -146,7 +141,7 @@ async function setPriceAction(key, price, opts) {
146
141
  key,
147
142
  price,
148
143
  priceWei: priceWei.toString(),
149
- txHash: receipt.transactionHash,
144
+ txHash: receipt.hash,
150
145
  };
151
146
  if (opts && opts.json) {
152
147
  console.log(JSON.stringify(result, null, 2));
@@ -157,9 +152,6 @@ async function setPriceAction(key, price, opts) {
157
152
  }
158
153
 
159
154
  async function sellAction(key, price, opts = {}) {
160
- if (process.env.SAGE_ENABLE_PERSONAL !== '1') {
161
- throw new Error('Personal libraries are disabled. Set SAGE_ENABLE_PERSONAL=1 to enable experimental commands.');
162
- }
163
155
 
164
156
  if (!price || Number.isNaN(Number(price))) {
165
157
  throw new Error('Price must be a numeric value (in SXXX).');
@@ -181,7 +173,7 @@ async function sellAction(key, price, opts = {}) {
181
173
  const tx = await facet.createPersonalRegistry(policy);
182
174
  const rcpt = await tx.wait();
183
175
  if (!opts.json) {
184
- console.log(`📚 Personal registry created (policy=${policy}) -> tx ${rcpt.transactionHash}`);
176
+ console.log(`📚 Personal registry created (policy=${policy}) -> tx ${rcpt.hash}`);
185
177
  }
186
178
  }
187
179
 
@@ -253,10 +245,12 @@ async function sellAction(key, price, opts = {}) {
253
245
  throw new Error('Lit encryption helpers not available. Ensure @lit-protocol/encryption is installed.');
254
246
  }
255
247
 
256
- const litNetwork = opts.litNetwork || process.env.LIT_NETWORK || 'serrano';
257
- const client = new LitNodeClient({ litNetwork });
248
+ const litNetwork = opts.litNetwork || process.env.LIT_NETWORK || 'datil-test';
249
+ const client = new LitNodeClient({ litNetwork, debug: false });
258
250
  await client.connect();
259
251
 
252
+ const litChain = await inferLitChain(provider, opts.chain);
253
+
260
254
  let sessionSigs = null;
261
255
  if (opts.session) {
262
256
  sessionSigs = loadJsonFile(opts.session, '--session');
@@ -270,13 +264,14 @@ async function sellAction(key, price, opts = {}) {
270
264
  authSig = loadJsonFile(opts.authSig, '--auth-sig');
271
265
  } else if (process.env.LIT_AUTH_SIG) {
272
266
  authSig = loadJsonFile(process.env.LIT_AUTH_SIG, 'LIT_AUTH_SIG');
273
- }
274
- if (!authSig) {
275
- 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);
276
273
  }
277
274
  }
278
-
279
- const litChain = await inferLitChain(provider, opts.chain);
280
275
  const accessConditions = buildAccessControlConditions(receiptAddress, receiptId, litChain);
281
276
 
282
277
  const encResp = await encryptUint8Array({
@@ -337,12 +332,12 @@ async function sellAction(key, price, opts = {}) {
337
332
  const marketplace = new Contract(marketplaceAddress, marketplaceAbi, wallet);
338
333
  const priceTx = await marketplace.setPrice(keyHash, priceWei);
339
334
  const priceReceipt = await priceTx.wait();
340
- result.txHash = priceReceipt.transactionHash;
335
+ result.txHash = priceReceipt.hash;
341
336
 
342
337
  if (opts.json) {
343
338
  console.log(JSON.stringify(result, null, 2));
344
339
  } else {
345
- console.log(`✅ Listed ${key} for ${price} SXXX (${priceReceipt.transactionHash})`);
340
+ console.log(`✅ Listed ${key} for ${price} SXXX (tx: ${priceReceipt.hash})`);
346
341
  if (result.encryptedCid) {
347
342
  console.log(`🔒 Encrypted CID: ${result.encryptedCid}`);
348
343
  console.log(`🗃️ Manifest CID: ${result.manifestCid}`);
@@ -357,9 +352,6 @@ async function unsellAction(key, opts = {}) {
357
352
  }
358
353
 
359
354
  async function priceAction(creator, key, opts = {}) {
360
- if (process.env.SAGE_ENABLE_PERSONAL !== '1') {
361
- throw new Error('Personal libraries are disabled. Set SAGE_ENABLE_PERSONAL=1 to enable experimental commands.');
362
- }
363
355
 
364
356
  const provider = await getProvider();
365
357
  const marketplaceAddress = getConfigAddress('PERSONAL_MARKETPLACE_ADDRESS');
@@ -406,9 +398,6 @@ async function priceAction(creator, key, opts = {}) {
406
398
  }
407
399
 
408
400
  async function listAction(opts = {}) {
409
- if (process.env.SAGE_ENABLE_PERSONAL !== '1') {
410
- throw new Error('Personal libraries are disabled. Set SAGE_ENABLE_PERSONAL=1 to enable experimental commands.');
411
- }
412
401
 
413
402
  const provider = await getProvider();
414
403
  const wallet = await getWallet(provider);
@@ -445,7 +434,48 @@ async function listAction(opts = {}) {
445
434
  let personalResourceMap = new Map();
446
435
 
447
436
  if (!explicitKeys.length && subgraphUrl) {
448
- 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 = `
449
479
  query($creator: Bytes!, $first: Int!) {
450
480
  licensePurchases(where: { creator: $creator }, first: $first, orderBy: blockTimestamp, orderDirection: desc) {
451
481
  key
@@ -459,7 +489,7 @@ async function listAction(opts = {}) {
459
489
  }
460
490
  `;
461
491
  try {
462
- const data = await subgraphQuery(subgraphUrl, document, {
492
+ const data = await subgraphQuery(subgraphUrl, purchasesQuery, {
463
493
  creator: creatorAddress.toLowerCase(),
464
494
  first: limit,
465
495
  });
@@ -467,7 +497,15 @@ async function listAction(opts = {}) {
467
497
  for (const purchase of data?.licensePurchases || []) {
468
498
  const keyHash = String(purchase.key);
469
499
  const idKey = `hash:${keyHash}`;
470
- 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 {
471
509
  entries.set(idKey, {
472
510
  type: 'hash',
473
511
  keyHash,
@@ -516,7 +554,10 @@ async function listAction(opts = {}) {
516
554
  }
517
555
 
518
556
  if (!entries.size) {
519
- 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.');
520
561
  return [];
521
562
  }
522
563
 
@@ -592,9 +633,6 @@ async function listAction(opts = {}) {
592
633
  }
593
634
 
594
635
  async function myLicensesAction(opts = {}) {
595
- if (process.env.SAGE_ENABLE_PERSONAL !== '1') {
596
- throw new Error('Personal libraries are disabled. Set SAGE_ENABLE_PERSONAL=1 to enable experimental commands.');
597
- }
598
636
 
599
637
  const provider = await getProvider();
600
638
  const wallet = await getWallet(provider);
@@ -712,9 +750,6 @@ async function myLicensesAction(opts = {}) {
712
750
  }
713
751
 
714
752
  async function buyAction(creator, key, expectedPriceArg, opts = {}) {
715
- if (process.env.SAGE_ENABLE_PERSONAL !== '1') {
716
- throw new Error('Personal libraries are disabled. Set SAGE_ENABLE_PERSONAL=1 to enable experimental commands.');
717
- }
718
753
 
719
754
  const provider = await getProvider();
720
755
  const wallet = await getWallet(provider);
@@ -772,7 +807,7 @@ async function buyAction(creator, key, expectedPriceArg, opts = {}) {
772
807
  const approveTx = await sxxx.approve(marketplaceAddress, approveAmount);
773
808
  const approveReceipt = await approveTx.wait();
774
809
  if (!opts.json) {
775
- console.log(`✅ SXXX approval tx ${approveReceipt.transactionHash}`);
810
+ console.log(`✅ SXXX approval tx ${approveReceipt.hash}`);
776
811
  }
777
812
  }
778
813
 
@@ -799,7 +834,7 @@ async function buyAction(creator, key, expectedPriceArg, opts = {}) {
799
834
  : sdk.personal.computeReceiptId(creatorAddress, key);
800
835
 
801
836
  const result = {
802
- txHash: receipt.transactionHash,
837
+ txHash: receipt.hash,
803
838
  creator: creatorAddress,
804
839
  buyer: buyerAddress,
805
840
  key,
@@ -827,9 +862,6 @@ async function buyAction(creator, key, expectedPriceArg, opts = {}) {
827
862
  }
828
863
 
829
864
  async function accessAction(creator, key, opts) {
830
- if (process.env.SAGE_ENABLE_PERSONAL !== '1') {
831
- throw new Error('Personal libraries are disabled. Set SAGE_ENABLE_PERSONAL=1 to enable experimental commands.');
832
- }
833
865
 
834
866
  const provider = await getProvider();
835
867
  const wallet = await getWallet(provider);
@@ -903,10 +935,12 @@ async function accessAction(creator, key, opts) {
903
935
 
904
936
  if (!opts.skipDecrypt && payloadObject) {
905
937
  const { LitNodeClient } = requireLit();
906
- const litNetwork = opts.litNetwork || process.env.LIT_NETWORK || 'serrano';
907
- const client = new LitNodeClient({ litNetwork });
938
+ const litNetwork = opts.litNetwork || process.env.LIT_NETWORK || 'datil-test';
939
+ const client = new LitNodeClient({ litNetwork, debug: false });
908
940
  await client.connect();
909
941
 
942
+ const litChain = await inferLitChain(provider, opts.chain);
943
+
910
944
  let sessionSigs = null;
911
945
  if (opts.session) {
912
946
  sessionSigs = loadJsonFile(opts.session, '--session');
@@ -915,13 +949,20 @@ async function accessAction(creator, key, opts) {
915
949
  }
916
950
 
917
951
  let authSig = null;
918
- if (opts.authSig) {
919
- authSig = loadJsonFile(opts.authSig, '--auth-sig');
920
- } else if (process.env.LIT_AUTH_SIG) {
921
- 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
+ }
922
964
  }
923
965
 
924
- const litChain = await inferLitChain(provider, opts.chain);
925
966
  decrypted = await sdk.personal.decryptWithLit({
926
967
  encryptedCid: payloadObject,
927
968
  receiptId,
@@ -993,59 +1034,21 @@ async function accessAction(creator, key, opts) {
993
1034
  }
994
1035
 
995
1036
  function register(program) {
996
- const cmd = program.command('personal').description('[experimental] Manage personal registries and marketplace');
1037
+ const { Command } = require('commander');
1038
+ const cmd = program.command('personal').description('Manage personal prompts and premium content');
1039
+
1040
+ // --- Registry management ---
997
1041
  cmd
998
1042
  .command('create')
999
1043
  .description('Create a personal registry (owned by your EOA)')
1000
1044
  .option('--policy <n>', 'Fork policy (0=open,1=gov_only,2=disabled)', '0')
1001
1045
  .action((opts) => createAction(opts).catch((err) => { console.error(err.message); process.exit(1); }));
1002
- cmd
1003
- .command('set-price <key> <price>')
1004
- .description('Set price in SXXX (18 decimals) for a content key')
1005
- .option('--json', 'Emit machine-readable JSON output', false)
1006
- .action((key, price, opts) => setPriceAction(key, price, opts).catch((err) => { console.error(err.message); process.exit(1); }));
1007
- cmd
1008
- .command('sell <key> <price>')
1009
- .description('List a personal prompt key for sale and optionally encrypt the payload')
1010
- .option('--encrypt', 'Encrypt content and upload manifest to IPFS', false)
1011
- .option('--file <path>', 'Path to plaintext prompt/content (required with --encrypt)')
1012
- .option('--name <name>', 'Friendly name for the encrypted payload')
1013
- .option('--description <text>', 'Description stored alongside the encrypted payload')
1014
- .option('--metadata <file>', 'Path to JSON metadata to embed in the manifest')
1015
- .option('--manifest <file>', 'Write manifest JSON to this path')
1016
- .option('--policy <n>', 'Optional: create personal registry with policy (0=open,1=gov_only,2=disabled) before selling')
1017
- .option('--session <file>', 'Lit session signatures JSON (preferred)')
1018
- .option('--auth-sig <file>', 'Lit AuthSig JSON (fallback if no session signatures)')
1019
- .option('--chain <litChain>', 'Override Lit chain key (default: infer)')
1020
- .option('--lit-network <name>', 'Lit network (serrano | datil-test | datil-dev)', process.env.LIT_NETWORK || 'serrano')
1021
- .option('--json', 'Emit machine-readable JSON output', false)
1022
- .action((key, price, opts) => sellAction(key, price, opts).catch((err) => { console.error(err.message); process.exit(1); }));
1023
- cmd
1024
- .command('unsell <key>')
1025
- .description('Remove a price listing (sets price to 0)')
1026
- .option('--json', 'Emit machine-readable JSON output', false)
1027
- .action((key, opts) => unsellAction(key, opts).catch((err) => { console.error(err.message); process.exit(1); }));
1028
- cmd
1029
- .command('buy <creator> <key> [expectedPrice]')
1030
- .description('Buy a license for a content key')
1031
- .option('--max-price <sxxx>', 'Maximum price you are willing to pay (SXXX)')
1032
- .option('--deadline <seconds>', 'Relative deadline window in seconds (default: 600)', '600')
1033
- .option('--auto-approve', 'Automatically approve SXXX allowance if needed', false)
1034
- .option('--unlimited', 'When auto-approving, approve unlimited allowance', false)
1035
- .option('--json', 'Emit machine-readable JSON output', false)
1036
- .action((creator, key, expectedPrice, opts) => buyAction(creator, key, expectedPrice, opts).catch((err) => { console.error(err.message); process.exit(1); }));
1037
-
1038
- cmd
1039
- .command('price <creator> <key>')
1040
- .description('Show current listing price and fee breakdown for a key')
1041
- .option('--json', 'Emit machine-readable JSON output', false)
1042
- .action((creator, key, opts) => priceAction(creator, key, opts).catch((err) => { console.error(err.message); process.exit(1); }));
1043
1046
 
1044
1047
  cmd
1045
1048
  .command('list')
1046
- .description('List active or recent personal listings for a creator')
1049
+ .description('List personal prompts for a creator')
1047
1050
  .option('--creator <address>', 'Creator address to inspect')
1048
- .option('--mine', 'List keys for the active wallet')
1051
+ .option('--mine', 'List prompts for the active wallet')
1049
1052
  .option('--keys <keys...>', 'Explicit plaintext keys to list (skips subgraph)')
1050
1053
  .option('--key <key>', 'Single plaintext key to list')
1051
1054
  .option('--limit <n>', 'Maximum records to pull from subgraph (default 25)')
@@ -1055,28 +1058,76 @@ function register(program) {
1055
1058
 
1056
1059
  cmd
1057
1060
  .command('my-licenses')
1058
- .description('Show personal licenses owned by the active (or provided) wallet')
1061
+ .description('Show premium licenses owned by the active wallet')
1059
1062
  .option('--holder <address>', 'Override holder address')
1060
1063
  .option('--limit <n>', 'Maximum records to pull (default 25)')
1061
1064
  .option('--subgraph <url>', 'Override subgraph endpoint')
1062
1065
  .option('--json', 'Emit machine-readable JSON output', false)
1063
1066
  .action((opts) => myLicensesAction(opts).catch((err) => { console.error(err.message); process.exit(1); }));
1064
1067
 
1065
- cmd
1068
+ // --- Premium subcommand group ---
1069
+ const premium = new Command('premium').description('Premium (paid) personal prompts');
1070
+
1071
+ premium
1072
+ .command('publish <key>')
1073
+ .description('Publish premium content for sale (encrypted, requires purchase)')
1074
+ .requiredOption('--price <sxxx>', 'Price in SXXX (18 decimals)')
1075
+ .requiredOption('--file <path>', 'Path to content file to encrypt')
1076
+ .option('--name <name>', 'Friendly name for the content')
1077
+ .option('--description <text>', 'Description of the content')
1078
+ .option('--metadata <file>', 'Path to JSON metadata to embed in the manifest')
1079
+ .option('--manifest <file>', 'Write manifest JSON to this path')
1080
+ .option('--policy <n>', 'Create personal registry with policy before publishing')
1081
+ .option('--session <file>', 'Lit session signatures JSON (preferred)')
1082
+ .option('--auth-sig <file>', 'Lit AuthSig JSON (fallback)')
1083
+ .option('--chain <litChain>', 'Override Lit chain key (default: infer)')
1084
+ .option('--lit-network <name>', 'Lit network (datil-test | datil-dev)', process.env.LIT_NETWORK || 'datil-test')
1085
+ .option('--json', 'Emit machine-readable JSON output', false)
1086
+ .action((key, opts) => {
1087
+ // Call sellAction with encrypt always true for premium
1088
+ const sellOpts = { ...opts, encrypt: true };
1089
+ sellAction(key, opts.price, sellOpts).catch((err) => { console.error(err.message); process.exit(1); });
1090
+ });
1091
+
1092
+ premium
1093
+ .command('buy <creator> <key> [expectedPrice]')
1094
+ .description('Purchase a license for premium content')
1095
+ .option('--max-price <sxxx>', 'Maximum price you are willing to pay (SXXX)')
1096
+ .option('--deadline <seconds>', 'Relative deadline window in seconds (default: 600)', '600')
1097
+ .option('--auto-approve', 'Automatically approve SXXX allowance if needed', false)
1098
+ .option('--unlimited', 'When auto-approving, approve unlimited allowance', false)
1099
+ .option('--json', 'Emit machine-readable JSON output', false)
1100
+ .action((creator, key, expectedPrice, opts) => buyAction(creator, key, expectedPrice, opts).catch((err) => { console.error(err.message); process.exit(1); }));
1101
+
1102
+ premium
1066
1103
  .command('access <creator> <key>')
1067
- .description('Resolve encrypted personal content and decrypt via Lit (requires license)')
1104
+ .description('Decrypt and view purchased premium content')
1068
1105
  .option('--holder <address>', 'Override holder address (defaults to active wallet)')
1069
- .option('--subgraph <url>', 'Override subgraph endpoint (defaults to SUBGRAPH_URL env)')
1070
- .option('--gateway <url>', 'IPFS gateway for encrypted payload fetch')
1106
+ .option('--subgraph <url>', 'Override subgraph endpoint')
1107
+ .option('--gateway <url>', 'IPFS gateway for payload fetch')
1071
1108
  .option('--session <file>', 'Path to Lit session signatures JSON')
1072
- .option('--auth-sig <file>', 'Path to Lit AuthSig JSON (fallback if session signatures unavailable)')
1073
- .option('--chain <litChain>', 'Lit chain identifier (default: auto from RPC or LIT_CHAIN env)')
1074
- .option('--lit-network <name>', 'Lit network (serrano | datil-test | datil-dev)', process.env.LIT_NETWORK || 'serrano')
1109
+ .option('--auth-sig <file>', 'Path to Lit AuthSig JSON (fallback)')
1110
+ .option('--chain <litChain>', 'Lit chain identifier')
1111
+ .option('--lit-network <name>', 'Lit network (datil-test | datil-dev)', process.env.LIT_NETWORK || 'datil-test')
1075
1112
  .option('--out <file>', 'Write decrypted output to file')
1076
- .option('--skip-decrypt', 'Skip Lit decryption and only report license status')
1077
- .option('--encrypted-cid <cid>', 'Override encrypted CID when subgraph manifests are not yet indexed')
1113
+ .option('--skip-decrypt', 'Skip decryption and only report license status')
1114
+ .option('--encrypted-cid <cid>', 'Override encrypted CID')
1078
1115
  .option('--json', 'Emit machine-readable JSON report', false)
1079
1116
  .action((creator, key, opts) => accessAction(creator, key, opts).catch((err) => { console.error(err.message); process.exit(1); }));
1117
+
1118
+ premium
1119
+ .command('price <creator> <key>')
1120
+ .description('Show price and fee breakdown for premium content')
1121
+ .option('--json', 'Emit machine-readable JSON output', false)
1122
+ .action((creator, key, opts) => priceAction(creator, key, opts).catch((err) => { console.error(err.message); process.exit(1); }));
1123
+
1124
+ premium
1125
+ .command('unlist <key>')
1126
+ .description('Remove a premium listing (sets price to 0)')
1127
+ .option('--json', 'Emit machine-readable JSON output', false)
1128
+ .action((key, opts) => unsellAction(key, opts).catch((err) => { console.error(err.message); process.exit(1); }));
1129
+
1130
+ cmd.addCommand(premium);
1080
1131
  }
1081
1132
 
1082
1133
  module.exports = { register };