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,354 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Blockchain Tokenization Example
5
+ *
6
+ * Demonstrates creating a tokenized ZIP file with blockchain NFT minting.
7
+ * This is a minimal example showing the basic tokenization flow.
8
+ *
9
+ * SECURITY WARNING:
10
+ * - NEVER use mainnet private keys in examples
11
+ * - ONLY use testnet keys with minimal test funds
12
+ * - NEVER commit private keys to version control
13
+ * - Store private keys in .env file (excluded from git)
14
+ * - Rotate keys immediately if accidentally exposed
15
+ * - Wallet files (wallet/neozip-wallet.json) are automatically excluded from git
16
+ *
17
+ * See SECURITY.md for complete security guidelines.
18
+ *
19
+ * Note: This example requires:
20
+ * - A wallet private key with testnet ETH
21
+ * - Network configuration (defaults to Base Sepolia testnet)
22
+ * - Gas fees for minting
23
+ */
24
+
25
+ import { ZipkitNode } from '../src/node';
26
+ import { ZipkitMinter } from '../src/blockchain/core/ZipkitMinter';
27
+ import type { CompressOptions } from '../src/core';
28
+ import type { TokenMetadata } from '../src/types';
29
+ import { TOKENIZED_METADATA } from '../src/core/constants/Headers';
30
+ import { crc32 } from '../src/core/encryption/ZipCrypto';
31
+ import * as fs from 'fs';
32
+ import * as path from 'path';
33
+ import dotenv from 'dotenv';
34
+
35
+ // Load .env.local first (local overrides), then .env
36
+ dotenv.config({ path: '.env.local' });
37
+ dotenv.config(); // Loads .env if .env.local doesn't exist
38
+
39
+ async function main() {
40
+ console.log('Blockchain Tokenization Example\n');
41
+
42
+ // Check for wallet private key
43
+ const walletPrivateKey = process.env.NEOZIP_WALLET_PASSKEY;
44
+ if (!walletPrivateKey) {
45
+ console.error('❌ Error: NEOZIP_WALLET_PASSKEY environment variable is required');
46
+ console.error(' Please set your wallet private key:');
47
+ console.error(' export NEOZIP_WALLET_PASSKEY="0x..."');
48
+ console.error('\n💡 Get testnet ETH from:');
49
+ console.error(' https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet');
50
+ process.exit(1);
51
+ }
52
+
53
+ // Network configuration (default to Base Sepolia testnet)
54
+ const network = process.env.NEOZIP_NETWORK || 'base-sepolia';
55
+
56
+ // Create some test files
57
+ const testFiles: string[] = [];
58
+ const testDir = path.join(__dirname, 'test-files');
59
+
60
+ if (!fs.existsSync(testDir)) {
61
+ fs.mkdirSync(testDir, { recursive: true });
62
+ }
63
+
64
+ const file1 = path.join(testDir, 'document.txt');
65
+ const file2 = path.join(testDir, 'data.json');
66
+
67
+ if (!fs.existsSync(file1)) {
68
+ fs.writeFileSync(file1, 'This is a sample document.\nIt will be tokenized on the blockchain.');
69
+ }
70
+ testFiles.push(file1);
71
+
72
+ if (!fs.existsSync(file2)) {
73
+ fs.writeFileSync(file2, JSON.stringify({ name: 'Sample Data', value: 12345 }, null, 2));
74
+ }
75
+ testFiles.push(file2);
76
+
77
+ console.log('Source files:');
78
+ testFiles.forEach(file => {
79
+ const stats = fs.statSync(file);
80
+ console.log(` - ${path.basename(file)} (${stats.size} bytes)`);
81
+ });
82
+ console.log();
83
+
84
+ // Create ZipkitNode instance
85
+ const zip = new ZipkitNode();
86
+
87
+ // Define output ZIP file path
88
+ const outputZip = path.join(__dirname, 'output', 'tokenized.zip');
89
+ const outputDir = path.dirname(outputZip);
90
+ if (!fs.existsSync(outputDir)) {
91
+ fs.mkdirSync(outputDir, { recursive: true });
92
+ }
93
+
94
+ // Compression options with SHA-256 enabled (required for merkle root calculation)
95
+ const options: CompressOptions = {
96
+ level: 6,
97
+ useZstd: true,
98
+ useSHA256: true // IMPORTANT: Enable SHA-256 for blockchain features
99
+ };
100
+
101
+ try {
102
+ console.log('Step 1: Creating ZIP archive with SHA-256 hashes...');
103
+
104
+ // Create ZIP file from files
105
+ await zip.createZipFromFiles(testFiles, outputZip, options);
106
+
107
+ console.log(`✅ ZIP archive created: ${outputZip}\n`);
108
+
109
+ // Load the ZIP to get entries and calculate merkle root
110
+ console.log('Step 2: Calculating merkle root...');
111
+ await zip.loadZipFile(outputZip);
112
+
113
+ // Get merkle root (this requires SHA-256 hashes to be calculated)
114
+ const merkleRoot = (zip as any).getMerkleRoot?.();
115
+
116
+ if (!merkleRoot) {
117
+ console.error('❌ Error: Could not calculate merkle root');
118
+ console.error(' Make sure useSHA256: true is set in compression options');
119
+ await zip.closeFile(); // Close file handle before exiting
120
+ process.exit(1);
121
+ }
122
+
123
+ console.log(`✅ Merkle root calculated: ${merkleRoot}\n`);
124
+
125
+ // Close file handle to prevent warnings
126
+ await zip.closeFile();
127
+
128
+ // Initialize blockchain minter
129
+ console.log('Step 3: Initializing blockchain minter...');
130
+ const minter = new ZipkitMinter(merkleRoot, {
131
+ walletPrivateKey: walletPrivateKey,
132
+ network: network,
133
+ verbose: true,
134
+ debug: false
135
+ });
136
+
137
+ // Get wallet information
138
+ const walletInfo = await minter.getWalletInfo();
139
+ console.log(`✅ Wallet: ${walletInfo.address}`);
140
+ console.log(` Balance: ${walletInfo.balance} ETH`);
141
+ console.log(` Network: ${walletInfo.networkName}\n`);
142
+
143
+ // Check for existing tokens
144
+ console.log('Step 4: Checking for existing tokens...');
145
+ const duplicateCheck = await minter.checkForDuplicates();
146
+
147
+ if (duplicateCheck.hasExistingTokens) {
148
+ console.log(`⚠️ Found ${duplicateCheck.allTokens.length} existing token(s) with this merkle root:`);
149
+ duplicateCheck.userOwnedTokens.forEach(token => {
150
+ console.log(` - Token ID ${token.tokenId} (owned by you)`);
151
+ });
152
+ duplicateCheck.othersTokens.forEach(token => {
153
+ console.log(` - Token ID ${token.tokenId} (owned by others)`);
154
+ });
155
+ console.log('\n💡 This example will proceed with minting a new token.');
156
+ console.log(' In a real application, you might want to use an existing token instead.\n');
157
+ } else {
158
+ console.log('✅ No existing tokens found. Proceeding with new mint.\n');
159
+ }
160
+
161
+ // Estimate gas costs
162
+ console.log('Step 5: Estimating gas costs...');
163
+ const gasCosts = await minter.estimateGasCosts();
164
+ console.log(` Estimated gas cost: ${gasCosts.estimatedCost} ETH\n`);
165
+
166
+ // Mint the token
167
+ console.log('Step 6: Minting NFT token on blockchain...');
168
+ console.log(' This will incur gas costs. Please wait...\n');
169
+
170
+ const mintResult = await minter.mintToken();
171
+
172
+ if (mintResult.success) {
173
+ console.log(`✅ Token minted successfully!`);
174
+ console.log(` Token ID: ${mintResult.tokenId}`);
175
+ console.log(` Transaction: ${mintResult.transactionHash}`);
176
+ console.log(` Contract: ${mintResult.contractAddress}`);
177
+ if (mintResult.gasUsed) {
178
+ console.log(` Gas Used: ${mintResult.gasUsed}`);
179
+ }
180
+ if (mintResult.gasCost) {
181
+ console.log(` Gas Cost: ${mintResult.gasCost} ETH`);
182
+ }
183
+ console.log();
184
+
185
+ // Step 7: Add token metadata to ZIP file
186
+ console.log('Step 7: Adding token metadata to ZIP file...');
187
+
188
+ // Create token metadata object
189
+ const tokenMetadata: TokenMetadata = {
190
+ version: '1.0',
191
+ tokenId: mintResult.tokenId!,
192
+ contractAddress: mintResult.contractAddress!,
193
+ network: walletInfo.networkName,
194
+ networkChainId: walletInfo.networkName === 'Base Sepolia' ? 84532 : undefined,
195
+ transactionHash: mintResult.transactionHash,
196
+ merkleRoot: merkleRoot,
197
+ mintedAt: new Date().toISOString(),
198
+ mintDate: new Date().toISOString()
199
+ };
200
+
201
+ // Rebuild ZIP with token metadata
202
+ await addTokenMetadataToZip(zip, outputZip, tokenMetadata, testFiles, options);
203
+
204
+ console.log(`✅ Token metadata added to ZIP file`);
205
+ console.log(` Metadata file: ${TOKENIZED_METADATA}`);
206
+ console.log();
207
+ console.log(`📄 View token on explorer:`);
208
+ const explorerUrl = `https://sepolia.basescan.org/token/${mintResult.contractAddress}?a=${mintResult.tokenId}`;
209
+ console.log(` ${explorerUrl}`);
210
+
211
+ // Explicitly exit to prevent hanging
212
+ process.exit(0);
213
+
214
+ } else {
215
+ console.error(`❌ Token minting failed: ${mintResult.message}`);
216
+ process.exit(1);
217
+ }
218
+
219
+ } catch (error) {
220
+ console.error('❌ Error during tokenization:');
221
+ console.error(error instanceof Error ? error.message : String(error));
222
+ if (error instanceof Error && error.stack) {
223
+ console.error('\nStack trace:');
224
+ console.error(error.stack);
225
+ }
226
+ // Ensure file handle is closed on error
227
+ try {
228
+ await zip.closeFile();
229
+ } catch (closeError) {
230
+ // Ignore close errors
231
+ }
232
+ process.exit(1);
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Add token metadata to ZIP file by rebuilding it with the metadata entry
238
+ */
239
+ async function addTokenMetadataToZip(
240
+ zip: ZipkitNode,
241
+ zipPath: string,
242
+ tokenMetadata: TokenMetadata,
243
+ originalFiles: string[],
244
+ options: CompressOptions
245
+ ): Promise<void> {
246
+ // Create token metadata content
247
+ const tokenContent = JSON.stringify(tokenMetadata, null, 2);
248
+ const tokenBuffer = Buffer.from(tokenContent, 'utf8');
249
+
250
+ // Create temporary ZIP file
251
+ const tempZipPath = zipPath + '.tmp';
252
+
253
+ // Create a fresh ZipkitNode instance for the new ZIP
254
+ const newZip = new ZipkitNode();
255
+
256
+ // Initialize new ZIP file
257
+ const writer = await newZip.initializeZipFile(tempZipPath);
258
+
259
+ try {
260
+ // Add all original files
261
+ for (const filePath of originalFiles) {
262
+ const entry = await newZip.prepareEntryFromFile(filePath);
263
+ await newZip.writeZipEntry(writer, entry, filePath, options);
264
+ }
265
+
266
+ // Add token metadata entry (STORED, uncompressed)
267
+ const tokenEntry = newZip.createZipEntry(TOKENIZED_METADATA);
268
+ tokenEntry.timeDateDOS = tokenEntry.setDateTime(new Date());
269
+ tokenEntry.uncompressedSize = tokenBuffer.length;
270
+ tokenEntry.compressedSize = tokenBuffer.length;
271
+ tokenEntry.cmpMethod = 0; // STORED (no compression)
272
+ tokenEntry.crc = crc32(tokenBuffer);
273
+ tokenEntry.fileBuffer = tokenBuffer;
274
+
275
+ // Add entry to ZIP entries list
276
+ newZip.getDirectory().push(tokenEntry);
277
+
278
+ // Write token entry manually (STORED method)
279
+ tokenEntry.localHdrOffset = writer.currentPosition;
280
+ writer.entryPositions.set(TOKENIZED_METADATA, tokenEntry.localHdrOffset);
281
+ const localHeader = tokenEntry.createLocalHdr();
282
+
283
+ await new Promise<void>((resolve, reject) => {
284
+ writer.outputStream.write(localHeader, (error) => {
285
+ if (error) {
286
+ reject(error);
287
+ } else {
288
+ writer.currentPosition += localHeader.length;
289
+ resolve();
290
+ }
291
+ });
292
+ });
293
+
294
+ // Write token data
295
+ await new Promise<void>((resolve, reject) => {
296
+ writer.outputStream.write(tokenBuffer, (error) => {
297
+ if (error) {
298
+ reject(error);
299
+ } else {
300
+ writer.currentPosition += tokenBuffer.length;
301
+ resolve();
302
+ }
303
+ });
304
+ });
305
+
306
+ // Get all entries (including token metadata)
307
+ const allEntries = newZip.getDirectory();
308
+
309
+ // Write central directory
310
+ const centralDirOffset = writer.currentPosition;
311
+ const centralDirSize = await newZip.writeCentralDirectory(writer, allEntries);
312
+
313
+ // Write EOCD
314
+ await newZip.writeEndOfCentralDirectory(
315
+ writer,
316
+ allEntries.length,
317
+ centralDirSize,
318
+ centralDirOffset
319
+ );
320
+
321
+ // Finalize and close
322
+ await newZip.finalizeZipFile(writer);
323
+
324
+ // Wait a moment for file system to sync
325
+ await new Promise(resolve => setTimeout(resolve, 100));
326
+
327
+ // Replace original ZIP with new one
328
+ if (fs.existsSync(zipPath)) {
329
+ fs.unlinkSync(zipPath);
330
+ }
331
+ fs.renameSync(tempZipPath, zipPath);
332
+
333
+ // Ensure file handles are released
334
+ await new Promise(resolve => setTimeout(resolve, 100));
335
+
336
+ } catch (error) {
337
+ // Clean up temp file on error
338
+ if (fs.existsSync(tempZipPath)) {
339
+ try {
340
+ fs.unlinkSync(tempZipPath);
341
+ } catch (unlinkError) {
342
+ // Ignore unlink errors
343
+ }
344
+ }
345
+ throw error;
346
+ }
347
+ }
348
+
349
+ // Run the example
350
+ main().catch((error) => {
351
+ console.error('Fatal error:', error);
352
+ process.exit(1);
353
+ });
354
+
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Create ZIP Example
5
+ *
6
+ * Demonstrates creating a ZIP archive from multiple files using ZipkitNode.
7
+ * This is a minimal example showing the basic API usage.
8
+ */
9
+
10
+ import ZipkitNode from '../src/node';
11
+ import type { CompressOptions } from '../src/core';
12
+ import * as fs from 'fs';
13
+ import * as path from 'path';
14
+
15
+ /**
16
+ * Helper function to format bytes
17
+ */
18
+ function formatBytes(bytes: number): string {
19
+ if (bytes === 0) return '0 B';
20
+ const k = 1024;
21
+ const sizes = ['B', 'KB', 'MB', 'GB'];
22
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
23
+ return (bytes / Math.pow(k, i)).toFixed(1) + ' ' + sizes[i];
24
+ }
25
+
26
+ /**
27
+ * Helper function to pad string to the right
28
+ */
29
+ function padRight(str: string, length: number): string {
30
+ return (str + ' '.repeat(length)).slice(0, length);
31
+ }
32
+
33
+ /**
34
+ * Helper function to pad string to the left
35
+ */
36
+ function padLeft(str: string, length: number): string {
37
+ return (' '.repeat(length) + str).slice(-length);
38
+ }
39
+
40
+ async function main() {
41
+ console.log('Creating ZIP archive example...\n');
42
+
43
+ // Test files to compress (located in test-files directory)
44
+ const testDir = path.join(__dirname, 'test-files');
45
+ const testFiles = [
46
+ path.join(testDir, 'file1.txt'),
47
+ path.join(testDir, 'file2.txt'),
48
+ path.join(testDir, 'document.md'),
49
+ path.join(testDir, 'data.json')
50
+ ];
51
+
52
+ // Verify all test files exist
53
+ for (const file of testFiles) {
54
+ if (!fs.existsSync(file)) {
55
+ console.error(`❌ Error: Test file not found: ${file}`);
56
+ console.error(' Make sure test-files directory contains the required files.');
57
+ process.exit(1);
58
+ }
59
+ }
60
+
61
+ console.log('Source files:');
62
+ testFiles.forEach(file => {
63
+ const stats = fs.statSync(file);
64
+ console.log(` - ${path.basename(file)} (${stats.size} bytes)`);
65
+ });
66
+ console.log();
67
+
68
+ // Create ZipkitNode instance
69
+ const zip = new ZipkitNode();
70
+
71
+ // Define output ZIP file path
72
+ const outputZip = path.join(__dirname, 'output', 'example.zip');
73
+
74
+ // Ensure output directory exists
75
+ const outputDir = path.dirname(outputZip);
76
+ if (!fs.existsSync(outputDir)) {
77
+ fs.mkdirSync(outputDir, { recursive: true });
78
+ }
79
+
80
+ // Compression options
81
+ const options: CompressOptions = {
82
+ level: 6, // Compression level (0-9, higher = better compression but slower)
83
+ useZstd: false, // Use Deflate compression (standard ZIP)
84
+ useSHA256: false // Don't calculate SHA-256 hashes (faster, but needed for blockchain features)
85
+ };
86
+
87
+ try {
88
+ console.log('Creating ZIP archive...');
89
+
90
+ // Method 1: Simple API - create ZIP from file paths
91
+ // This is the easiest way to create a ZIP file
92
+ await zip.createZipFromFiles(testFiles, outputZip, options);
93
+
94
+ console.log(`✅ ZIP archive created successfully: ${outputZip}\n`);
95
+
96
+ // Load the ZIP to get entry details
97
+ await zip.loadZipFile(outputZip);
98
+ const entries = zip.getDirectory();
99
+
100
+ // Display summary of compressed files
101
+ console.log('Compression Summary:');
102
+ console.log('─'.repeat(80));
103
+ console.log(
104
+ padRight('Filename', 30) +
105
+ padLeft('Original', 10) +
106
+ padLeft('Compressed', 12) +
107
+ padLeft('Ratio', 10) +
108
+ ' ' +
109
+ padRight('Method', 10)
110
+ );
111
+ console.log('─'.repeat(80));
112
+
113
+ let totalOriginal = 0;
114
+ let totalCompressed = 0;
115
+
116
+ entries.forEach((entry) => {
117
+ const filename = entry.filename || '(unnamed)';
118
+ const original = entry.uncompressedSize || 0;
119
+ const compressed = entry.compressedSize || 0;
120
+ const ratio = original > 0 ? ((1 - compressed / original) * 100).toFixed(1) : '0.0';
121
+ const method = entry.cmpMethodToString();
122
+
123
+ totalOriginal += original;
124
+ totalCompressed += compressed;
125
+
126
+ console.log(
127
+ padRight(filename.length > 28 ? filename.substring(0, 25) + '...' : filename, 30) +
128
+ padLeft(formatBytes(original), 10) +
129
+ padLeft(formatBytes(compressed), 12) +
130
+ padLeft(ratio + '%', 10) +
131
+ ' ' +
132
+ padRight(method, 10)
133
+ );
134
+ });
135
+
136
+ console.log('─'.repeat(80));
137
+ const totalRatio = totalOriginal > 0 ? ((1 - totalCompressed / totalOriginal) * 100).toFixed(1) : '0.0';
138
+ console.log(
139
+ padRight('Total', 30) +
140
+ padLeft(formatBytes(totalOriginal), 10) +
141
+ padLeft(formatBytes(totalCompressed), 12) +
142
+ padLeft(totalRatio + '%', 10) +
143
+ ' ' +
144
+ padRight('', 10)
145
+ );
146
+ console.log('─'.repeat(80));
147
+
148
+ // Verify the ZIP was created
149
+ if (fs.existsSync(outputZip)) {
150
+ const zipStats = fs.statSync(outputZip);
151
+ console.log(`\nArchive file size: ${formatBytes(zipStats.size)}`);
152
+ }
153
+
154
+ console.log('\n💡 Tip: You can also use addFileToZip() for more control:');
155
+ console.log(' const zip = new ZipkitNode();');
156
+ console.log(' await zip.addFileToZip("file.txt", "file.txt", options);');
157
+ console.log(' // ... add more files ...');
158
+ console.log(' // Then manually write ZIP structure');
159
+
160
+ } catch (error) {
161
+ console.error('❌ Error creating ZIP archive:');
162
+ console.error(error instanceof Error ? error.message : String(error));
163
+ process.exit(1);
164
+ }
165
+ }
166
+
167
+ // Run the example
168
+ main().catch((error) => {
169
+ console.error('Fatal error:', error);
170
+ process.exit(1);
171
+ });
172
+
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Extract ZIP Example
5
+ *
6
+ * Demonstrates extracting files from a ZIP archive using ZipkitNode.
7
+ * This is a minimal example showing the basic extraction API.
8
+ */
9
+
10
+ import ZipkitNode from '../src/node';
11
+ import { crc32 } from '../src/core/encryption/ZipCrypto';
12
+ import * as fs from 'fs';
13
+ import * as path from 'path';
14
+
15
+ async function main() {
16
+ console.log('Extracting ZIP archive example...\n');
17
+
18
+ // Example: Use the ZIP file created by create-zip.ts
19
+ // You can also specify your own ZIP file path here
20
+ const archivePath = path.join(__dirname, 'output', 'example.zip');
21
+ const destination = path.join(__dirname, 'extracted');
22
+
23
+ // Check if ZIP file exists
24
+ if (!fs.existsSync(archivePath)) {
25
+ console.error(`❌ ZIP file not found: ${archivePath}`);
26
+ console.error('💡 Tip: Run create-zip.ts first to create a test ZIP file,');
27
+ console.error(' or modify archivePath to point to your own ZIP file.');
28
+ process.exit(1);
29
+ }
30
+
31
+ console.log(`Archive: ${archivePath}`);
32
+ console.log(`Destination: ${destination}\n`);
33
+
34
+ // Create ZipkitNode instance
35
+ const zip = new ZipkitNode();
36
+
37
+ try {
38
+ // Method 1: Simple API - extract entire ZIP to directory
39
+ // This is the easiest way to extract a ZIP file
40
+ console.log('Loading ZIP file...');
41
+ await zip.loadZipFile(archivePath);
42
+
43
+ // Get directory listing to show what will be extracted
44
+ const entries = zip.getDirectory();
45
+ console.log(`Found ${entries.length} file(s) in archive:\n`);
46
+
47
+ entries.forEach((entry, index) => {
48
+ const size = entry.uncompressedSize || 0;
49
+ const compressed = entry.compressedSize || 0;
50
+ const method = entry.cmpMethodToString();
51
+ console.log(` ${index + 1}. ${entry.filename}`);
52
+ console.log(` Size: ${size} bytes (compressed: ${compressed} bytes, ${method})`);
53
+ });
54
+ console.log();
55
+
56
+ // Extract all files to destination directory
57
+ console.log('Extracting files...');
58
+ const result = await zip.extractZipFile(archivePath, destination, {
59
+ overwrite: true, // Overwrite existing files
60
+ preserveTimestamps: true, // Preserve file timestamps
61
+ skipHashCheck: false // Verify file integrity (CRC/SHA checks)
62
+ });
63
+
64
+ console.log(`✅ Extraction completed successfully!`);
65
+ console.log(` Files extracted: ${result.filesExtracted}`);
66
+ console.log(` Total bytes: ${result.bytesExtracted}`);
67
+
68
+ // Verify CRC-32 for each extracted file
69
+ console.log('\nCRC-32 Verification:');
70
+ const extractedFiles = getAllFiles(destination);
71
+ let allCrcMatch = true;
72
+
73
+ // Create a map of filename to entry for quick lookup
74
+ const entryMap = new Map<string, typeof entries[0]>();
75
+ entries.forEach(entry => {
76
+ const filename = path.basename(entry.filename);
77
+ entryMap.set(filename, entry);
78
+ });
79
+
80
+ extractedFiles.forEach(file => {
81
+ const relativePath = path.relative(destination, file);
82
+ const filename = path.basename(file);
83
+ const stats = fs.statSync(file);
84
+ const entry = entryMap.get(filename);
85
+
86
+ if (entry) {
87
+ const storedCrc = entry.crc || 0;
88
+ const storedCrcHex = `0x${storedCrc.toString(16).padStart(8, '0').toUpperCase()}`;
89
+
90
+ // Calculate CRC-32 of extracted file
91
+ const fileData = fs.readFileSync(file);
92
+ const calculatedCrc = crc32(fileData);
93
+ const calculatedCrcHex = `0x${calculatedCrc.toString(16).padStart(8, '0').toUpperCase()}`;
94
+
95
+ // Compare CRC-32 values
96
+ const crcMatch = storedCrc === calculatedCrc;
97
+ const status = crcMatch ? '✓' : '✗';
98
+ const statusText = crcMatch ? 'PASS' : 'FAILED';
99
+
100
+ if (!crcMatch) {
101
+ allCrcMatch = false;
102
+ }
103
+
104
+ console.log(` ${filename}:`);
105
+ console.log(` Stored CRC-32: ${storedCrcHex}`);
106
+ console.log(` Calculated CRC-32: ${calculatedCrcHex}`);
107
+ console.log(` Status: ${status} ${statusText}`);
108
+ } else {
109
+ console.log(` ${filename}: Entry not found in ZIP`);
110
+ }
111
+ });
112
+
113
+ if (allCrcMatch) {
114
+ console.log('\n✅ All CRC-32 checks passed!');
115
+ } else {
116
+ console.log('\n❌ Some CRC-32 checks failed!');
117
+ }
118
+
119
+ console.log('\n💡 Tip: You can also extract individual entries:');
120
+ console.log(' await zip.loadZipFile("archive.zip");');
121
+ console.log(' const entries = zip.getDirectory();');
122
+ console.log(' await zip.extractToFile(entries[0], "output.txt");');
123
+
124
+ } catch (error) {
125
+ console.error('❌ Error extracting ZIP archive:');
126
+ console.error(error instanceof Error ? error.message : String(error));
127
+ if (error instanceof Error && error.stack) {
128
+ console.error('\nStack trace:');
129
+ console.error(error.stack);
130
+ }
131
+ process.exit(1);
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Helper function to recursively get all files in a directory
137
+ */
138
+ function getAllFiles(dirPath: string, arrayOfFiles: string[] = []): string[] {
139
+ const files = fs.readdirSync(dirPath);
140
+
141
+ files.forEach((file) => {
142
+ const filePath = path.join(dirPath, file);
143
+ if (fs.statSync(filePath).isDirectory()) {
144
+ arrayOfFiles = getAllFiles(filePath, arrayOfFiles);
145
+ } else {
146
+ arrayOfFiles.push(filePath);
147
+ }
148
+ });
149
+
150
+ return arrayOfFiles;
151
+ }
152
+
153
+ // Run the example
154
+ main().catch((error) => {
155
+ console.error('Fatal error:', error);
156
+ process.exit(1);
157
+ });
158
+