neozip-cli 0.80.0 → 0.95.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.
Files changed (74) hide show
  1. package/AGENTS.md +93 -0
  2. package/CHANGELOG.md +117 -12
  3. package/DOCUMENTATION.md +33 -38
  4. package/README.md +137 -63
  5. package/dist/src/account/account-state.js +95 -0
  6. package/dist/src/account/format-account-status.js +62 -0
  7. package/dist/src/account/identity-provision.js +79 -0
  8. package/dist/src/account/identity-wrap.js +106 -0
  9. package/dist/src/account/profile-crypto.js +85 -0
  10. package/dist/src/account/profile-store.js +129 -0
  11. package/dist/src/account/require-account.js +32 -0
  12. package/dist/src/account/types.js +3 -0
  13. package/dist/src/account/wallet-evm.js +46 -0
  14. package/dist/src/account/wallet-setup.js +33 -0
  15. package/dist/src/archive/crypto-self.js +117 -0
  16. package/dist/src/archive/identity-key.js +217 -0
  17. package/dist/src/archive/recipient-lookup.js +61 -0
  18. package/dist/src/cli/output.js +100 -0
  19. package/dist/src/cli/params.js +122 -0
  20. package/dist/src/cli/schema.js +186 -0
  21. package/dist/src/cli/validate.js +119 -0
  22. package/dist/src/commands/mintTimestampProof.js +26 -14
  23. package/dist/src/config/ConfigSetup.js +82 -423
  24. package/dist/src/connect/command.js +364 -0
  25. package/dist/src/connection/bootstrap.js +50 -0
  26. package/dist/src/connection/cli-guidance.js +101 -0
  27. package/dist/src/connection/cli-prefs.js +180 -0
  28. package/dist/src/connection/cli-settings.js +140 -0
  29. package/dist/src/connection/cli-types.js +14 -0
  30. package/dist/src/connection/coordinator.js +83 -0
  31. package/dist/src/connection/credentials.js +33 -0
  32. package/dist/src/connection/crypto.js +96 -0
  33. package/dist/src/connection/dump.js +117 -0
  34. package/dist/src/connection/funding.js +187 -0
  35. package/dist/src/connection/incomplete-setup.js +89 -0
  36. package/dist/src/connection/interactive.js +871 -0
  37. package/dist/src/connection/legacy-profile-reader.js +87 -0
  38. package/dist/src/connection/magic-link.js +142 -0
  39. package/dist/src/connection/migrate.js +115 -0
  40. package/dist/src/connection/onboarding.js +616 -0
  41. package/dist/src/connection/origin.js +69 -0
  42. package/dist/src/connection/phase.js +101 -0
  43. package/dist/src/connection/phone.js +26 -0
  44. package/dist/src/connection/promote-active.js +56 -0
  45. package/dist/src/connection/reset.js +56 -0
  46. package/dist/src/connection/status-report.js +52 -0
  47. package/dist/src/connection/store.js +406 -0
  48. package/dist/src/connection/token-auth.js +44 -0
  49. package/dist/src/connection/types.js +3 -0
  50. package/dist/src/connection/wallet-json-migration.js +155 -0
  51. package/dist/src/connection/wallet-login.js +65 -0
  52. package/dist/src/connection/wallet-setup.js +83 -0
  53. package/dist/src/constants/wallet-identity.js +14 -0
  54. package/dist/src/exit-codes.js +54 -10
  55. package/dist/src/neolist.js +100 -10
  56. package/dist/src/neounzip.js +236 -65
  57. package/dist/src/neozip/blockchain.js +18 -18
  58. package/dist/src/neozip/createZip.js +118 -94
  59. package/dist/src/neozip/upgradeZip.js +14 -11
  60. package/dist/src/neozip.js +269 -91
  61. package/dist/src/skills/command.js +256 -0
  62. package/dist/src/skills/locate.js +99 -0
  63. package/dist/src/util/mask.js +34 -0
  64. package/dist/src/util/token-service-fetch.js +26 -0
  65. package/env.example +18 -85
  66. package/package.json +89 -73
  67. package/skills/neozip-connect/SKILL.md +95 -0
  68. package/skills/neozip-create/SKILL.md +57 -0
  69. package/skills/neozip-extract/SKILL.md +58 -0
  70. package/skills/neozip-legacy/SKILL.md +48 -0
  71. package/skills/neozip-list/SKILL.md +56 -0
  72. package/skills/neozip-shared/SKILL.md +60 -0
  73. package/dist/src/commands/verifyEmail.js +0 -146
  74. package/dist/src/config/ConfigStore.js +0 -406
@@ -37,12 +37,13 @@ var __importStar = (this && this.__importStar) || (function () {
37
37
  })();
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  exports.isSupportedNetwork = isSupportedNetwork;
40
+ exports.getConnectionWalletKey = getConnectionWalletKey;
40
41
  exports.getWalletPasskey = getWalletPasskey;
41
42
  exports.addTokenMetaToZip = addTokenMetaToZip;
42
43
  exports.handleTokenMinting = handleTokenMinting;
43
44
  const neozipkit_1 = require("neozipkit");
44
45
  const neozip_blockchain_1 = require("neozip-blockchain");
45
- const ConfigStore_1 = require("../config/ConfigStore");
46
+ const credentials_1 = require("../connection/credentials");
46
47
  const readline = __importStar(require("readline"));
47
48
  /**
48
49
  * Check if the network is supported (uses nameAliases from CONTRACT_CONFIGS)
@@ -51,34 +52,29 @@ function isSupportedNetwork(network) {
51
52
  return (0, neozip_blockchain_1.getChainIdByName)(network) !== null;
52
53
  }
53
54
  /**
54
- * Check if the required wallet passkey is available and valid
55
- * Priority: CLI arg > wallet.json > ENV var
56
- * @param cliWalletKey - Optional wallet key from CLI
57
- * @param showError - Whether to show error messages (default: true)
55
+ * Resolve wallet key from connection store (optional CLI override for automation).
58
56
  */
59
- function getWalletPasskey(cliWalletKey, showError = true) {
60
- // Get config with CLI wallet key taking precedence
61
- const config = ConfigStore_1.ConfigStore.getConfig(cliWalletKey);
62
- const passkey = config.walletKey;
57
+ function getConnectionWalletKey(cliWalletKey, showError = true) {
58
+ const passkey = cliWalletKey?.trim() || (0, credentials_1.readConnectionCredentials)().walletKey;
63
59
  if (!passkey) {
64
60
  if (showError) {
65
61
  console.error('❌ Error: Wallet private key is required for blockchain operations');
66
62
  console.error('');
67
- console.error(' Option 1 (Recommended): Run interactive setup');
68
- console.error(' $ neozip init');
63
+ console.error(' Run Token Service setup:');
64
+ console.error(' $ neozip connect');
69
65
  console.error('');
70
- console.error(' Option 2: Use command-line flag');
66
+ console.error(' Or use a one-off override:');
71
67
  console.error(' $ neozip -b -w 0x... <archive> <files>');
72
68
  console.error('');
73
- console.error(' Option 3: Set environment variable');
74
- console.error(' $ export NEOZIP_WALLET_PASSKEY="0x..."');
75
69
  console.error('');
76
- console.error(' Get testnet ETH from: https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet');
70
+ console.error(' Fund your Data Wallet from the Token Service:');
71
+ console.error(' $ neozip connect fund');
72
+ console.error(' (or get testnet ETH from https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet)');
77
73
  }
78
74
  return null;
79
75
  }
80
- // Validate the private key format
81
- if (!(0, neozip_blockchain_1.validatePrivateKey)(passkey)) {
76
+ const normalized = passkey.startsWith('0x') ? passkey : `0x${passkey}`;
77
+ if (!(0, neozip_blockchain_1.validatePrivateKey)(normalized)) {
82
78
  if (showError) {
83
79
  console.error('❌ Error: Invalid private key format');
84
80
  console.error(' Private key should be a 64-character hex string starting with 0x');
@@ -86,7 +82,11 @@ function getWalletPasskey(cliWalletKey, showError = true) {
86
82
  }
87
83
  return null;
88
84
  }
89
- return passkey;
85
+ return normalized;
86
+ }
87
+ /** @deprecated Use getConnectionWalletKey */
88
+ function getWalletPasskey(cliWalletKey, showError = true) {
89
+ return getConnectionWalletKey(cliWalletKey, showError);
90
90
  }
91
91
  /**
92
92
  * Add token metadata to ZIP file using the constant
@@ -48,12 +48,17 @@ const neozipkit_1 = require("neozipkit");
48
48
  const node_1 = __importDefault(require("neozipkit/node"));
49
49
  const neozip_blockchain_1 = require("neozip-blockchain");
50
50
  const ots_1 = require("neozip-blockchain/ots");
51
- const zipstamp_server_1 = require("neozip-blockchain/zipstamp-server");
51
+ const token_service_1 = require("neozip-blockchain/token-service");
52
52
  const CommentManager_1 = require("./CommentManager");
53
53
  const utils_1 = require("./utils");
54
54
  const file_operations_1 = require("./file-operations");
55
55
  const blockchain_1 = require("./blockchain");
56
- const ConfigStore_1 = require("../config/ConfigStore");
56
+ const cli_guidance_1 = require("../connection/cli-guidance");
57
+ const wallet_login_1 = require("../connection/wallet-login");
58
+ const funding_1 = require("../connection/funding");
59
+ const store_1 = require("../connection/store");
60
+ const cli_prefs_1 = require("../connection/cli-prefs");
61
+ const bootstrap_1 = require("../connection/bootstrap");
57
62
  const user_interaction_1 = require("./user-interaction");
58
63
  const exit_codes_1 = require("../exit-codes");
59
64
  const version_1 = require("../version");
@@ -257,7 +262,7 @@ class ZipCreator {
257
262
  this.centralDirOffset = 0;
258
263
  this.zip = new node_1.default(); // Use ZipkitNode for ZIP operations
259
264
  // Initialize HashAccumulator if blockchain features are enabled
260
- if (this.options.blockchain || this.options.blockchainOts || this.options.blockchainZipstamp) {
265
+ if (this.options.blockchain || this.options.blockchainOts || this.options.blockchainTokenService) {
261
266
  this.hashAccumulator = new neozipkit_1.HashCalculator({ enableAccumulation: true });
262
267
  }
263
268
  }
@@ -287,7 +292,7 @@ class ZipCreator {
287
292
  */
288
293
  async writeChunk(data) {
289
294
  // For in-memory non-blockchain mode, write to buffer
290
- if (this.options.inMemory && !this.options.blockchain && !this.options.blockchainOts && !this.options.blockchainZipstamp) {
295
+ if (this.options.inMemory && !this.options.blockchain && !this.options.blockchainOts && !this.options.blockchainTokenService) {
291
296
  const bufferWriter = this.zip.bufferWriter;
292
297
  if (bufferWriter) {
293
298
  // Determine if this is a header or data by checking signature
@@ -336,7 +341,7 @@ class ZipCreator {
336
341
  // Initialize output stream for file-based mode OR in-memory blockchain mode
337
342
  // For in-memory blockchain mode, we need to write directly to file during compression
338
343
  // For in-memory non-blockchain mode, output is written directly during compression
339
- if (!this.options.inMemory || (this.options.blockchain || this.options.blockchainOts || this.options.blockchainZipstamp)) {
344
+ if (!this.options.inMemory || (this.options.blockchain || this.options.blockchainOts || this.options.blockchainTokenService)) {
340
345
  await this.initializeOutput();
341
346
  }
342
347
  await this.processFiles();
@@ -404,11 +409,12 @@ class ZipCreator {
404
409
  const compressionDesc = this.options.level === 0 ? 'store (no compression)' : `${this.options.compression} (level ${this.options.level})`;
405
410
  (0, utils_1.log)(`🔧 Compression: ${compressionDesc}`, this.options);
406
411
  (0, utils_1.log)(`📊 Block size: ${(0, utils_1.formatBytes)(this.options.blockSize || 64 * 1024)}`, this.options);
407
- if (!this.options.blockchainZipstamp && !this.options.blockchainOts) {
412
+ if (!this.options.blockchainTokenService && !this.options.blockchainOts) {
408
413
  (0, utils_1.log)(`🔗 Tokenization: ${this.options.blockchain ? 'enabled' : 'disabled'}`, this.options);
409
414
  }
410
- const encryptionMethod = this.options.encryptionMethod || 'pkzip';
411
- (0, utils_1.log)(`🔐 Encryption: ${this.options.encrypt ? `${encryptionMethod.toUpperCase()} enabled` : 'disabled'}`, this.options);
415
+ const encryptionMethod = this.options.encryptionMethod || 'aes256';
416
+ const encryptionLabel = encryptionMethod === 'aes256' ? 'AES-256' : 'PKZIP';
417
+ (0, utils_1.log)(`🔐 Encryption: ${this.options.encrypt ? `${encryptionLabel} enabled` : 'disabled'}`, this.options);
412
418
  (0, utils_1.log)('', this.options);
413
419
  if (this.options.debug) {
414
420
  (0, utils_1.logDebug)('Debug mode enabled', this.options);
@@ -432,15 +438,15 @@ class ZipCreator {
432
438
  (0, utils_1.log)(`Blockchain: enabled (default)`, this.options);
433
439
  }
434
440
  (0, utils_1.log)(`Tokenization: enabled`, this.options);
435
- (0, utils_1.log)(`Network: ${this.options.network || 'base-sepolia'}`, this.options);
441
+ (0, utils_1.log)(`Network: ${(0, cli_prefs_1.resolveNetwork)(this.options.network)}`, this.options);
436
442
  }
437
443
  else if (this.options.blockchainOts) {
438
444
  (0, utils_1.log)(`Blockchain: enabled (OpenTimestamp)`, this.options);
439
445
  (0, utils_1.log)(`Bitcoin blockchain: enabled`, this.options);
440
446
  }
441
- else if (this.options.blockchainZipstamp) {
442
- (0, utils_1.log)(`Blockchain: enabled (Zipstamp)`, this.options);
443
- (0, utils_1.log)(`Zipstamp: enabled`, this.options);
447
+ else if (this.options.blockchainTokenService) {
448
+ (0, utils_1.log)(`Blockchain: enabled (Token Service)`, this.options);
449
+ (0, utils_1.log)(`Token Service: enabled`, this.options);
444
450
  }
445
451
  else {
446
452
  (0, utils_1.log)(`Blockchain: disabled`, this.options);
@@ -820,9 +826,9 @@ class ZipCreator {
820
826
  const compressionOptions = {
821
827
  level: level,
822
828
  useZstd: level === 0 ? false : (this.options.compression || 'zstd') === 'zstd',
823
- useSHA256: this.options.blockchain || this.options.blockchainOts || this.options.blockchainZipstamp || false,
829
+ useSHA256: this.options.blockchain || this.options.blockchainOts || this.options.blockchainTokenService || false,
824
830
  password: this.options.encrypt ? this.options.password : null,
825
- encryptionMethod: this.options.encryptionMethod || 'pkzip'
831
+ encryptionMethod: (this.options.encryptionMethod === 'pkzip' ? 'zipcrypto' : 'aes256')
826
832
  };
827
833
  // Get entries from zip.getDirectory() (populated by processFiles())
828
834
  // This is the single source of truth for entry order
@@ -838,7 +844,7 @@ class ZipCreator {
838
844
  // Create ZipkitNode instance for buffer-based compression
839
845
  const zipkit = new node_1.default();
840
846
  // Determine if we need to write to file (for blockchain mode)
841
- const writeToFile = this.options.blockchain || this.options.blockchainOts || this.options.blockchainZipstamp;
847
+ const writeToFile = this.options.blockchain || this.options.blockchainOts || this.options.blockchainTokenService;
842
848
  // Create appropriate output writer
843
849
  let writer;
844
850
  const positionRef = { current: this.currentPosition };
@@ -923,8 +929,8 @@ class ZipCreator {
923
929
  if (filename !== neozip_blockchain_1.TOKENIZED_METADATA &&
924
930
  filename !== ots_1.TIMESTAMP_METADATA &&
925
931
  filename !== ots_1.TIMESTAMP_SUBMITTED &&
926
- filename !== zipstamp_server_1.SUBMIT_METADATA &&
927
- filename !== zipstamp_server_1.TIMESTAMP_METADATA) {
932
+ filename !== token_service_1.SUBMIT_METADATA &&
933
+ filename !== token_service_1.TIMESTAMP_METADATA) {
928
934
  const hashBuffer = Buffer.from(entry.sha256, 'hex');
929
935
  this.hashAccumulator.addHash(hashBuffer);
930
936
  if (this.options.verbose) {
@@ -992,8 +998,8 @@ class ZipCreator {
992
998
  if (entry.filename === neozip_blockchain_1.TOKENIZED_METADATA ||
993
999
  entry.filename === ots_1.TIMESTAMP_METADATA ||
994
1000
  entry.filename === ots_1.TIMESTAMP_SUBMITTED ||
995
- entry.filename === zipstamp_server_1.SUBMIT_METADATA ||
996
- entry.filename === zipstamp_server_1.TIMESTAMP_METADATA) {
1001
+ entry.filename === token_service_1.SUBMIT_METADATA ||
1002
+ entry.filename === token_service_1.TIMESTAMP_METADATA) {
997
1003
  zipEntries.splice(index, 1);
998
1004
  entryCnt--;
999
1005
  index--;
@@ -1075,8 +1081,8 @@ class ZipCreator {
1075
1081
  if (filename !== neozip_blockchain_1.TOKENIZED_METADATA &&
1076
1082
  filename !== ots_1.TIMESTAMP_METADATA &&
1077
1083
  filename !== ots_1.TIMESTAMP_SUBMITTED &&
1078
- filename !== zipstamp_server_1.SUBMIT_METADATA &&
1079
- filename !== zipstamp_server_1.TIMESTAMP_METADATA) {
1084
+ filename !== token_service_1.SUBMIT_METADATA &&
1085
+ filename !== token_service_1.TIMESTAMP_METADATA) {
1080
1086
  this.hashAccumulator.addHash(hash);
1081
1087
  if (this.options.verbose) {
1082
1088
  (0, utils_1.logDebug)(`Added SHA-256 hash to accumulator for ${filename}`, this.options);
@@ -1157,8 +1163,8 @@ class ZipCreator {
1157
1163
  return filename !== neozip_blockchain_1.TOKENIZED_METADATA &&
1158
1164
  filename !== ots_1.TIMESTAMP_METADATA &&
1159
1165
  filename !== ots_1.TIMESTAMP_SUBMITTED &&
1160
- filename !== zipstamp_server_1.SUBMIT_METADATA &&
1161
- filename !== zipstamp_server_1.TIMESTAMP_METADATA;
1166
+ filename !== token_service_1.SUBMIT_METADATA &&
1167
+ filename !== token_service_1.TIMESTAMP_METADATA;
1162
1168
  });
1163
1169
  // Add SHA-256 hashes to accumulator
1164
1170
  for (const entry of contentEntries) {
@@ -1175,27 +1181,36 @@ class ZipCreator {
1175
1181
  let tokenMeta = null;
1176
1182
  let tokenInfoEntry = null;
1177
1183
  let otsMetaEntry = null;
1178
- let zipstampMetaEntry = null;
1184
+ let tokenServiceMetaEntry = null;
1179
1185
  let merkleRoot = null;
1180
1186
  if (this.options.blockchain) {
1181
- // Check for wallet passkey AFTER compression is complete
1182
- // Priority: -w option > wallet.json > environment variable
1183
- // Don't show error yet - we'll prompt user if key is missing
1184
- const walletPasskey = (0, blockchain_1.getWalletPasskey)(this.options.walletKey, false);
1187
+ const connectError = (0, cli_guidance_1.requireConnectionReady)('Blockchain tokenization (-b)', 'wallet');
1188
+ if (connectError) {
1189
+ console.error(' Token Service connection not ready');
1190
+ console.error(connectError);
1191
+ if (!this.options.nonInteractive) {
1192
+ const answer = await (0, user_interaction_1.promptUser)('Continue without blockchain tokenization? (y/n): ');
1193
+ if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
1194
+ this.options.blockchain = false;
1195
+ this.options.blockchainOts = false;
1196
+ this.options.blockchainTokenService = false;
1197
+ return;
1198
+ }
1199
+ }
1200
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
1201
+ }
1202
+ const walletPasskey = (0, blockchain_1.getConnectionWalletKey)(this.options.walletKey, false);
1185
1203
  if (!walletPasskey) {
1186
- // Show error message and prompt user
1187
1204
  console.error('\n❌ Error: Wallet private key is required for blockchain operations');
1188
1205
  console.error('');
1189
- console.error(' Option 1 (Recommended): Run interactive setup');
1190
- console.error(' $ neozip init');
1206
+ console.error(' Run: neozip connect');
1191
1207
  console.error('');
1192
- console.error(' Option 2: Use command-line flag');
1208
+ console.error(' Or use a one-off override:');
1193
1209
  console.error(' $ neozip -b -w 0x... <archive> <files>');
1194
1210
  console.error('');
1195
- console.error(' Option 3: Set environment variable');
1196
- console.error(' $ export NEOZIP_WALLET_PASSKEY="0x..."');
1197
- console.error('');
1198
- console.error(' Get testnet ETH from: https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet');
1211
+ console.error(' Fund your Data Wallet from the Token Service:');
1212
+ console.error(' $ neozip connect fund');
1213
+ console.error(' (or get testnet ETH from https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet)');
1199
1214
  console.error('');
1200
1215
  // Prompt user to continue without blockchain tokenization
1201
1216
  if (!this.options.nonInteractive) {
@@ -1204,18 +1219,18 @@ class ZipCreator {
1204
1219
  (0, utils_1.log)('⚠️ Continuing without blockchain tokenization (ZIP file is already created)...', this.options);
1205
1220
  this.options.blockchain = false;
1206
1221
  this.options.blockchainOts = false;
1207
- this.options.blockchainZipstamp = false;
1222
+ this.options.blockchainTokenService = false;
1208
1223
  return; // Skip tokenization, ZIP is already complete
1209
1224
  }
1210
1225
  else {
1211
- (0, utils_1.logError)('💡 Tip: Run "neozip init" to set up your wallet configuration');
1226
+ (0, utils_1.logError)('💡 Tip: Run "neozip connect" to set up your wallet');
1212
1227
  (0, utils_1.logError)('💡 Tip: Omit blockchain flags to create ZIP without blockchain operations');
1213
1228
  (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
1214
1229
  }
1215
1230
  }
1216
1231
  else {
1217
1232
  // Non-interactive mode - exit with error
1218
- (0, utils_1.logError)('💡 Tip: Run "neozip init" to set up your wallet configuration');
1233
+ (0, utils_1.logError)('💡 Tip: Run "neozip connect" to set up your wallet');
1219
1234
  (0, utils_1.logError)('💡 Tip: Omit blockchain flags to create ZIP without blockchain operations');
1220
1235
  (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
1221
1236
  }
@@ -1291,9 +1306,13 @@ class ZipCreator {
1291
1306
  if (merkleRoot) {
1292
1307
  console.log(`\n📋 Merkle Root: ${merkleRoot}`);
1293
1308
  // Validate network
1294
- const network = this.options.network || 'base-sepolia';
1309
+ const network = (0, cli_prefs_1.resolveNetwork)(this.options.network);
1295
1310
  // Always display network when tokenization is enabled
1296
1311
  console.log(`🌐 Network: ${network}`);
1312
+ const accountEmail = (0, store_1.getActiveConnection)()?.email?.trim();
1313
+ if (accountEmail) {
1314
+ console.log(`📧 Account: ${accountEmail}`);
1315
+ }
1297
1316
  // Get network config for contract address and version info
1298
1317
  const networkConfig = (0, neozip_blockchain_1.getNetworkByName)(network);
1299
1318
  let contractAddress;
@@ -1342,6 +1361,9 @@ class ZipCreator {
1342
1361
  ]);
1343
1362
  console.log(`💳 Wallet: ${processResult.walletInfo.address}`);
1344
1363
  console.log(`💰 Balance: ${processResult.walletInfo.balance} ETH`);
1364
+ if ((0, funding_1.isLowWalletBalance)(processResult.walletInfo.balance)) {
1365
+ console.log(`⚠️ ${(0, funding_1.formatLowBalanceFundingHint)()}`);
1366
+ }
1345
1367
  // Network config already retrieved above (contractAddress and networkChainId are available)
1346
1368
  // Check if tokens already exist for this merkle root
1347
1369
  if (processResult.duplicateCheck.hasExistingTokens) {
@@ -1605,12 +1627,12 @@ class ZipCreator {
1605
1627
  }
1606
1628
  }
1607
1629
  }
1608
- else if (this.options.blockchainZipstamp) {
1609
- // Handle Zipstamp timestamp for blockchain
1630
+ else if (this.options.blockchainTokenService) {
1631
+ // Handle Token Service timestamp for blockchain
1610
1632
  if (this.options.debug) {
1611
- (0, utils_1.logDebug)('Zipstamp process starting...', this.options);
1633
+ (0, utils_1.logDebug)('Token Service process starting...', this.options);
1612
1634
  }
1613
- console.log('🔗 Zipstamp: Creating timestamp proof on blockchain...');
1635
+ console.log('🔗 Token Service: Creating timestamp proof on blockchain...');
1614
1636
  // Calculate merkle root (reuse same logic as OTS)
1615
1637
  let merkleRoot = null;
1616
1638
  if (this.hashAccumulator && this.hashAccumulator.leafCount() > 0) {
@@ -1650,7 +1672,7 @@ class ZipCreator {
1650
1672
  merkleRoot = this.calculateMerkleRootFromEntries(entriesForMerkle);
1651
1673
  }
1652
1674
  if (!merkleRoot) {
1653
- console.error('❌ Error calculating merkle root for Zipstamp');
1675
+ console.error('❌ Error calculating merkle root for Token Service');
1654
1676
  console.error(' Make sure files have been compressed with SHA-256 hashes.');
1655
1677
  if (this.options.verbose) {
1656
1678
  const hashCount = this.hashAccumulator ? this.hashAccumulator.leafCount() : 0;
@@ -1663,22 +1685,35 @@ class ZipCreator {
1663
1685
  }
1664
1686
  if (merkleRoot) {
1665
1687
  console.log(`📋 Merkle Root: ${merkleRoot}`);
1666
- const recipientEmail = this.options.timestampEmail ||
1667
- process.env.NEOZIP_TIMESTAMP_EMAIL ||
1668
- ConfigStore_1.ConfigStore.getConfig().timestampEmail;
1669
- console.log('🔗 Submitting hash digest to ZipStamp server...');
1670
- console.log(` Zipstamp Server: ${(0, zipstamp_server_1.getZipStampServerUrl)()}`);
1671
- console.log(`📧 Email: ${recipientEmail || '(none set)'}`);
1688
+ await (0, wallet_login_1.ensureFreshTokenServiceToken)();
1689
+ const setupError = (0, cli_guidance_1.requireConnectionReady)('Blockchain timestamp (-ts)');
1690
+ if (setupError) {
1691
+ console.error(' Token Service not ready');
1692
+ console.error(setupError);
1693
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
1694
+ }
1695
+ const tsRuntime = (0, bootstrap_1.getTokenServiceRuntimeOptions)(this.options.verbose);
1696
+ if (!tsRuntime) {
1697
+ console.error('❌ Token Service credentials missing from connection store');
1698
+ console.error((0, cli_guidance_1.requireConnectionReady)('Blockchain timestamp (-ts)') ?? 'Run: neozip connect');
1699
+ (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
1700
+ }
1701
+ const recipientEmail = tsRuntime.recipientEmail;
1702
+ const serverUrl = tsRuntime.serverUrl;
1703
+ console.log('🔗 Submitting hash digest to Token Service...');
1704
+ console.log(` Token Service: ${serverUrl}`);
1705
+ console.log(`📧 Email: ${recipientEmail}`);
1672
1706
  try {
1673
- const zipstampMetadata = await (0, zipstamp_server_1.createTimestamp)(merkleRoot, {
1674
- recipientEmail: recipientEmail || undefined,
1707
+ const tokenServiceMetadata = await (0, token_service_1.createTimestamp)(merkleRoot, {
1708
+ recipientEmail,
1709
+ serverUrl,
1675
1710
  debug: this.options.verbose
1676
1711
  });
1677
- if (!zipstampMetadata) {
1678
- throw new Error('Failed to create Zipstamp timestamp');
1712
+ if (!tokenServiceMetadata) {
1713
+ throw new Error('Failed to create Token Service timestamp');
1679
1714
  }
1680
- console.log('📄 Zipstamp metadata prepared');
1681
- const metaEntry = (0, zipstamp_server_1.createTimestampMetadataEntry)(this.zip, zipstampMetadata);
1715
+ console.log('📄 Token Service metadata prepared');
1716
+ const metaEntry = (0, token_service_1.createTimestampMetadataEntry)(this.zip, tokenServiceMetadata);
1682
1717
  if (metaEntry) {
1683
1718
  // createTimestampMetadataEntry sets filename based on status (TS-SUBMIT.NZIP or TIMESTAMP.NZIP)
1684
1719
  metaEntry.cmpMethod = 0; // STORED
@@ -1687,7 +1722,7 @@ class ZipCreator {
1687
1722
  console.log(`📂 Final timestamp entry: ${metaEntry.filename}`);
1688
1723
  console.log(`📏 Final timestamp entry size: ${metaEntry.fileBuffer?.length || metaEntry.uncompressedSize || 0} bytes`);
1689
1724
  }
1690
- console.log('✅ Zipstamp proof created and queued for inclusion');
1725
+ console.log('✅ Token Service proof created and queued for inclusion');
1691
1726
  const isConfirmed = (metaEntry.filename || '').includes('TIMESTAMP') && !(metaEntry.filename || '').includes('TS-SUBMIT');
1692
1727
  console.log(isConfirmed
1693
1728
  ? ' Timestamp proof is recorded on the blockchain.'
@@ -1698,40 +1733,31 @@ class ZipCreator {
1698
1733
  }
1699
1734
  const localHdr = metaEntry.createLocalHdr();
1700
1735
  if (this.options.verbose) {
1701
- (0, utils_1.log)(`📝 Writing Zipstamp entry: ${metaEntry.filename} at offset ${this.currentPosition}`, this.options);
1702
- (0, utils_1.log)(`📊 Zipstamp entry size: ${metaEntry.fileBuffer?.length || 0} bytes`, this.options);
1736
+ (0, utils_1.log)(`📝 Writing Token Service entry: ${metaEntry.filename} at offset ${this.currentPosition}`, this.options);
1737
+ (0, utils_1.log)(`📊 Token Service entry size: ${metaEntry.fileBuffer?.length || 0} bytes`, this.options);
1703
1738
  }
1704
1739
  await this.writeChunk(localHdr);
1705
1740
  if (metaEntry.fileBuffer) {
1706
1741
  await this.writeChunk(metaEntry.fileBuffer);
1707
1742
  }
1708
- zipstampMetaEntry = metaEntry;
1743
+ tokenServiceMetaEntry = metaEntry;
1709
1744
  }
1710
1745
  else {
1711
- console.warn('⚠️ Warning: Failed to create Zipstamp metadata entry');
1746
+ console.warn('⚠️ Warning: Failed to create Token Service metadata entry');
1712
1747
  }
1713
1748
  }
1714
1749
  catch (error) {
1715
1750
  const errorMessage = error instanceof Error ? error.message : String(error);
1716
- console.error('❌ Failed to create Zipstamp proof:', errorMessage);
1751
+ console.error('❌ Failed to create Token Service proof:', errorMessage);
1717
1752
  const isValidationOrEmailError = errorMessage.toLowerCase().includes('validation') ||
1718
1753
  errorMessage.toLowerCase().includes('email') ||
1719
1754
  errorMessage.toLowerCase().includes('verify');
1720
1755
  if (isValidationOrEmailError) {
1721
1756
  console.error('');
1722
- if (recipientEmail) {
1723
- console.error(` Email used: ${recipientEmail}`);
1724
- console.error('');
1725
- }
1726
- else {
1727
- console.error(' No email was set (use --timestamp-email, NEOZIP_TIMESTAMP_EMAIL, or neozip verify-email).');
1728
- console.error('');
1729
- }
1730
- console.error('💡 Zipstamp requires a verified email. Run:');
1731
- console.error(' neozip verify-email');
1757
+ console.error(` Email used: ${recipientEmail}`);
1732
1758
  console.error('');
1733
- console.error(' Or use: --timestamp-email <your-verified-email>');
1734
- console.error(' Or set: NEOZIP_TIMESTAMP_EMAIL environment variable');
1759
+ console.error('💡 Token Service requires a verified email. Run:');
1760
+ console.error(' neozip connect');
1735
1761
  console.error('');
1736
1762
  }
1737
1763
  throw error;
@@ -1741,7 +1767,7 @@ class ZipCreator {
1741
1767
  }
1742
1768
  async finalize() {
1743
1769
  // Check if this is in-memory non-blockchain mode (needs special handling)
1744
- if (this.options.inMemory && !this.options.blockchain && !this.options.blockchainOts && !this.options.blockchainZipstamp) {
1770
+ if (this.options.inMemory && !this.options.blockchain && !this.options.blockchainOts && !this.options.blockchainTokenService) {
1745
1771
  // For in-memory non-blockchain mode, write complete ZIP file from buffer
1746
1772
  // Metadata should already be in the buffer (added via writeChunk() in handleTokenization())
1747
1773
  const bufferWriter = this.zip.bufferWriter;
@@ -1904,7 +1930,7 @@ async function testArchiveIntegrity(archiveName, options) {
1904
1930
  try {
1905
1931
  // Always show when integrity testing starts
1906
1932
  (0, utils_1.log)(`\n🧪 Testing archive integrity: ${archiveName}`, options);
1907
- if (options.blockchainZipstamp) {
1933
+ if (options.blockchainTokenService) {
1908
1934
  (0, utils_1.log)(` (Validating file integrity only; timestamp not yet confirmed on blockchain)`, options);
1909
1935
  }
1910
1936
  // Import child_process for shelling out
@@ -1915,9 +1941,9 @@ async function testArchiveIntegrity(archiveName, options) {
1915
1941
  return new Promise((resolve) => {
1916
1942
  // Build neounzip command arguments
1917
1943
  const args = ['-t'];
1918
- // For Zipstamp timestamped files: skip blockchain verification during integrity test.
1944
+ // For Token Service timestamped files: skip blockchain verification during integrity test.
1919
1945
  // We only validate file integrity (SHA-256); timestamp is pending and not yet minted.
1920
- if (options.blockchainZipstamp) {
1946
+ if (options.blockchainTokenService) {
1921
1947
  args.push('--skip-blockchain');
1922
1948
  }
1923
1949
  // Add password if encryption is enabled
@@ -1966,8 +1992,8 @@ async function testArchiveIntegrity(archiveName, options) {
1966
1992
  else {
1967
1993
  (0, utils_1.log)(`✅ Archive integrity test passed`, options);
1968
1994
  }
1969
- // For Zipstamp: clarify that timestamp is not validated and not minted
1970
- if (options.blockchainZipstamp) {
1995
+ // For Token Service: clarify that timestamp is not validated and not minted
1996
+ if (options.blockchainTokenService) {
1971
1997
  (0, utils_1.log)(` Note: File integrity validated. Timestamp is pending (not yet confirmed on blockchain).`, options);
1972
1998
  }
1973
1999
  resolve(true);
@@ -2089,8 +2115,8 @@ async function upgradeZipForTokenization(inputZipPath, options) {
2089
2115
  if (filename === neozip_blockchain_1.TOKENIZED_METADATA ||
2090
2116
  filename === ots_1.TIMESTAMP_METADATA ||
2091
2117
  filename === ots_1.TIMESTAMP_SUBMITTED ||
2092
- filename === zipstamp_server_1.SUBMIT_METADATA ||
2093
- filename === zipstamp_server_1.TIMESTAMP_METADATA ||
2118
+ filename === token_service_1.SUBMIT_METADATA ||
2119
+ filename === token_service_1.TIMESTAMP_METADATA ||
2094
2120
  entry.isDirectory) {
2095
2121
  continue;
2096
2122
  }
@@ -2246,21 +2272,19 @@ async function upgradeZipForTokenization(inputZipPath, options) {
2246
2272
  }
2247
2273
  // Mint new token before finalizing ZIP (so we can add metadata)
2248
2274
  // Check for wallet passkey - don't show error yet
2249
- const walletPasskey = (0, blockchain_1.getWalletPasskey)(options.walletKey, false);
2275
+ const walletPasskey = (0, blockchain_1.getConnectionWalletKey)(options.walletKey, false);
2250
2276
  if (!walletPasskey) {
2251
2277
  // Show error message and prompt user
2252
2278
  console.error('❌ Error: Wallet private key is required for blockchain operations');
2253
2279
  console.error('');
2254
- console.error(' Option 1 (Recommended): Run interactive setup');
2255
- console.error(' $ neozip init');
2280
+ console.error(' Run: neozip connect');
2256
2281
  console.error('');
2257
- console.error(' Option 2: Use command-line flag');
2282
+ console.error(' Or use a one-off override:');
2258
2283
  console.error(' $ neozip --upgrade -w 0x... <archive>');
2259
2284
  console.error('');
2260
- console.error(' Option 3: Set environment variable');
2261
- console.error(' $ export NEOZIP_WALLET_PASSKEY="0x..."');
2262
- console.error('');
2263
- console.error(' Get testnet ETH from: https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet');
2285
+ console.error(' Fund your Data Wallet from the Token Service:');
2286
+ console.error(' $ neozip connect fund');
2287
+ console.error(' (or get testnet ETH from https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet)');
2264
2288
  console.error('');
2265
2289
  // Prompt user to continue without blockchain tokenization
2266
2290
  if (!options.nonInteractive) {
@@ -2270,20 +2294,20 @@ async function upgradeZipForTokenization(inputZipPath, options) {
2270
2294
  // Skip token minting - ZIP will be upgraded with SHA-256 hashes but no token metadata
2271
2295
  }
2272
2296
  else {
2273
- (0, utils_1.logError)('💡 Tip: Run "neozip init" to set up your wallet configuration');
2297
+ (0, utils_1.logError)('💡 Tip: Run "neozip connect" to set up your wallet');
2274
2298
  (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.BLOCKCHAIN_CONFIG_ERROR);
2275
2299
  }
2276
2300
  }
2277
2301
  else {
2278
2302
  // Non-interactive mode - exit with error
2279
- (0, utils_1.logError)('💡 Tip: Run "neozip init" to set up your wallet configuration');
2303
+ (0, utils_1.logError)('💡 Tip: Run "neozip connect" to set up your wallet');
2280
2304
  (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.BLOCKCHAIN_CONFIG_ERROR);
2281
2305
  }
2282
2306
  }
2283
2307
  // Only mint token if wallet passkey is available
2284
2308
  if (walletPasskey) {
2285
2309
  (0, utils_1.log)(` Minting new token on blockchain...`, options);
2286
- const network = options.network || 'base-sepolia';
2310
+ const network = (0, cli_prefs_1.resolveNetwork)(options.network);
2287
2311
  if (!(0, blockchain_1.isSupportedNetwork)(network)) {
2288
2312
  (0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.BLOCKCHAIN_CONFIG_ERROR, `Error: Unsupported network: ${network}`);
2289
2313
  }