neozipkit 0.2.1 → 0.3.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 (301) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +410 -186
  3. package/contracts/ABI.txt +889 -0
  4. package/contracts/Bytecode.txt +1 -0
  5. package/contracts/COMPILATION_NOTES.md +59 -0
  6. package/contracts/QUICK_DEPLOY.md +286 -0
  7. package/contracts/README.md +235 -131
  8. package/contracts/VERIFICATION.md +308 -0
  9. package/contracts/deploy-interactive.js +448 -0
  10. package/contracts/deployment-arbitrum-sepolia.json +12 -0
  11. package/contracts/deployment-arbitrum.json +12 -0
  12. package/contracts/deployment-eth-sepolia.json +12 -0
  13. package/contracts/hardhat.config.js +114 -0
  14. package/contracts/package.json +20 -0
  15. package/contracts/scripts/compile-and-extract.js +119 -0
  16. package/contracts/scripts/verify-contract.js +223 -0
  17. package/contracts/src/{NZIP-NFT-Private.sol → NZIP-NFT-v2.0.sol} +66 -151
  18. package/contracts/src/NZIP-NFT.sol +9 -15
  19. package/dist/blockchain/browser/TokenVerifierBrowser.d.ts +67 -0
  20. package/dist/blockchain/browser/TokenVerifierBrowser.d.ts.map +1 -0
  21. package/dist/blockchain/browser/TokenVerifierBrowser.js +313 -0
  22. package/dist/blockchain/browser/TokenVerifierBrowser.js.map +1 -0
  23. package/dist/blockchain/browser/WalletManagerBrowser.d.ts +98 -0
  24. package/dist/blockchain/browser/WalletManagerBrowser.d.ts.map +1 -0
  25. package/dist/blockchain/browser/WalletManagerBrowser.js +434 -0
  26. package/dist/blockchain/browser/WalletManagerBrowser.js.map +1 -0
  27. package/dist/blockchain/browser/ZipkitMinterBrowser.d.ts +58 -0
  28. package/dist/blockchain/browser/ZipkitMinterBrowser.d.ts.map +1 -0
  29. package/dist/blockchain/browser/ZipkitMinterBrowser.js +317 -0
  30. package/dist/blockchain/browser/ZipkitMinterBrowser.js.map +1 -0
  31. package/dist/blockchain/browser/index.d.ts +11 -0
  32. package/dist/blockchain/browser/index.d.ts.map +1 -0
  33. package/dist/blockchain/browser/index.js +16 -0
  34. package/dist/blockchain/browser/index.js.map +1 -0
  35. package/dist/blockchain/core/WalletManager.d.ts +124 -0
  36. package/dist/blockchain/core/WalletManager.d.ts.map +1 -0
  37. package/dist/blockchain/{ZipKitWallet.js → core/WalletManager.js} +157 -177
  38. package/dist/blockchain/core/WalletManager.js.map +1 -0
  39. package/dist/blockchain/{ZipKitMinter.d.ts → core/ZipkitMinter.d.ts} +46 -11
  40. package/dist/blockchain/core/ZipkitMinter.d.ts.map +1 -0
  41. package/dist/blockchain/core/ZipkitMinter.js +548 -0
  42. package/dist/blockchain/core/ZipkitMinter.js.map +1 -0
  43. package/dist/blockchain/{ZipKitOTS.d.ts → core/ZipkitOTS.d.ts} +6 -15
  44. package/dist/blockchain/core/ZipkitOTS.d.ts.map +1 -0
  45. package/dist/blockchain/{ZipKitOTS.js → core/ZipkitOTS.js} +26 -84
  46. package/dist/blockchain/core/ZipkitOTS.js.map +1 -0
  47. package/dist/blockchain/core/ZipkitVerifier.d.ts +177 -0
  48. package/dist/blockchain/core/ZipkitVerifier.d.ts.map +1 -0
  49. package/dist/blockchain/core/ZipkitVerifier.js +632 -0
  50. package/dist/blockchain/core/ZipkitVerifier.js.map +1 -0
  51. package/dist/blockchain/core/contracts.d.ts +83 -0
  52. package/dist/blockchain/core/contracts.d.ts.map +1 -0
  53. package/dist/blockchain/core/contracts.js +341 -0
  54. package/dist/blockchain/core/contracts.js.map +1 -0
  55. package/dist/blockchain/core/index.d.ts +12 -0
  56. package/dist/blockchain/core/index.d.ts.map +1 -0
  57. package/dist/blockchain/core/index.js +59 -0
  58. package/dist/blockchain/core/index.js.map +1 -0
  59. package/dist/blockchain/index.d.ts +11 -7
  60. package/dist/blockchain/index.d.ts.map +1 -0
  61. package/dist/blockchain/index.js +18 -34
  62. package/dist/blockchain/index.js.map +1 -0
  63. package/dist/blockchain/node/WalletManagerNode.d.ts +47 -0
  64. package/dist/blockchain/node/WalletManagerNode.d.ts.map +1 -0
  65. package/dist/blockchain/node/WalletManagerNode.js +203 -0
  66. package/dist/blockchain/node/WalletManagerNode.js.map +1 -0
  67. package/dist/blockchain/node/index.d.ts +12 -0
  68. package/dist/blockchain/node/index.d.ts.map +1 -0
  69. package/dist/blockchain/node/index.js +24 -0
  70. package/dist/blockchain/node/index.js.map +1 -0
  71. package/dist/browser/ZipkitBrowser.d.ts +27 -0
  72. package/dist/browser/ZipkitBrowser.d.ts.map +1 -0
  73. package/dist/browser/{ZipKitBrowser.js → ZipkitBrowser.js} +96 -43
  74. package/dist/browser/ZipkitBrowser.js.map +1 -0
  75. package/dist/browser/index.d.ts +12 -0
  76. package/dist/browser/index.d.ts.map +1 -0
  77. package/dist/browser/index.js +42 -0
  78. package/dist/browser/index.js.map +1 -0
  79. package/dist/browser-esm/index.d.ts +12 -0
  80. package/dist/browser-esm/index.js +59559 -0
  81. package/dist/browser-esm/index.js.map +7 -0
  82. package/dist/browser-umd/index.d.ts +12 -0
  83. package/dist/browser-umd/index.js +59576 -0
  84. package/dist/browser-umd/index.js.map +7 -0
  85. package/dist/browser-umd/index.min.js +63 -0
  86. package/dist/browser.d.ts +8 -14
  87. package/dist/browser.js +13 -28
  88. package/dist/core/ZipCompress.d.ts +99 -0
  89. package/dist/core/ZipCompress.d.ts.map +1 -0
  90. package/dist/core/ZipCompress.js +309 -0
  91. package/dist/core/ZipCompress.js.map +1 -0
  92. package/dist/core/ZipDecompress.d.ts +58 -0
  93. package/dist/core/ZipDecompress.d.ts.map +1 -0
  94. package/dist/core/ZipDecompress.js +172 -0
  95. package/dist/core/ZipDecompress.js.map +1 -0
  96. package/dist/{shared → core}/ZipEntry.d.ts +8 -1
  97. package/dist/core/ZipEntry.d.ts.map +1 -0
  98. package/dist/{shared → core}/ZipEntry.js +225 -82
  99. package/dist/core/ZipEntry.js.map +1 -0
  100. package/dist/core/Zipkit.d.ts +315 -0
  101. package/dist/core/Zipkit.d.ts.map +1 -0
  102. package/dist/core/Zipkit.js +647 -0
  103. package/dist/core/Zipkit.js.map +1 -0
  104. package/dist/core/components/HashCalculator.d.ts +138 -0
  105. package/dist/core/components/HashCalculator.d.ts.map +1 -0
  106. package/dist/core/components/HashCalculator.js +360 -0
  107. package/dist/core/components/HashCalculator.js.map +1 -0
  108. package/dist/core/components/Logger.d.ts +73 -0
  109. package/dist/core/components/Logger.d.ts.map +1 -0
  110. package/dist/core/components/Logger.js +156 -0
  111. package/dist/core/components/Logger.js.map +1 -0
  112. package/dist/core/components/ProgressTracker.d.ts +43 -0
  113. package/dist/core/components/ProgressTracker.d.ts.map +1 -0
  114. package/dist/core/components/ProgressTracker.js +112 -0
  115. package/dist/core/components/ProgressTracker.js.map +1 -0
  116. package/dist/{shared → core}/components/Support.d.ts +1 -0
  117. package/dist/core/components/Support.d.ts.map +1 -0
  118. package/dist/{shared → core}/components/Support.js +1 -0
  119. package/dist/core/components/Support.js.map +1 -0
  120. package/dist/{shared → core}/components/Util.d.ts +7 -2
  121. package/dist/core/components/Util.d.ts.map +1 -0
  122. package/dist/{shared → core}/components/Util.js +14 -34
  123. package/dist/core/components/Util.js.map +1 -0
  124. package/dist/{shared → core}/constants/Errors.d.ts +1 -2
  125. package/dist/core/constants/Errors.d.ts.map +1 -0
  126. package/dist/{shared → core}/constants/Errors.js +1 -3
  127. package/dist/core/constants/Errors.js.map +1 -0
  128. package/dist/{shared → core}/constants/Headers.d.ts +3 -0
  129. package/dist/core/constants/Headers.d.ts.map +1 -0
  130. package/dist/{shared → core}/constants/Headers.js +20 -17
  131. package/dist/core/constants/Headers.js.map +1 -0
  132. package/dist/core/encryption/Manager.d.ts +58 -0
  133. package/dist/core/encryption/Manager.d.ts.map +1 -0
  134. package/dist/core/encryption/Manager.js +121 -0
  135. package/dist/core/encryption/Manager.js.map +1 -0
  136. package/dist/core/encryption/ZipCrypto.d.ts +172 -0
  137. package/dist/core/encryption/ZipCrypto.d.ts.map +1 -0
  138. package/dist/core/encryption/ZipCrypto.js +554 -0
  139. package/dist/core/encryption/ZipCrypto.js.map +1 -0
  140. package/dist/core/encryption/index.d.ts +9 -0
  141. package/dist/core/encryption/index.d.ts.map +1 -0
  142. package/dist/core/encryption/index.js +17 -0
  143. package/dist/core/encryption/index.js.map +1 -0
  144. package/dist/core/encryption/types.d.ts +29 -0
  145. package/dist/core/encryption/types.d.ts.map +1 -0
  146. package/dist/core/encryption/types.js +12 -0
  147. package/dist/core/encryption/types.js.map +1 -0
  148. package/dist/core/index.d.ts +24 -0
  149. package/dist/core/index.d.ts.map +1 -0
  150. package/dist/core/index.js +57 -0
  151. package/dist/core/index.js.map +1 -0
  152. package/dist/core/version.d.ts +5 -0
  153. package/dist/core/version.d.ts.map +1 -0
  154. package/dist/core/version.js +31 -0
  155. package/dist/core/version.js.map +1 -0
  156. package/dist/index.d.ts +8 -18
  157. package/dist/index.d.ts.map +1 -0
  158. package/dist/index.js +29 -35
  159. package/dist/index.js.map +1 -0
  160. package/dist/node/ZipCompressNode.d.ts +123 -0
  161. package/dist/node/ZipCompressNode.d.ts.map +1 -0
  162. package/dist/node/ZipCompressNode.js +576 -0
  163. package/dist/node/ZipCompressNode.js.map +1 -0
  164. package/dist/node/ZipDecompressNode.d.ts +120 -0
  165. package/dist/node/ZipDecompressNode.d.ts.map +1 -0
  166. package/dist/node/ZipDecompressNode.js +461 -0
  167. package/dist/node/ZipDecompressNode.js.map +1 -0
  168. package/dist/node/ZipkitNode.d.ts +406 -0
  169. package/dist/node/ZipkitNode.d.ts.map +1 -0
  170. package/dist/node/ZipkitNode.js +1305 -0
  171. package/dist/node/ZipkitNode.js.map +1 -0
  172. package/dist/node/index.d.ts +26 -0
  173. package/dist/node/index.d.ts.map +1 -0
  174. package/dist/node/index.js +65 -0
  175. package/dist/node/index.js.map +1 -0
  176. package/dist/types/index.d.ts +59 -0
  177. package/dist/types/index.d.ts.map +1 -0
  178. package/dist/types/index.js +36 -1
  179. package/dist/types/index.js.map +1 -0
  180. package/examples/README.md +269 -0
  181. package/examples/blockchain-tokenize.ts +354 -0
  182. package/examples/create-zip.ts +172 -0
  183. package/examples/extract-zip.ts +158 -0
  184. package/examples/list-zip.ts +161 -0
  185. package/examples/test-files/data.json +116 -0
  186. package/examples/test-files/document.md +80 -0
  187. package/examples/test-files/document.txt +2 -0
  188. package/examples/test-files/file1.txt +48 -0
  189. package/examples/test-files/file2.txt +80 -0
  190. package/examples/tsconfig.json +44 -0
  191. package/examples/unzip-token.ts +491 -0
  192. package/examples/verify-tokenized-zip.ts +305 -0
  193. package/examples/zip-token.ts +604 -0
  194. package/package.json +108 -24
  195. package/src/blockchain/README.md +59 -66
  196. package/src/{browser/TokenVerifierBrowser.ts-remove → blockchain/browser/TokenVerifierBrowser.ts} +125 -79
  197. package/src/blockchain/browser/WalletManagerBrowser.ts +486 -0
  198. package/src/blockchain/browser/ZipkitMinterBrowser.ts +400 -0
  199. package/src/blockchain/browser/index.ts +13 -0
  200. package/src/blockchain/{ZipKitWallet.ts → core/WalletManager.ts} +241 -143
  201. package/src/blockchain/core/ZipkitMinter.ts +716 -0
  202. package/src/blockchain/{ZipKitOTS.ts → core/ZipkitOTS.ts} +28 -62
  203. package/src/blockchain/core/ZipkitVerifier.ts +853 -0
  204. package/src/blockchain/core/contracts.ts +370 -0
  205. package/src/blockchain/core/index.ts +71 -0
  206. package/src/blockchain/index.ts +21 -55
  207. package/src/blockchain/node/WalletManagerNode.ts +171 -0
  208. package/src/blockchain/node/index.ts +40 -0
  209. package/src/browser/{ZipKitBrowser.ts → ZipkitBrowser.ts} +104 -41
  210. package/src/browser/index.esm.ts +37 -0
  211. package/src/browser/index.ts +25 -0
  212. package/src/core/ZipCompress.ts +398 -0
  213. package/src/core/ZipDecompress.ts +212 -0
  214. package/src/{shared → core}/ZipEntry.ts +240 -90
  215. package/src/core/Zipkit.ts +794 -0
  216. package/src/core/components/HashCalculator.ts +384 -0
  217. package/src/core/components/Logger.ts +180 -0
  218. package/src/core/components/ProgressTracker.ts +134 -0
  219. package/src/{shared → core}/components/Util.ts +12 -34
  220. package/src/{shared → core}/constants/Errors.ts +0 -4
  221. package/src/{shared → core}/constants/Headers.ts +19 -17
  222. package/src/core/encryption/Manager.ts +137 -0
  223. package/src/core/encryption/ZipCrypto.ts +650 -0
  224. package/src/core/encryption/index.ts +15 -0
  225. package/src/core/encryption/types.ts +33 -0
  226. package/src/core/index.ts +34 -0
  227. package/src/core/version.ts +33 -0
  228. package/src/index.ts +54 -25
  229. package/src/node/ZipCompressNode.ts +632 -0
  230. package/src/node/ZipDecompressNode.ts +508 -0
  231. package/src/node/ZipkitNode.ts +1559 -0
  232. package/src/node/index.ts +69 -0
  233. package/src/types/index.ts +131 -1
  234. package/src/types/modules.d.ts +1 -11
  235. package/src/types/opentimestamps.d.ts +1 -23
  236. package/contracts/INTEGRATION.md +0 -338
  237. package/contracts/NETWORKS.md +0 -156
  238. package/contracts/NZIP-NFT-bytecode.txt +0 -1
  239. package/contracts/constants.ts +0 -952
  240. package/contracts/deploy-bytecode.mjs +0 -94
  241. package/dist/blockchain/CertificateToken.d.ts +0 -48
  242. package/dist/blockchain/CertificateToken.js +0 -386
  243. package/dist/blockchain/ZipKitMinter.js +0 -347
  244. package/dist/blockchain/ZipKitNFT.d.ts +0 -3
  245. package/dist/blockchain/ZipKitNFT.js +0 -7
  246. package/dist/blockchain/ZipKitVerifier.d.ts +0 -69
  247. package/dist/blockchain/ZipKitVerifier.js +0 -289
  248. package/dist/blockchain/ZipKitWallet.d.ts +0 -69
  249. package/dist/blockchain/contracts.d.ts +0 -14
  250. package/dist/blockchain/contracts.js +0 -77
  251. package/dist/blockchain/types.d.ts +0 -47
  252. package/dist/blockchain/types.js +0 -30
  253. package/dist/browser/ZipKitBrowser.d.ts +0 -18
  254. package/dist/browser/ZipKitStampBrowser.d.ts +0 -2
  255. package/dist/browser/ZipKitStampBrowser.js +0 -12
  256. package/dist/browser-index.d.ts +0 -18
  257. package/dist/browser-index.js +0 -57
  258. package/dist/server/ZipKitServer.d.ts +0 -74
  259. package/dist/server/ZipKitServer.js +0 -310
  260. package/dist/shared/ZipKit.d.ts +0 -243
  261. package/dist/shared/ZipKit.js +0 -772
  262. package/dist/shared/components/CertificateOTS.d.ts +0 -15
  263. package/dist/shared/components/CertificateOTS.js +0 -116
  264. package/dist/shared/components/FileSys.d.ts +0 -2
  265. package/dist/shared/components/FileSys.js +0 -113
  266. package/dist/shared/components/HashAccumulator.d.ts +0 -55
  267. package/dist/shared/components/HashAccumulator.js +0 -100
  268. package/dist/shared/components/ZipCrypto.d.ts +0 -3
  269. package/dist/shared/components/ZipCrypto.js +0 -78
  270. package/dist/shared/components/merkleTree.d.ts +0 -66
  271. package/dist/shared/components/merkleTree.js +0 -136
  272. package/dist/shared/types/index.d.ts +0 -21
  273. package/dist/shared/types/index.js +0 -3
  274. package/dist/shared/types.d.ts +0 -33
  275. package/dist/shared/types.js +0 -8
  276. package/dist/shared/version.d.ts +0 -2
  277. package/dist/shared/version.js +0 -6
  278. package/src/blockchain/CertificateToken.ts +0 -444
  279. package/src/blockchain/ZipKitMinter.ts +0 -470
  280. package/src/blockchain/ZipKitNFT.ts +0 -12
  281. package/src/blockchain/ZipKitVerifier.ts +0 -382
  282. package/src/blockchain/contracts.ts +0 -88
  283. package/src/blockchain/types.ts +0 -91
  284. package/src/browser/CertificateGeneratorBrowser.ts-remove +0 -498
  285. package/src/browser/ZipKitStampBrowser.ts +0 -9
  286. package/src/browser-index.ts +0 -36
  287. package/src/server/README.md +0 -25
  288. package/src/server/ZipKitServer.ts +0 -305
  289. package/src/shared/ZipKit.ts +0 -881
  290. package/src/shared/components/CertificateOTS.ts +0 -132
  291. package/src/shared/components/FileSys.ts +0 -87
  292. package/src/shared/components/HashAccumulator.ts +0 -113
  293. package/src/shared/components/ZipCrypto.ts +0 -91
  294. package/src/shared/components/merkleTree.ts +0 -162
  295. package/src/shared/types/index.ts +0 -25
  296. package/src/shared/types/modules.d.ts +0 -22
  297. package/src/shared/types/opentimestamps.d.ts +0 -23
  298. package/src/shared/types.d.ts +0 -8
  299. package/src/shared/types.ts +0 -43
  300. package/src/shared/version.ts +0 -3
  301. /package/src/{shared → core}/components/Support.ts +0 -0
@@ -0,0 +1,491 @@
1
+ #!/usr/bin/env node
2
+
3
+ // ======================================
4
+ // unzip-token.ts
5
+ // A command-line utility for extracting and managing ZIP archives with advanced features
6
+ // including decryption, blockchain token verification, and SHA-256 validation.
7
+ // Copyright (c) 2025 NeoWare, Inc. All rights reserved.
8
+ // ======================================
9
+
10
+ import { exit } from 'process';
11
+ import * as fs from 'fs';
12
+ import * as path from 'path';
13
+ import readline from 'readline';
14
+ import moment from 'moment-timezone';
15
+
16
+ import {
17
+ NEOZIPKIT_INFO,
18
+ ZipKitServer,
19
+ ZipEntry,
20
+ TIMESTAMP_METADATA,
21
+ TIMESTAMP_SUBMITTED,
22
+ verifyTimestamp
23
+ } from 'neozipkit';
24
+
25
+ import yargs from 'yargs';
26
+ import { hideBin } from 'yargs/helpers';
27
+ import { sprintf } from 'sprintf-js';
28
+
29
+ // Import blockchain components for token verification
30
+ import { NZipTokenInfo } from './blockchain/types';
31
+ import { TOKENIZED_METADATA } from '../src/constants/Headers';
32
+
33
+ // Import token verification functionality
34
+ import {
35
+ checkForTokenization,
36
+ TokenVerificationOptions
37
+ } from './blockchain/TokenVerifier';
38
+
39
+ // Import version from the package
40
+ import { NEOZIPKIT_INFO } from '../src/shared/types';
41
+
42
+ // Add NeoUnzip version constants (derived from package version)
43
+ const NEOUNZIP_VERSION = NEOZIPKIT_INFO.version;
44
+ const NEOUNZIP_RELEASE_DATE = NEOZIPKIT_INFO.releaseDate;
45
+
46
+ // Display copyright and version header on startup
47
+ console.log(`NeoUnzip v${NEOUNZIP_VERSION} (${NEOUNZIP_RELEASE_DATE}) Copyright (c) 2025 NeoWare, Inc. All rights reserved`);
48
+ console.log(`Using NeoZipKit v${NEOZIPKIT_INFO.version} (${NEOZIPKIT_INFO.releaseDate})`);
49
+
50
+ const options = yargs(hideBin(process.argv))
51
+ .usage("Usage: $0 <zipfile> <extract path>")
52
+ .demandCommand(1, "Error - The .zip filename is required.")
53
+ .option('t', { alias: 'test', describe: 'Test archive files', type: 'boolean' })
54
+ .option('u', { alias: 'update', describe: 'Update files, create if neccessary', type: 'boolean' })
55
+ .option('f', { alias: 'freshen', describe: 'Freshen by extracting only if older file on disk.', type: 'boolean' })
56
+ .option('d', { alias: 'directory', describe: 'Specify a different directory', type: 'string' })
57
+ .option('x', { alias: 'exclude', describe: 'Exclude specified files', type: 'array' })
58
+ .option('j', { alias: 'junk', describe: 'Junk paths (don\'t make directories)', type: 'boolean' })
59
+ .option('q', { alias: 'quiet', describe: 'Quiet mode', type: 'boolean' })
60
+ .option('o', { alias: 'overwrite', describe: 'Overwrite files without prompting', type: 'boolean' })
61
+ .option('n', { alias: 'never', describe: 'Never overwrite existing files', type: 'boolean' })
62
+ .option('L', { alias: 'license', describe: 'Display software license', type: 'boolean' })
63
+ .option('H', { alias: 'Hash SHA-256', describe: 'Calculate and validate SHA-256 Hash on entries', type: 'boolean' })
64
+ .option('skip-hash', { describe: 'Skip SHA-256 hash validation', type: 'boolean' })
65
+ .option('skip-token', { describe: 'Skip NFT token verification', type: 'boolean' })
66
+ .option('S', { alias: 'Skip Timestamp', describe: 'Do not validate timestamped Zip', type: 'boolean' })
67
+ .option('C', { alias: 'Timestamp Certificate HTML', describe: 'Create a timestamp certicate as HTML file', type: 'boolean' })
68
+ .option('P', { alias: 'Timestamp Certificate PDF', describe: 'Create a timestamp certicate as PDF file', type: 'boolean' })
69
+ .option('c', { alias: 'certificate', describe: 'Generate token certificate', type: 'boolean' })
70
+ .help('help', 'Show help').alias('help', 'h')
71
+ .wrap(null)
72
+ .epilog('Copyright (c) 2025 NeoWare, Inc. - Type "neounzip "-L" for software license.\n')
73
+ .parseSync()
74
+
75
+ const zipFile = options._[0] as string;
76
+ const zipKit = new ZipKitServer();
77
+
78
+ // Global variables for token verification
79
+ let isTokenizedZip = false;
80
+ let tokenMetadata: NZipTokenInfo | null = null;
81
+ let calculatedMerkleRoot: string | null = null;
82
+
83
+ async function main() {
84
+ try {
85
+ // Check if the file exists before trying to read it
86
+ if (!fs.existsSync(zipFile)) {
87
+ console.error(`Error: Zip file "${zipFile}" does not exist`);
88
+ exit(1);
89
+ }
90
+
91
+ const inBuffer = fs.readFileSync(zipFile);
92
+ zipKit.loadZip(inBuffer);
93
+
94
+ // Check if this is a tokenized ZIP file
95
+ const verificationOptions: TokenVerificationOptions = {
96
+ skipHash: options['skip-hash'],
97
+ skipToken: options['skip-token'],
98
+ generateCertificate: options.c,
99
+ zipFileName: zipFile
100
+ };
101
+
102
+ const result = await checkForTokenization(zipKit, verificationOptions);
103
+
104
+ // Update global variables with results
105
+ isTokenizedZip = result.isTokenized;
106
+ tokenMetadata = result.tokenMetadata;
107
+ calculatedMerkleRoot = result.calculatedMerkleRoot;
108
+
109
+ } catch (error) {
110
+ console.error(`Error: Failed to read zip file "${zipFile}"`);
111
+ console.error(error);
112
+ exit(1);
113
+ }
114
+
115
+ // command options
116
+ if (options.t) {
117
+ // Test the CRC of the zip file
118
+ await extractFiles(true);
119
+ } else if (options.z) {
120
+ // Archive comment onlyzip
121
+ } else if (options.L) {
122
+ displayLicense();
123
+ } else {
124
+ // No options, extract all files
125
+ await extractFiles(false)
126
+ }
127
+ }
128
+
129
+ // Start the main function
130
+ main().catch(error => {
131
+ console.error('Unhandled error:', error);
132
+ exit(1);
133
+ });
134
+
135
+ // Display the software license
136
+ function displayLicense() {
137
+ prt('Copyright (c) 2025 by NeoWare, Inc. All rights reserved\n');
138
+ exit(0);
139
+ }
140
+
141
+ /**
142
+ * Extracts or tests files from the ZIP archive
143
+ * @param test - If true, only tests archive integrity without extracting
144
+ */
145
+ async function extractFiles(test: boolean = false) {
146
+ try {
147
+ let zipEntries = zipKit.getDirectory() as ZipEntry[];
148
+
149
+ // Check if we have any entries
150
+ if (!zipEntries || zipEntries.length === 0) {
151
+ console.log('\nArchive is empty or invalid: ', zipFile);
152
+ return;
153
+ }
154
+
155
+ let zipComment = zipKit.getZipComment();
156
+
157
+ console.log('\nArchive: ', zipFile);
158
+ if (zipComment)
159
+ console.log(zipComment);
160
+
161
+ let _extFiles = 0;
162
+ let _total = 0;
163
+ let _cmpTotal = 0;
164
+ let _password = null;
165
+ let _localData = null;
166
+ let _metaStamp = null;
167
+ for (const entry of zipEntries) {
168
+ // Check if Zip Entry is encrypted
169
+ if (entry.isEncrypted) {
170
+ if (entry.isStrongEncrypt) {
171
+ prt(sprintf(" skipping: %-25s Strong Encryption not supported\n", entry.filename));
172
+ continue;
173
+ }
174
+ for (var i=0; i < 3; i++) {
175
+ if (_password == null) {
176
+ _password = await inputPassword(entry, i > 0);
177
+ }
178
+ _localData = zipKit.decryptEntry(entry, _password);
179
+ if (_localData) break;
180
+ _password = null;
181
+ }
182
+ if (!_localData) {
183
+ prt(sprintf(" skipping: %-25s incorrect password\n", entry.filename));
184
+ continue;
185
+ }
186
+ }
187
+
188
+ test ? prt(sprintf(" Testing: %-25s ", entry.filename)) :
189
+ prt(sprintf(" Extracting: %-25s ", entry.filename));
190
+ try {
191
+ let _outBuf = await zipKit.extract(entry);
192
+
193
+ if (entry.filename === TIMESTAMP_METADATA) {
194
+ _metaStamp = _outBuf;
195
+ console.log(' Timestamp Metadata');
196
+ continue;
197
+ } else if (entry.filename === TIMESTAMP_SUBMITTED) {
198
+ _metaStamp = _outBuf;
199
+ console.log(' Timestamp Submitted');
200
+ continue;
201
+ } else if (entry.filename === TOKENIZED_METADATA) {
202
+ console.log(' NFT Token Metadata (not extracted)');
203
+ continue;
204
+ } else if (!test) {
205
+ const _path = options.d ? options.d + path.sep + entry.filename : entry.filename;
206
+ const _overwrite = await testOverwrite(_path);
207
+ if (_overwrite) {
208
+ if (_outBuf) {
209
+ writeFile(_path, _outBuf, entry, entry.extFileAttr);
210
+ } else {
211
+ prt("Error: No data to write\n");
212
+ continue;
213
+ }
214
+ } else if (options.n) {
215
+ prt("file exists, Skipped\n");
216
+ continue;
217
+ } else {
218
+ prt(" Skipped\n");
219
+ continue;
220
+ }
221
+ }
222
+
223
+ // Automatically validate SHA-256 if available and not skipped
224
+ if (entry.sha256 && !options['skip-hash']) {
225
+ console.log(' OK SHA-256 ✅');
226
+ } else if (entry.sha256 && options['skip-hash']) {
227
+ console.log(' OK (SHA-256 skipped)');
228
+ } else {
229
+ console.log(' OK');
230
+ }
231
+
232
+ _extFiles++;
233
+ _total += entry.uncompressedSize;
234
+ _cmpTotal += entry.compressedSize;
235
+ } catch (e) {
236
+ prt(" Failed\n");
237
+ console.log(e);
238
+ }
239
+ };
240
+ console.log('No Errors where detected in %d files %s.', _extFiles, test ? 'tested' : 'extracted');
241
+
242
+ // Display token verification results if this is a tokenized ZIP
243
+ if (isTokenizedZip && tokenMetadata) {
244
+ console.log('\n🔗 Token Verification Summary:');
245
+ console.log('═'.repeat(50));
246
+
247
+ // Full NFT token info only
248
+ console.log(`Token ID: ${tokenMetadata.tokenId}`);
249
+ console.log(`Network: ${tokenMetadata.network}`);
250
+ console.log(`Contract: ${tokenMetadata.contractAddress}`);
251
+
252
+ if (options['skip-token']) {
253
+ console.log('⏭️ Token verification: SKIPPED');
254
+ } else if (options['skip-hash']) {
255
+ console.log('⏭️ Archive integrity: SKIPPED');
256
+ console.log(' Hash calculation disabled - cannot verify');
257
+ } else if (calculatedMerkleRoot) {
258
+ console.log('🌐 Archive integrity: BLOCKCHAIN VERIFIED');
259
+ console.log(' See verification details above');
260
+ } else {
261
+ console.log('⚠️ Archive integrity: CANNOT VERIFY');
262
+ console.log(' Unable to calculate merkle root for comparison');
263
+ }
264
+ console.log('═'.repeat(50));
265
+ }
266
+
267
+ let _merkleRoot = zipKit.checkForTimestamp();
268
+ if (_merkleRoot) {
269
+ if (options.S) {
270
+ console.log('Archive contains timestamp metadata - Skipping Validation');
271
+ return;
272
+ }
273
+ console.log('Archive is timestamped - Pending Validation');
274
+ if (!_merkleRoot) {
275
+ console.log('No timestamp metadata found');
276
+ console.log('Archive timestamp validation failed!');
277
+ } else {
278
+ // Validate the timestamp
279
+ let _ots = await zipKit.getOts();
280
+ const _timestampResult = await verifyTimestamp(_merkleRoot, _ots);
281
+
282
+ // First check if _timestampResult is not null
283
+ if (_timestampResult) {
284
+ // Type guard to check if we have a successful result with the verified property
285
+ if ('verified' in _timestampResult && _timestampResult.verified) {
286
+ // Check if results property exists
287
+ if ('results' in _timestampResult && _timestampResult.results) {
288
+ for (const chain in _timestampResult.results) {
289
+ let _results = _timestampResult.results[chain];
290
+ const _date = moment(_results.timestamp * 1000).tz(moment.tz.guess()).format('MM-DD-YYYY hh:mma z');
291
+ const _blockchain = chain.charAt(0).toUpperCase() + chain.slice(1);
292
+ console.log('Success! ' + _blockchain + ' block ' + _results.height + ' attests existence as of ' + _date);
293
+ }
294
+ }
295
+
296
+ // Check if upgradedOts property exists
297
+ if ('upgradedOts' in _timestampResult && _timestampResult.upgradedOts) {
298
+ const upgrade = await askUpgrade();
299
+ if (upgrade) {
300
+ let upgradeBuf = Buffer.from(_timestampResult.upgradedOts);
301
+ await zipKit.upgradeOTS(zipFile, upgradeBuf);
302
+ console.log('OTS upgraded - Certificate generation is now possible');
303
+ } else {
304
+ console.log('Certificate generation is not possible until timestamp is validated');
305
+ }
306
+ }
307
+ } else if ('error' in _timestampResult && !_timestampResult.error) {
308
+ console.log('Archive timestamp awaiting submittion to blockchain');
309
+ if (options.C || options.P) {
310
+ console.log('Certificate generation is not possible until timestamp is validated');
311
+ }
312
+ }
313
+ } else {
314
+ console.log('No timestamp information available');
315
+ }
316
+ }
317
+ }
318
+ } catch (error) {
319
+ console.error('Error processing zip file:', error);
320
+ exit(1);
321
+ }
322
+ }
323
+
324
+ /**
325
+ * Writes an extracted file to disk
326
+ * @param filename - Path where the file should be written
327
+ * @param outBuf - Buffer containing file data
328
+ * @param entry - ZIP entry associated with the file
329
+ * @param fileAttr - Optional Unix file permissions
330
+ * @returns boolean indicating success
331
+ */
332
+ function writeFile(filename: string, outBuf: Buffer, entry?: ZipEntry, fileAttr?: number | undefined) {
333
+ // get Unix file permissions
334
+ const _fattr = fileAttr ? (((fileAttr >>> 0) | 0) >> 16) & 0xfff : 0;
335
+
336
+ var fd;
337
+ try {
338
+ fd = fs.openSync(filename, "w", 438); // 0666
339
+ } catch (e) {
340
+ fs.chmodSync(filename, 438);
341
+ fd = fs.openSync(filename, "w", 438);
342
+ }
343
+ if (!fd) return false;
344
+
345
+ try {
346
+ fs.writeSync(fd, outBuf, 0, outBuf.length, 0);
347
+ } finally {
348
+ fs.closeSync(fd);
349
+ }
350
+
351
+ if (_fattr)
352
+ fs.chmodSync(filename, _fattr);
353
+
354
+ // Set file modification time if universal time is available
355
+ if (entry && entry.universalTime) {
356
+ const mtime = new Date(entry.universalTime * 1000); // Convert Unix timestamp (seconds) to milliseconds
357
+ try {
358
+ // Set both access time and modification time to the universal time
359
+ fs.utimesSync(filename, mtime, mtime);
360
+ } catch (e) {
361
+ console.error(`Warning: Could not set file time for ${filename}: ${e}`);
362
+ }
363
+ }
364
+
365
+ // Set owner and group if UID and GID are available (Unix-like systems only)
366
+ if (entry && (entry.uid !== null || entry.gid !== null)) {
367
+ try {
368
+ // Use process functions as fallbacks if they exist (Unix-like systems)
369
+ // Default to 0 (root) if neither entry values nor process functions are available
370
+ const uid = entry.uid !== null ? entry.uid :
371
+ (typeof process.getuid === 'function' ? process.getuid() : 0);
372
+ const gid = entry.gid !== null ? entry.gid :
373
+ (typeof process.getgid === 'function' ? process.getgid() : 0);
374
+
375
+ // Change owner and group of the file
376
+ fs.chownSync(filename, uid, gid);
377
+ } catch (e) {
378
+ // This might fail on Windows or if user doesn't have permission
379
+ console.error(`Warning: Could not set owner/group for ${filename}: ${e}`);
380
+ }
381
+ }
382
+
383
+ return true;
384
+ }
385
+
386
+ /**
387
+ * Checks if a file should be overwritten during extraction
388
+ * @param filename - Path of the file to check
389
+ * @returns Promise<boolean> indicating if file should be overwritten
390
+ */
391
+ async function testOverwrite(filename: string): Promise<boolean> {
392
+ // Check if we need to create a new folder
393
+ const _folder = path.dirname(filename);
394
+ if (!fs.existsSync(_folder)) {
395
+ console.log('Need to create directory: ', _folder);
396
+ // makeDir(_folder);
397
+ }
398
+
399
+ const _stat = fs.statSync(filename);
400
+ if (_stat.isDirectory()) {
401
+ console.log(': ', filename);
402
+ return false;
403
+ }
404
+
405
+ if (!fs.existsSync(filename))
406
+ return true;
407
+
408
+ if (options.n) {
409
+ return false;
410
+ } else if (options.o) {
411
+ return true;
412
+ }
413
+
414
+ return new Promise((resolve) => {
415
+ process.stdin.setRawMode(true);
416
+ process.stdin.resume();
417
+ process.stdout.write("file exists, Overwrite? (y/n/a): ");
418
+
419
+ process.stdin.once('data', (data: Buffer) => {
420
+ const char = data.toString().toLowerCase();
421
+
422
+ // Restore stdin to its previous state
423
+ process.stdin.setRawMode(false);
424
+ process.stdin.pause();
425
+ process.stdout.write(char);
426
+
427
+ if (char === 'y') {
428
+ resolve(true);
429
+ } else if (char === 'a') {
430
+ prt(" Aborted\n");
431
+ exit(0);
432
+ } else {
433
+ resolve(false);
434
+ }
435
+ });
436
+ });
437
+ }
438
+
439
+ /**
440
+ * Prompts user to confirm timestamp upgrade
441
+ * @returns Promise<boolean> indicating user's choice
442
+ */
443
+ async function askUpgrade(): Promise<boolean> {
444
+ return new Promise((resolve) => {
445
+ process.stdin.setRawMode(true);
446
+ process.stdin.resume();
447
+ process.stdout.write("Upgrade NeoTimestamp? (y/n): ");
448
+
449
+ process.stdin.once('data', (data: Buffer) => {
450
+ const char = data.toString().toLowerCase();
451
+
452
+ // Restore stdin to its previous state
453
+ process.stdin.setRawMode(false);
454
+ process.stdin.pause();
455
+ process.stdout.write(char + '\n');
456
+
457
+ if (char === 'y') {
458
+ resolve(true);
459
+ } else {
460
+ resolve(false);
461
+ }
462
+ });
463
+ });
464
+ }
465
+
466
+ /**
467
+ * Prompts for password when extracting encrypted files
468
+ * @param entry - ZIP entry requiring password
469
+ * @param retry - Boolean indicating if this is a retry attempt
470
+ * @returns Promise<string> containing the entered password
471
+ */
472
+ async function inputPassword(entry: ZipEntry, retry: boolean): Promise<string> {
473
+ const rl = readline.createInterface({
474
+ input: process.stdin,
475
+ output: process.stdout,
476
+ terminal: true
477
+ });
478
+
479
+ return new Promise<string>((resolve) => {
480
+ rl.question(retry ?
481
+ 'password incorrect - renter: ' :
482
+ `[${zipFile}] ${entry.filename} password: `, (input: string) => {
483
+ rl.close();
484
+ resolve(input);
485
+ });
486
+ });
487
+ }
488
+
489
+ function prt(msg: string) {
490
+ process.stdout.write(msg);
491
+ }