neozip-blockchain 0.5.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 (127) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +189 -0
  3. package/dist/browser/TokenVerifierBrowser.d.ts +63 -0
  4. package/dist/browser/TokenVerifierBrowser.d.ts.map +1 -0
  5. package/dist/browser/TokenVerifierBrowser.js +358 -0
  6. package/dist/browser/TokenVerifierBrowser.js.map +1 -0
  7. package/dist/browser/WalletManagerBrowser.d.ts +99 -0
  8. package/dist/browser/WalletManagerBrowser.d.ts.map +1 -0
  9. package/dist/browser/WalletManagerBrowser.js +434 -0
  10. package/dist/browser/WalletManagerBrowser.js.map +1 -0
  11. package/dist/browser/ZipkitMinterBrowser.d.ts +59 -0
  12. package/dist/browser/ZipkitMinterBrowser.d.ts.map +1 -0
  13. package/dist/browser/ZipkitMinterBrowser.js +337 -0
  14. package/dist/browser/ZipkitMinterBrowser.js.map +1 -0
  15. package/dist/browser/index.d.ts +12 -0
  16. package/dist/browser/index.d.ts.map +1 -0
  17. package/dist/browser/index.js +19 -0
  18. package/dist/browser/index.js.map +1 -0
  19. package/dist/constants/index.d.ts +5 -0
  20. package/dist/constants/index.d.ts.map +1 -0
  21. package/dist/constants/index.js +21 -0
  22. package/dist/constants/index.js.map +1 -0
  23. package/dist/constants/metadata.d.ts +18 -0
  24. package/dist/constants/metadata.d.ts.map +1 -0
  25. package/dist/constants/metadata.js +33 -0
  26. package/dist/constants/metadata.js.map +1 -0
  27. package/dist/constants/servers.d.ts +38 -0
  28. package/dist/constants/servers.d.ts.map +1 -0
  29. package/dist/constants/servers.js +54 -0
  30. package/dist/constants/servers.js.map +1 -0
  31. package/dist/core/ContractVersionRegistry.d.ts +63 -0
  32. package/dist/core/ContractVersionRegistry.d.ts.map +1 -0
  33. package/dist/core/ContractVersionRegistry.js +128 -0
  34. package/dist/core/ContractVersionRegistry.js.map +1 -0
  35. package/dist/core/WalletManager.d.ts +123 -0
  36. package/dist/core/WalletManager.d.ts.map +1 -0
  37. package/dist/core/WalletManager.js +360 -0
  38. package/dist/core/WalletManager.js.map +1 -0
  39. package/dist/core/ZipkitMinter.d.ts +155 -0
  40. package/dist/core/ZipkitMinter.d.ts.map +1 -0
  41. package/dist/core/ZipkitMinter.js +625 -0
  42. package/dist/core/ZipkitMinter.js.map +1 -0
  43. package/dist/core/ZipkitVerifier.d.ts +252 -0
  44. package/dist/core/ZipkitVerifier.d.ts.map +1 -0
  45. package/dist/core/ZipkitVerifier.js +1370 -0
  46. package/dist/core/ZipkitVerifier.js.map +1 -0
  47. package/dist/core/adapters/AdapterFactory.d.ts +22 -0
  48. package/dist/core/adapters/AdapterFactory.d.ts.map +1 -0
  49. package/dist/core/adapters/AdapterFactory.js +62 -0
  50. package/dist/core/adapters/AdapterFactory.js.map +1 -0
  51. package/dist/core/adapters/ContractVersionAdapter.d.ts +96 -0
  52. package/dist/core/adapters/ContractVersionAdapter.d.ts.map +1 -0
  53. package/dist/core/adapters/ContractVersionAdapter.js +9 -0
  54. package/dist/core/adapters/ContractVersionAdapter.js.map +1 -0
  55. package/dist/core/adapters/V2_10Adapter.d.ts +24 -0
  56. package/dist/core/adapters/V2_10Adapter.d.ts.map +1 -0
  57. package/dist/core/adapters/V2_10Adapter.js +87 -0
  58. package/dist/core/adapters/V2_10Adapter.js.map +1 -0
  59. package/dist/core/adapters/V2_11Adapter.d.ts +24 -0
  60. package/dist/core/adapters/V2_11Adapter.d.ts.map +1 -0
  61. package/dist/core/adapters/V2_11Adapter.js +87 -0
  62. package/dist/core/adapters/V2_11Adapter.js.map +1 -0
  63. package/dist/core/adapters/V2_50Adapter.d.ts +105 -0
  64. package/dist/core/adapters/V2_50Adapter.d.ts.map +1 -0
  65. package/dist/core/adapters/V2_50Adapter.js +263 -0
  66. package/dist/core/adapters/V2_50Adapter.js.map +1 -0
  67. package/dist/core/contracts.d.ts +169 -0
  68. package/dist/core/contracts.d.ts.map +1 -0
  69. package/dist/core/contracts.js +731 -0
  70. package/dist/core/contracts.js.map +1 -0
  71. package/dist/core/index.d.ts +24 -0
  72. package/dist/core/index.d.ts.map +1 -0
  73. package/dist/core/index.js +82 -0
  74. package/dist/core/index.js.map +1 -0
  75. package/dist/index.d.ts +15 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +40 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/node/WalletManagerNode.d.ts +47 -0
  80. package/dist/node/WalletManagerNode.d.ts.map +1 -0
  81. package/dist/node/WalletManagerNode.js +203 -0
  82. package/dist/node/WalletManagerNode.js.map +1 -0
  83. package/dist/node/index.d.ts +12 -0
  84. package/dist/node/index.d.ts.map +1 -0
  85. package/dist/node/index.js +21 -0
  86. package/dist/node/index.js.map +1 -0
  87. package/dist/ots/ZipkitOTS.d.ts +152 -0
  88. package/dist/ots/ZipkitOTS.d.ts.map +1 -0
  89. package/dist/ots/ZipkitOTS.js +544 -0
  90. package/dist/ots/ZipkitOTS.js.map +1 -0
  91. package/dist/ots/index.d.ts +9 -0
  92. package/dist/ots/index.d.ts.map +1 -0
  93. package/dist/ots/index.js +25 -0
  94. package/dist/ots/index.js.map +1 -0
  95. package/dist/types/index.d.ts +84 -0
  96. package/dist/types/index.d.ts.map +1 -0
  97. package/dist/types/index.js +37 -0
  98. package/dist/types/index.js.map +1 -0
  99. package/dist/utils/Logger.d.ts +73 -0
  100. package/dist/utils/Logger.d.ts.map +1 -0
  101. package/dist/utils/Logger.js +156 -0
  102. package/dist/utils/Logger.js.map +1 -0
  103. package/dist/utils/crc32.d.ts +6 -0
  104. package/dist/utils/crc32.d.ts.map +1 -0
  105. package/dist/utils/crc32.js +23 -0
  106. package/dist/utils/crc32.js.map +1 -0
  107. package/dist/zipstamp-server/CalendarManager.d.ts +238 -0
  108. package/dist/zipstamp-server/CalendarManager.d.ts.map +1 -0
  109. package/dist/zipstamp-server/CalendarManager.js +364 -0
  110. package/dist/zipstamp-server/CalendarManager.js.map +1 -0
  111. package/dist/zipstamp-server/ZipstampServerAPI.d.ts +427 -0
  112. package/dist/zipstamp-server/ZipstampServerAPI.d.ts.map +1 -0
  113. package/dist/zipstamp-server/ZipstampServerAPI.js +696 -0
  114. package/dist/zipstamp-server/ZipstampServerAPI.js.map +1 -0
  115. package/dist/zipstamp-server/ZipstampServerClient.d.ts +590 -0
  116. package/dist/zipstamp-server/ZipstampServerClient.d.ts.map +1 -0
  117. package/dist/zipstamp-server/ZipstampServerClient.js +433 -0
  118. package/dist/zipstamp-server/ZipstampServerClient.js.map +1 -0
  119. package/dist/zipstamp-server/ZipstampServerHelpers.d.ts +430 -0
  120. package/dist/zipstamp-server/ZipstampServerHelpers.d.ts.map +1 -0
  121. package/dist/zipstamp-server/ZipstampServerHelpers.js +503 -0
  122. package/dist/zipstamp-server/ZipstampServerHelpers.js.map +1 -0
  123. package/dist/zipstamp-server/index.d.ts +24 -0
  124. package/dist/zipstamp-server/index.d.ts.map +1 -0
  125. package/dist/zipstamp-server/index.js +67 -0
  126. package/dist/zipstamp-server/index.js.map +1 -0
  127. package/package.json +117 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 NeoWare, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,189 @@
1
+ # neozip-blockchain
2
+
3
+ **Open-source companion to [neozipkit](https://www.npmjs.com/package/neozipkit)** — blockchain functionality for NeoZip: **Zipstamp server timestamping** (stamp, upgrade, mint, verify), NFT minting, verification, and wallet management.
4
+
5
+ > **Pre-1.0:** This package is under active development. The API may change before 1.0; use in production with caution.
6
+
7
+ This repository provides the client-side API and utilities that work with the **neozipkit** NPM package for full NZIP (NeoZip) workflows. The **Zipstamp server** is a **separate application**; this library contains the **Zipstamp server API client and helpers** used to communicate with that server (submit digests, poll for confirmations, fetch proofs, etc.). Run the Zipstamp server separately when using timestamping features.
8
+
9
+ ## Features
10
+
11
+ - **Zipstamp server timestamping** (recommended): Submit digest to Zipstamp server, batch to blockchain, upgrade to TIMESTAMP.NZIP, mint NFT proof. Uses the **Zipstamp server API** in this repo to talk to a **separate Zipstamp server application**.
12
+ - **NFT Minting**: Mint ZIP file hashes as NFTs on Base network
13
+ - **Token Verification**: Verify ZIP file authenticity against blockchain
14
+ - **Wallet Management**: Browser and Node.js wallet integrations
15
+ - **Multi-Network Support**: Base Mainnet, Base Sepolia, and more
16
+ - **Examples**: Runnable scripts for stamp, upgrade, mint, verify, and token-create flows (see `examples/` and `examples/README.md`)
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install neozip-blockchain
22
+ # or
23
+ yarn add neozip-blockchain
24
+ ```
25
+
26
+ For full NZIP creation and verification you typically use **neozipkit** together with this package:
27
+
28
+ ```bash
29
+ npm install neozipkit neozip-blockchain
30
+ ```
31
+
32
+ ## Zipstamp server (separate application)
33
+
34
+ The **Zipstamp server** is a **separate application** (not part of this repo). It runs the backend that batches digest submissions and writes timestamps to the blockchain. This library provides the **Zipstamp server API client and helpers** (`src/zipstamp-server/`) used by your app to:
35
+
36
+ - Submit digests and poll for confirmations
37
+ - Fetch TIMESTAMP.NZIP and proof data
38
+ - Support stamp → upgrade → mint workflows
39
+
40
+ Configure your app with the Zipstamp server URL (e.g. `ZIPSTAMP_SERVER_URL`) and run the Zipstamp server separately when using timestamping features. See `examples/` and `.env.sample` for usage.
41
+
42
+ ## Quick Start
43
+
44
+ ### Minting a ZIP File NFT
45
+
46
+ ```typescript
47
+ import { ZipkitMinter } from 'neozip-blockchain';
48
+
49
+ const minter = new ZipkitMinter('merkleRoot123...', {
50
+ walletPrivateKey: '0x...',
51
+ network: 'base-sepolia'
52
+ });
53
+
54
+ const result = await minter.mintToken();
55
+ console.log(`Token ID: ${result.tokenId}`);
56
+ ```
57
+
58
+ ### Verifying a Token
59
+
60
+ ```typescript
61
+ import { ZipkitVerifier } from 'neozip-blockchain';
62
+
63
+ const verifier = new ZipkitVerifier({ debug: false });
64
+
65
+ // Verify token metadata
66
+ const result = await verifier.verifyToken(tokenMetadata);
67
+ if (result.success) {
68
+ console.log('Token verified!');
69
+ }
70
+ ```
71
+
72
+ ### Wallet Management
73
+
74
+ ```typescript
75
+ // Browser
76
+ import { WalletManagerBrowser } from 'neozip-blockchain/browser';
77
+
78
+ const wallet = new WalletManagerBrowser();
79
+ await wallet.connect();
80
+
81
+ // Node.js
82
+ import { WalletManagerNode } from 'neozip-blockchain/node';
83
+
84
+ const wallet = new WalletManagerNode();
85
+ await wallet.setupWallet(privateKey);
86
+ ```
87
+
88
+ ### Zipstamp server timestamping (stamp, upgrade, mint)
89
+
90
+ Use the Zipstamp server to stamp a ZIP (submit digest), upgrade once the batch is confirmed (get TIMESTAMP.NZIP), then mint an NFT. See examples: `stamp-zip`, `upgrade-zip`, `mint-nft`, `token-create`.
91
+
92
+ ## Supported Networks
93
+
94
+ | Network | Chain ID | Status |
95
+ |---------|----------|--------|
96
+ | Base Mainnet | 8453 | Production |
97
+ | Base Sepolia | 84532 | Testnet |
98
+
99
+ ## API Reference
100
+
101
+ ### Core Exports
102
+
103
+ - `ZipkitMinter` - NFT minting functionality
104
+ - `ZipkitVerifier` - Token verification
105
+ - `CoreWalletManager` - Platform-agnostic wallet operations
106
+ - `WalletAnalyzer` - Wallet analysis and token scanning
107
+ - `CONTRACT_CONFIGS` - Network configurations
108
+ - `NZIP_CONTRACT_ABI` - Contract ABI
109
+
110
+ ### Zipstamp server API (client for separate Zipstamp server app)
111
+
112
+ - `ZipstampServerClient` - HTTP client for the Zipstamp server
113
+ - `submitDigest`, `verifyDigest`, `getTimestampProof`, etc. (see `src/zipstamp-server/`) - Helpers and verification used by examples and apps that talk to the Zipstamp server
114
+
115
+ ### Browser Exports
116
+
117
+ - `WalletManagerBrowser` - Browser wallet with MetaMask support
118
+ - `ZipkitMinterBrowser` - Browser-based minting
119
+ - `TokenVerifierBrowser` - Browser token verification
120
+
121
+ ### Node.js Exports
122
+
123
+ - `WalletManagerNode` - Node.js wallet management
124
+ - `ZipkitWallet` - Wallet utilities
125
+
126
+ ## OpenTimestamps (OTS) add-on
127
+
128
+ **Zipstamp server timestamping is the recommended and supported path.** OpenTimestamps (OTS) is provided as an **optional add-on** for Bitcoin-backed timestamps and backward compatibility. OTS may be **deprecated in a future release** in favor of Zipstamp server timestamps.
129
+
130
+ - **Access**: OTS is **not** on the main package entry. Use the subpath: `import { createTimestamp, verifyOtsZip } from 'neozip-blockchain/ots'`
131
+ - **Metadata**: OTS uses `TIMESTAMP.OTS` / `TS-SUBMIT.OTS`; Zipstamp server uses `TIMESTAMP.NZIP` / `TS-SUBMIT.NZIP`.
132
+ - **Functions**: `createTimestamp()`, `verifyOts()`, `verifyOtsZip()`, `deserializeOts()`, `parseVerifyResult()`, `upgradeOTS()`, `createOtsMetadataEntry()`, `getOtsEntry()`, `getOtsBuffer()`, `getMerkleRootSafe()`, `bufferToArrayBuffer()`
133
+ - **Note**: `upgradeOTS()` requires a Zipkit instance from neozipkit for ZIP file manipulation; pass it as the third argument.
134
+
135
+ ## Integration with neozipkit
136
+
137
+ This project is the **open-source companion** to the **[neozipkit](https://www.npmjs.com/package/neozipkit)** NPM package. Use neozipkit for ZIP creation, merkle roots, and file handling; use this package for blockchain timestamping, NFT minting, and verification. They work together for full NZIP workflows:
138
+
139
+ ```typescript
140
+ import { ZipkitNode } from 'neozipkit/node';
141
+ import { ZipkitMinter, ZipkitVerifier } from 'neozip-blockchain';
142
+
143
+ // Create and tokenize a ZIP
144
+ const zip = new ZipkitNode();
145
+ await zip.createZipFromFiles(files, 'archive.zip', { useSHA256: true });
146
+
147
+ // Get merkle root from ZIP
148
+ const merkleRoot = zip.getMerkleRoot();
149
+
150
+ // Mint as NFT
151
+ const minter = new ZipkitMinter(merkleRoot, {
152
+ walletPrivateKey: process.env.WALLET_KEY,
153
+ network: 'base-sepolia'
154
+ });
155
+ const result = await minter.mintToken();
156
+ ```
157
+
158
+ ## Smart Contracts
159
+
160
+ The NZIP-NFT smart contracts are included in the `contracts/` directory:
161
+
162
+ - `NZIP-NFT.sol` - Main NFT contract (v2.11)
163
+ - `NZIP-NFT-v2.10.sol` - Previous version
164
+ - Deployment scripts and configurations
165
+
166
+ ### Contract Versions
167
+
168
+ | Version | Features |
169
+ |---------|----------|
170
+ | v2.11 | encryptedHash support, improved verification |
171
+ | v2.10 | Base production deployment |
172
+
173
+ ## License
174
+
175
+ MIT License - see [LICENSE](LICENSE) for details.
176
+
177
+ ## Contributing
178
+
179
+ Contributions are welcome! Please read our contributing guidelines before submitting PRs.
180
+
181
+ ## Links
182
+
183
+ - [neozipkit (NPM)](https://www.npmjs.com/package/neozipkit) - ZIP file processing library; use with this package for full NZIP workflows
184
+ - [NeoZipKit (source)](https://github.com/NeoWareInc/neozipkit) - Open-source ZIP library repo
185
+ - [Documentation](https://neozip.io/docs)
186
+ - [NeoWare](https://neoware.com)
187
+
188
+ **Note:** The **Zipstamp server** is a separate application (not in this repo). This library only contains the client API used to communicate with it.
189
+
@@ -0,0 +1,63 @@
1
+ import { TokenMetadata, ZipEntryLike, ZipkitLike } from '../types';
2
+ export interface TokenVerificationOptions {
3
+ skipHash?: boolean;
4
+ skipToken?: boolean;
5
+ generateCertificate?: boolean;
6
+ zipFileName?: string;
7
+ }
8
+ export interface TokenVerificationResult {
9
+ isTokenized: boolean;
10
+ tokenMetadata: TokenMetadata | null;
11
+ calculatedMerkleRoot: string | null;
12
+ blockchainMerkleRoot: string | null;
13
+ blockchainTimestamp?: number;
14
+ verificationPassed: boolean;
15
+ certificatePath?: string;
16
+ errorMessage?: string;
17
+ }
18
+ export interface BlockchainVerification {
19
+ merkleRootMatches: boolean;
20
+ blockchainMerkleRoot: string;
21
+ calculatedMerkleRoot: string;
22
+ verificationStatus: 'PASSED' | 'FAILED' | 'UNAVAILABLE';
23
+ verificationTime?: number;
24
+ blockNumber?: number;
25
+ }
26
+ /**
27
+ * Browser-compatible token verification class
28
+ * Works with any Zipkit-like instance for ZIP file operations
29
+ */
30
+ export declare class TokenVerifierBrowser {
31
+ private zipkit;
32
+ constructor(zipkit: ZipkitLike);
33
+ /**
34
+ * Checks if the ZIP file contains NFT token metadata and verifies the merkle root
35
+ */
36
+ checkForTokenization(zipEntries: ZipEntryLike[], options?: TokenVerificationOptions): Promise<TokenVerificationResult>;
37
+ /**
38
+ * Validates token metadata structure
39
+ * Validates required fields: tokenId, contractAddress, network, merkleRoot, networkChainId, contractVersion
40
+ */
41
+ private validateTokenInfo;
42
+ /**
43
+ * Queries the blockchain to get the actual merkle root, timestamp, and owner stored in the smart contract
44
+ */
45
+ private queryBlockchainData;
46
+ /**
47
+ * Helper to convert Blob to string
48
+ */
49
+ private blobToString;
50
+ /**
51
+ * Creates a formatted summary of token information
52
+ */
53
+ createTokenSummary(tokenMetadata: TokenMetadata): string;
54
+ }
55
+ /**
56
+ * Creates a new TokenVerifierBrowser instance
57
+ */
58
+ export declare function createTokenVerifier(zipkit: ZipkitLike): TokenVerifierBrowser;
59
+ /**
60
+ * Convenience function to check for tokenization
61
+ */
62
+ export declare function checkForTokenization(zipkit: ZipkitLike, zipEntries: ZipEntryLike[], options?: TokenVerificationOptions): Promise<TokenVerificationResult>;
63
+ //# sourceMappingURL=TokenVerifierBrowser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenVerifierBrowser.d.ts","sourceRoot":"","sources":["../../src/browser/TokenVerifierBrowser.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAInE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,sBAAsB;IACrC,iBAAiB,EAAE,OAAO,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAKD;;;GAGG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAa;gBAEf,MAAM,EAAE,UAAU;IAI9B;;OAEG;IACG,oBAAoB,CACxB,UAAU,EAAE,YAAY,EAAE,EAC1B,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,uBAAuB,CAAC;IA2LnC;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IA+BzB;;OAEG;YACW,mBAAmB;IA2GjC;;OAEG;YACW,YAAY;IAS1B;;OAEG;IACH,kBAAkB,CAAC,aAAa,EAAE,aAAa,GAAG,MAAM;CAWzD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,oBAAoB,CAE5E;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,YAAY,EAAE,EAC1B,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,uBAAuB,CAAC,CAGlC"}
@@ -0,0 +1,358 @@
1
+ "use strict";
2
+ // ======================================
3
+ // TokenVerifierBrowser.ts
4
+ // Browser-compatible blockchain token verification utilities for ZIP archives
5
+ // Copyright (c) 2025 NeoWare, Inc. All rights reserved.
6
+ // ======================================
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.TokenVerifierBrowser = void 0;
9
+ exports.createTokenVerifier = createTokenVerifier;
10
+ exports.checkForTokenization = checkForTokenization;
11
+ const contracts_1 = require("../core/contracts");
12
+ const ethers_1 = require("ethers");
13
+ // Use the complete contract ABI from constants
14
+ const CONTRACT_ABI = contracts_1.NZIP_CONTRACT_ABI;
15
+ /**
16
+ * Browser-compatible token verification class
17
+ * Works with any Zipkit-like instance for ZIP file operations
18
+ */
19
+ class TokenVerifierBrowser {
20
+ constructor(zipkit) {
21
+ this.zipkit = zipkit;
22
+ }
23
+ /**
24
+ * Checks if the ZIP file contains NFT token metadata and verifies the merkle root
25
+ */
26
+ async checkForTokenization(zipEntries, options = {}) {
27
+ // Look for the tokenized metadata file (check new standard first, then legacy)
28
+ let tokenEntry = zipEntries.find(entry => entry.filename === contracts_1.TOKENIZED_METADATA);
29
+ // Fallback to legacy NZIP.TOKEN for backward compatibility
30
+ if (!tokenEntry) {
31
+ tokenEntry = zipEntries.find(entry => entry.filename === contracts_1.TOKENIZED_METADATA_LEGACY);
32
+ if (tokenEntry && typeof console !== 'undefined' && console.warn) {
33
+ console.warn('[TokenVerifierBrowser] Reading legacy NZIP.TOKEN. Write new files as TOKEN.NZIP.');
34
+ }
35
+ }
36
+ if (!tokenEntry) {
37
+ return {
38
+ isTokenized: false,
39
+ tokenMetadata: null,
40
+ calculatedMerkleRoot: null,
41
+ blockchainMerkleRoot: null,
42
+ verificationPassed: false
43
+ };
44
+ }
45
+ try {
46
+ // Extract the token metadata using the zipkit interface
47
+ const extractMethod = this.zipkit.extractBlob || this.zipkit.extract;
48
+ if (!extractMethod) {
49
+ return {
50
+ isTokenized: false,
51
+ tokenMetadata: null,
52
+ calculatedMerkleRoot: null,
53
+ blockchainMerkleRoot: null,
54
+ verificationPassed: false,
55
+ errorMessage: 'Zipkit instance does not support extraction'
56
+ };
57
+ }
58
+ const tokenData = await extractMethod.call(this.zipkit, tokenEntry);
59
+ if (!tokenData) {
60
+ return {
61
+ isTokenized: false,
62
+ tokenMetadata: null,
63
+ calculatedMerkleRoot: null,
64
+ blockchainMerkleRoot: null,
65
+ verificationPassed: false,
66
+ errorMessage: 'Could not read token metadata'
67
+ };
68
+ }
69
+ // Handle different data formats (Blob, Buffer, ArrayBuffer)
70
+ let tokenContent;
71
+ if (tokenData instanceof Blob) {
72
+ tokenContent = await this.blobToString(tokenData);
73
+ }
74
+ else if (Buffer.isBuffer(tokenData)) {
75
+ tokenContent = tokenData.toString('utf-8');
76
+ }
77
+ else if (tokenData instanceof ArrayBuffer) {
78
+ tokenContent = new TextDecoder().decode(tokenData);
79
+ }
80
+ else if (typeof tokenData === 'string') {
81
+ tokenContent = tokenData;
82
+ }
83
+ else {
84
+ return {
85
+ isTokenized: false,
86
+ tokenMetadata: null,
87
+ calculatedMerkleRoot: null,
88
+ blockchainMerkleRoot: null,
89
+ verificationPassed: false,
90
+ errorMessage: 'Unsupported token data format'
91
+ };
92
+ }
93
+ const tokenMetadata = JSON.parse(tokenContent);
94
+ // Validate token metadata structure
95
+ if (!this.validateTokenInfo(tokenMetadata)) {
96
+ return {
97
+ isTokenized: false,
98
+ tokenMetadata: null,
99
+ calculatedMerkleRoot: null,
100
+ blockchainMerkleRoot: null,
101
+ verificationPassed: false,
102
+ errorMessage: 'Invalid token metadata structure'
103
+ };
104
+ }
105
+ // CRITICAL SECURITY CHECK: Validate contract address matches expected contract for network
106
+ // This prevents attackers from creating fake metadata pointing to malicious contracts
107
+ if (tokenMetadata.networkChainId) {
108
+ const contractValidation = (0, contracts_1.validateContractAddress)(tokenMetadata.contractAddress, tokenMetadata.networkChainId, false // debug flag - browser verifier doesn't have debug mode
109
+ );
110
+ if (!contractValidation.success) {
111
+ return {
112
+ isTokenized: true,
113
+ tokenMetadata,
114
+ calculatedMerkleRoot: null,
115
+ blockchainMerkleRoot: null,
116
+ verificationPassed: false,
117
+ errorMessage: `Contract address validation failed: ${contractValidation.error}`
118
+ };
119
+ }
120
+ }
121
+ // Skip verification if requested
122
+ if (options.skipHash || options.skipToken) {
123
+ return {
124
+ isTokenized: true,
125
+ tokenMetadata,
126
+ calculatedMerkleRoot: null,
127
+ blockchainMerkleRoot: null,
128
+ verificationPassed: false,
129
+ errorMessage: options.skipHash ? 'Hash verification skipped' : 'Token verification skipped'
130
+ };
131
+ }
132
+ // Calculate merkle root excluding token file
133
+ const calculatedMerkleRoot = this.zipkit.getMerkleRoot?.() || null;
134
+ if (!calculatedMerkleRoot) {
135
+ return {
136
+ isTokenized: true,
137
+ tokenMetadata,
138
+ calculatedMerkleRoot: null,
139
+ blockchainMerkleRoot: null,
140
+ verificationPassed: false,
141
+ errorMessage: 'Could not calculate merkle root'
142
+ };
143
+ }
144
+ // Query blockchain for the actual merkle root and timestamp
145
+ const blockchainData = await this.queryBlockchainData(tokenMetadata);
146
+ if (!blockchainData.merkleRoot) {
147
+ // Add owner information to tokenMetadata even if merkle root is not available
148
+ const enhancedTokenMetadata = {
149
+ ...tokenMetadata,
150
+ owner: blockchainData.owner || undefined
151
+ };
152
+ return {
153
+ isTokenized: true,
154
+ tokenMetadata: enhancedTokenMetadata,
155
+ calculatedMerkleRoot,
156
+ blockchainMerkleRoot: null,
157
+ blockchainTimestamp: blockchainData.timestamp ?? undefined,
158
+ verificationPassed: false,
159
+ errorMessage: 'Could not retrieve merkle root from blockchain'
160
+ };
161
+ }
162
+ // Direct string comparison - merkle roots are hex strings and must match exactly
163
+ // Case-sensitive comparison prevents encoding issues and false positives
164
+ // Only trim whitespace (no case normalization)
165
+ const normalizedBlockchain = blockchainData.merkleRoot?.trim() || '';
166
+ const normalizedCalculated = calculatedMerkleRoot?.trim() || '';
167
+ const verificationPassed = normalizedBlockchain === normalizedCalculated;
168
+ // Add owner information to tokenMetadata
169
+ const enhancedTokenMetadata = {
170
+ ...tokenMetadata,
171
+ owner: blockchainData.owner || undefined
172
+ };
173
+ return {
174
+ isTokenized: true,
175
+ tokenMetadata: enhancedTokenMetadata,
176
+ calculatedMerkleRoot,
177
+ blockchainMerkleRoot: blockchainData.merkleRoot,
178
+ blockchainTimestamp: blockchainData.timestamp ?? undefined,
179
+ verificationPassed,
180
+ errorMessage: verificationPassed ? undefined : `Merkle root mismatch - Calculated: ${calculatedMerkleRoot}, Blockchain: ${blockchainData.merkleRoot}`
181
+ };
182
+ }
183
+ catch (error) {
184
+ return {
185
+ isTokenized: false,
186
+ tokenMetadata: null,
187
+ calculatedMerkleRoot: null,
188
+ blockchainMerkleRoot: null,
189
+ verificationPassed: false,
190
+ errorMessage: `Error processing token: ${error instanceof Error ? error.message : String(error)}`
191
+ };
192
+ }
193
+ }
194
+ /**
195
+ * Validates token metadata structure
196
+ * Validates required fields: tokenId, contractAddress, network, merkleRoot, networkChainId, contractVersion
197
+ */
198
+ validateTokenInfo(tokenMetadata) {
199
+ // Check basic structure
200
+ if (!tokenMetadata || typeof tokenMetadata !== 'object') {
201
+ return false;
202
+ }
203
+ // Required core fields
204
+ if (typeof tokenMetadata.tokenId !== 'string' || !tokenMetadata.tokenId) {
205
+ return false;
206
+ }
207
+ if (typeof tokenMetadata.contractAddress !== 'string' || !tokenMetadata.contractAddress) {
208
+ return false;
209
+ }
210
+ if (typeof tokenMetadata.network !== 'string' || !tokenMetadata.network) {
211
+ return false;
212
+ }
213
+ if (typeof tokenMetadata.merkleRoot !== 'string' || !tokenMetadata.merkleRoot) {
214
+ return false;
215
+ }
216
+ // Required version fields (new requirement)
217
+ if (typeof tokenMetadata.networkChainId !== 'number' || tokenMetadata.networkChainId === undefined) {
218
+ return false;
219
+ }
220
+ if (typeof tokenMetadata.contractVersion !== 'string' || !tokenMetadata.contractVersion) {
221
+ return false;
222
+ }
223
+ return true;
224
+ }
225
+ /**
226
+ * Queries the blockchain to get the actual merkle root, timestamp, and owner stored in the smart contract
227
+ */
228
+ async queryBlockchainData(tokenMetadata) {
229
+ try {
230
+ // Get network configuration from contracts.ts (single source of truth)
231
+ if (!tokenMetadata.networkChainId) {
232
+ console.error(`[TokenVerifier] ❌ No chainId in token metadata`);
233
+ return { merkleRoot: null, timestamp: null, owner: null };
234
+ }
235
+ const networkConfig = (0, contracts_1.getContractConfig)(tokenMetadata.networkChainId);
236
+ if (!networkConfig) {
237
+ console.error(`[TokenVerifier] ❌ Could not resolve network configuration for chainId: ${tokenMetadata.networkChainId}`);
238
+ return { merkleRoot: null, timestamp: null, owner: null };
239
+ }
240
+ // Test RPC endpoints first to find working ones (same as server-side)
241
+ const workingRpcUrls = [];
242
+ for (const rpcUrl of networkConfig.rpcUrls) {
243
+ try {
244
+ const controller = new AbortController();
245
+ const timeoutId = setTimeout(() => controller.abort(), 5000);
246
+ const testResponse = await fetch(rpcUrl, {
247
+ method: 'POST',
248
+ headers: { 'Content-Type': 'application/json' },
249
+ body: JSON.stringify({
250
+ jsonrpc: '2.0',
251
+ method: 'eth_chainId',
252
+ params: [],
253
+ id: 1
254
+ }),
255
+ signal: controller.signal
256
+ });
257
+ clearTimeout(timeoutId);
258
+ if (testResponse.ok) {
259
+ const contentType = testResponse.headers.get('content-type');
260
+ if (contentType && contentType.includes('application/json')) {
261
+ const testData = await testResponse.json();
262
+ if (testData?.jsonrpc && testData?.result) {
263
+ const actualChainId = parseInt(testData.result, 16);
264
+ if (actualChainId === tokenMetadata.networkChainId) {
265
+ workingRpcUrls.push(rpcUrl);
266
+ }
267
+ }
268
+ }
269
+ }
270
+ }
271
+ catch (testError) {
272
+ // Silently skip failed endpoints
273
+ }
274
+ }
275
+ if (workingRpcUrls.length === 0) {
276
+ // Fallback to all endpoints if none tested successfully
277
+ workingRpcUrls.push(...networkConfig.rpcUrls);
278
+ }
279
+ // Try multiple RPC endpoints (only working ones if available)
280
+ for (let i = 0; i < workingRpcUrls.length; i++) {
281
+ const rpcUrl = workingRpcUrls[i];
282
+ try {
283
+ const provider = new ethers_1.ethers.JsonRpcProvider(rpcUrl);
284
+ // Test connection with a timeout
285
+ await Promise.race([
286
+ provider.getBlockNumber(),
287
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), 5000))
288
+ ]);
289
+ // Create contract instance
290
+ const contract = new ethers_1.ethers.Contract(tokenMetadata.contractAddress, CONTRACT_ABI, provider);
291
+ // Call getZipFileInfo to get the blockchain-stored data
292
+ // Using minimal ABI that works with both v2.10 and v2.11 contracts
293
+ const zipInfo = await contract.getZipFileInfo(tokenMetadata.tokenId);
294
+ // Get the token owner
295
+ const owner = await contract.ownerOf(tokenMetadata.tokenId);
296
+ // Extract merkle root and timestamp (fields present in both v2.10 and v2.11)
297
+ const merkleRoot = zipInfo.merkleRootHash;
298
+ const timestamp = Number(zipInfo.tokenizationTime);
299
+ return {
300
+ merkleRoot: merkleRoot,
301
+ timestamp: timestamp,
302
+ owner: owner
303
+ };
304
+ }
305
+ catch (error) {
306
+ // Continue to next endpoint on error
307
+ continue;
308
+ }
309
+ }
310
+ console.error(`[TokenVerifier] ❌ All RPC endpoints failed for network: ${tokenMetadata.network}`);
311
+ return { merkleRoot: null, timestamp: null, owner: null };
312
+ }
313
+ catch (error) {
314
+ console.error(`[TokenVerifier] ❌ Blockchain query error:`, error?.message || error);
315
+ return { merkleRoot: null, timestamp: null, owner: null };
316
+ }
317
+ }
318
+ /**
319
+ * Helper to convert Blob to string
320
+ */
321
+ async blobToString(blob) {
322
+ return new Promise((resolve, reject) => {
323
+ const reader = new FileReader();
324
+ reader.onload = () => resolve(reader.result);
325
+ reader.onerror = reject;
326
+ reader.readAsText(blob);
327
+ });
328
+ }
329
+ /**
330
+ * Creates a formatted summary of token information
331
+ */
332
+ createTokenSummary(tokenMetadata) {
333
+ return `
334
+ 🎫 NFT Token Information:
335
+ Token ID: ${tokenMetadata.tokenId}
336
+ Network: ${tokenMetadata.network}
337
+ Contract: ${tokenMetadata.contractAddress}
338
+ Transaction: ${tokenMetadata.transactionHash}
339
+ Type: Tokenized Archive
340
+ Minted: ${tokenMetadata.mintedAt ? new Date(tokenMetadata.mintedAt).toLocaleString() : 'Unknown'}
341
+ `;
342
+ }
343
+ }
344
+ exports.TokenVerifierBrowser = TokenVerifierBrowser;
345
+ /**
346
+ * Creates a new TokenVerifierBrowser instance
347
+ */
348
+ function createTokenVerifier(zipkit) {
349
+ return new TokenVerifierBrowser(zipkit);
350
+ }
351
+ /**
352
+ * Convenience function to check for tokenization
353
+ */
354
+ async function checkForTokenization(zipkit, zipEntries, options = {}) {
355
+ const verifier = new TokenVerifierBrowser(zipkit);
356
+ return verifier.checkForTokenization(zipEntries, options);
357
+ }
358
+ //# sourceMappingURL=TokenVerifierBrowser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenVerifierBrowser.js","sourceRoot":"","sources":["../../src/browser/TokenVerifierBrowser.ts"],"names":[],"mappings":"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"}