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.
- package/AGENTS.md +93 -0
- package/CHANGELOG.md +117 -12
- package/DOCUMENTATION.md +33 -38
- package/README.md +137 -63
- package/dist/src/account/account-state.js +95 -0
- package/dist/src/account/format-account-status.js +62 -0
- package/dist/src/account/identity-provision.js +79 -0
- package/dist/src/account/identity-wrap.js +106 -0
- package/dist/src/account/profile-crypto.js +85 -0
- package/dist/src/account/profile-store.js +129 -0
- package/dist/src/account/require-account.js +32 -0
- package/dist/src/account/types.js +3 -0
- package/dist/src/account/wallet-evm.js +46 -0
- package/dist/src/account/wallet-setup.js +33 -0
- package/dist/src/archive/crypto-self.js +117 -0
- package/dist/src/archive/identity-key.js +217 -0
- package/dist/src/archive/recipient-lookup.js +61 -0
- package/dist/src/cli/output.js +100 -0
- package/dist/src/cli/params.js +122 -0
- package/dist/src/cli/schema.js +186 -0
- package/dist/src/cli/validate.js +119 -0
- package/dist/src/commands/mintTimestampProof.js +26 -14
- package/dist/src/config/ConfigSetup.js +82 -423
- package/dist/src/connect/command.js +364 -0
- package/dist/src/connection/bootstrap.js +50 -0
- package/dist/src/connection/cli-guidance.js +101 -0
- package/dist/src/connection/cli-prefs.js +180 -0
- package/dist/src/connection/cli-settings.js +140 -0
- package/dist/src/connection/cli-types.js +14 -0
- package/dist/src/connection/coordinator.js +83 -0
- package/dist/src/connection/credentials.js +33 -0
- package/dist/src/connection/crypto.js +96 -0
- package/dist/src/connection/dump.js +117 -0
- package/dist/src/connection/funding.js +187 -0
- package/dist/src/connection/incomplete-setup.js +89 -0
- package/dist/src/connection/interactive.js +871 -0
- package/dist/src/connection/legacy-profile-reader.js +87 -0
- package/dist/src/connection/magic-link.js +142 -0
- package/dist/src/connection/migrate.js +115 -0
- package/dist/src/connection/onboarding.js +616 -0
- package/dist/src/connection/origin.js +69 -0
- package/dist/src/connection/phase.js +101 -0
- package/dist/src/connection/phone.js +26 -0
- package/dist/src/connection/promote-active.js +56 -0
- package/dist/src/connection/reset.js +56 -0
- package/dist/src/connection/status-report.js +52 -0
- package/dist/src/connection/store.js +406 -0
- package/dist/src/connection/token-auth.js +44 -0
- package/dist/src/connection/types.js +3 -0
- package/dist/src/connection/wallet-json-migration.js +155 -0
- package/dist/src/connection/wallet-login.js +65 -0
- package/dist/src/connection/wallet-setup.js +83 -0
- package/dist/src/constants/wallet-identity.js +14 -0
- package/dist/src/exit-codes.js +54 -10
- package/dist/src/neolist.js +100 -10
- package/dist/src/neounzip.js +236 -65
- package/dist/src/neozip/blockchain.js +18 -18
- package/dist/src/neozip/createZip.js +118 -94
- package/dist/src/neozip/upgradeZip.js +14 -11
- package/dist/src/neozip.js +269 -91
- package/dist/src/skills/command.js +256 -0
- package/dist/src/skills/locate.js +99 -0
- package/dist/src/util/mask.js +34 -0
- package/dist/src/util/token-service-fetch.js +26 -0
- package/env.example +18 -85
- package/package.json +89 -73
- package/skills/neozip-connect/SKILL.md +95 -0
- package/skills/neozip-create/SKILL.md +57 -0
- package/skills/neozip-extract/SKILL.md +58 -0
- package/skills/neozip-legacy/SKILL.md +48 -0
- package/skills/neozip-list/SKILL.md +56 -0
- package/skills/neozip-shared/SKILL.md +60 -0
- package/dist/src/commands/verifyEmail.js +0 -146
- 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
|
|
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
|
-
*
|
|
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
|
|
60
|
-
|
|
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('
|
|
68
|
-
console.error(' $ neozip
|
|
63
|
+
console.error(' Run Token Service setup:');
|
|
64
|
+
console.error(' $ neozip connect');
|
|
69
65
|
console.error('');
|
|
70
|
-
console.error('
|
|
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('
|
|
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
|
-
|
|
81
|
-
if (!(0, neozip_blockchain_1.validatePrivateKey)(
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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 || '
|
|
411
|
-
|
|
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
|
|
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.
|
|
442
|
-
(0, utils_1.log)(`Blockchain: enabled (
|
|
443
|
-
(0, utils_1.log)(`
|
|
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.
|
|
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
|
|
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.
|
|
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 !==
|
|
927
|
-
filename !==
|
|
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 ===
|
|
996
|
-
entry.filename ===
|
|
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 !==
|
|
1079
|
-
filename !==
|
|
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 !==
|
|
1161
|
-
filename !==
|
|
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
|
|
1184
|
+
let tokenServiceMetaEntry = null;
|
|
1179
1185
|
let merkleRoot = null;
|
|
1180
1186
|
if (this.options.blockchain) {
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
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('
|
|
1190
|
-
console.error(' $ neozip init');
|
|
1206
|
+
console.error(' Run: neozip connect');
|
|
1191
1207
|
console.error('');
|
|
1192
|
-
console.error('
|
|
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('
|
|
1196
|
-
console.error(' $
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
1609
|
-
// Handle
|
|
1630
|
+
else if (this.options.blockchainTokenService) {
|
|
1631
|
+
// Handle Token Service timestamp for blockchain
|
|
1610
1632
|
if (this.options.debug) {
|
|
1611
|
-
(0, utils_1.logDebug)('
|
|
1633
|
+
(0, utils_1.logDebug)('Token Service process starting...', this.options);
|
|
1612
1634
|
}
|
|
1613
|
-
console.log('🔗
|
|
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
|
|
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
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
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
|
|
1674
|
-
recipientEmail
|
|
1707
|
+
const tokenServiceMetadata = await (0, token_service_1.createTimestamp)(merkleRoot, {
|
|
1708
|
+
recipientEmail,
|
|
1709
|
+
serverUrl,
|
|
1675
1710
|
debug: this.options.verbose
|
|
1676
1711
|
});
|
|
1677
|
-
if (!
|
|
1678
|
-
throw new Error('Failed to create
|
|
1712
|
+
if (!tokenServiceMetadata) {
|
|
1713
|
+
throw new Error('Failed to create Token Service timestamp');
|
|
1679
1714
|
}
|
|
1680
|
-
console.log('📄
|
|
1681
|
-
const metaEntry = (0,
|
|
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('✅
|
|
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
|
|
1702
|
-
(0, utils_1.log)(`📊
|
|
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
|
-
|
|
1743
|
+
tokenServiceMetaEntry = metaEntry;
|
|
1709
1744
|
}
|
|
1710
1745
|
else {
|
|
1711
|
-
console.warn('⚠️ Warning: Failed to create
|
|
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
|
|
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
|
-
|
|
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('
|
|
1734
|
-
console.error('
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
1970
|
-
if (options.
|
|
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 ===
|
|
2093
|
-
filename ===
|
|
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.
|
|
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('
|
|
2255
|
-
console.error(' $ neozip init');
|
|
2280
|
+
console.error(' Run: neozip connect');
|
|
2256
2281
|
console.error('');
|
|
2257
|
-
console.error('
|
|
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('
|
|
2261
|
-
console.error(' $
|
|
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
|
|
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
|
|
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
|
|
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
|
}
|