neozip-cli 0.90.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 +58 -1
- package/DOCUMENTATION.md +22 -30
- package/README.md +104 -42
- 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 +93 -9
- package/dist/src/neounzip.js +217 -59
- package/dist/src/neozip/blockchain.js +18 -18
- package/dist/src/neozip/createZip.js +114 -91
- package/dist/src/neozip/upgradeZip.js +14 -11
- package/dist/src/neozip.js +252 -75
- 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 -82
- 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
|
@@ -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,7 +409,7 @@ 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
415
|
const encryptionMethod = this.options.encryptionMethod || 'aes256';
|
|
@@ -433,15 +438,15 @@ class ZipCreator {
|
|
|
433
438
|
(0, utils_1.log)(`Blockchain: enabled (default)`, this.options);
|
|
434
439
|
}
|
|
435
440
|
(0, utils_1.log)(`Tokenization: enabled`, this.options);
|
|
436
|
-
(0, utils_1.log)(`Network: ${this.options.network
|
|
441
|
+
(0, utils_1.log)(`Network: ${(0, cli_prefs_1.resolveNetwork)(this.options.network)}`, this.options);
|
|
437
442
|
}
|
|
438
443
|
else if (this.options.blockchainOts) {
|
|
439
444
|
(0, utils_1.log)(`Blockchain: enabled (OpenTimestamp)`, this.options);
|
|
440
445
|
(0, utils_1.log)(`Bitcoin blockchain: enabled`, this.options);
|
|
441
446
|
}
|
|
442
|
-
else if (this.options.
|
|
443
|
-
(0, utils_1.log)(`Blockchain: enabled (
|
|
444
|
-
(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);
|
|
445
450
|
}
|
|
446
451
|
else {
|
|
447
452
|
(0, utils_1.log)(`Blockchain: disabled`, this.options);
|
|
@@ -821,7 +826,7 @@ class ZipCreator {
|
|
|
821
826
|
const compressionOptions = {
|
|
822
827
|
level: level,
|
|
823
828
|
useZstd: level === 0 ? false : (this.options.compression || 'zstd') === 'zstd',
|
|
824
|
-
useSHA256: this.options.blockchain || this.options.blockchainOts || this.options.
|
|
829
|
+
useSHA256: this.options.blockchain || this.options.blockchainOts || this.options.blockchainTokenService || false,
|
|
825
830
|
password: this.options.encrypt ? this.options.password : null,
|
|
826
831
|
encryptionMethod: (this.options.encryptionMethod === 'pkzip' ? 'zipcrypto' : 'aes256')
|
|
827
832
|
};
|
|
@@ -839,7 +844,7 @@ class ZipCreator {
|
|
|
839
844
|
// Create ZipkitNode instance for buffer-based compression
|
|
840
845
|
const zipkit = new node_1.default();
|
|
841
846
|
// Determine if we need to write to file (for blockchain mode)
|
|
842
|
-
const writeToFile = this.options.blockchain || this.options.blockchainOts || this.options.
|
|
847
|
+
const writeToFile = this.options.blockchain || this.options.blockchainOts || this.options.blockchainTokenService;
|
|
843
848
|
// Create appropriate output writer
|
|
844
849
|
let writer;
|
|
845
850
|
const positionRef = { current: this.currentPosition };
|
|
@@ -924,8 +929,8 @@ class ZipCreator {
|
|
|
924
929
|
if (filename !== neozip_blockchain_1.TOKENIZED_METADATA &&
|
|
925
930
|
filename !== ots_1.TIMESTAMP_METADATA &&
|
|
926
931
|
filename !== ots_1.TIMESTAMP_SUBMITTED &&
|
|
927
|
-
filename !==
|
|
928
|
-
filename !==
|
|
932
|
+
filename !== token_service_1.SUBMIT_METADATA &&
|
|
933
|
+
filename !== token_service_1.TIMESTAMP_METADATA) {
|
|
929
934
|
const hashBuffer = Buffer.from(entry.sha256, 'hex');
|
|
930
935
|
this.hashAccumulator.addHash(hashBuffer);
|
|
931
936
|
if (this.options.verbose) {
|
|
@@ -993,8 +998,8 @@ class ZipCreator {
|
|
|
993
998
|
if (entry.filename === neozip_blockchain_1.TOKENIZED_METADATA ||
|
|
994
999
|
entry.filename === ots_1.TIMESTAMP_METADATA ||
|
|
995
1000
|
entry.filename === ots_1.TIMESTAMP_SUBMITTED ||
|
|
996
|
-
entry.filename ===
|
|
997
|
-
entry.filename ===
|
|
1001
|
+
entry.filename === token_service_1.SUBMIT_METADATA ||
|
|
1002
|
+
entry.filename === token_service_1.TIMESTAMP_METADATA) {
|
|
998
1003
|
zipEntries.splice(index, 1);
|
|
999
1004
|
entryCnt--;
|
|
1000
1005
|
index--;
|
|
@@ -1076,8 +1081,8 @@ class ZipCreator {
|
|
|
1076
1081
|
if (filename !== neozip_blockchain_1.TOKENIZED_METADATA &&
|
|
1077
1082
|
filename !== ots_1.TIMESTAMP_METADATA &&
|
|
1078
1083
|
filename !== ots_1.TIMESTAMP_SUBMITTED &&
|
|
1079
|
-
filename !==
|
|
1080
|
-
filename !==
|
|
1084
|
+
filename !== token_service_1.SUBMIT_METADATA &&
|
|
1085
|
+
filename !== token_service_1.TIMESTAMP_METADATA) {
|
|
1081
1086
|
this.hashAccumulator.addHash(hash);
|
|
1082
1087
|
if (this.options.verbose) {
|
|
1083
1088
|
(0, utils_1.logDebug)(`Added SHA-256 hash to accumulator for ${filename}`, this.options);
|
|
@@ -1158,8 +1163,8 @@ class ZipCreator {
|
|
|
1158
1163
|
return filename !== neozip_blockchain_1.TOKENIZED_METADATA &&
|
|
1159
1164
|
filename !== ots_1.TIMESTAMP_METADATA &&
|
|
1160
1165
|
filename !== ots_1.TIMESTAMP_SUBMITTED &&
|
|
1161
|
-
filename !==
|
|
1162
|
-
filename !==
|
|
1166
|
+
filename !== token_service_1.SUBMIT_METADATA &&
|
|
1167
|
+
filename !== token_service_1.TIMESTAMP_METADATA;
|
|
1163
1168
|
});
|
|
1164
1169
|
// Add SHA-256 hashes to accumulator
|
|
1165
1170
|
for (const entry of contentEntries) {
|
|
@@ -1176,27 +1181,36 @@ class ZipCreator {
|
|
|
1176
1181
|
let tokenMeta = null;
|
|
1177
1182
|
let tokenInfoEntry = null;
|
|
1178
1183
|
let otsMetaEntry = null;
|
|
1179
|
-
let
|
|
1184
|
+
let tokenServiceMetaEntry = null;
|
|
1180
1185
|
let merkleRoot = null;
|
|
1181
1186
|
if (this.options.blockchain) {
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
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);
|
|
1186
1203
|
if (!walletPasskey) {
|
|
1187
|
-
// Show error message and prompt user
|
|
1188
1204
|
console.error('\n❌ Error: Wallet private key is required for blockchain operations');
|
|
1189
1205
|
console.error('');
|
|
1190
|
-
console.error('
|
|
1191
|
-
console.error(' $ neozip init');
|
|
1206
|
+
console.error(' Run: neozip connect');
|
|
1192
1207
|
console.error('');
|
|
1193
|
-
console.error('
|
|
1208
|
+
console.error(' Or use a one-off override:');
|
|
1194
1209
|
console.error(' $ neozip -b -w 0x... <archive> <files>');
|
|
1195
1210
|
console.error('');
|
|
1196
|
-
console.error('
|
|
1197
|
-
console.error(' $
|
|
1198
|
-
console.error('');
|
|
1199
|
-
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)');
|
|
1200
1214
|
console.error('');
|
|
1201
1215
|
// Prompt user to continue without blockchain tokenization
|
|
1202
1216
|
if (!this.options.nonInteractive) {
|
|
@@ -1205,18 +1219,18 @@ class ZipCreator {
|
|
|
1205
1219
|
(0, utils_1.log)('⚠️ Continuing without blockchain tokenization (ZIP file is already created)...', this.options);
|
|
1206
1220
|
this.options.blockchain = false;
|
|
1207
1221
|
this.options.blockchainOts = false;
|
|
1208
|
-
this.options.
|
|
1222
|
+
this.options.blockchainTokenService = false;
|
|
1209
1223
|
return; // Skip tokenization, ZIP is already complete
|
|
1210
1224
|
}
|
|
1211
1225
|
else {
|
|
1212
|
-
(0, utils_1.logError)('💡 Tip: Run "neozip
|
|
1226
|
+
(0, utils_1.logError)('💡 Tip: Run "neozip connect" to set up your wallet');
|
|
1213
1227
|
(0, utils_1.logError)('💡 Tip: Omit blockchain flags to create ZIP without blockchain operations');
|
|
1214
1228
|
(0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
|
|
1215
1229
|
}
|
|
1216
1230
|
}
|
|
1217
1231
|
else {
|
|
1218
1232
|
// Non-interactive mode - exit with error
|
|
1219
|
-
(0, utils_1.logError)('💡 Tip: Run "neozip
|
|
1233
|
+
(0, utils_1.logError)('💡 Tip: Run "neozip connect" to set up your wallet');
|
|
1220
1234
|
(0, utils_1.logError)('💡 Tip: Omit blockchain flags to create ZIP without blockchain operations');
|
|
1221
1235
|
(0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.PARAMETER_ERROR);
|
|
1222
1236
|
}
|
|
@@ -1292,9 +1306,13 @@ class ZipCreator {
|
|
|
1292
1306
|
if (merkleRoot) {
|
|
1293
1307
|
console.log(`\n📋 Merkle Root: ${merkleRoot}`);
|
|
1294
1308
|
// Validate network
|
|
1295
|
-
const network = this.options.network
|
|
1309
|
+
const network = (0, cli_prefs_1.resolveNetwork)(this.options.network);
|
|
1296
1310
|
// Always display network when tokenization is enabled
|
|
1297
1311
|
console.log(`🌐 Network: ${network}`);
|
|
1312
|
+
const accountEmail = (0, store_1.getActiveConnection)()?.email?.trim();
|
|
1313
|
+
if (accountEmail) {
|
|
1314
|
+
console.log(`📧 Account: ${accountEmail}`);
|
|
1315
|
+
}
|
|
1298
1316
|
// Get network config for contract address and version info
|
|
1299
1317
|
const networkConfig = (0, neozip_blockchain_1.getNetworkByName)(network);
|
|
1300
1318
|
let contractAddress;
|
|
@@ -1343,6 +1361,9 @@ class ZipCreator {
|
|
|
1343
1361
|
]);
|
|
1344
1362
|
console.log(`💳 Wallet: ${processResult.walletInfo.address}`);
|
|
1345
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
|
+
}
|
|
1346
1367
|
// Network config already retrieved above (contractAddress and networkChainId are available)
|
|
1347
1368
|
// Check if tokens already exist for this merkle root
|
|
1348
1369
|
if (processResult.duplicateCheck.hasExistingTokens) {
|
|
@@ -1606,12 +1627,12 @@ class ZipCreator {
|
|
|
1606
1627
|
}
|
|
1607
1628
|
}
|
|
1608
1629
|
}
|
|
1609
|
-
else if (this.options.
|
|
1610
|
-
// Handle
|
|
1630
|
+
else if (this.options.blockchainTokenService) {
|
|
1631
|
+
// Handle Token Service timestamp for blockchain
|
|
1611
1632
|
if (this.options.debug) {
|
|
1612
|
-
(0, utils_1.logDebug)('
|
|
1633
|
+
(0, utils_1.logDebug)('Token Service process starting...', this.options);
|
|
1613
1634
|
}
|
|
1614
|
-
console.log('🔗
|
|
1635
|
+
console.log('🔗 Token Service: Creating timestamp proof on blockchain...');
|
|
1615
1636
|
// Calculate merkle root (reuse same logic as OTS)
|
|
1616
1637
|
let merkleRoot = null;
|
|
1617
1638
|
if (this.hashAccumulator && this.hashAccumulator.leafCount() > 0) {
|
|
@@ -1651,7 +1672,7 @@ class ZipCreator {
|
|
|
1651
1672
|
merkleRoot = this.calculateMerkleRootFromEntries(entriesForMerkle);
|
|
1652
1673
|
}
|
|
1653
1674
|
if (!merkleRoot) {
|
|
1654
|
-
console.error('❌ Error calculating merkle root for
|
|
1675
|
+
console.error('❌ Error calculating merkle root for Token Service');
|
|
1655
1676
|
console.error(' Make sure files have been compressed with SHA-256 hashes.');
|
|
1656
1677
|
if (this.options.verbose) {
|
|
1657
1678
|
const hashCount = this.hashAccumulator ? this.hashAccumulator.leafCount() : 0;
|
|
@@ -1664,22 +1685,35 @@ class ZipCreator {
|
|
|
1664
1685
|
}
|
|
1665
1686
|
if (merkleRoot) {
|
|
1666
1687
|
console.log(`📋 Merkle Root: ${merkleRoot}`);
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
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}`);
|
|
1673
1706
|
try {
|
|
1674
|
-
const
|
|
1675
|
-
recipientEmail
|
|
1707
|
+
const tokenServiceMetadata = await (0, token_service_1.createTimestamp)(merkleRoot, {
|
|
1708
|
+
recipientEmail,
|
|
1709
|
+
serverUrl,
|
|
1676
1710
|
debug: this.options.verbose
|
|
1677
1711
|
});
|
|
1678
|
-
if (!
|
|
1679
|
-
throw new Error('Failed to create
|
|
1712
|
+
if (!tokenServiceMetadata) {
|
|
1713
|
+
throw new Error('Failed to create Token Service timestamp');
|
|
1680
1714
|
}
|
|
1681
|
-
console.log('📄
|
|
1682
|
-
const metaEntry = (0,
|
|
1715
|
+
console.log('📄 Token Service metadata prepared');
|
|
1716
|
+
const metaEntry = (0, token_service_1.createTimestampMetadataEntry)(this.zip, tokenServiceMetadata);
|
|
1683
1717
|
if (metaEntry) {
|
|
1684
1718
|
// createTimestampMetadataEntry sets filename based on status (TS-SUBMIT.NZIP or TIMESTAMP.NZIP)
|
|
1685
1719
|
metaEntry.cmpMethod = 0; // STORED
|
|
@@ -1688,7 +1722,7 @@ class ZipCreator {
|
|
|
1688
1722
|
console.log(`📂 Final timestamp entry: ${metaEntry.filename}`);
|
|
1689
1723
|
console.log(`📏 Final timestamp entry size: ${metaEntry.fileBuffer?.length || metaEntry.uncompressedSize || 0} bytes`);
|
|
1690
1724
|
}
|
|
1691
|
-
console.log('✅
|
|
1725
|
+
console.log('✅ Token Service proof created and queued for inclusion');
|
|
1692
1726
|
const isConfirmed = (metaEntry.filename || '').includes('TIMESTAMP') && !(metaEntry.filename || '').includes('TS-SUBMIT');
|
|
1693
1727
|
console.log(isConfirmed
|
|
1694
1728
|
? ' Timestamp proof is recorded on the blockchain.'
|
|
@@ -1699,40 +1733,31 @@ class ZipCreator {
|
|
|
1699
1733
|
}
|
|
1700
1734
|
const localHdr = metaEntry.createLocalHdr();
|
|
1701
1735
|
if (this.options.verbose) {
|
|
1702
|
-
(0, utils_1.log)(`📝 Writing
|
|
1703
|
-
(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);
|
|
1704
1738
|
}
|
|
1705
1739
|
await this.writeChunk(localHdr);
|
|
1706
1740
|
if (metaEntry.fileBuffer) {
|
|
1707
1741
|
await this.writeChunk(metaEntry.fileBuffer);
|
|
1708
1742
|
}
|
|
1709
|
-
|
|
1743
|
+
tokenServiceMetaEntry = metaEntry;
|
|
1710
1744
|
}
|
|
1711
1745
|
else {
|
|
1712
|
-
console.warn('⚠️ Warning: Failed to create
|
|
1746
|
+
console.warn('⚠️ Warning: Failed to create Token Service metadata entry');
|
|
1713
1747
|
}
|
|
1714
1748
|
}
|
|
1715
1749
|
catch (error) {
|
|
1716
1750
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1717
|
-
console.error('❌ Failed to create
|
|
1751
|
+
console.error('❌ Failed to create Token Service proof:', errorMessage);
|
|
1718
1752
|
const isValidationOrEmailError = errorMessage.toLowerCase().includes('validation') ||
|
|
1719
1753
|
errorMessage.toLowerCase().includes('email') ||
|
|
1720
1754
|
errorMessage.toLowerCase().includes('verify');
|
|
1721
1755
|
if (isValidationOrEmailError) {
|
|
1722
1756
|
console.error('');
|
|
1723
|
-
|
|
1724
|
-
console.error(` Email used: ${recipientEmail}`);
|
|
1725
|
-
console.error('');
|
|
1726
|
-
}
|
|
1727
|
-
else {
|
|
1728
|
-
console.error(' No email was set (use --timestamp-email, NEOZIP_TIMESTAMP_EMAIL, or neozip verify-email).');
|
|
1729
|
-
console.error('');
|
|
1730
|
-
}
|
|
1731
|
-
console.error('💡 Zipstamp requires a verified email. Run:');
|
|
1732
|
-
console.error(' neozip verify-email');
|
|
1757
|
+
console.error(` Email used: ${recipientEmail}`);
|
|
1733
1758
|
console.error('');
|
|
1734
|
-
console.error('
|
|
1735
|
-
console.error('
|
|
1759
|
+
console.error('💡 Token Service requires a verified email. Run:');
|
|
1760
|
+
console.error(' neozip connect');
|
|
1736
1761
|
console.error('');
|
|
1737
1762
|
}
|
|
1738
1763
|
throw error;
|
|
@@ -1742,7 +1767,7 @@ class ZipCreator {
|
|
|
1742
1767
|
}
|
|
1743
1768
|
async finalize() {
|
|
1744
1769
|
// Check if this is in-memory non-blockchain mode (needs special handling)
|
|
1745
|
-
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) {
|
|
1746
1771
|
// For in-memory non-blockchain mode, write complete ZIP file from buffer
|
|
1747
1772
|
// Metadata should already be in the buffer (added via writeChunk() in handleTokenization())
|
|
1748
1773
|
const bufferWriter = this.zip.bufferWriter;
|
|
@@ -1905,7 +1930,7 @@ async function testArchiveIntegrity(archiveName, options) {
|
|
|
1905
1930
|
try {
|
|
1906
1931
|
// Always show when integrity testing starts
|
|
1907
1932
|
(0, utils_1.log)(`\n🧪 Testing archive integrity: ${archiveName}`, options);
|
|
1908
|
-
if (options.
|
|
1933
|
+
if (options.blockchainTokenService) {
|
|
1909
1934
|
(0, utils_1.log)(` (Validating file integrity only; timestamp not yet confirmed on blockchain)`, options);
|
|
1910
1935
|
}
|
|
1911
1936
|
// Import child_process for shelling out
|
|
@@ -1916,9 +1941,9 @@ async function testArchiveIntegrity(archiveName, options) {
|
|
|
1916
1941
|
return new Promise((resolve) => {
|
|
1917
1942
|
// Build neounzip command arguments
|
|
1918
1943
|
const args = ['-t'];
|
|
1919
|
-
// For
|
|
1944
|
+
// For Token Service timestamped files: skip blockchain verification during integrity test.
|
|
1920
1945
|
// We only validate file integrity (SHA-256); timestamp is pending and not yet minted.
|
|
1921
|
-
if (options.
|
|
1946
|
+
if (options.blockchainTokenService) {
|
|
1922
1947
|
args.push('--skip-blockchain');
|
|
1923
1948
|
}
|
|
1924
1949
|
// Add password if encryption is enabled
|
|
@@ -1967,8 +1992,8 @@ async function testArchiveIntegrity(archiveName, options) {
|
|
|
1967
1992
|
else {
|
|
1968
1993
|
(0, utils_1.log)(`✅ Archive integrity test passed`, options);
|
|
1969
1994
|
}
|
|
1970
|
-
// For
|
|
1971
|
-
if (options.
|
|
1995
|
+
// For Token Service: clarify that timestamp is not validated and not minted
|
|
1996
|
+
if (options.blockchainTokenService) {
|
|
1972
1997
|
(0, utils_1.log)(` Note: File integrity validated. Timestamp is pending (not yet confirmed on blockchain).`, options);
|
|
1973
1998
|
}
|
|
1974
1999
|
resolve(true);
|
|
@@ -2090,8 +2115,8 @@ async function upgradeZipForTokenization(inputZipPath, options) {
|
|
|
2090
2115
|
if (filename === neozip_blockchain_1.TOKENIZED_METADATA ||
|
|
2091
2116
|
filename === ots_1.TIMESTAMP_METADATA ||
|
|
2092
2117
|
filename === ots_1.TIMESTAMP_SUBMITTED ||
|
|
2093
|
-
filename ===
|
|
2094
|
-
filename ===
|
|
2118
|
+
filename === token_service_1.SUBMIT_METADATA ||
|
|
2119
|
+
filename === token_service_1.TIMESTAMP_METADATA ||
|
|
2095
2120
|
entry.isDirectory) {
|
|
2096
2121
|
continue;
|
|
2097
2122
|
}
|
|
@@ -2247,21 +2272,19 @@ async function upgradeZipForTokenization(inputZipPath, options) {
|
|
|
2247
2272
|
}
|
|
2248
2273
|
// Mint new token before finalizing ZIP (so we can add metadata)
|
|
2249
2274
|
// Check for wallet passkey - don't show error yet
|
|
2250
|
-
const walletPasskey = (0, blockchain_1.
|
|
2275
|
+
const walletPasskey = (0, blockchain_1.getConnectionWalletKey)(options.walletKey, false);
|
|
2251
2276
|
if (!walletPasskey) {
|
|
2252
2277
|
// Show error message and prompt user
|
|
2253
2278
|
console.error('❌ Error: Wallet private key is required for blockchain operations');
|
|
2254
2279
|
console.error('');
|
|
2255
|
-
console.error('
|
|
2256
|
-
console.error(' $ neozip init');
|
|
2280
|
+
console.error(' Run: neozip connect');
|
|
2257
2281
|
console.error('');
|
|
2258
|
-
console.error('
|
|
2282
|
+
console.error(' Or use a one-off override:');
|
|
2259
2283
|
console.error(' $ neozip --upgrade -w 0x... <archive>');
|
|
2260
2284
|
console.error('');
|
|
2261
|
-
console.error('
|
|
2262
|
-
console.error(' $
|
|
2263
|
-
console.error('');
|
|
2264
|
-
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)');
|
|
2265
2288
|
console.error('');
|
|
2266
2289
|
// Prompt user to continue without blockchain tokenization
|
|
2267
2290
|
if (!options.nonInteractive) {
|
|
@@ -2271,20 +2294,20 @@ async function upgradeZipForTokenization(inputZipPath, options) {
|
|
|
2271
2294
|
// Skip token minting - ZIP will be upgraded with SHA-256 hashes but no token metadata
|
|
2272
2295
|
}
|
|
2273
2296
|
else {
|
|
2274
|
-
(0, utils_1.logError)('💡 Tip: Run "neozip
|
|
2297
|
+
(0, utils_1.logError)('💡 Tip: Run "neozip connect" to set up your wallet');
|
|
2275
2298
|
(0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.BLOCKCHAIN_CONFIG_ERROR);
|
|
2276
2299
|
}
|
|
2277
2300
|
}
|
|
2278
2301
|
else {
|
|
2279
2302
|
// Non-interactive mode - exit with error
|
|
2280
|
-
(0, utils_1.logError)('💡 Tip: Run "neozip
|
|
2303
|
+
(0, utils_1.logError)('💡 Tip: Run "neozip connect" to set up your wallet');
|
|
2281
2304
|
(0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.BLOCKCHAIN_CONFIG_ERROR);
|
|
2282
2305
|
}
|
|
2283
2306
|
}
|
|
2284
2307
|
// Only mint token if wallet passkey is available
|
|
2285
2308
|
if (walletPasskey) {
|
|
2286
2309
|
(0, utils_1.log)(` Minting new token on blockchain...`, options);
|
|
2287
|
-
const network = options.network
|
|
2310
|
+
const network = (0, cli_prefs_1.resolveNetwork)(options.network);
|
|
2288
2311
|
if (!(0, blockchain_1.isSupportedNetwork)(network)) {
|
|
2289
2312
|
(0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.BLOCKCHAIN_CONFIG_ERROR, `Error: Unsupported network: ${network}`);
|
|
2290
2313
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Upgrade
|
|
3
|
+
* Upgrade Token Service timestamp from pending (TS-SUBMIT.NZIP) to confirmed (TIMESTAMP.NZIP)
|
|
4
4
|
*/
|
|
5
5
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
6
|
if (k2 === undefined) k2 = k;
|
|
@@ -45,15 +45,16 @@ const path = __importStar(require("path"));
|
|
|
45
45
|
const os = __importStar(require("os"));
|
|
46
46
|
const node_1 = __importDefault(require("neozipkit/node"));
|
|
47
47
|
const node_2 = require("neozipkit/node");
|
|
48
|
-
const
|
|
48
|
+
const token_service_1 = require("neozip-blockchain/token-service");
|
|
49
49
|
const exit_codes_1 = require("../exit-codes");
|
|
50
|
+
const bootstrap_1 = require("../connection/bootstrap");
|
|
50
51
|
/**
|
|
51
52
|
* Extract timestamp metadata from a ZIP entry.
|
|
52
53
|
* Tries the library's extractTimestampData first; if it fails (e.g. file-based ZIP),
|
|
53
54
|
* fall back to extracting to a temp file and parsing JSON.
|
|
54
55
|
*/
|
|
55
56
|
async function extractTimestampMetadata(zip, entry) {
|
|
56
|
-
let metadata = await (0,
|
|
57
|
+
let metadata = await (0, token_service_1.extractTimestampData)(zip, entry);
|
|
57
58
|
if (metadata)
|
|
58
59
|
return metadata;
|
|
59
60
|
// Fallback for file-based ZIPs where zip.extract() may not work
|
|
@@ -74,7 +75,7 @@ async function extractTimestampMetadata(zip, entry) {
|
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
/**
|
|
77
|
-
* Upgrade a ZIP file with pending
|
|
78
|
+
* Upgrade a ZIP file with pending Token Service timestamp to confirmed status.
|
|
78
79
|
* Replaces TS-SUBMIT.NZIP with TIMESTAMP.NZIP when the batch is confirmed on the blockchain.
|
|
79
80
|
*/
|
|
80
81
|
async function upgradeZipForTimestamp(inputPath, outputPath, options = {}) {
|
|
@@ -85,9 +86,9 @@ async function upgradeZipForTimestamp(inputPath, outputPath, options = {}) {
|
|
|
85
86
|
const zip = new node_1.default();
|
|
86
87
|
await zip.loadZipFile(inputPath);
|
|
87
88
|
const entries = zip.getDirectory() || [];
|
|
88
|
-
const metadataResult = (0,
|
|
89
|
+
const metadataResult = (0, token_service_1.findMetadataEntry)(entries);
|
|
89
90
|
if (!metadataResult) {
|
|
90
|
-
console.log('No
|
|
91
|
+
console.log('No Token Service timestamp found in ZIP file');
|
|
91
92
|
return;
|
|
92
93
|
}
|
|
93
94
|
if (metadataResult.type === 'confirmed') {
|
|
@@ -98,21 +99,23 @@ async function upgradeZipForTimestamp(inputPath, outputPath, options = {}) {
|
|
|
98
99
|
if (!metadata || !metadata.digest) {
|
|
99
100
|
(0, exit_codes_1.exitZip)(exit_codes_1.ZIP_EXIT_CODES.BAD_ARCHIVE_FORMAT, 'Error: Failed to extract timestamp metadata');
|
|
100
101
|
}
|
|
101
|
-
if (!(0,
|
|
102
|
+
if (!(0, token_service_1.shouldUpgrade)(metadata, metadataResult.type)) {
|
|
102
103
|
console.log('✓ Timestamp does not need upgrade');
|
|
103
104
|
return;
|
|
104
105
|
}
|
|
105
106
|
const digest = metadata.digest;
|
|
106
107
|
const chainId = metadata.chainId && metadata.chainId > 0 ? metadata.chainId : undefined;
|
|
107
108
|
const batchId = metadata.batchId ?? undefined;
|
|
109
|
+
const serverUrl = (0, bootstrap_1.resolveVerifyServerUrl)(metadata.serverUrl);
|
|
110
|
+
const verifyOpts = { debug, serverUrl };
|
|
108
111
|
let verified = null;
|
|
109
112
|
if (wait) {
|
|
110
113
|
if (verbose || debug)
|
|
111
114
|
console.log('Polling for confirmation (--wait)...');
|
|
112
|
-
verified = await (0,
|
|
115
|
+
verified = await (0, token_service_1.pollForConfirmation)(digest, chainId, batchId, 300000, 5000, verifyOpts);
|
|
113
116
|
}
|
|
114
117
|
else {
|
|
115
|
-
const verifyRes = await (0,
|
|
118
|
+
const verifyRes = await (0, token_service_1.verifyDigest)(digest, chainId, batchId, undefined, verifyOpts);
|
|
116
119
|
if (verifyRes.verified) {
|
|
117
120
|
verified = verifyRes;
|
|
118
121
|
}
|
|
@@ -135,7 +138,7 @@ async function upgradeZipForTimestamp(inputPath, outputPath, options = {}) {
|
|
|
135
138
|
blockNumber: verified.blockNumber ?? metadata.blockNumber,
|
|
136
139
|
timestamp: verified.timestamp ?? metadata.timestamp
|
|
137
140
|
};
|
|
138
|
-
const metadataFiles = (0,
|
|
141
|
+
const metadataFiles = (0, token_service_1.getMetadataFileNames)();
|
|
139
142
|
const outPath = outputPath ?? inputPath.replace(/(\.nzip|\.zip)$/i, '-upgrade$1');
|
|
140
143
|
const tempDir = path.dirname(outPath) || '.';
|
|
141
144
|
const tempPath = path.join(tempDir, `.neozip-upgrade-${Date.now()}.tmp`);
|
|
@@ -144,7 +147,7 @@ async function upgradeZipForTimestamp(inputPath, outputPath, options = {}) {
|
|
|
144
147
|
const { destPath, dataEndOffset, copiedEntries } = await zipCopy.copyZipEntriesOnly(inputPath, tempPath, {
|
|
145
148
|
entryFilter: (entry) => !metadataFiles.includes(entry.filename || '')
|
|
146
149
|
});
|
|
147
|
-
const newEntry = (0,
|
|
150
|
+
const newEntry = (0, token_service_1.createTimestampMetadataEntry)(zip, confirmedMetadata);
|
|
148
151
|
if (!newEntry) {
|
|
149
152
|
throw new Error('Failed to create timestamp metadata entry');
|
|
150
153
|
}
|