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.
- package/LICENSE +22 -0
- package/README.md +410 -186
- package/contracts/ABI.txt +889 -0
- package/contracts/Bytecode.txt +1 -0
- package/contracts/COMPILATION_NOTES.md +59 -0
- package/contracts/QUICK_DEPLOY.md +286 -0
- package/contracts/README.md +235 -131
- package/contracts/VERIFICATION.md +308 -0
- package/contracts/deploy-interactive.js +448 -0
- package/contracts/deployment-arbitrum-sepolia.json +12 -0
- package/contracts/deployment-arbitrum.json +12 -0
- package/contracts/deployment-eth-sepolia.json +12 -0
- package/contracts/hardhat.config.js +114 -0
- package/contracts/package.json +20 -0
- package/contracts/scripts/compile-and-extract.js +119 -0
- package/contracts/scripts/verify-contract.js +223 -0
- package/contracts/src/{NZIP-NFT-Private.sol → NZIP-NFT-v2.0.sol} +66 -151
- package/contracts/src/NZIP-NFT.sol +9 -15
- package/dist/blockchain/browser/TokenVerifierBrowser.d.ts +67 -0
- package/dist/blockchain/browser/TokenVerifierBrowser.d.ts.map +1 -0
- package/dist/blockchain/browser/TokenVerifierBrowser.js +313 -0
- package/dist/blockchain/browser/TokenVerifierBrowser.js.map +1 -0
- package/dist/blockchain/browser/WalletManagerBrowser.d.ts +98 -0
- package/dist/blockchain/browser/WalletManagerBrowser.d.ts.map +1 -0
- package/dist/blockchain/browser/WalletManagerBrowser.js +434 -0
- package/dist/blockchain/browser/WalletManagerBrowser.js.map +1 -0
- package/dist/blockchain/browser/ZipkitMinterBrowser.d.ts +58 -0
- package/dist/blockchain/browser/ZipkitMinterBrowser.d.ts.map +1 -0
- package/dist/blockchain/browser/ZipkitMinterBrowser.js +317 -0
- package/dist/blockchain/browser/ZipkitMinterBrowser.js.map +1 -0
- package/dist/blockchain/browser/index.d.ts +11 -0
- package/dist/blockchain/browser/index.d.ts.map +1 -0
- package/dist/blockchain/browser/index.js +16 -0
- package/dist/blockchain/browser/index.js.map +1 -0
- package/dist/blockchain/core/WalletManager.d.ts +124 -0
- package/dist/blockchain/core/WalletManager.d.ts.map +1 -0
- package/dist/blockchain/{ZipKitWallet.js → core/WalletManager.js} +157 -177
- package/dist/blockchain/core/WalletManager.js.map +1 -0
- package/dist/blockchain/{ZipKitMinter.d.ts → core/ZipkitMinter.d.ts} +46 -11
- package/dist/blockchain/core/ZipkitMinter.d.ts.map +1 -0
- package/dist/blockchain/core/ZipkitMinter.js +548 -0
- package/dist/blockchain/core/ZipkitMinter.js.map +1 -0
- package/dist/blockchain/{ZipKitOTS.d.ts → core/ZipkitOTS.d.ts} +6 -15
- package/dist/blockchain/core/ZipkitOTS.d.ts.map +1 -0
- package/dist/blockchain/{ZipKitOTS.js → core/ZipkitOTS.js} +26 -84
- package/dist/blockchain/core/ZipkitOTS.js.map +1 -0
- package/dist/blockchain/core/ZipkitVerifier.d.ts +177 -0
- package/dist/blockchain/core/ZipkitVerifier.d.ts.map +1 -0
- package/dist/blockchain/core/ZipkitVerifier.js +632 -0
- package/dist/blockchain/core/ZipkitVerifier.js.map +1 -0
- package/dist/blockchain/core/contracts.d.ts +83 -0
- package/dist/blockchain/core/contracts.d.ts.map +1 -0
- package/dist/blockchain/core/contracts.js +341 -0
- package/dist/blockchain/core/contracts.js.map +1 -0
- package/dist/blockchain/core/index.d.ts +12 -0
- package/dist/blockchain/core/index.d.ts.map +1 -0
- package/dist/blockchain/core/index.js +59 -0
- package/dist/blockchain/core/index.js.map +1 -0
- package/dist/blockchain/index.d.ts +11 -7
- package/dist/blockchain/index.d.ts.map +1 -0
- package/dist/blockchain/index.js +18 -34
- package/dist/blockchain/index.js.map +1 -0
- package/dist/blockchain/node/WalletManagerNode.d.ts +47 -0
- package/dist/blockchain/node/WalletManagerNode.d.ts.map +1 -0
- package/dist/blockchain/node/WalletManagerNode.js +203 -0
- package/dist/blockchain/node/WalletManagerNode.js.map +1 -0
- package/dist/blockchain/node/index.d.ts +12 -0
- package/dist/blockchain/node/index.d.ts.map +1 -0
- package/dist/blockchain/node/index.js +24 -0
- package/dist/blockchain/node/index.js.map +1 -0
- package/dist/browser/ZipkitBrowser.d.ts +27 -0
- package/dist/browser/ZipkitBrowser.d.ts.map +1 -0
- package/dist/browser/{ZipKitBrowser.js → ZipkitBrowser.js} +96 -43
- package/dist/browser/ZipkitBrowser.js.map +1 -0
- package/dist/browser/index.d.ts +12 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +42 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser-esm/index.d.ts +12 -0
- package/dist/browser-esm/index.js +59559 -0
- package/dist/browser-esm/index.js.map +7 -0
- package/dist/browser-umd/index.d.ts +12 -0
- package/dist/browser-umd/index.js +59576 -0
- package/dist/browser-umd/index.js.map +7 -0
- package/dist/browser-umd/index.min.js +63 -0
- package/dist/browser.d.ts +8 -14
- package/dist/browser.js +13 -28
- package/dist/core/ZipCompress.d.ts +99 -0
- package/dist/core/ZipCompress.d.ts.map +1 -0
- package/dist/core/ZipCompress.js +309 -0
- package/dist/core/ZipCompress.js.map +1 -0
- package/dist/core/ZipDecompress.d.ts +58 -0
- package/dist/core/ZipDecompress.d.ts.map +1 -0
- package/dist/core/ZipDecompress.js +172 -0
- package/dist/core/ZipDecompress.js.map +1 -0
- package/dist/{shared → core}/ZipEntry.d.ts +8 -1
- package/dist/core/ZipEntry.d.ts.map +1 -0
- package/dist/{shared → core}/ZipEntry.js +225 -82
- package/dist/core/ZipEntry.js.map +1 -0
- package/dist/core/Zipkit.d.ts +315 -0
- package/dist/core/Zipkit.d.ts.map +1 -0
- package/dist/core/Zipkit.js +647 -0
- package/dist/core/Zipkit.js.map +1 -0
- package/dist/core/components/HashCalculator.d.ts +138 -0
- package/dist/core/components/HashCalculator.d.ts.map +1 -0
- package/dist/core/components/HashCalculator.js +360 -0
- package/dist/core/components/HashCalculator.js.map +1 -0
- package/dist/core/components/Logger.d.ts +73 -0
- package/dist/core/components/Logger.d.ts.map +1 -0
- package/dist/core/components/Logger.js +156 -0
- package/dist/core/components/Logger.js.map +1 -0
- package/dist/core/components/ProgressTracker.d.ts +43 -0
- package/dist/core/components/ProgressTracker.d.ts.map +1 -0
- package/dist/core/components/ProgressTracker.js +112 -0
- package/dist/core/components/ProgressTracker.js.map +1 -0
- package/dist/{shared → core}/components/Support.d.ts +1 -0
- package/dist/core/components/Support.d.ts.map +1 -0
- package/dist/{shared → core}/components/Support.js +1 -0
- package/dist/core/components/Support.js.map +1 -0
- package/dist/{shared → core}/components/Util.d.ts +7 -2
- package/dist/core/components/Util.d.ts.map +1 -0
- package/dist/{shared → core}/components/Util.js +14 -34
- package/dist/core/components/Util.js.map +1 -0
- package/dist/{shared → core}/constants/Errors.d.ts +1 -2
- package/dist/core/constants/Errors.d.ts.map +1 -0
- package/dist/{shared → core}/constants/Errors.js +1 -3
- package/dist/core/constants/Errors.js.map +1 -0
- package/dist/{shared → core}/constants/Headers.d.ts +3 -0
- package/dist/core/constants/Headers.d.ts.map +1 -0
- package/dist/{shared → core}/constants/Headers.js +20 -17
- package/dist/core/constants/Headers.js.map +1 -0
- package/dist/core/encryption/Manager.d.ts +58 -0
- package/dist/core/encryption/Manager.d.ts.map +1 -0
- package/dist/core/encryption/Manager.js +121 -0
- package/dist/core/encryption/Manager.js.map +1 -0
- package/dist/core/encryption/ZipCrypto.d.ts +172 -0
- package/dist/core/encryption/ZipCrypto.d.ts.map +1 -0
- package/dist/core/encryption/ZipCrypto.js +554 -0
- package/dist/core/encryption/ZipCrypto.js.map +1 -0
- package/dist/core/encryption/index.d.ts +9 -0
- package/dist/core/encryption/index.d.ts.map +1 -0
- package/dist/core/encryption/index.js +17 -0
- package/dist/core/encryption/index.js.map +1 -0
- package/dist/core/encryption/types.d.ts +29 -0
- package/dist/core/encryption/types.d.ts.map +1 -0
- package/dist/core/encryption/types.js +12 -0
- package/dist/core/encryption/types.js.map +1 -0
- package/dist/core/index.d.ts +24 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +57 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/version.d.ts +5 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +31 -0
- package/dist/core/version.js.map +1 -0
- package/dist/index.d.ts +8 -18
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -35
- package/dist/index.js.map +1 -0
- package/dist/node/ZipCompressNode.d.ts +123 -0
- package/dist/node/ZipCompressNode.d.ts.map +1 -0
- package/dist/node/ZipCompressNode.js +576 -0
- package/dist/node/ZipCompressNode.js.map +1 -0
- package/dist/node/ZipDecompressNode.d.ts +120 -0
- package/dist/node/ZipDecompressNode.d.ts.map +1 -0
- package/dist/node/ZipDecompressNode.js +461 -0
- package/dist/node/ZipDecompressNode.js.map +1 -0
- package/dist/node/ZipkitNode.d.ts +406 -0
- package/dist/node/ZipkitNode.d.ts.map +1 -0
- package/dist/node/ZipkitNode.js +1305 -0
- package/dist/node/ZipkitNode.js.map +1 -0
- package/dist/node/index.d.ts +26 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +65 -0
- package/dist/node/index.js.map +1 -0
- package/dist/types/index.d.ts +59 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +36 -1
- package/dist/types/index.js.map +1 -0
- package/examples/README.md +269 -0
- package/examples/blockchain-tokenize.ts +354 -0
- package/examples/create-zip.ts +172 -0
- package/examples/extract-zip.ts +158 -0
- package/examples/list-zip.ts +161 -0
- package/examples/test-files/data.json +116 -0
- package/examples/test-files/document.md +80 -0
- package/examples/test-files/document.txt +2 -0
- package/examples/test-files/file1.txt +48 -0
- package/examples/test-files/file2.txt +80 -0
- package/examples/tsconfig.json +44 -0
- package/examples/unzip-token.ts +491 -0
- package/examples/verify-tokenized-zip.ts +305 -0
- package/examples/zip-token.ts +604 -0
- package/package.json +108 -24
- package/src/blockchain/README.md +59 -66
- package/src/{browser/TokenVerifierBrowser.ts-remove → blockchain/browser/TokenVerifierBrowser.ts} +125 -79
- package/src/blockchain/browser/WalletManagerBrowser.ts +486 -0
- package/src/blockchain/browser/ZipkitMinterBrowser.ts +400 -0
- package/src/blockchain/browser/index.ts +13 -0
- package/src/blockchain/{ZipKitWallet.ts → core/WalletManager.ts} +241 -143
- package/src/blockchain/core/ZipkitMinter.ts +716 -0
- package/src/blockchain/{ZipKitOTS.ts → core/ZipkitOTS.ts} +28 -62
- package/src/blockchain/core/ZipkitVerifier.ts +853 -0
- package/src/blockchain/core/contracts.ts +370 -0
- package/src/blockchain/core/index.ts +71 -0
- package/src/blockchain/index.ts +21 -55
- package/src/blockchain/node/WalletManagerNode.ts +171 -0
- package/src/blockchain/node/index.ts +40 -0
- package/src/browser/{ZipKitBrowser.ts → ZipkitBrowser.ts} +104 -41
- package/src/browser/index.esm.ts +37 -0
- package/src/browser/index.ts +25 -0
- package/src/core/ZipCompress.ts +398 -0
- package/src/core/ZipDecompress.ts +212 -0
- package/src/{shared → core}/ZipEntry.ts +240 -90
- package/src/core/Zipkit.ts +794 -0
- package/src/core/components/HashCalculator.ts +384 -0
- package/src/core/components/Logger.ts +180 -0
- package/src/core/components/ProgressTracker.ts +134 -0
- package/src/{shared → core}/components/Util.ts +12 -34
- package/src/{shared → core}/constants/Errors.ts +0 -4
- package/src/{shared → core}/constants/Headers.ts +19 -17
- package/src/core/encryption/Manager.ts +137 -0
- package/src/core/encryption/ZipCrypto.ts +650 -0
- package/src/core/encryption/index.ts +15 -0
- package/src/core/encryption/types.ts +33 -0
- package/src/core/index.ts +34 -0
- package/src/core/version.ts +33 -0
- package/src/index.ts +54 -25
- package/src/node/ZipCompressNode.ts +632 -0
- package/src/node/ZipDecompressNode.ts +508 -0
- package/src/node/ZipkitNode.ts +1559 -0
- package/src/node/index.ts +69 -0
- package/src/types/index.ts +131 -1
- package/src/types/modules.d.ts +1 -11
- package/src/types/opentimestamps.d.ts +1 -23
- package/contracts/INTEGRATION.md +0 -338
- package/contracts/NETWORKS.md +0 -156
- package/contracts/NZIP-NFT-bytecode.txt +0 -1
- package/contracts/constants.ts +0 -952
- package/contracts/deploy-bytecode.mjs +0 -94
- package/dist/blockchain/CertificateToken.d.ts +0 -48
- package/dist/blockchain/CertificateToken.js +0 -386
- package/dist/blockchain/ZipKitMinter.js +0 -347
- package/dist/blockchain/ZipKitNFT.d.ts +0 -3
- package/dist/blockchain/ZipKitNFT.js +0 -7
- package/dist/blockchain/ZipKitVerifier.d.ts +0 -69
- package/dist/blockchain/ZipKitVerifier.js +0 -289
- package/dist/blockchain/ZipKitWallet.d.ts +0 -69
- package/dist/blockchain/contracts.d.ts +0 -14
- package/dist/blockchain/contracts.js +0 -77
- package/dist/blockchain/types.d.ts +0 -47
- package/dist/blockchain/types.js +0 -30
- package/dist/browser/ZipKitBrowser.d.ts +0 -18
- package/dist/browser/ZipKitStampBrowser.d.ts +0 -2
- package/dist/browser/ZipKitStampBrowser.js +0 -12
- package/dist/browser-index.d.ts +0 -18
- package/dist/browser-index.js +0 -57
- package/dist/server/ZipKitServer.d.ts +0 -74
- package/dist/server/ZipKitServer.js +0 -310
- package/dist/shared/ZipKit.d.ts +0 -243
- package/dist/shared/ZipKit.js +0 -772
- package/dist/shared/components/CertificateOTS.d.ts +0 -15
- package/dist/shared/components/CertificateOTS.js +0 -116
- package/dist/shared/components/FileSys.d.ts +0 -2
- package/dist/shared/components/FileSys.js +0 -113
- package/dist/shared/components/HashAccumulator.d.ts +0 -55
- package/dist/shared/components/HashAccumulator.js +0 -100
- package/dist/shared/components/ZipCrypto.d.ts +0 -3
- package/dist/shared/components/ZipCrypto.js +0 -78
- package/dist/shared/components/merkleTree.d.ts +0 -66
- package/dist/shared/components/merkleTree.js +0 -136
- package/dist/shared/types/index.d.ts +0 -21
- package/dist/shared/types/index.js +0 -3
- package/dist/shared/types.d.ts +0 -33
- package/dist/shared/types.js +0 -8
- package/dist/shared/version.d.ts +0 -2
- package/dist/shared/version.js +0 -6
- package/src/blockchain/CertificateToken.ts +0 -444
- package/src/blockchain/ZipKitMinter.ts +0 -470
- package/src/blockchain/ZipKitNFT.ts +0 -12
- package/src/blockchain/ZipKitVerifier.ts +0 -382
- package/src/blockchain/contracts.ts +0 -88
- package/src/blockchain/types.ts +0 -91
- package/src/browser/CertificateGeneratorBrowser.ts-remove +0 -498
- package/src/browser/ZipKitStampBrowser.ts +0 -9
- package/src/browser-index.ts +0 -36
- package/src/server/README.md +0 -25
- package/src/server/ZipKitServer.ts +0 -305
- package/src/shared/ZipKit.ts +0 -881
- package/src/shared/components/CertificateOTS.ts +0 -132
- package/src/shared/components/FileSys.ts +0 -87
- package/src/shared/components/HashAccumulator.ts +0 -113
- package/src/shared/components/ZipCrypto.ts +0 -91
- package/src/shared/components/merkleTree.ts +0 -162
- package/src/shared/types/index.ts +0 -25
- package/src/shared/types/modules.d.ts +0 -22
- package/src/shared/types/opentimestamps.d.ts +0 -23
- package/src/shared/types.d.ts +0 -8
- package/src/shared/types.ts +0 -43
- package/src/shared/version.ts +0 -3
- /package/src/{shared → core}/components/Support.ts +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Compile and Extract Script for NeoZip NFT Contract
|
|
5
|
+
*
|
|
6
|
+
* This script:
|
|
7
|
+
* 1. Compiles the NZIP-NFT.sol contract using Hardhat
|
|
8
|
+
* 2. Extracts the ABI and bytecode from compilation artifacts
|
|
9
|
+
* 3. Writes ABI.txt and Bytecode.txt in the contracts directory
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* node scripts/compile-and-extract.js
|
|
13
|
+
* or
|
|
14
|
+
* yarn compile:extract
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const hre = require("hardhat");
|
|
18
|
+
const fs = require("fs");
|
|
19
|
+
const path = require("path");
|
|
20
|
+
|
|
21
|
+
async function main() {
|
|
22
|
+
console.log("=".repeat(70));
|
|
23
|
+
console.log("🔨 Compiling NeoZip NFT Contract");
|
|
24
|
+
console.log("=".repeat(70));
|
|
25
|
+
console.log();
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
// Compile the contract
|
|
29
|
+
console.log("📦 Compiling contracts...");
|
|
30
|
+
await hre.run("compile");
|
|
31
|
+
console.log("✅ Compilation successful!");
|
|
32
|
+
console.log();
|
|
33
|
+
|
|
34
|
+
// Get the contract artifact
|
|
35
|
+
const contractName = "ZipFileNFTPublic";
|
|
36
|
+
|
|
37
|
+
// Read the build info to get the exact artifact
|
|
38
|
+
// Hardhat stores artifacts in artifacts/src/<source-file>/<contract-name>.json
|
|
39
|
+
const artifactPath = path.join(__dirname, "..", "artifacts", "src", "NZIP-NFT.sol", `${contractName}.json`);
|
|
40
|
+
|
|
41
|
+
if (!fs.existsSync(artifactPath)) {
|
|
42
|
+
throw new Error(`Artifact not found at ${artifactPath}. Make sure the contract compiled successfully.`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const artifact = JSON.parse(fs.readFileSync(artifactPath, "utf8"));
|
|
46
|
+
|
|
47
|
+
// Extract ABI
|
|
48
|
+
const abi = artifact.abi;
|
|
49
|
+
if (!abi || abi.length === 0) {
|
|
50
|
+
throw new Error("ABI not found in artifact");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Extract bytecode (deployment bytecode, not creation code)
|
|
54
|
+
let bytecode = artifact.bytecode;
|
|
55
|
+
if (!bytecode || bytecode === "0x") {
|
|
56
|
+
throw new Error("Bytecode not found in artifact");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Remove 0x prefix if present (deploy-interactive.js handles adding it)
|
|
60
|
+
if (bytecode.startsWith("0x")) {
|
|
61
|
+
bytecode = bytecode.slice(2);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Write to compiled files (NOT the deployment files)
|
|
65
|
+
// ABI.txt and Bytecode.txt are the DEPLOYED versions and must not be overwritten
|
|
66
|
+
const abiPath = path.join(__dirname, "..", "ABI-compiled.txt");
|
|
67
|
+
const bytecodePath = path.join(__dirname, "..", "Bytecode-compiled.txt");
|
|
68
|
+
|
|
69
|
+
fs.writeFileSync(abiPath, JSON.stringify(abi, null, "\t"), "utf8");
|
|
70
|
+
console.log(`✅ ABI written to: ${path.relative(process.cwd(), abiPath)}`);
|
|
71
|
+
console.log(` ⚠️ Note: This is the COMPILED ABI, not the deployed ABI.txt`);
|
|
72
|
+
|
|
73
|
+
fs.writeFileSync(bytecodePath, bytecode, "utf8");
|
|
74
|
+
console.log(`✅ Bytecode written to: ${path.relative(process.cwd(), bytecodePath)}`);
|
|
75
|
+
console.log(` ⚠️ Note: This is the COMPILED bytecode, not the deployed Bytecode.txt`);
|
|
76
|
+
console.log();
|
|
77
|
+
|
|
78
|
+
// Display summary
|
|
79
|
+
console.log("=".repeat(70));
|
|
80
|
+
console.log("📊 Compilation Summary");
|
|
81
|
+
console.log("=".repeat(70));
|
|
82
|
+
console.log(`Contract: ${contractName}`);
|
|
83
|
+
console.log(`ABI Functions: ${abi.filter(item => item.type === "function").length}`);
|
|
84
|
+
console.log(`Bytecode Length: ${bytecode.length} characters (${Math.floor(bytecode.length / 2)} bytes)`);
|
|
85
|
+
console.log();
|
|
86
|
+
console.log("⚠️ IMPORTANT: These are COMPILED files, not the deployed files!");
|
|
87
|
+
console.log(" - ABI-compiled.txt: Newly compiled ABI");
|
|
88
|
+
console.log(" - Bytecode-compiled.txt: Newly compiled bytecode");
|
|
89
|
+
console.log();
|
|
90
|
+
console.log(" The deployed files (ABI.txt and Bytecode.txt) were NOT modified.");
|
|
91
|
+
console.log(" To use the new compilation for deployment:");
|
|
92
|
+
console.log(" 1. Review the compiled files");
|
|
93
|
+
console.log(" 2. If correct, manually copy them to ABI.txt and Bytecode.txt");
|
|
94
|
+
console.log(" 3. Then use deploy-interactive.js to deploy");
|
|
95
|
+
console.log();
|
|
96
|
+
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error();
|
|
99
|
+
console.error("❌ Error during compilation:");
|
|
100
|
+
console.error(error.message);
|
|
101
|
+
if (error.stack) {
|
|
102
|
+
console.error();
|
|
103
|
+
console.error("Stack trace:");
|
|
104
|
+
console.error(error.stack);
|
|
105
|
+
}
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Run the script
|
|
111
|
+
main()
|
|
112
|
+
.then(() => {
|
|
113
|
+
process.exit(0);
|
|
114
|
+
})
|
|
115
|
+
.catch((error) => {
|
|
116
|
+
console.error(error);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
});
|
|
119
|
+
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Contract Verification Script for NeoZip NFT Contract
|
|
5
|
+
*
|
|
6
|
+
* This script verifies a deployed contract on the appropriate blockchain scanner
|
|
7
|
+
* using Hardhat's verify plugin and Etherscan API V2.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* node scripts/verify-contract.js <contractAddress> <network>
|
|
11
|
+
* or
|
|
12
|
+
* yarn verify <contractAddress> <network>
|
|
13
|
+
*
|
|
14
|
+
* Examples:
|
|
15
|
+
* node scripts/verify-contract.js 0x1234...5678 arbitrumSepolia
|
|
16
|
+
* node scripts/verify-contract.js 0x1234...5678 sepolia
|
|
17
|
+
* node scripts/verify-contract.js 0x1234...5678 baseSepolia
|
|
18
|
+
*
|
|
19
|
+
* Supported Networks:
|
|
20
|
+
* - ethereum (Ethereum Mainnet)
|
|
21
|
+
* - sepolia (Ethereum Sepolia)
|
|
22
|
+
* - base (Base Mainnet)
|
|
23
|
+
* - baseSepolia (Base Sepolia)
|
|
24
|
+
* - arbitrum (Arbitrum One)
|
|
25
|
+
* - arbitrumSepolia (Arbitrum Sepolia)
|
|
26
|
+
* - polygon (Polygon Mainnet)
|
|
27
|
+
* - polygonSepolia (Polygon Sepolia)
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
const hre = require("hardhat");
|
|
31
|
+
const path = require("path");
|
|
32
|
+
|
|
33
|
+
// Network name mapping (user-friendly to Hardhat network names)
|
|
34
|
+
const NETWORK_MAP = {
|
|
35
|
+
"eth": "ethereum",
|
|
36
|
+
"ethereum": "ethereum",
|
|
37
|
+
"eth-sepolia": "sepolia",
|
|
38
|
+
"sepolia": "sepolia",
|
|
39
|
+
"base": "base",
|
|
40
|
+
"base-sepolia": "baseSepolia",
|
|
41
|
+
"baseSepolia": "baseSepolia",
|
|
42
|
+
"arbitrum": "arbitrum",
|
|
43
|
+
"arbitrum-one": "arbitrum",
|
|
44
|
+
"arbitrum-sepolia": "arbitrumSepolia",
|
|
45
|
+
"arbitrumSepolia": "arbitrumSepolia",
|
|
46
|
+
"polygon": "polygon",
|
|
47
|
+
"polygon-sepolia": "polygonSepolia",
|
|
48
|
+
"polygonSepolia": "polygonSepolia",
|
|
49
|
+
"amoy": "polygonSepolia"
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
function getNetworkName(userInput) {
|
|
53
|
+
const normalized = userInput.toLowerCase().trim();
|
|
54
|
+
return NETWORK_MAP[normalized] || normalized;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function validateAddress(address) {
|
|
58
|
+
if (!address || typeof address !== "string") {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
// Basic Ethereum address validation
|
|
62
|
+
return /^0x[a-fA-F0-9]{40}$/.test(address);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function main() {
|
|
66
|
+
console.log("=".repeat(70));
|
|
67
|
+
console.log("🔍 NeoZip NFT Contract Verification");
|
|
68
|
+
console.log("=".repeat(70));
|
|
69
|
+
console.log();
|
|
70
|
+
|
|
71
|
+
// Parse command line arguments
|
|
72
|
+
const args = process.argv.slice(2);
|
|
73
|
+
|
|
74
|
+
if (args.length < 2) {
|
|
75
|
+
console.error("❌ Error: Missing required arguments");
|
|
76
|
+
console.error();
|
|
77
|
+
console.error("Usage: node scripts/verify-contract.js <contractAddress> <network>");
|
|
78
|
+
console.error();
|
|
79
|
+
console.error("Examples:");
|
|
80
|
+
console.error(" node scripts/verify-contract.js 0x1234...5678 arbitrumSepolia");
|
|
81
|
+
console.error(" node scripts/verify-contract.js 0x1234...5678 sepolia");
|
|
82
|
+
console.error();
|
|
83
|
+
console.error("Supported networks:");
|
|
84
|
+
console.error(" - ethereum, sepolia");
|
|
85
|
+
console.error(" - base, baseSepolia");
|
|
86
|
+
console.error(" - arbitrum, arbitrumSepolia");
|
|
87
|
+
console.error(" - polygon, polygonSepolia");
|
|
88
|
+
console.error();
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const contractAddress = args[0];
|
|
93
|
+
const networkInput = args[1];
|
|
94
|
+
const networkName = getNetworkName(networkInput);
|
|
95
|
+
|
|
96
|
+
// Validate contract address
|
|
97
|
+
if (!validateAddress(contractAddress)) {
|
|
98
|
+
console.error(`❌ Error: Invalid contract address: ${contractAddress}`);
|
|
99
|
+
console.error(" Address must be a valid Ethereum address (0x followed by 40 hex characters)");
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Check if network is configured
|
|
104
|
+
const networks = hre.config.networks;
|
|
105
|
+
if (!networks[networkName]) {
|
|
106
|
+
console.error(`❌ Error: Network '${networkName}' is not configured in hardhat.config.js`);
|
|
107
|
+
console.error();
|
|
108
|
+
console.error("Available networks:");
|
|
109
|
+
Object.keys(networks).forEach(net => {
|
|
110
|
+
console.error(` - ${net}`);
|
|
111
|
+
});
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Check for API key
|
|
116
|
+
const apiKey = hre.config.etherscan?.apiKey?.[networkName] ||
|
|
117
|
+
hre.config.etherscan?.apiKey?.mainnet ||
|
|
118
|
+
process.env.ETHERSCAN_API_KEY;
|
|
119
|
+
|
|
120
|
+
if (!apiKey) {
|
|
121
|
+
console.error("❌ Error: Etherscan API key not found");
|
|
122
|
+
console.error();
|
|
123
|
+
console.error("Please set one of the following:");
|
|
124
|
+
console.error(" - ETHERSCAN_API_KEY environment variable");
|
|
125
|
+
console.error(" - etherscan.apiKey in hardhat.config.js");
|
|
126
|
+
console.error();
|
|
127
|
+
console.error("Get your API key from:");
|
|
128
|
+
console.error(" https://etherscan.io/apis (works for all Etherscan-based explorers)");
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
console.log(`📋 Contract Address: ${contractAddress}`);
|
|
133
|
+
console.log(`🌐 Network: ${networkName}`);
|
|
134
|
+
console.log();
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
console.log("🔍 Verifying contract on blockchain scanner...");
|
|
138
|
+
console.log(" This may take a few moments...");
|
|
139
|
+
console.log();
|
|
140
|
+
|
|
141
|
+
// Verify the contract
|
|
142
|
+
// The contract has no constructor arguments
|
|
143
|
+
await hre.run("verify:verify", {
|
|
144
|
+
address: contractAddress,
|
|
145
|
+
network: networkName
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
console.log();
|
|
149
|
+
console.log("=".repeat(70));
|
|
150
|
+
console.log("✅ Contract verified successfully!");
|
|
151
|
+
console.log("=".repeat(70));
|
|
152
|
+
console.log();
|
|
153
|
+
|
|
154
|
+
// Get explorer URL
|
|
155
|
+
const networkConfig = networks[networkName];
|
|
156
|
+
let explorerUrl = "";
|
|
157
|
+
|
|
158
|
+
if (networkName === "sepolia") {
|
|
159
|
+
explorerUrl = `https://sepolia.etherscan.io/address/${contractAddress}`;
|
|
160
|
+
} else if (networkName === "ethereum") {
|
|
161
|
+
explorerUrl = `https://etherscan.io/address/${contractAddress}`;
|
|
162
|
+
} else if (networkName === "baseSepolia") {
|
|
163
|
+
explorerUrl = `https://sepolia.basescan.org/address/${contractAddress}`;
|
|
164
|
+
} else if (networkName === "base") {
|
|
165
|
+
explorerUrl = `https://basescan.org/address/${contractAddress}`;
|
|
166
|
+
} else if (networkName === "arbitrumSepolia") {
|
|
167
|
+
explorerUrl = `https://sepolia.arbiscan.io/address/${contractAddress}`;
|
|
168
|
+
} else if (networkName === "arbitrum") {
|
|
169
|
+
explorerUrl = `https://arbiscan.io/address/${contractAddress}`;
|
|
170
|
+
} else if (networkName === "polygonSepolia") {
|
|
171
|
+
explorerUrl = `https://amoy.polygonscan.com/address/${contractAddress}`;
|
|
172
|
+
} else if (networkName === "polygon") {
|
|
173
|
+
explorerUrl = `https://polygonscan.com/address/${contractAddress}`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (explorerUrl) {
|
|
177
|
+
console.log(`🔗 View contract on explorer:`);
|
|
178
|
+
console.log(` ${explorerUrl}`);
|
|
179
|
+
console.log();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
} catch (error) {
|
|
183
|
+
console.error();
|
|
184
|
+
console.error("❌ Verification failed:");
|
|
185
|
+
|
|
186
|
+
if (error.message.includes("Already Verified")) {
|
|
187
|
+
console.error(" Contract is already verified on the explorer.");
|
|
188
|
+
console.error(" This is not an error - the contract is already public.");
|
|
189
|
+
} else if (error.message.includes("bytecode")) {
|
|
190
|
+
console.error(" Bytecode mismatch detected.");
|
|
191
|
+
console.error(" This usually means:");
|
|
192
|
+
console.error(" 1. The contract was compiled with different settings");
|
|
193
|
+
console.error(" 2. The contract source code has changed");
|
|
194
|
+
console.error(" 3. The deployed bytecode doesn't match the source");
|
|
195
|
+
console.error();
|
|
196
|
+
console.error(" Solution:");
|
|
197
|
+
console.error(" 1. Recompile the contract: yarn compile:extract");
|
|
198
|
+
console.error(" 2. Redeploy with the new bytecode");
|
|
199
|
+
console.error(" 3. Or verify using the exact compiler settings used for deployment");
|
|
200
|
+
} else {
|
|
201
|
+
console.error(` ${error.message}`);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (error.stack && !error.message.includes("Already Verified")) {
|
|
205
|
+
console.error();
|
|
206
|
+
console.error("Stack trace:");
|
|
207
|
+
console.error(error.stack);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
process.exit(1);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Run the script
|
|
215
|
+
main()
|
|
216
|
+
.then(() => {
|
|
217
|
+
process.exit(0);
|
|
218
|
+
})
|
|
219
|
+
.catch((error) => {
|
|
220
|
+
console.error("Unexpected error:", error);
|
|
221
|
+
process.exit(1);
|
|
222
|
+
});
|
|
223
|
+
|
|
@@ -6,33 +6,31 @@ import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
|
|
|
6
6
|
import "@openzeppelin/contracts/access/Ownable.sol";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* @title NZIP NFT
|
|
10
|
-
* @dev
|
|
9
|
+
* @title NZIP NFT Contract v2.0
|
|
10
|
+
* @dev Main NFT contract for tokenizing ZIP files with blockchain metadata
|
|
11
11
|
* Features:
|
|
12
|
-
* - Blockchain metadata (block number, timestamps)
|
|
12
|
+
* - Blockchain metadata (block number, timestamps)
|
|
13
13
|
* - Multiple tokens allowed for same content (differentiated by timestamp)
|
|
14
|
-
* - PRIVATE access control - only token owners can verify their tokens
|
|
15
14
|
* - Enhanced events with blockchain context
|
|
16
|
-
* -
|
|
15
|
+
* - Structured data organization for better maintainability
|
|
17
16
|
* - Improved input validation and error handling
|
|
18
17
|
* - Removed unreliable block hash storage
|
|
19
18
|
*
|
|
20
19
|
* Version: 2.0 (New Production Contract - Previous contract deprecated)
|
|
20
|
+
* Previous Contract: 0xb78CB3bcC788fca38c731b1E9D70CF60b04CA015 (DEPRECATED)
|
|
21
21
|
* Network: Base Sepolia (for testing) / Base Mainnet (for production)
|
|
22
|
-
*
|
|
23
|
-
* Privacy Model: Owner-controlled verification with optional authorization
|
|
24
22
|
*/
|
|
25
|
-
contract
|
|
23
|
+
contract ZipFileNFT is ERC721, ERC721URIStorage, Ownable {
|
|
26
24
|
|
|
27
25
|
// Counter for token IDs
|
|
28
26
|
uint256 private _tokenIdCounter;
|
|
29
27
|
|
|
30
|
-
// Struct to store ZIP file information - Latest
|
|
28
|
+
// Struct to store ZIP file information - Latest Version
|
|
31
29
|
struct ZipFileInfo {
|
|
32
30
|
// File identification
|
|
33
31
|
string fileName; // Original ZIP file name
|
|
34
|
-
string merkleRootHash; // Merkle root hash of the ZIP contents
|
|
35
|
-
string ipfsHash; // IPFS hash where the ZIP file is stored
|
|
32
|
+
string merkleRootHash; // Merkle root hash of the ZIP contents
|
|
33
|
+
string ipfsHash; // IPFS hash where the ZIP file is stored
|
|
36
34
|
address creator; // Address that created/minted this token
|
|
37
35
|
|
|
38
36
|
// Timestamps (grouped together)
|
|
@@ -41,63 +39,28 @@ contract ZipFileNFTPrivate is ERC721, ERC721URIStorage, Ownable {
|
|
|
41
39
|
|
|
42
40
|
// Blockchain metadata
|
|
43
41
|
uint256 blockNumber; // Block number when the token was minted
|
|
44
|
-
// Note: Block hash removed - blockhash(block.number) always returns 0
|
|
45
42
|
}
|
|
46
43
|
|
|
47
|
-
//
|
|
48
|
-
mapping(uint256 => ZipFileInfo)
|
|
44
|
+
// Mapping from token ID to ZIP file information
|
|
45
|
+
mapping(uint256 => ZipFileInfo) public zipFileInfo;
|
|
49
46
|
|
|
50
47
|
// Mapping from composite key (merkleRoot + timestamp) to token ID
|
|
51
48
|
// This prevents duplicate tokens with same content AND same timestamp
|
|
52
|
-
mapping(bytes32 => uint256)
|
|
53
|
-
|
|
54
|
-
// Authorization system - token owners can authorize specific addresses for verification
|
|
55
|
-
mapping(uint256 => mapping(address => bool)) public authorizedVerifiers;
|
|
49
|
+
mapping(bytes32 => uint256) public compositeKeyToTokenId;
|
|
56
50
|
|
|
57
|
-
// Events - Enhanced with blockchain metadata
|
|
58
|
-
// Note: merkleRootHash included for verification - privacy handled via access control
|
|
59
|
-
// Note: ipfsHash excluded from event for privacy
|
|
60
|
-
// Note: Block hash removed - not reliably available during execution
|
|
51
|
+
// Events - Enhanced with blockchain metadata
|
|
61
52
|
event ZipFileTokenized(
|
|
62
53
|
uint256 indexed tokenId,
|
|
63
54
|
address indexed creator,
|
|
64
55
|
string fileName,
|
|
65
56
|
string merkleRootHash,
|
|
66
57
|
uint256 creationTimestamp,
|
|
58
|
+
string ipfsHash,
|
|
67
59
|
uint256 tokenizationTime,
|
|
68
60
|
uint256 blockNumber
|
|
69
61
|
);
|
|
70
62
|
|
|
71
|
-
|
|
72
|
-
uint256 indexed tokenId,
|
|
73
|
-
address indexed authorizedAddress,
|
|
74
|
-
bool authorized
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
// Custom errors
|
|
78
|
-
error NotTokenOwner(uint256 tokenId, address caller);
|
|
79
|
-
error NotAuthorized(uint256 tokenId, address caller);
|
|
80
|
-
error TokenDoesNotExist(uint256 tokenId);
|
|
81
|
-
error ZipFileAlreadyTokenized(string merkleRootHash, uint256 timestamp);
|
|
82
|
-
|
|
83
|
-
// Access control modifier
|
|
84
|
-
modifier onlyTokenOwner(uint256 tokenId) {
|
|
85
|
-
if (ownerOf(tokenId) != msg.sender) {
|
|
86
|
-
revert NotTokenOwner(tokenId, msg.sender);
|
|
87
|
-
}
|
|
88
|
-
_;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Access control modifier for authorized verifiers
|
|
92
|
-
modifier onlyAuthorized(uint256 tokenId) {
|
|
93
|
-
address owner = ownerOf(tokenId);
|
|
94
|
-
if (owner != msg.sender && !authorizedVerifiers[tokenId][msg.sender]) {
|
|
95
|
-
revert NotAuthorized(tokenId, msg.sender);
|
|
96
|
-
}
|
|
97
|
-
_;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
constructor() ERC721("NeoZip File NFT Private v2", "NZIPPRV") Ownable(msg.sender) {}
|
|
63
|
+
constructor() ERC721("NeoZip File NFT v2", "NZIP") Ownable(msg.sender) {}
|
|
101
64
|
|
|
102
65
|
/**
|
|
103
66
|
* @dev Get the contract version
|
|
@@ -145,9 +108,7 @@ contract ZipFileNFTPrivate is ERC721, ERC721URIStorage, Ownable {
|
|
|
145
108
|
bytes32 compositeKey = generateCompositeKey(merkleRootHash, creationTimestamp);
|
|
146
109
|
|
|
147
110
|
// Check if this exact combination already exists
|
|
148
|
-
|
|
149
|
-
revert ZipFileAlreadyTokenized(merkleRootHash, creationTimestamp);
|
|
150
|
-
}
|
|
111
|
+
require(compositeKeyToTokenId[compositeKey] == 0, "ZIP file with this content and timestamp already tokenized");
|
|
151
112
|
|
|
152
113
|
// Increment token counter
|
|
153
114
|
_tokenIdCounter++;
|
|
@@ -175,13 +136,14 @@ contract ZipFileNFTPrivate is ERC721, ERC721URIStorage, Ownable {
|
|
|
175
136
|
// Store the composite key mapping
|
|
176
137
|
compositeKeyToTokenId[compositeKey] = tokenId;
|
|
177
138
|
|
|
178
|
-
// Emit event with
|
|
139
|
+
// Emit event with blockchain metadata
|
|
179
140
|
emit ZipFileTokenized(
|
|
180
141
|
tokenId,
|
|
181
142
|
msg.sender,
|
|
182
143
|
fileName,
|
|
183
144
|
merkleRootHash,
|
|
184
145
|
creationTimestamp,
|
|
146
|
+
ipfsHash,
|
|
185
147
|
block.timestamp,
|
|
186
148
|
block.number
|
|
187
149
|
);
|
|
@@ -190,46 +152,21 @@ contract ZipFileNFTPrivate is ERC721, ERC721URIStorage, Ownable {
|
|
|
190
152
|
}
|
|
191
153
|
|
|
192
154
|
/**
|
|
193
|
-
* @dev Get ZIP file information for a token
|
|
155
|
+
* @dev Get ZIP file information for a token
|
|
194
156
|
* @param tokenId The token ID to query
|
|
195
157
|
* @return ZipFileInfo struct containing all file and blockchain metadata
|
|
196
158
|
*/
|
|
197
|
-
function getZipFileInfo(uint256 tokenId) external view
|
|
198
|
-
|
|
199
|
-
revert TokenDoesNotExist(tokenId);
|
|
200
|
-
}
|
|
159
|
+
function getZipFileInfo(uint256 tokenId) external view returns (ZipFileInfo memory) {
|
|
160
|
+
require(_ownerOf(tokenId) != address(0), "Token does not exist");
|
|
201
161
|
return zipFileInfo[tokenId];
|
|
202
162
|
}
|
|
203
163
|
|
|
204
164
|
/**
|
|
205
|
-
* @dev
|
|
206
|
-
* @param tokenId The token ID to query
|
|
207
|
-
* @return fileName The file name
|
|
208
|
-
* @return creator The creator address
|
|
209
|
-
* @return tokenizationTime When the token was minted
|
|
210
|
-
* @return blockNumber Block number when minted
|
|
211
|
-
*/
|
|
212
|
-
function getPublicTokenInfo(uint256 tokenId) external view returns (
|
|
213
|
-
string memory fileName,
|
|
214
|
-
address creator,
|
|
215
|
-
uint256 tokenizationTime,
|
|
216
|
-
uint256 blockNumber
|
|
217
|
-
) {
|
|
218
|
-
if (_ownerOf(tokenId) == address(0)) {
|
|
219
|
-
revert TokenDoesNotExist(tokenId);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
ZipFileInfo memory info = zipFileInfo[tokenId];
|
|
223
|
-
return (info.fileName, info.creator, info.tokenizationTime, info.blockNumber);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* @dev Check if a ZIP file is already tokenized (for minting validation)
|
|
165
|
+
* @dev Check if a ZIP file is already tokenized
|
|
228
166
|
* @param merkleRootHash The merkle root hash to check
|
|
229
167
|
* @param creationTimestamp The creation timestamp to check
|
|
230
168
|
* @return exists Whether the combination exists
|
|
231
169
|
* @return tokenId The token ID if it exists (0 if not)
|
|
232
|
-
* Note: This is public for minting validation, but doesn't reveal token details
|
|
233
170
|
*/
|
|
234
171
|
function isZipFileTokenized(
|
|
235
172
|
string memory merkleRootHash,
|
|
@@ -241,62 +178,46 @@ contract ZipFileNFTPrivate is ERC721, ERC721URIStorage, Ownable {
|
|
|
241
178
|
}
|
|
242
179
|
|
|
243
180
|
/**
|
|
244
|
-
* @dev
|
|
245
|
-
* @param
|
|
246
|
-
* @
|
|
247
|
-
* @return isValid Whether the token matches the provided merkle root
|
|
181
|
+
* @dev Get all token IDs for a specific merkle root (across all timestamps)
|
|
182
|
+
* @param merkleRoot The merkle root to search for
|
|
183
|
+
* @return tokenIds Array of token IDs with this merkle root
|
|
248
184
|
*/
|
|
249
|
-
function
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
185
|
+
function getTokensByMerkleRoot(string memory merkleRoot) external view returns (uint256[] memory) {
|
|
186
|
+
// Create dynamic array to collect matching tokens
|
|
187
|
+
uint256[] memory tempTokens = new uint256[](_tokenIdCounter);
|
|
188
|
+
uint256 count = 0;
|
|
189
|
+
|
|
190
|
+
// Search through all tokens
|
|
191
|
+
for (uint256 i = 1; i <= _tokenIdCounter; i++) {
|
|
192
|
+
if (_ownerOf(i) != address(0)) { // Token exists
|
|
193
|
+
if (keccak256(abi.encodePacked(zipFileInfo[i].merkleRootHash)) ==
|
|
194
|
+
keccak256(abi.encodePacked(merkleRoot))) {
|
|
195
|
+
tempTokens[count] = i;
|
|
196
|
+
count++;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
253
199
|
}
|
|
254
200
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
* @param authorizedAddress The address to authorize or revoke
|
|
263
|
-
* @param authorized Whether to grant or revoke access
|
|
264
|
-
*/
|
|
265
|
-
function authorizeVerifier(
|
|
266
|
-
uint256 tokenId,
|
|
267
|
-
address authorizedAddress,
|
|
268
|
-
bool authorized
|
|
269
|
-
) external onlyTokenOwner(tokenId) {
|
|
270
|
-
authorizedVerifiers[tokenId][authorizedAddress] = authorized;
|
|
271
|
-
emit VerifierAuthorized(tokenId, authorizedAddress, authorized);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* @dev Check if an address is authorized to verify a specific token
|
|
276
|
-
* @param tokenId The token ID to check
|
|
277
|
-
* @param verifierAddress The address to check authorization for
|
|
278
|
-
* @return Whether the address is authorized
|
|
279
|
-
*/
|
|
280
|
-
function isAuthorizedVerifier(uint256 tokenId, address verifierAddress)
|
|
281
|
-
external view returns (bool) {
|
|
282
|
-
return authorizedVerifiers[tokenId][verifierAddress];
|
|
201
|
+
// Create result array with exact size
|
|
202
|
+
uint256[] memory result = new uint256[](count);
|
|
203
|
+
for (uint256 i = 0; i < count; i++) {
|
|
204
|
+
result[i] = tempTokens[i];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return result;
|
|
283
208
|
}
|
|
284
209
|
|
|
285
210
|
/**
|
|
286
|
-
* @dev
|
|
287
|
-
* @param tokenId The token ID to
|
|
288
|
-
* @
|
|
289
|
-
* @return
|
|
211
|
+
* @dev Verify that a token matches the provided merkle root
|
|
212
|
+
* @param tokenId The token ID to verify
|
|
213
|
+
* @param providedMerkleRoot The merkle root to check against
|
|
214
|
+
* @return isValid Whether the token matches the provided merkle root
|
|
290
215
|
*/
|
|
291
|
-
function
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
revert TokenDoesNotExist(tokenId);
|
|
297
|
-
}
|
|
298
|
-
ZipFileInfo memory info = zipFileInfo[tokenId];
|
|
299
|
-
return (info.blockNumber, info.tokenizationTime);
|
|
216
|
+
function verifyZipFile(uint256 tokenId, string memory providedMerkleRoot) external view returns (bool isValid) {
|
|
217
|
+
require(_ownerOf(tokenId) != address(0), "Token does not exist");
|
|
218
|
+
|
|
219
|
+
return keccak256(abi.encodePacked(zipFileInfo[tokenId].merkleRootHash)) ==
|
|
220
|
+
keccak256(abi.encodePacked(providedMerkleRoot));
|
|
300
221
|
}
|
|
301
222
|
|
|
302
223
|
/**
|
|
@@ -318,24 +239,18 @@ contract ZipFileNFTPrivate is ERC721, ERC721URIStorage, Ownable {
|
|
|
318
239
|
}
|
|
319
240
|
|
|
320
241
|
/**
|
|
321
|
-
* @dev Get
|
|
322
|
-
* @param
|
|
323
|
-
* @return
|
|
242
|
+
* @dev Get blockchain metadata for a token
|
|
243
|
+
* @param tokenId The token ID to query
|
|
244
|
+
* @return blockNumber Block number when token was minted
|
|
245
|
+
* @return tokenizationTime Exact timestamp when token was minted
|
|
324
246
|
*/
|
|
325
|
-
function
|
|
326
|
-
uint256
|
|
327
|
-
uint256
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
result[counter] = i;
|
|
333
|
-
counter++;
|
|
334
|
-
if (counter >= balance) break;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
return result;
|
|
247
|
+
function getBlockchainMetadata(uint256 tokenId) public view returns (
|
|
248
|
+
uint256 blockNumber,
|
|
249
|
+
uint256 tokenizationTime
|
|
250
|
+
) {
|
|
251
|
+
require(_ownerOf(tokenId) != address(0), "Token does not exist");
|
|
252
|
+
ZipFileInfo memory info = zipFileInfo[tokenId];
|
|
253
|
+
return (info.blockNumber, info.tokenizationTime);
|
|
339
254
|
}
|
|
340
255
|
|
|
341
256
|
// Override required by Solidity
|