neozipkit 0.1.1

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 (135) hide show
  1. package/README.md +400 -0
  2. package/contracts/Lock.sol +34 -0
  3. package/contracts/bytecode.txt +1 -0
  4. package/contracts/compile-contract.js +168 -0
  5. package/contracts/deploy/deploy-both-contracts.js +286 -0
  6. package/contracts/deploy/deploy-enhanced-contract.js +197 -0
  7. package/contracts/deploy/deploy-private-contract.js +190 -0
  8. package/contracts/deploy/deploy-public-clean.js +1063 -0
  9. package/contracts/deploy/deploy-public-contract.js +1107 -0
  10. package/contracts/deployment.config.example.js +25 -0
  11. package/contracts/remix-compile.js +222 -0
  12. package/contracts/setup-deployment.js +51 -0
  13. package/contracts/src/NZIP-NFT-Private.sol +350 -0
  14. package/contracts/src/NZIP-NFT.sol +265 -0
  15. package/contracts/src/ZipFileNFT-DEPRECATED-6field.sol +260 -0
  16. package/contracts/src/ZipFileNFT-DEPRECATED-Enhanced.sol +289 -0
  17. package/dist/browser/CertificateGeneratorBrowser.d.ts +75 -0
  18. package/dist/browser/CertificateGeneratorBrowser.js +433 -0
  19. package/dist/browser/TokenVerifierBrowser.d.ts +76 -0
  20. package/dist/browser/TokenVerifierBrowser.js +299 -0
  21. package/dist/browser/ZipKitBrowser.d.ts +18 -0
  22. package/dist/browser/ZipKitBrowser.js +250 -0
  23. package/dist/browser/ZipKitStampBrowser.d.ts +2 -0
  24. package/dist/browser/ZipKitStampBrowser.js +12 -0
  25. package/dist/browser-index.d.ts +21 -0
  26. package/dist/browser-index.js +58 -0
  27. package/dist/browser.d.ts +21 -0
  28. package/dist/browser.js +58 -0
  29. package/dist/index.d.ts +29 -0
  30. package/dist/index.js +76 -0
  31. package/dist/server/blockchain/CertificateToken.d.ts +48 -0
  32. package/dist/server/blockchain/CertificateToken.js +386 -0
  33. package/dist/server/blockchain/NFTMinter.d.ts +41 -0
  34. package/dist/server/blockchain/NFTMinter.js +323 -0
  35. package/dist/server/blockchain/TokenQuerier.d.ts +31 -0
  36. package/dist/server/blockchain/TokenQuerier.js +259 -0
  37. package/dist/server/blockchain/TokenVerifier.d.ts +20 -0
  38. package/dist/server/blockchain/TokenVerifier.js +395 -0
  39. package/dist/server/blockchain/WalletAnalyzer.d.ts +81 -0
  40. package/dist/server/blockchain/WalletAnalyzer.js +356 -0
  41. package/dist/server/blockchain/WalletFormatter.d.ts +39 -0
  42. package/dist/server/blockchain/WalletFormatter.js +196 -0
  43. package/dist/server/blockchain/WalletManager.d.ts +46 -0
  44. package/dist/server/blockchain/WalletManager.js +294 -0
  45. package/dist/server/blockchain/ZipMetadata.d.ts +27 -0
  46. package/dist/server/blockchain/ZipMetadata.js +131 -0
  47. package/dist/server/blockchain/ZipTokenProcessor.d.ts +44 -0
  48. package/dist/server/blockchain/ZipTokenProcessor.js +204 -0
  49. package/dist/server/blockchain/constants.d.ts +102 -0
  50. package/dist/server/blockchain/constants.js +968 -0
  51. package/dist/server/blockchain/index.d.ts +9 -0
  52. package/dist/server/blockchain/index.js +44 -0
  53. package/dist/server/blockchain/test-certificate.d.ts +8 -0
  54. package/dist/server/blockchain/test-certificate.js +100 -0
  55. package/dist/server/blockchain/types.d.ts +69 -0
  56. package/dist/server/blockchain/types.js +51 -0
  57. package/dist/server/platform/server/ZipKitServer.d.ts +105 -0
  58. package/dist/server/platform/server/ZipKitServer.js +437 -0
  59. package/dist/server/platform/servercomponents/ZipKitOTS.d.ts +91 -0
  60. package/dist/server/platform/servercomponents/ZipKitOTS.js +271 -0
  61. package/dist/shared/ZipEntry.d.ts +131 -0
  62. package/dist/shared/ZipEntry.js +686 -0
  63. package/dist/shared/ZipKit.d.ts +249 -0
  64. package/dist/shared/ZipKit.js +789 -0
  65. package/dist/shared/components/CertificateOTS.d.ts +15 -0
  66. package/dist/shared/components/CertificateOTS.js +116 -0
  67. package/dist/shared/components/FileSys.d.ts +2 -0
  68. package/dist/shared/components/FileSys.js +113 -0
  69. package/dist/shared/components/HashAccumulator.d.ts +55 -0
  70. package/dist/shared/components/HashAccumulator.js +100 -0
  71. package/dist/shared/components/Support.d.ts +63 -0
  72. package/dist/shared/components/Support.js +70 -0
  73. package/dist/shared/components/Util.d.ts +21 -0
  74. package/dist/shared/components/Util.js +115 -0
  75. package/dist/shared/components/ZipCrypto.d.ts +3 -0
  76. package/dist/shared/components/ZipCrypto.js +78 -0
  77. package/dist/shared/components/merkleTree.d.ts +66 -0
  78. package/dist/shared/components/merkleTree.js +136 -0
  79. package/dist/shared/constants/Errors.d.ts +53 -0
  80. package/dist/shared/constants/Errors.js +69 -0
  81. package/dist/shared/constants/Headers.d.ts +167 -0
  82. package/dist/shared/constants/Headers.js +191 -0
  83. package/dist/shared/types/index.d.ts +21 -0
  84. package/dist/shared/types/index.js +3 -0
  85. package/dist/shared/types.d.ts +33 -0
  86. package/dist/shared/types.js +8 -0
  87. package/dist/shared/version.d.ts +4 -0
  88. package/dist/shared/version.js +7 -0
  89. package/dist/types/index.d.ts +21 -0
  90. package/dist/types/index.js +3 -0
  91. package/examples/unzip-token.ts +488 -0
  92. package/examples/zip-token.ts +604 -0
  93. package/package.json +117 -0
  94. package/src/browser/CertificateGeneratorBrowser.ts +498 -0
  95. package/src/browser/TokenVerifierBrowser.ts +344 -0
  96. package/src/browser/ZipKitBrowser.ts +242 -0
  97. package/src/browser/ZipKitStampBrowser.ts +9 -0
  98. package/src/browser-index.ts +36 -0
  99. package/src/index.ts +48 -0
  100. package/src/server/blockchain/CertificateToken.ts +444 -0
  101. package/src/server/blockchain/NFTMinter.ts +357 -0
  102. package/src/server/blockchain/TokenQuerier.ts +287 -0
  103. package/src/server/blockchain/TokenVerifier.ts +453 -0
  104. package/src/server/blockchain/WalletAnalyzer.ts +397 -0
  105. package/src/server/blockchain/WalletFormatter.ts +206 -0
  106. package/src/server/blockchain/WalletManager.ts +294 -0
  107. package/src/server/blockchain/ZipMetadata.ts +117 -0
  108. package/src/server/blockchain/ZipTokenProcessor.ts +234 -0
  109. package/src/server/blockchain/constants.ts +969 -0
  110. package/src/server/blockchain/index.ts +42 -0
  111. package/src/server/blockchain/test-certificate.ts +137 -0
  112. package/src/server/blockchain/types.ts +134 -0
  113. package/src/server/platform/server/ZipKitServer.ts +459 -0
  114. package/src/server/platform/servercomponents/ZipKitOTS.ts +313 -0
  115. package/src/server/platform/servercomponents/opentimestamps.d.ts +23 -0
  116. package/src/shared/ZipEntry.ts +767 -0
  117. package/src/shared/ZipKit.ts +899 -0
  118. package/src/shared/components/CertificateOTS.ts +132 -0
  119. package/src/shared/components/FileSys.ts +87 -0
  120. package/src/shared/components/HashAccumulator.ts +113 -0
  121. package/src/shared/components/Support.ts +77 -0
  122. package/src/shared/components/Util.ts +113 -0
  123. package/src/shared/components/ZipCrypto.ts +91 -0
  124. package/src/shared/components/merkleTree.ts +162 -0
  125. package/src/shared/constants/Errors.ts +82 -0
  126. package/src/shared/constants/Headers.ts +203 -0
  127. package/src/shared/types/index.ts +25 -0
  128. package/src/shared/types/modules.d.ts +22 -0
  129. package/src/shared/types/opentimestamps.d.ts +23 -0
  130. package/src/shared/types.d.ts +8 -0
  131. package/src/shared/types.ts +43 -0
  132. package/src/shared/version.ts +4 -0
  133. package/src/types/index.ts +25 -0
  134. package/src/types/modules.d.ts +22 -0
  135. package/src/types/opentimestamps.d.ts +23 -0
@@ -0,0 +1,444 @@
1
+ // ======================================
2
+ // CertificateToken.ts
3
+ // Copyright (c) 2025 NeoWare, Inc. All rights reserved.
4
+ //
5
+ // Standalone certificate generator for tokenized ZIP files
6
+ // This will be integrated into neozipkit once fully functional
7
+ // ======================================
8
+
9
+ import fs from 'fs';
10
+ import path from 'path';
11
+
12
+ // Token-specific types
13
+ export interface TokenInfo {
14
+ tokenId: string;
15
+ contractAddress: string;
16
+ network: string;
17
+ transactionHash: string;
18
+ wallet?: string;
19
+ timestamp?: number;
20
+ note?: string;
21
+ }
22
+
23
+ export interface BlockchainVerification {
24
+ merkleRootMatches: boolean;
25
+ blockchainMerkleRoot: string;
26
+ calculatedMerkleRoot: string;
27
+ verificationStatus: 'PASSED' | 'FAILED' | 'UNAVAILABLE';
28
+ verificationTime?: number;
29
+ blockNumber?: number;
30
+ }
31
+
32
+ export interface WalletInfo {
33
+ address: string;
34
+ balance?: string;
35
+ network: string;
36
+ ensName?: string;
37
+ }
38
+
39
+ export interface ZipFileInfo {
40
+ filename: string;
41
+ size: number;
42
+ date: string;
43
+ hash: string;
44
+ }
45
+
46
+ /**
47
+ * Generates a certificate HTML document for tokenized ZIP files
48
+ *
49
+ * @param tokenInfo - NFT token information
50
+ * @param zipFile - Name of the zip file
51
+ * @param blockchainVerification - Blockchain verification results
52
+ * @param walletInfo - Wallet information (optional)
53
+ * @param zipFiles - Array of file information (optional)
54
+ * @param options - Certificate generation options
55
+ * @returns Generated HTML certificate as string
56
+ */
57
+ export function createTokenCertificate(
58
+ tokenInfo: TokenInfo,
59
+ zipFile: string,
60
+ blockchainVerification: BlockchainVerification,
61
+ walletInfo?: WalletInfo,
62
+ zipFiles?: ZipFileInfo[],
63
+ options?: { narrow?: boolean; includeQR?: boolean }
64
+ ): string {
65
+
66
+ // Generate token information HTML
67
+ const tokenHTML = generateTokenSection(tokenInfo);
68
+
69
+ // Generate blockchain verification HTML
70
+ const verificationHTML = generateVerificationSection(blockchainVerification);
71
+
72
+ // Generate wallet information HTML
73
+ const walletHTML = walletInfo ? generateWalletSection(walletInfo) : '';
74
+
75
+ // Generate files table HTML
76
+ const filesTableHTML = zipFiles ? generateFilesTable(zipFiles) : '';
77
+
78
+ // Get the complete HTML template
79
+ const htmlTemplate = getCertificateTemplate();
80
+
81
+ // Create the complete attestation HTML combining all sections
82
+ const attestHTML = tokenHTML + verificationHTML + walletHTML;
83
+
84
+ // Replace placeholders in the template
85
+ const html = htmlTemplate
86
+ .replace(/{{ATTEST_STR}}/g, `NFT Token Certificate for ${zipFile}`)
87
+ .replace(/{{UPDATE_WARNING}}/g, blockchainVerification.verificationStatus === 'FAILED' ?
88
+ '<div class="warning">⚠️ Warning: Blockchain verification failed. This archive may have been tampered with.</div>' : '')
89
+ .replace(/{{ZIP_FILE}}/g, zipFile)
90
+ .replace(/{{HASH_DIGEST}}/g, blockchainVerification.calculatedMerkleRoot)
91
+ .replace(/{{ATTESTATION_HTML}}/g, attestHTML)
92
+ .replace(/{{FILES_TABLE_HTML}}/g, filesTableHTML)
93
+ .replace(/{{GENERATION_TIME}}/g, new Date().toUTCString());
94
+
95
+ return html;
96
+ }
97
+
98
+ /**
99
+ * Saves a certificate to disk
100
+ */
101
+ export function saveCertificate(
102
+ fileName: string,
103
+ certificateHTML: string,
104
+ outputDir?: string
105
+ ): string {
106
+ try {
107
+ const dir = outputDir || path.dirname(fileName);
108
+ const baseName = path.basename(fileName, '.zip');
109
+ const certFileName = path.join(dir, `${baseName}.token-certificate.html`);
110
+
111
+ // Ensure directory exists
112
+ if (!fs.existsSync(dir)) {
113
+ fs.mkdirSync(dir, { recursive: true });
114
+ }
115
+
116
+ // Write the certificate HTML to a file
117
+ fs.writeFileSync(certFileName, certificateHTML, { encoding: 'utf8' });
118
+ return certFileName;
119
+ } catch (error) {
120
+ throw new Error(`Failed to save certificate: ${error}`);
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Generate token information section
126
+ */
127
+ function generateTokenSection(tokenInfo: TokenInfo): string {
128
+ return `
129
+ <div class="token-section">
130
+ <h3>🎫 NFT Token Information</h3>
131
+ <div class="key-value-pair">
132
+ <div class="key">Token ID:</div>
133
+ <div class="value">${tokenInfo.tokenId}</div>
134
+ </div>
135
+ <div class="key-value-pair">
136
+ <div class="key">Contract Address:</div>
137
+ <div class="value"><code>${tokenInfo.contractAddress}</code></div>
138
+ </div>
139
+ <div class="key-value-pair">
140
+ <div class="key">Network:</div>
141
+ <div class="value">${tokenInfo.network}</div>
142
+ </div>
143
+ <div class="key-value-pair">
144
+ <div class="key">Minting Transaction:</div>
145
+ <div class="value"><code>${tokenInfo.transactionHash}</code></div>
146
+ </div>
147
+ ${tokenInfo.timestamp ? `
148
+ <div class="key-value-pair">
149
+ <div class="key">Token Created:</div>
150
+ <div class="value">${new Date(tokenInfo.timestamp * 1000).toUTCString()}</div>
151
+ </div>
152
+ ` : ''}
153
+ ${tokenInfo.note ? `
154
+ <div class="key-value-pair">
155
+ <div class="key">Note:</div>
156
+ <div class="value">${tokenInfo.note}</div>
157
+ </div>
158
+ ` : ''}
159
+ </div>
160
+ `;
161
+ }
162
+
163
+ /**
164
+ * Generate blockchain verification section
165
+ */
166
+ function generateVerificationSection(verification: BlockchainVerification): string {
167
+ const statusIcon = verification.verificationStatus === 'PASSED' ? '✅' :
168
+ verification.verificationStatus === 'FAILED' ? '❌' : '⚠️';
169
+
170
+ return `
171
+ <div class="verification-section ${verification.verificationStatus.toLowerCase()}">
172
+ <h3>🔐 Blockchain Verification</h3>
173
+ <div class="verification-status ${verification.verificationStatus.toLowerCase()}">
174
+ ${statusIcon} <strong>Status: ${verification.verificationStatus}</strong>
175
+ </div>
176
+ <div class="key-value-pair">
177
+ <div class="key">Blockchain Merkle Root:</div>
178
+ <div class="value"><code>${verification.blockchainMerkleRoot}</code></div>
179
+ </div>
180
+ <div class="key-value-pair">
181
+ <div class="key">Calculated Merkle Root:</div>
182
+ <div class="value"><code>${verification.calculatedMerkleRoot}</code></div>
183
+ </div>
184
+ <div class="key-value-pair">
185
+ <div class="key">Integrity Check:</div>
186
+ <div class="value">${verification.merkleRootMatches ?
187
+ '✅ Archive contents match blockchain record' :
188
+ '❌ Archive contents do not match blockchain record'}</div>
189
+ </div>
190
+ ${verification.verificationTime ? `
191
+ <div class="key-value-pair">
192
+ <div class="key">Verified At:</div>
193
+ <div class="value">${new Date(verification.verificationTime * 1000).toUTCString()}</div>
194
+ </div>
195
+ ` : ''}
196
+ ${verification.blockNumber ? `
197
+ <div class="key-value-pair">
198
+ <div class="key">Block Number:</div>
199
+ <div class="value">${verification.blockNumber}</div>
200
+ </div>
201
+ ` : ''}
202
+ </div>
203
+ `;
204
+ }
205
+
206
+ /**
207
+ * Generate wallet information section
208
+ */
209
+ function generateWalletSection(walletInfo: WalletInfo): string {
210
+ return `
211
+ <div class="wallet-section">
212
+ <h3>👛 Wallet Information</h3>
213
+ <div class="key-value-pair">
214
+ <div class="key">Wallet Address:</div>
215
+ <div class="value"><code>${walletInfo.address}</code></div>
216
+ </div>
217
+ ${walletInfo.ensName ? `
218
+ <div class="key-value-pair">
219
+ <div class="key">ENS Name:</div>
220
+ <div class="value">${walletInfo.ensName}</div>
221
+ </div>
222
+ ` : ''}
223
+ <div class="key-value-pair">
224
+ <div class="key">Network:</div>
225
+ <div class="value">${walletInfo.network}</div>
226
+ </div>
227
+ ${walletInfo.balance ? `
228
+ <div class="key-value-pair">
229
+ <div class="key">Balance:</div>
230
+ <div class="value">${walletInfo.balance}</div>
231
+ </div>
232
+ ` : ''}
233
+ </div>
234
+ `;
235
+ }
236
+
237
+ /**
238
+ * Generate files table HTML
239
+ */
240
+ function generateFilesTable(files: ZipFileInfo[]): string {
241
+ let filesTableHTML = '';
242
+
243
+ files.forEach((file) => {
244
+ filesTableHTML += `
245
+ <tr>
246
+ <td class="table-data1">${file.filename}</td>
247
+ <td class="table-data">${file.size.toString()}</td>
248
+ <td class="table-data">${file.date}</td>
249
+ <td class="table-data"><code>${file.hash}</code></td>
250
+ </tr>
251
+ `;
252
+ });
253
+
254
+ return filesTableHTML;
255
+ }
256
+
257
+ /**
258
+ * Get the HTML template for certificates
259
+ */
260
+ function getCertificateTemplate(): string {
261
+ return `<!DOCTYPE html>
262
+ <html lang="en">
263
+ <head>
264
+ <meta charset="UTF-8">
265
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
266
+ <title>NFT Token Certificate - {{ZIP_FILE}}</title>
267
+ <style>
268
+ body {
269
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
270
+ line-height: 1.6;
271
+ margin: 0;
272
+ padding: 20px;
273
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
274
+ min-height: 100vh;
275
+ }
276
+ .certificate {
277
+ max-width: 900px;
278
+ margin: 0 auto;
279
+ background: white;
280
+ border-radius: 15px;
281
+ box-shadow: 0 20px 40px rgba(0,0,0,0.1);
282
+ overflow: hidden;
283
+ }
284
+ .header {
285
+ background: linear-gradient(135deg, #2c3e50 0%, #3498db 100%);
286
+ color: white;
287
+ padding: 30px;
288
+ text-align: center;
289
+ }
290
+ .header h1 {
291
+ margin: 0;
292
+ font-size: 2.5em;
293
+ font-weight: 300;
294
+ }
295
+ .header h2 {
296
+ margin: 10px 0 0 0;
297
+ font-size: 1.2em;
298
+ opacity: 0.9;
299
+ }
300
+ .content {
301
+ padding: 40px;
302
+ }
303
+ .token-section, .verification-section, .wallet-section {
304
+ margin-bottom: 30px;
305
+ padding: 20px;
306
+ border-radius: 10px;
307
+ border-left: 4px solid #3498db;
308
+ background: #f8f9fa;
309
+ }
310
+ .verification-section.passed {
311
+ border-left-color: #27ae60;
312
+ }
313
+ .verification-section.failed {
314
+ border-left-color: #e74c3c;
315
+ }
316
+ .verification-section.unavailable {
317
+ border-left-color: #f39c12;
318
+ }
319
+ .verification-status {
320
+ font-size: 1.2em;
321
+ margin-bottom: 15px;
322
+ padding: 10px;
323
+ border-radius: 5px;
324
+ }
325
+ .verification-status.passed {
326
+ background: #d4edda;
327
+ color: #155724;
328
+ }
329
+ .verification-status.failed {
330
+ background: #f8d7da;
331
+ color: #721c24;
332
+ }
333
+ .verification-status.unavailable {
334
+ background: #fff3cd;
335
+ color: #856404;
336
+ }
337
+ .key-value-pair {
338
+ display: flex;
339
+ margin-bottom: 10px;
340
+ align-items: flex-start;
341
+ }
342
+ .key {
343
+ font-weight: bold;
344
+ min-width: 200px;
345
+ color: #2c3e50;
346
+ }
347
+ .value {
348
+ flex: 1;
349
+ word-break: break-all;
350
+ }
351
+ .value code {
352
+ background: #e9ecef;
353
+ padding: 2px 6px;
354
+ border-radius: 3px;
355
+ font-family: 'Monaco', 'Menlo', monospace;
356
+ font-size: 0.9em;
357
+ }
358
+ .files-section {
359
+ margin-top: 30px;
360
+ }
361
+ .files-table {
362
+ width: 100%;
363
+ border-collapse: collapse;
364
+ margin-top: 15px;
365
+ }
366
+ .files-table th,
367
+ .files-table td {
368
+ padding: 12px;
369
+ text-align: left;
370
+ border-bottom: 1px solid #dee2e6;
371
+ }
372
+ .files-table th {
373
+ background: #f8f9fa;
374
+ font-weight: bold;
375
+ color: #2c3e50;
376
+ }
377
+ .table-data1 {
378
+ font-weight: bold;
379
+ }
380
+ .warning {
381
+ background: #fff3cd;
382
+ color: #856404;
383
+ padding: 15px;
384
+ border-radius: 5px;
385
+ margin-bottom: 20px;
386
+ border-left: 4px solid #ffc107;
387
+ }
388
+ .footer {
389
+ text-align: center;
390
+ padding: 20px;
391
+ background: #f8f9fa;
392
+ color: #6c757d;
393
+ font-size: 0.9em;
394
+ }
395
+ h3 {
396
+ margin-top: 0;
397
+ color: #2c3e50;
398
+ font-size: 1.3em;
399
+ }
400
+ </style>
401
+ </head>
402
+ <body>
403
+ <div class="certificate">
404
+ <div class="header">
405
+ <h1>🎫 NFT Token Certificate</h1>
406
+ <h2>Blockchain-Verified Digital Archive</h2>
407
+ </div>
408
+
409
+ <div class="content">
410
+ {{UPDATE_WARNING}}
411
+
412
+ <div class="key-value-pair" style="margin-bottom: 30px; font-size: 1.1em;">
413
+ <div class="key">Archive File:</div>
414
+ <div class="value"><strong>{{ZIP_FILE}}</strong></div>
415
+ </div>
416
+
417
+ {{ATTESTATION_HTML}}
418
+
419
+ <div class="files-section">
420
+ <h3>📁 Archive Contents</h3>
421
+ <table class="files-table">
422
+ <thead>
423
+ <tr>
424
+ <th>File Name</th>
425
+ <th>Size (bytes)</th>
426
+ <th>Date Modified</th>
427
+ <th>SHA256 Hash</th>
428
+ </tr>
429
+ </thead>
430
+ <tbody>
431
+ {{FILES_TABLE_HTML}}
432
+ </tbody>
433
+ </table>
434
+ </div>
435
+ </div>
436
+
437
+ <div class="footer">
438
+ <p>This certificate verifies the integrity and authenticity of the tokenized archive through blockchain technology.</p>
439
+ <p>Generated on: {{GENERATION_TIME}}</p>
440
+ </div>
441
+ </div>
442
+ </body>
443
+ </html>`;
444
+ }