neozipkit 0.1.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 (330) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +371 -200
  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 +256 -0
  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/{browser → blockchain/browser}/TokenVerifierBrowser.d.ts +11 -20
  20. package/dist/blockchain/browser/TokenVerifierBrowser.d.ts.map +1 -0
  21. package/dist/{browser → blockchain/browser}/TokenVerifierBrowser.js +106 -92
  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/{server/blockchain/WalletAnalyzer.d.ts → blockchain/core/WalletManager.d.ts} +69 -26
  36. package/dist/blockchain/core/WalletManager.d.ts.map +1 -0
  37. package/dist/{server/blockchain/WalletAnalyzer.js → blockchain/core/WalletManager.js} +172 -160
  38. package/dist/blockchain/core/WalletManager.js.map +1 -0
  39. package/dist/blockchain/core/ZipkitMinter.d.ts +141 -0
  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/core/ZipkitOTS.d.ts +126 -0
  44. package/dist/blockchain/core/ZipkitOTS.d.ts.map +1 -0
  45. package/dist/blockchain/core/ZipkitOTS.js +506 -0
  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 -0
  60. package/dist/blockchain/index.d.ts.map +1 -0
  61. package/dist/blockchain/index.js +34 -0
  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 -17
  87. package/dist/browser.js +13 -29
  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 +224 -81
  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/{shared → core}/version.d.ts +1 -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 -25
  157. package/dist/index.d.ts.map +1 -0
  158. package/dist/index.js +29 -47
  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 +6 -3
  192. package/examples/verify-tokenized-zip.ts +305 -0
  193. package/package.json +117 -23
  194. package/src/blockchain/README.md +222 -0
  195. package/src/{browser → blockchain/browser}/TokenVerifierBrowser.ts +125 -79
  196. package/src/blockchain/browser/WalletManagerBrowser.ts +486 -0
  197. package/src/blockchain/browser/ZipkitMinterBrowser.ts +400 -0
  198. package/src/blockchain/browser/index.ts +13 -0
  199. package/src/blockchain/core/WalletManager.ts +436 -0
  200. package/src/blockchain/core/ZipkitMinter.ts +716 -0
  201. package/src/blockchain/core/ZipkitOTS.ts +588 -0
  202. package/src/blockchain/core/ZipkitVerifier.ts +853 -0
  203. package/src/blockchain/core/contracts.ts +370 -0
  204. package/src/blockchain/core/index.ts +71 -0
  205. package/src/blockchain/index.ts +27 -0
  206. package/src/blockchain/node/WalletManagerNode.ts +171 -0
  207. package/src/blockchain/node/index.ts +40 -0
  208. package/src/browser/{ZipKitBrowser.ts → ZipkitBrowser.ts} +104 -41
  209. package/src/browser/index.esm.ts +37 -0
  210. package/src/browser/index.ts +25 -0
  211. package/src/core/ZipCompress.ts +398 -0
  212. package/src/core/ZipDecompress.ts +212 -0
  213. package/src/{shared → core}/ZipEntry.ts +239 -89
  214. package/src/core/Zipkit.ts +794 -0
  215. package/src/core/components/HashCalculator.ts +384 -0
  216. package/src/core/components/Logger.ts +180 -0
  217. package/src/core/components/ProgressTracker.ts +134 -0
  218. package/src/{shared → core}/components/Util.ts +12 -34
  219. package/src/{shared → core}/constants/Errors.ts +0 -4
  220. package/src/{shared → core}/constants/Headers.ts +19 -17
  221. package/src/core/encryption/Manager.ts +137 -0
  222. package/src/core/encryption/ZipCrypto.ts +650 -0
  223. package/src/core/encryption/index.ts +15 -0
  224. package/src/core/encryption/types.ts +33 -0
  225. package/src/core/index.ts +34 -0
  226. package/src/core/version.ts +33 -0
  227. package/src/index.ts +54 -32
  228. package/src/node/ZipCompressNode.ts +632 -0
  229. package/src/node/ZipDecompressNode.ts +508 -0
  230. package/src/node/ZipkitNode.ts +1559 -0
  231. package/src/node/index.ts +69 -0
  232. package/src/types/index.ts +131 -1
  233. package/src/types/opentimestamps.d.ts +1 -23
  234. package/contracts/Lock.sol +0 -34
  235. package/contracts/bytecode.txt +0 -1
  236. package/contracts/compile-contract.js +0 -168
  237. package/contracts/deploy/deploy-both-contracts.js +0 -286
  238. package/contracts/deploy/deploy-enhanced-contract.js +0 -197
  239. package/contracts/deploy/deploy-private-contract.js +0 -190
  240. package/contracts/deploy/deploy-public-clean.js +0 -1063
  241. package/contracts/deploy/deploy-public-contract.js +0 -1107
  242. package/contracts/deployment.config.example.js +0 -25
  243. package/contracts/remix-compile.js +0 -222
  244. package/contracts/setup-deployment.js +0 -51
  245. package/contracts/src/ZipFileNFT-DEPRECATED-6field.sol +0 -260
  246. package/contracts/src/ZipFileNFT-DEPRECATED-Enhanced.sol +0 -289
  247. package/dist/browser/CertificateGeneratorBrowser.d.ts +0 -75
  248. package/dist/browser/CertificateGeneratorBrowser.js +0 -433
  249. package/dist/browser/ZipKitBrowser.d.ts +0 -18
  250. package/dist/browser/ZipKitStampBrowser.d.ts +0 -2
  251. package/dist/browser/ZipKitStampBrowser.js +0 -12
  252. package/dist/browser-index.d.ts +0 -21
  253. package/dist/browser-index.js +0 -58
  254. package/dist/server/blockchain/CertificateToken.d.ts +0 -48
  255. package/dist/server/blockchain/CertificateToken.js +0 -386
  256. package/dist/server/blockchain/NFTMinter.d.ts +0 -41
  257. package/dist/server/blockchain/NFTMinter.js +0 -323
  258. package/dist/server/blockchain/TokenQuerier.d.ts +0 -31
  259. package/dist/server/blockchain/TokenQuerier.js +0 -259
  260. package/dist/server/blockchain/TokenVerifier.d.ts +0 -20
  261. package/dist/server/blockchain/TokenVerifier.js +0 -395
  262. package/dist/server/blockchain/WalletFormatter.d.ts +0 -39
  263. package/dist/server/blockchain/WalletFormatter.js +0 -196
  264. package/dist/server/blockchain/WalletManager.d.ts +0 -46
  265. package/dist/server/blockchain/WalletManager.js +0 -294
  266. package/dist/server/blockchain/ZipMetadata.d.ts +0 -27
  267. package/dist/server/blockchain/ZipMetadata.js +0 -131
  268. package/dist/server/blockchain/ZipTokenProcessor.d.ts +0 -44
  269. package/dist/server/blockchain/ZipTokenProcessor.js +0 -204
  270. package/dist/server/blockchain/constants.d.ts +0 -102
  271. package/dist/server/blockchain/constants.js +0 -968
  272. package/dist/server/blockchain/index.d.ts +0 -9
  273. package/dist/server/blockchain/index.js +0 -44
  274. package/dist/server/blockchain/test-certificate.d.ts +0 -8
  275. package/dist/server/blockchain/test-certificate.js +0 -100
  276. package/dist/server/blockchain/types.d.ts +0 -69
  277. package/dist/server/blockchain/types.js +0 -51
  278. package/dist/server/platform/server/ZipKitServer.d.ts +0 -105
  279. package/dist/server/platform/server/ZipKitServer.js +0 -437
  280. package/dist/server/platform/servercomponents/ZipKitOTS.d.ts +0 -91
  281. package/dist/server/platform/servercomponents/ZipKitOTS.js +0 -271
  282. package/dist/shared/ZipKit.d.ts +0 -249
  283. package/dist/shared/ZipKit.js +0 -789
  284. package/dist/shared/components/CertificateOTS.d.ts +0 -15
  285. package/dist/shared/components/CertificateOTS.js +0 -116
  286. package/dist/shared/components/FileSys.d.ts +0 -2
  287. package/dist/shared/components/FileSys.js +0 -113
  288. package/dist/shared/components/HashAccumulator.d.ts +0 -55
  289. package/dist/shared/components/HashAccumulator.js +0 -100
  290. package/dist/shared/components/ZipCrypto.d.ts +0 -3
  291. package/dist/shared/components/ZipCrypto.js +0 -78
  292. package/dist/shared/components/merkleTree.d.ts +0 -66
  293. package/dist/shared/components/merkleTree.js +0 -136
  294. package/dist/shared/types/index.d.ts +0 -21
  295. package/dist/shared/types/index.js +0 -3
  296. package/dist/shared/types.d.ts +0 -33
  297. package/dist/shared/types.js +0 -8
  298. package/dist/shared/version.js +0 -7
  299. package/src/browser/CertificateGeneratorBrowser.ts +0 -498
  300. package/src/browser/ZipKitStampBrowser.ts +0 -9
  301. package/src/browser-index.ts +0 -36
  302. package/src/server/blockchain/CertificateToken.ts +0 -444
  303. package/src/server/blockchain/NFTMinter.ts +0 -357
  304. package/src/server/blockchain/TokenQuerier.ts +0 -287
  305. package/src/server/blockchain/TokenVerifier.ts +0 -453
  306. package/src/server/blockchain/WalletAnalyzer.ts +0 -397
  307. package/src/server/blockchain/WalletFormatter.ts +0 -206
  308. package/src/server/blockchain/WalletManager.ts +0 -294
  309. package/src/server/blockchain/ZipMetadata.ts +0 -117
  310. package/src/server/blockchain/ZipTokenProcessor.ts +0 -234
  311. package/src/server/blockchain/constants.ts +0 -969
  312. package/src/server/blockchain/index.ts +0 -42
  313. package/src/server/blockchain/test-certificate.ts +0 -137
  314. package/src/server/blockchain/types.ts +0 -134
  315. package/src/server/platform/server/ZipKitServer.ts +0 -459
  316. package/src/server/platform/servercomponents/ZipKitOTS.ts +0 -313
  317. package/src/server/platform/servercomponents/opentimestamps.d.ts +0 -23
  318. package/src/shared/ZipKit.ts +0 -899
  319. package/src/shared/components/CertificateOTS.ts +0 -132
  320. package/src/shared/components/FileSys.ts +0 -87
  321. package/src/shared/components/HashAccumulator.ts +0 -113
  322. package/src/shared/components/ZipCrypto.ts +0 -91
  323. package/src/shared/components/merkleTree.ts +0 -162
  324. package/src/shared/types/index.ts +0 -25
  325. package/src/shared/types/modules.d.ts +0 -22
  326. package/src/shared/types/opentimestamps.d.ts +0 -23
  327. package/src/shared/types.d.ts +0 -8
  328. package/src/shared/types.ts +0 -43
  329. package/src/shared/version.ts +0 -4
  330. /package/src/{shared → core}/components/Support.ts +0 -0
@@ -0,0 +1,588 @@
1
+ /**
2
+ * ======================================
3
+ * ZipkitOTS.ts - OpenTimestamps Integration
4
+ * ======================================
5
+ *
6
+ * This module provides comprehensive OpenTimestamps (OTS) functionality for ZIP files,
7
+ * including timestamp creation, verification, certificate generation, and proof upgrades.
8
+ *
9
+ * Key Features:
10
+ * - Bitcoin blockchain timestamping via OpenTimestamps
11
+ * - Merkle root calculation and verification
12
+ * - OTS proof upgrade capabilities
13
+ * - Certificate generation for verified timestamps
14
+ * - Integration with ZIP file metadata
15
+ *
16
+ * @fileoverview OpenTimestamps utilities for blockchain-enabled ZIP files
17
+ * @author NeoWare Inc.
18
+ */
19
+ "use server";
20
+ "use strict";
21
+
22
+ // ===== Imports =====
23
+ import moment from 'moment-timezone';
24
+ import Zipkit from '../../core';
25
+ import { TIMESTAMP_METADATA, TIMESTAMP_SUBMITTED, CMP_METHOD } from '../../core/constants/Headers';
26
+ import { crc32 } from '../../core/encryption/ZipCrypto';
27
+
28
+ // Platform detection
29
+ const isNode = typeof process !== 'undefined' && process.versions && process.versions.node;
30
+
31
+ // Node.js specific imports
32
+ let fs: any = null;
33
+ if (isNode) {
34
+ fs = require('fs');
35
+ }
36
+
37
+ // Type declaration for opentimestamps module
38
+ // @ts-ignore
39
+
40
+ // Some environments inject a global bitcore object which interferes with
41
+ // OpenTimestamps. Clearing it avoids runtime errors when importing the module.
42
+ declare global {
43
+ var _bitcore: any;
44
+ }
45
+ if ((globalThis as any)._bitcore) delete (globalThis as any)._bitcore;
46
+
47
+ let OTSInstance: any = null;
48
+
49
+ /**
50
+ * Lazily loads the OpenTimestamps module to avoid import conflicts.
51
+ * @returns Promise resolving to OpenTimestamps module instance
52
+ */
53
+ async function getOpenTimestamps() {
54
+ if (!OTSInstance) {
55
+ // @ts-ignore
56
+ OTSInstance = (await import('opentimestamps')).default;
57
+ }
58
+ return OTSInstance;
59
+ }
60
+
61
+ /**
62
+ * Executes a function with OpenTimestamps logging control.
63
+ * @param debug - If true, keeps logging enabled; if false, suppresses console output
64
+ * @param fn - Function to execute with controlled logging
65
+ * @returns Promise resolving to function result
66
+ */
67
+ async function withOtsLogging<T>(debug: boolean | undefined, fn: () => Promise<T>): Promise<T> {
68
+ if (debug) return fn();
69
+ const originalLog = console.log;
70
+ const originalDebug = console.debug;
71
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
72
+ console.log = () => {};
73
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
74
+ console.debug = () => {};
75
+ try {
76
+ return await fn();
77
+ } finally {
78
+ console.log = originalLog;
79
+ console.debug = originalDebug;
80
+ }
81
+ }
82
+
83
+ // ===== Types & Interfaces =====
84
+ export interface TimestampResult {
85
+ merkleRoot: string | null;
86
+ ots: ArrayBuffer | null;
87
+ verified: boolean;
88
+ results: any | null;
89
+ error: string | null;
90
+ attestations: any | null;
91
+ upgradedOts: ArrayBuffer | null;
92
+ }
93
+
94
+ export interface TimestampInfo {
95
+ message: string;
96
+ results: string[];
97
+ attestDate: Date | null;
98
+ attestHeight: number | null;
99
+ submittedUri: string | null;
100
+ otsUpgraded: boolean;
101
+ }
102
+
103
+ export interface DeserializeOtsResult {
104
+ attestStr: string | null;
105
+ needsUpdateMsg: string | null;
106
+ attestationValues: any[];
107
+ }
108
+
109
+ export interface OtsVerifyResult {
110
+ status: 'none' | 'valid' | 'pending' | 'error';
111
+ message?: string;
112
+ blockHeight?: number;
113
+ attestedAt?: Date;
114
+ upgraded?: boolean;
115
+ upgradedOts?: Buffer;
116
+ }
117
+
118
+ /**
119
+ * Verifies an OpenTimestamps proof against a hash digest.
120
+ * @param hashDigest - SHA256 hash as hex string to verify
121
+ * @param ots - OpenTimestamps proof data
122
+ * @param options - Configuration options
123
+ * @param options.debug - Enable debug logging
124
+ * @returns Promise resolving to verification result, error object, or null if inputs invalid
125
+ */
126
+ export async function verifyOts(
127
+ hashDigest: string | null,
128
+ ots: ArrayBuffer | null,
129
+ options?: { debug?: boolean },
130
+ ): Promise<TimestampResult | { error: string } | null> {
131
+ if (!hashDigest || !ots) return null;
132
+
133
+ const tsResult: TimestampResult = {
134
+ merkleRoot: hashDigest,
135
+ ots,
136
+ verified: false,
137
+ results: null,
138
+ error: null,
139
+ attestations: null,
140
+ upgradedOts: null,
141
+ };
142
+
143
+ try {
144
+ return await withOtsLogging(options?.debug, async () => {
145
+ const OpenTimestamps = await getOpenTimestamps();
146
+ const _otsBuffer = Buffer.from(ots);
147
+ const detachedOts = OpenTimestamps.DetachedTimestampFile.deserialize(_otsBuffer);
148
+
149
+ const digest = Buffer.from(hashDigest!, 'hex');
150
+ const hashOts = OpenTimestamps.DetachedTimestampFile.fromHash(
151
+ new OpenTimestamps.Ops.OpSHA256(),
152
+ digest
153
+ );
154
+
155
+ const upgrade = await OpenTimestamps.upgrade(detachedOts);
156
+ if (upgrade) {
157
+ console.log('verifyOts === Timestamp should be upgraded!');
158
+ tsResult.upgradedOts = detachedOts.serializeToBytes();
159
+ }
160
+
161
+ tsResult.results = await OpenTimestamps.verify(detachedOts, hashOts, {
162
+ ignoreBitcoinNode: true,
163
+ timeout: 5000,
164
+ });
165
+
166
+ const _attest: any[] = [];
167
+ detachedOts.timestamp.allAttestations().forEach((attestation: any) => {
168
+ if (!(attestation instanceof OpenTimestamps.Notary.UnknownAttestation)) {
169
+ _attest.push(attestation);
170
+ }
171
+ });
172
+ tsResult.attestations = JSON.stringify(_attest);
173
+
174
+ tsResult.verified = !!tsResult.results && Object.keys(tsResult.results).length > 0;
175
+ if (!tsResult.verified) tsResult.results = null;
176
+
177
+ console.log('verifyOts === tsResult: ', tsResult);
178
+ return tsResult;
179
+ });
180
+ } catch (error: any) {
181
+ let errMsg = error?.message || 'Timestamp Verification Failed!';
182
+ if (errMsg.includes('ESOCKETTIMEDOUT')) errMsg = 'Server timed out, Try again in a few minutes.';
183
+ else if (errMsg.includes('502')) errMsg = 'Server failed to respond, Try again in a few minutes.';
184
+ else if (errMsg.includes('ECONNRESET')) errMsg = 'Server connection reset, Try again in a few minutes.';
185
+ return { error: errMsg };
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Converts a Node.js Buffer to an ArrayBuffer.
191
+ * @param buf - Buffer to convert
192
+ * @returns ArrayBuffer with same data
193
+ */
194
+ export function bufferToArrayBuffer(buf: Buffer): ArrayBuffer {
195
+ const ab = new ArrayBuffer(buf.byteLength);
196
+ const view = new Uint8Array(ab);
197
+ view.set(buf);
198
+ return ab;
199
+ }
200
+
201
+ /**
202
+ * Finds the OpenTimestamps entry in a ZIP file.
203
+ * Searches for TIMESTAMP_METADATA first, then TIMESTAMP_SUBMITTED.
204
+ * @param zip - Zipkit instance to search
205
+ * @returns ZIP entry containing OTS proof, or null if not found
206
+ */
207
+ export function getOtsEntry(zip: any): any | null {
208
+ try {
209
+ // Include metadata entries in the directory
210
+ const entries = zip.getDirectory?.(true) || [];
211
+
212
+ // Prefer upgraded metadata entry first
213
+ let entry = entries.find((e: any) => e && e.filename === TIMESTAMP_METADATA);
214
+ if (entry) return entry;
215
+
216
+ // Fallback to submitted proof entry
217
+ entry = entries.find((e: any) => e && e.filename === TIMESTAMP_SUBMITTED);
218
+ if (entry) return entry;
219
+ } catch {
220
+ return null;
221
+ }
222
+ }
223
+
224
+ /**
225
+ * Extracts OTS proof data from a ZIP entry.
226
+ * @param zip - Zipkit instance
227
+ * @param otsEntry - ZIP entry containing OTS data
228
+ * @returns Promise resolving to OTS proof buffer, or null if extraction fails
229
+ */
230
+ export async function getOtsBuffer(zip: any, otsEntry: any): Promise<Buffer | null> {
231
+ try {
232
+ const data = await zip.extract(otsEntry, true);
233
+ return Buffer.isBuffer(data) ? (data as Buffer) : null;
234
+ } catch {
235
+ return null;
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Safely extracts merkle root from a ZIP file.
241
+ * @param zip - Zipkit instance
242
+ * @returns Merkle root hash string, or null if not available
243
+ */
244
+ export function getMerkleRootSafe(zip: any): string | null {
245
+ try {
246
+ const mr = zip.getMerkleRoot?.();
247
+ return (typeof mr === 'string' && mr.length > 0) ? mr : null;
248
+ } catch {
249
+ return null;
250
+ }
251
+ }
252
+
253
+ /**
254
+ * Converts various date formats to a Date object.
255
+ * @param val - Date value (number timestamp, string, or Date)
256
+ * @returns Date object or undefined if invalid
257
+ */
258
+ function coerceDate(val: any): Date | undefined {
259
+ if (!val) return undefined;
260
+ if (typeof val === 'number') return new Date(val * (val > 10_000_000_000 ? 1 : 1000));
261
+ if (typeof val === 'string') return new Date(val);
262
+ return undefined;
263
+ }
264
+
265
+ /**
266
+ * Verifies OpenTimestamps proof within a ZIP file.
267
+ * Extracts merkle root and OTS proof, then verifies against Bitcoin blockchain.
268
+ * @param zip - Zipkit instance containing files and OTS proof
269
+ * @returns Promise resolving to verification result with status: 'none', 'error', 'pending', or 'valid'
270
+ */
271
+ export async function verifyOtsZip(zip: any): Promise<OtsVerifyResult> {
272
+ const mr = getMerkleRootSafe(zip);
273
+ const entry = getOtsEntry(zip);
274
+ if (!entry) return { status: 'none' };
275
+ const otsBuf = await getOtsBuffer(zip, entry);
276
+ if (!otsBuf || !mr) return { status: 'error' };
277
+ try {
278
+ const result: any = await (verifyOts as any)(mr, bufferToArrayBuffer(otsBuf));
279
+ if (result?.verified === true) {
280
+ const bitcoin = result?.results?.bitcoin || {};
281
+ const blockHeight: number | undefined = result.blockHeight ?? result.block ?? result.height ?? bitcoin.height;
282
+ const attestedAt: Date | undefined = coerceDate(result.attestedAt ?? result.attested ?? result.time ?? bitcoin.timestamp);
283
+ const upgraded: boolean | undefined = Boolean(result.upgraded || result.upgradedOts);
284
+ const upgradedOts: Buffer | undefined = result.upgradedOts ? Buffer.from(result.upgradedOts) : undefined;
285
+ return { status: 'valid', blockHeight, attestedAt, upgraded, upgradedOts };
286
+ }
287
+ return { status: 'pending' };
288
+ } catch (e: any) {
289
+ return { status: 'pending', message: e?.message };
290
+ }
291
+ }
292
+
293
+ /**
294
+ * Creates an OpenTimestamps proof for a hash digest.
295
+ * Submits hash to OpenTimestamps servers for Bitcoin blockchain anchoring.
296
+ * @param hashDigest - SHA256 hash as hex string to timestamp
297
+ * @param options - Configuration options
298
+ * @param options.debug - Enable debug logging
299
+ * @returns Promise resolving to OTS proof buffer, or null if creation failed
300
+ */
301
+ export async function createTimestamp(hashDigest: string | null, options?: { debug?: boolean }): Promise<Buffer | null> {
302
+ if (!hashDigest) return null;
303
+ try {
304
+ return await withOtsLogging(options?.debug, async () => {
305
+ const OpenTimestamps = await getOpenTimestamps();
306
+ const hashBuffer = Buffer.from(hashDigest, 'hex');
307
+ const detached = OpenTimestamps.DetachedTimestampFile.fromHash(
308
+ new OpenTimestamps.Ops.OpSHA256(),
309
+ hashBuffer
310
+ );
311
+ await OpenTimestamps.stamp(detached);
312
+ return Buffer.from(detached.serializeToBytes());
313
+ });
314
+ } catch (error) {
315
+ console.error('Error creating timestamp:', error);
316
+ throw new Error('Error creating timestamp');
317
+ }
318
+ }
319
+
320
+ /**
321
+ * Deserializes OpenTimestamps verification result into JSON format.
322
+ * Extracts blockchain attestation data and transaction details.
323
+ * @param tsResult - Timestamp verification result to deserialize
324
+ * @param options - Configuration options
325
+ * @param options.debug - Enable debug logging
326
+ * @returns Promise resolving to JSON string with attestation data, or null if failed
327
+ */
328
+ export async function deserializeOts(
329
+ tsResult: TimestampResult,
330
+ options?: { debug?: boolean },
331
+ ): Promise<string | null> {
332
+ let result: DeserializeOtsResult = {
333
+ attestStr: null,
334
+ needsUpdateMsg: null,
335
+ attestationValues: [],
336
+ };
337
+
338
+ for (const chain in tsResult.results) {
339
+ const _results = tsResult.results[chain];
340
+ const _attestDate = moment(_results.timestamp * 1000).tz(moment.tz.guess()).format('MM-DD-YYYY hh:mma z');
341
+ const blockchain = chain.charAt(0).toUpperCase() + chain.slice(1);
342
+ result.attestStr = `<b>${blockchain} block ${_results.height}</b> attests existence as of <b>${_attestDate}</b>`;
343
+ }
344
+
345
+ let timestamp = tsResult.ots;
346
+ if (tsResult.upgradedOts != null) {
347
+ result.needsUpdateMsg = 'This Zip file requires updated Timestamp Metadata!';
348
+ timestamp = tsResult.upgradedOts;
349
+ }
350
+
351
+ if (!timestamp) return null;
352
+ const infoResult = await withOtsLogging(options?.debug, async () => {
353
+ const OpenTimestamps = await getOpenTimestamps();
354
+ const detached = OpenTimestamps.DetachedTimestampFile.deserialize(Buffer.from(timestamp));
355
+ return OpenTimestamps.info(detached);
356
+ });
357
+
358
+ const transactionIdMatches = [...infoResult.matchAll(/transaction id ([a-f0-9]+)/gi)];
359
+ const transactionIds = transactionIdMatches.map((m) => m[1]);
360
+
361
+ const blockHeightMatches = [...infoResult.matchAll(/verify BitcoinBlockHeaderAttestation\((\d+)\)/g)];
362
+ const blockHeights = blockHeightMatches.map((m) => m[1]);
363
+
364
+ const merkleRootMatches = [...infoResult.matchAll(/block merkle root ([a-f0-9]+)/gi)];
365
+ const merkleRoots = merkleRootMatches.map((m) => m[1]);
366
+
367
+ result.attestationValues = [];
368
+ if (transactionIds.length === blockHeights.length && transactionIds.length === merkleRoots.length) {
369
+ for (let i = 0; i < transactionIds.length; i++) {
370
+ result.attestationValues.push({
371
+ blockHeight: blockHeights[i],
372
+ transactionId: transactionIds[i],
373
+ merkleRoot: merkleRoots[i],
374
+ });
375
+ }
376
+ result.attestationValues.sort((a, b) => a.blockHeight - b.blockHeight);
377
+ }
378
+
379
+ return JSON.stringify(result);
380
+ }
381
+
382
+ /**
383
+ * Parses timestamp verification result into readable information.
384
+ * Formats blockchain attestation data with human-readable messages and dates.
385
+ * @param verifyResult - Timestamp verification result to parse
386
+ * @returns Promise resolving to formatted timestamp information
387
+ */
388
+ export async function parseVerifyResult(verifyResult: TimestampResult): Promise<TimestampInfo> {
389
+ let tsInfo: TimestampInfo = {
390
+ message: '',
391
+ results: [],
392
+ attestDate: null,
393
+ attestHeight: null,
394
+ submittedUri: null,
395
+ otsUpgraded: false,
396
+ };
397
+
398
+ for (const chain in verifyResult?.results) {
399
+ const _results = verifyResult.results[chain];
400
+ const _date = moment(_results.timestamp * 1000).tz('UTC').format('MM-DD-YYYY hh:mma z');
401
+ const _blockchain = chain.charAt(0).toUpperCase() + chain.slice(1);
402
+ tsInfo.message = `Validated - ${_blockchain} block ${_results.height} attests existence as of ${_date}`;
403
+ if (tsInfo.attestHeight == null) {
404
+ tsInfo.attestDate = new Date(_results.timestamp * 1000);
405
+ tsInfo.attestHeight = _results.height;
406
+ }
407
+ tsInfo.results.push(tsInfo.message);
408
+ }
409
+
410
+ if (verifyResult?.upgradedOts) {
411
+ tsInfo.otsUpgraded = true;
412
+ tsInfo.results.push('Notice: Please select "Upgrade Timestamp" to save the upgraded timestamp.');
413
+ }
414
+ return tsInfo;
415
+ }
416
+
417
+ /**
418
+ * Upgrades OpenTimestamps proof in an existing ZIP file.
419
+ * Replaces old timestamp metadata with upgraded OTS proof data.
420
+ * @param zipFilePath - Path to ZIP file to upgrade
421
+ * @param upgradedOts - Buffer containing upgraded OTS proof
422
+ * @returns Promise that resolves when upgrade is complete
423
+ * @throws Error if upgrade fails
424
+ */
425
+ export async function upgradeOTS(zipFilePath: string, upgradedOts: Buffer): Promise<void> {
426
+ if (!fs) {
427
+ throw new Error('upgradeOTS() is only available in Node.js environment');
428
+ }
429
+
430
+ if (!fs.existsSync(zipFilePath)) {
431
+ throw new Error(`Zip file not found: ${zipFilePath}`);
432
+ }
433
+
434
+ if (!upgradedOts || upgradedOts.length === 0) {
435
+ throw new Error('Invalid upgraded OTS data provided');
436
+ }
437
+
438
+ // Create a temporary file for the upgrade process
439
+ const tempPath = `${zipFilePath}.upgrading.${Date.now()}.${process.pid}`;
440
+
441
+ try {
442
+ // Load the existing zip file
443
+ const zipKit = new Zipkit();
444
+ const zipData = fs.readFileSync(zipFilePath);
445
+ zipKit.loadZip(zipData);
446
+ const zipEntries = zipKit.getDirectory(false) || [];
447
+
448
+ if (!zipEntries || zipEntries.length === 0) {
449
+ throw new Error('No entries found in zip file or file is corrupted');
450
+ }
451
+
452
+ // Prepare buffers for the new zip file
453
+ const buffers: Buffer[] = [];
454
+ let offset = 0;
455
+ const keptEntries: any[] = [];
456
+
457
+ // Process existing entries, excluding old timestamp entries
458
+ for (const entry of zipEntries) {
459
+ if (entry.filename === TIMESTAMP_METADATA ||
460
+ entry.filename === TIMESTAMP_SUBMITTED) {
461
+ // Skip old timestamp entries - they will be replaced
462
+ continue;
463
+ }
464
+
465
+ // Copy the entry data
466
+ const entryData = await zipKit.copyEntry(entry);
467
+ if (!entryData) {
468
+ throw new Error(`Failed to copy entry data for: ${entry.filename}`);
469
+ }
470
+
471
+ // Update the entry's local header offset
472
+ entry.localHdrOffset = offset;
473
+ offset += entryData.length;
474
+
475
+ buffers.push(entryData);
476
+ keptEntries.push(entry);
477
+ }
478
+
479
+ // Create the new upgraded timestamp entry with standard filename
480
+ const tsEntry = zipKit.createZipEntry(TIMESTAMP_METADATA);
481
+ if (!tsEntry) {
482
+ throw new Error('Failed to create timestamp metadata entry');
483
+ }
484
+
485
+ // Configure the timestamp entry
486
+ tsEntry.timeDateDOS = tsEntry.setDateTime(new Date());
487
+ tsEntry.compressedSize = upgradedOts.length;
488
+ tsEntry.uncompressedSize = upgradedOts.length;
489
+ tsEntry.cmpMethod = CMP_METHOD.STORED; // Store without compression
490
+ tsEntry.crc = crc32(upgradedOts);
491
+ (tsEntry as any).fileData = upgradedOts; // Cast to any to avoid type issues
492
+
493
+ // Create and add the local header for the timestamp entry
494
+ const localHdr = tsEntry.createLocalHdr();
495
+ if (!localHdr) {
496
+ throw new Error('Failed to create local header for timestamp entry');
497
+ }
498
+
499
+ tsEntry.localHdrOffset = offset;
500
+ offset += localHdr.length + tsEntry.compressedSize;
501
+
502
+ buffers.push(localHdr);
503
+ buffers.push(upgradedOts);
504
+
505
+ // Add the timestamp entry to our list of entries
506
+ keptEntries.push(tsEntry);
507
+
508
+ // Create central directory
509
+ const centralDirOffset = offset;
510
+ let centralDirSize = 0;
511
+
512
+ for (const entry of keptEntries) {
513
+ const centralDirEntry = entry.centralDirEntry();
514
+ if (!centralDirEntry) {
515
+ throw new Error(`Failed to create central directory entry for: ${entry.filename}`);
516
+ }
517
+
518
+ centralDirSize += centralDirEntry.length;
519
+ buffers.push(centralDirEntry);
520
+ }
521
+
522
+ // Create end of central directory record
523
+ const endOfCentralDir = Buffer.alloc(22);
524
+ endOfCentralDir.writeUInt32LE(0x06054b50, 0); // End of central dir signature
525
+ endOfCentralDir.writeUInt16LE(0, 4); // Number of this disk
526
+ endOfCentralDir.writeUInt16LE(0, 6); // Disk where central directory starts
527
+ endOfCentralDir.writeUInt16LE(keptEntries.length, 8); // Number of central directory records on this disk
528
+ endOfCentralDir.writeUInt16LE(keptEntries.length, 10); // Total number of central directory records
529
+ endOfCentralDir.writeUInt32LE(centralDirSize, 12); // Size of central directory
530
+ endOfCentralDir.writeUInt32LE(centralDirOffset, 16); // Offset of start of central directory
531
+ endOfCentralDir.writeUInt16LE(0, 20); // ZIP file comment length
532
+
533
+ buffers.push(endOfCentralDir);
534
+
535
+ // Write the complete new zip file to temporary location
536
+ const finalBuffer = Buffer.concat(buffers);
537
+ fs.writeFileSync(tempPath, finalBuffer);
538
+
539
+ // Validate the temporary file was created successfully
540
+ if (!fs.existsSync(tempPath)) {
541
+ throw new Error('Failed to create temporary upgraded file');
542
+ }
543
+
544
+ const tempStats = fs.statSync(tempPath);
545
+ if (tempStats.size === 0) {
546
+ throw new Error('Temporary upgraded file is empty');
547
+ }
548
+
549
+ // Replace the original file with the upgraded version
550
+ fs.unlinkSync(zipFilePath);
551
+ fs.renameSync(tempPath, zipFilePath);
552
+
553
+ } catch (error) {
554
+ // Clean up temporary file if it exists
555
+ if (fs.existsSync(tempPath)) {
556
+ try {
557
+ fs.unlinkSync(tempPath);
558
+ } catch (cleanupError) {
559
+ // Log cleanup error but don't throw - main error is more important
560
+ console.warn(`Warning: Could not clean up temporary file ${tempPath}: ${cleanupError}`);
561
+ }
562
+ }
563
+
564
+ // Re-throw the original error
565
+ throw error;
566
+ }
567
+ }
568
+
569
+ /**
570
+ * Creates a ZIP metadata entry containing OpenTimestamps proof.
571
+ * Creates a special ZIP entry marked as metadata that stores OTS proof data.
572
+ * @param zipKit - Zipkit instance to add metadata entry to
573
+ * @param ots - Buffer containing OpenTimestamps proof data
574
+ * @returns ZIP entry containing OTS metadata, or null if creation failed
575
+ */
576
+ export function createOtsMetadataEntry(zipKit: any, ots: Buffer | null): any | null {
577
+ if (!ots || !zipKit) return null;
578
+
579
+ const tsEntry = zipKit.createZipEntry(TIMESTAMP_SUBMITTED);
580
+ tsEntry.crc = crc32(ots);
581
+ tsEntry.uncompressedSize = ots.length;
582
+ tsEntry.compressedSize = ots.length;
583
+ tsEntry.cmpMethod = CMP_METHOD.STORED;
584
+ tsEntry.fileBuffer = ots;
585
+ tsEntry.isMetaData = true;
586
+
587
+ return tsEntry;
588
+ }