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,294 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as readline from 'readline';
4
+ import { ethers } from 'ethers';
5
+ import {
6
+ WalletSetupResult,
7
+ WalletInfo,
8
+ NetworkConfig,
9
+ NETWORKS,
10
+ MintingOptions
11
+ } from './types';
12
+
13
+ export class WalletManager {
14
+ private wallet: ethers.Wallet | null = null;
15
+ private provider: ethers.JsonRpcProvider | null = null;
16
+
17
+ /**
18
+ * Prompts the user for input
19
+ */
20
+ private async promptUser(question: string): Promise<string> {
21
+ const rl = readline.createInterface({
22
+ input: process.stdin,
23
+ output: process.stdout
24
+ });
25
+
26
+ return new Promise<string>((resolve) => {
27
+ rl.question(question, (answer: string) => {
28
+ rl.close();
29
+ resolve(answer.trim());
30
+ });
31
+ });
32
+ }
33
+
34
+ /**
35
+ * Looks for existing wallet files in the current directory and wallet subdirectory
36
+ */
37
+ private findExistingWallets(): string[] {
38
+ const walletFiles: string[] = [];
39
+ const currentDir = process.cwd();
40
+ const walletDir = path.join(currentDir, 'wallet');
41
+
42
+ // Common wallet file names to look for
43
+ const walletFileNames = [
44
+ 'neozip-wallet.json',
45
+ 'wallet.json',
46
+ 'private-key.txt',
47
+ 'private.key'
48
+ ];
49
+
50
+ // Search in current directory
51
+ for (const fileName of walletFileNames) {
52
+ const filePath = path.join(currentDir, fileName);
53
+ if (fs.existsSync(filePath)) {
54
+ walletFiles.push(filePath);
55
+ }
56
+ }
57
+
58
+ // Search in wallet subdirectory
59
+ if (fs.existsSync(walletDir)) {
60
+ for (const fileName of walletFileNames) {
61
+ const filePath = path.join(walletDir, fileName);
62
+ if (fs.existsSync(filePath)) {
63
+ walletFiles.push(filePath);
64
+ }
65
+ }
66
+ }
67
+
68
+ return walletFiles;
69
+ }
70
+
71
+ /**
72
+ * Loads wallet information from a file
73
+ */
74
+ private loadWalletFromFile(filePath: string): string | null {
75
+ try {
76
+ const content = fs.readFileSync(filePath, 'utf8').trim();
77
+
78
+ // Try to parse as JSON first (for neozip-wallet.json format)
79
+ try {
80
+ const walletData = JSON.parse(content);
81
+ if (walletData.privateKey) {
82
+ console.log(`Found wallet file: ${filePath}`);
83
+ console.log(`Wallet address: ${walletData.address}`);
84
+ return walletData.privateKey;
85
+ }
86
+ } catch {
87
+ // If not JSON, treat as plain private key
88
+ if (content.startsWith('0x') && content.length === 66) {
89
+ console.log(`Found private key file: ${filePath}`);
90
+ return content;
91
+ }
92
+ }
93
+
94
+ return null;
95
+ } catch (error) {
96
+ console.warn(`Could not read wallet file ${filePath}:`, error);
97
+ return null;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Sets up a Base wallet for token operations
103
+ */
104
+ async setupWallet(options: MintingOptions): Promise<WalletSetupResult> {
105
+ try {
106
+ const networkConfig = NETWORKS[options.network] || NETWORKS['base-sepolia'];
107
+
108
+ let privateKey: string;
109
+
110
+ // Check if wallet is explicitly provided via command line
111
+ if (options.wallet) {
112
+ if (fs.existsSync(options.wallet)) {
113
+ // Read wallet from specified file
114
+ const loadedKey = this.loadWalletFromFile(options.wallet);
115
+ if (!loadedKey) {
116
+ throw new Error(`Could not load valid private key from ${options.wallet}`);
117
+ }
118
+ privateKey = loadedKey;
119
+ } else {
120
+ // Use directly provided private key or mnemonic
121
+ privateKey = options.wallet;
122
+ }
123
+ } else {
124
+ // Look for existing wallet files
125
+ const existingWallets = this.findExistingWallets();
126
+
127
+ if (existingWallets.length > 0) {
128
+ // Automatically use the first available wallet
129
+ const selectedWallet = existingWallets[0];
130
+ const relativePath = path.relative(process.cwd(), selectedWallet);
131
+ console.log(`Using existing wallet: ${relativePath}`);
132
+
133
+ const loadedKey = this.loadWalletFromFile(selectedWallet);
134
+ if (!loadedKey) {
135
+ throw new Error(`Could not load valid private key from ${selectedWallet}`);
136
+ }
137
+ privateKey = loadedKey;
138
+ } else {
139
+ // Automatically create new wallet
140
+ console.log('No existing wallet found. Creating new wallet...');
141
+ privateKey = await this.createNewWallet();
142
+ }
143
+ }
144
+
145
+ // Create wallet instance without provider first
146
+ this.wallet = new ethers.Wallet(privateKey);
147
+ console.log(`Using wallet: ${this.wallet.address}`);
148
+
149
+ // Try to connect to the network - FAIL if connection fails
150
+ const networkConnected = await this.connectToNetwork(networkConfig, options.mintToken);
151
+
152
+ if (!networkConnected) {
153
+ return {
154
+ wallet: null,
155
+ provider: null,
156
+ success: false,
157
+ message: `Failed to connect to ${networkConfig.name} network. Blockchain operations require network connectivity.`
158
+ };
159
+ }
160
+
161
+ return {
162
+ wallet: this.wallet,
163
+ provider: this.provider,
164
+ success: true,
165
+ message: `Wallet setup successful for ${networkConfig.name}`
166
+ };
167
+
168
+ } catch (error) {
169
+ console.error('Error setting up wallet:', error);
170
+ return {
171
+ wallet: null,
172
+ provider: null,
173
+ success: false,
174
+ message: `Wallet setup failed: ${error instanceof Error ? error.message : String(error)}`
175
+ };
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Creates a new wallet and saves it to file
181
+ */
182
+ private async createNewWallet(): Promise<string> {
183
+ console.log('Creating a new wallet...');
184
+ const newWallet = ethers.Wallet.createRandom();
185
+
186
+ // Save the wallet info
187
+ const walletInfo: WalletInfo = {
188
+ address: newWallet.address,
189
+ privateKey: newWallet.privateKey,
190
+ mnemonic: newWallet.mnemonic?.phrase || ""
191
+ };
192
+
193
+ // Ensure wallet directory exists
194
+ const walletDir = path.join(process.cwd(), 'wallet');
195
+ if (!fs.existsSync(walletDir)) {
196
+ fs.mkdirSync(walletDir, { recursive: true });
197
+ }
198
+
199
+ const walletFilePath = path.join(walletDir, 'neozip-wallet.json');
200
+ fs.writeFileSync(walletFilePath, JSON.stringify(walletInfo, null, 2));
201
+
202
+ console.log(`New wallet created and saved to ${walletFilePath}`);
203
+ console.log(`Wallet address: ${newWallet.address}`);
204
+ console.log(`IMPORTANT: Please fund this wallet with BASE to use for minting NFTs!`);
205
+
206
+ return newWallet.privateKey;
207
+ }
208
+
209
+ /**
210
+ * Connects to the specified blockchain network
211
+ */
212
+ private async connectToNetwork(networkConfig: NetworkConfig, mintToken: boolean): Promise<boolean> {
213
+ try {
214
+ console.log(`Attempting to connect to ${networkConfig.name} network...`);
215
+ this.provider = new ethers.JsonRpcProvider(networkConfig.rpcUrl);
216
+
217
+ // Set a timeout for network connection
218
+ let networkTimedOut = false;
219
+ const networkTimeout = setTimeout(() => {
220
+ networkTimedOut = true;
221
+ console.error("Network connection timeout");
222
+ }, 5000);
223
+
224
+ // Test the connection
225
+ const network = await Promise.race([
226
+ this.provider.getNetwork(),
227
+ new Promise((_, reject) =>
228
+ setTimeout(() => {
229
+ if (networkTimedOut) reject(new Error("Network connection timeout"));
230
+ }, 5100)
231
+ )
232
+ ]);
233
+
234
+ clearTimeout(networkTimeout);
235
+
236
+ // Connect wallet to provider
237
+ if (this.wallet) {
238
+ this.wallet = this.wallet.connect(this.provider);
239
+
240
+ // Check wallet balance
241
+ const balance = await this.provider.getBalance(this.wallet.address);
242
+ const balanceEth = ethers.formatEther(balance);
243
+ console.log(`Wallet balance: ${balanceEth} ETH`);
244
+
245
+ // Check if balance is sufficient for minting
246
+ const minBalance = 0.0001;
247
+ if (parseFloat(balanceEth) < minBalance && mintToken) {
248
+ console.error(`ERROR: Insufficient balance (${balanceEth} ETH). Minimum required: ${minBalance} ETH`);
249
+ console.error('Get testnet ETH from: https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet');
250
+ throw new Error(`Insufficient balance for minting. Current: ${balanceEth} ETH, Required: ${minBalance} ETH`);
251
+ } else if (mintToken) {
252
+ console.log(`✅ Sufficient balance for token minting`);
253
+ }
254
+ }
255
+
256
+ console.log(`✅ Successfully connected to ${networkConfig.name}`);
257
+ return true;
258
+
259
+ } catch (networkError: unknown) {
260
+ const errorMessage = networkError instanceof Error ? networkError.message : String(networkError);
261
+ console.error(`Failed to connect to ${networkConfig.name} network: ${errorMessage}`);
262
+ this.provider = null;
263
+ return false;
264
+ }
265
+ }
266
+
267
+ /**
268
+ * Gets the current wallet instance
269
+ */
270
+ getWallet(): ethers.Wallet | null {
271
+ return this.wallet;
272
+ }
273
+
274
+ /**
275
+ * Gets the current provider instance
276
+ */
277
+ getProvider(): ethers.JsonRpcProvider | null {
278
+ return this.provider;
279
+ }
280
+
281
+ /**
282
+ * Checks if wallet is connected and ready for transactions
283
+ */
284
+ isReady(): boolean {
285
+ return this.wallet !== null;
286
+ }
287
+
288
+ /**
289
+ * Checks if provider is connected
290
+ */
291
+ isOnline(): boolean {
292
+ return this.provider !== null;
293
+ }
294
+ }
@@ -0,0 +1,117 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { NZipTokenInfo, ContractInfo, NETWORKS } from './types';
4
+
5
+ export class ZipMetadata {
6
+ /**
7
+ * Creates the META-INF/NZIP.TOKEN content
8
+ */
9
+ static createTokenInfo(
10
+ tokenId: string,
11
+ transactionHash: string,
12
+ contractInfo: ContractInfo,
13
+ merkleRoot: string,
14
+ fileName: string,
15
+ network: string,
16
+ blockNumber?: number,
17
+ ipfsHash?: string,
18
+ creationTimestamp?: number
19
+ ): NZipTokenInfo {
20
+ const networkConfig = NETWORKS[network];
21
+
22
+ return {
23
+ version: "1.0",
24
+ tokenId,
25
+ contractAddress: contractInfo.address,
26
+ network: networkConfig.name,
27
+ networkChainId: networkConfig.chainId,
28
+ transactionHash,
29
+ merkleRoot,
30
+ fileName,
31
+ mintedAt: new Date().toISOString(),
32
+ creationTimestamp,
33
+ blockNumber,
34
+ ipfsHash
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Creates the META-INF directory and NZIP.TOKEN file
40
+ */
41
+ static async createTokenFile(tokenInfo: NZipTokenInfo): Promise<string> {
42
+ const currentDir = process.cwd();
43
+
44
+ // Create META-INF directory in current directory
45
+ const metaInfDir = path.join(currentDir, 'META-INF');
46
+ if (!fs.existsSync(metaInfDir)) {
47
+ fs.mkdirSync(metaInfDir, { recursive: true });
48
+ }
49
+
50
+ // Create NZIP.TOKEN file
51
+ const tokenFilePath = path.join(metaInfDir, 'NZIP.TOKEN');
52
+ const tokenContent = JSON.stringify(tokenInfo, null, 2);
53
+
54
+ fs.writeFileSync(tokenFilePath, tokenContent);
55
+ console.log(`Created token metadata file: ${path.relative(currentDir, tokenFilePath)}`);
56
+
57
+ return tokenFilePath;
58
+ }
59
+
60
+ /**
61
+ * Reads token information from a ZIP file's META-INF/NZIP.TOKEN
62
+ */
63
+ static readTokenInfo(zipFilePath: string): NZipTokenInfo | null {
64
+ // This would require extracting the META-INF/NZIP.TOKEN file from the ZIP
65
+ // For now, return null - this can be implemented when needed
66
+ return null;
67
+ }
68
+
69
+ /**
70
+ * Validates token information structure
71
+ */
72
+ static validateTokenInfo(tokenInfo: any): tokenInfo is NZipTokenInfo {
73
+ return (
74
+ typeof tokenInfo === 'object' &&
75
+ typeof tokenInfo.version === 'string' &&
76
+ typeof tokenInfo.tokenId === 'string' &&
77
+ typeof tokenInfo.contractAddress === 'string' &&
78
+ typeof tokenInfo.network === 'string' &&
79
+ typeof tokenInfo.networkChainId === 'number' &&
80
+ typeof tokenInfo.transactionHash === 'string' &&
81
+ typeof tokenInfo.merkleRoot === 'string' &&
82
+ typeof tokenInfo.fileName === 'string' &&
83
+ typeof tokenInfo.mintedAt === 'string'
84
+ );
85
+ }
86
+
87
+ /**
88
+ * Creates a human-readable summary of the token information
89
+ */
90
+ static createTokenSummary(tokenInfo: NZipTokenInfo): string {
91
+ return `
92
+ ═══════════════════════════════════════════════════════════════
93
+ NeoZip Token Information
94
+ ═══════════════════════════════════════════════════════════════
95
+ Token ID: ${tokenInfo.tokenId}
96
+ Contract: ${tokenInfo.contractAddress}
97
+ Network: ${tokenInfo.network} (Chain ID: ${tokenInfo.networkChainId})
98
+ Transaction: ${tokenInfo.transactionHash}
99
+ Block Number: ${tokenInfo.blockNumber || 'Unknown'}
100
+ Merkle Root: ${tokenInfo.merkleRoot}
101
+ File Name: ${tokenInfo.fileName}
102
+ Minted At: ${tokenInfo.mintedAt}
103
+ IPFS Hash: ${tokenInfo.ipfsHash || 'Not uploaded'}
104
+ Version: ${tokenInfo.version}
105
+ ═══════════════════════════════════════════════════════════════
106
+ `.trim();
107
+ }
108
+
109
+ /**
110
+ * No cleanup needed since we write to the current directory
111
+ */
112
+ static cleanupTokenFile(tokenFilePath: string): void {
113
+ // No cleanup needed since we're writing to the current directory
114
+ // The META-INF/NZIP.TOKEN file should remain in the current directory
115
+ console.log(`Token metadata file preserved at: ${path.relative(process.cwd(), tokenFilePath)}`);
116
+ }
117
+ }
@@ -0,0 +1,234 @@
1
+ import * as path from 'path';
2
+ import * as fs from 'fs';
3
+ import { ethers } from 'ethers';
4
+ import { WalletManager } from './WalletManager';
5
+ import { NFTMinter } from './NFTMinter';
6
+ import { ZipMetadata } from './ZipMetadata';
7
+ import {
8
+ MintingOptions,
9
+ ZipTokenData,
10
+ WalletSetupResult,
11
+ MintingResult,
12
+ ContractInfo,
13
+ NZipTokenInfo
14
+ } from './types';
15
+
16
+ interface ProcessorState {
17
+ walletSetup?: WalletSetupResult;
18
+ mintingResult?: MintingResult;
19
+ tokenInfo?: NZipTokenInfo;
20
+ error?: string;
21
+ }
22
+
23
+ export class ZipTokenProcessor {
24
+ private walletManager: WalletManager;
25
+ private nftMinter: NFTMinter | null = null;
26
+ private zipTokenData: ZipTokenData;
27
+
28
+ constructor(zipFile: string, merkleRoot: string, options: MintingOptions) {
29
+ this.walletManager = new WalletManager();
30
+
31
+ this.zipTokenData = {
32
+ zipFile,
33
+ merkleRoot,
34
+ fileName: path.basename(zipFile),
35
+ timestamp: new Date().toISOString()
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Processes the complete ZIP token workflow
41
+ */
42
+ async processZipToken(options: MintingOptions): Promise<ProcessorState> {
43
+ const state: ProcessorState = {};
44
+
45
+ try {
46
+ // Setup wallet if needed
47
+ if (options.wallet || options.mintToken) {
48
+ console.log('Setting up wallet...');
49
+ const walletResult = await this.walletManager.setupWallet(options);
50
+ state.walletSetup = walletResult;
51
+
52
+ if (!walletResult.success) {
53
+ state.error = `Wallet setup failed: ${walletResult.message}`;
54
+ return state;
55
+ }
56
+
57
+ // Initialize NFT minter with wallet and provider
58
+ this.nftMinter = new NFTMinter(
59
+ walletResult.wallet,
60
+ walletResult.provider
61
+ );
62
+ }
63
+
64
+ // Mint token if requested
65
+ if (options.mintToken && this.nftMinter) {
66
+ console.log('Minting NFT token...');
67
+ const mintingResult = await this.nftMinter.mintZipFileNFT(this.zipTokenData);
68
+ state.mintingResult = mintingResult;
69
+
70
+ if (!mintingResult.success) {
71
+ state.error = `Minting failed: ${mintingResult.message}`;
72
+ return state;
73
+ }
74
+
75
+ // Validate that we have complete token data for successful minting
76
+ if (!mintingResult.tokenId || !mintingResult.txHash) {
77
+ state.error = `Minting incomplete: Missing token ID or transaction hash`;
78
+ return state;
79
+ }
80
+
81
+ console.log('Preparing token metadata...');
82
+
83
+ // Check if this was an existing token (message contains "existing token")
84
+ if (mintingResult.message.includes('existing token')) {
85
+ console.log('Using existing token from your wallet...');
86
+ // Create token info from existing token data
87
+ const tokenInfo = await this.createTokenInfoFromExisting(mintingResult, options);
88
+ if (!tokenInfo) {
89
+ state.error = `Failed to create token metadata from existing token`;
90
+ return state;
91
+ }
92
+ state.tokenInfo = tokenInfo;
93
+ } else {
94
+ // Create token info from new minting
95
+ const tokenInfo = this.createTokenInfo(mintingResult, options);
96
+ if (!tokenInfo) {
97
+ state.error = `Failed to create token metadata`;
98
+ return state;
99
+ }
100
+ state.tokenInfo = tokenInfo;
101
+ }
102
+
103
+ console.log('\n' + ZipMetadata.createTokenSummary(state.tokenInfo));
104
+ }
105
+
106
+ return state;
107
+
108
+ } catch (error) {
109
+ const errorMessage = error instanceof Error ? error.message : String(error);
110
+ console.error('Error in ZIP token processing:', error);
111
+ state.error = `Processing error: ${errorMessage}`;
112
+ return state;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Gets the ZIP token data
118
+ */
119
+ getZipTokenData(): ZipTokenData {
120
+ return this.zipTokenData;
121
+ }
122
+
123
+ /**
124
+ * Gets the wallet manager instance
125
+ */
126
+ getWalletManager(): WalletManager {
127
+ return this.walletManager;
128
+ }
129
+
130
+ /**
131
+ * Gets the NFT minter instance
132
+ */
133
+ getNFTMinter(): NFTMinter | null {
134
+ return this.nftMinter;
135
+ }
136
+
137
+ /**
138
+ * Loads contract deployment information
139
+ */
140
+ private loadContractInfo(): ContractInfo | null {
141
+ try {
142
+ const contractInfoPath = path.join(process.cwd(), 'zipfile-nft-deployment.json');
143
+
144
+ if (!fs.existsSync(contractInfoPath)) {
145
+ return null;
146
+ }
147
+
148
+ const contractInfo = JSON.parse(fs.readFileSync(contractInfoPath, 'utf8'));
149
+ return contractInfo as ContractInfo;
150
+ } catch (error) {
151
+ console.error('Error loading contract info:', error);
152
+ return null;
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Creates token information object
158
+ */
159
+ private createTokenInfo(
160
+ mintingResult: MintingResult,
161
+ options: MintingOptions
162
+ ): NZipTokenInfo | null {
163
+ if (!mintingResult.success || !mintingResult.tokenId || !mintingResult.txHash) {
164
+ console.error('Cannot create token metadata: minting was not successful or missing token data');
165
+ return null;
166
+ }
167
+
168
+ try {
169
+ // Load contract information
170
+ const contractInfo = this.loadContractInfo();
171
+ if (!contractInfo) {
172
+ console.error('Cannot load contract information for token metadata');
173
+ return null;
174
+ }
175
+
176
+ // Create token information with REAL data only
177
+ const tokenInfo = ZipMetadata.createTokenInfo(
178
+ mintingResult.tokenId,
179
+ mintingResult.txHash,
180
+ contractInfo,
181
+ this.zipTokenData.merkleRoot,
182
+ this.zipTokenData.fileName,
183
+ options.network,
184
+ undefined, // blockNumber - will be filled later if needed
185
+ undefined, // ipfsHash - not implemented yet
186
+ Math.floor(Date.now() / 1000) // creationTimestamp
187
+ );
188
+
189
+ return tokenInfo;
190
+
191
+ } catch (error) {
192
+ console.error('Error creating token metadata:', error);
193
+ return null;
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Creates token information object from existing token
199
+ */
200
+ private async createTokenInfoFromExisting(
201
+ mintingResult: MintingResult,
202
+ options: MintingOptions
203
+ ): Promise<NZipTokenInfo | null> {
204
+ if (!mintingResult.success || !mintingResult.tokenId || !mintingResult.txHash) {
205
+ console.error('Cannot create token metadata: minting was not successful or missing token data');
206
+ return null;
207
+ }
208
+
209
+ try {
210
+ // Load contract information
211
+ const contractInfo = this.loadContractInfo();
212
+ if (!contractInfo) {
213
+ console.error('Cannot load contract information for token metadata');
214
+ return null;
215
+ }
216
+
217
+ // Create token information with REAL data only
218
+ const tokenInfo = ZipMetadata.createTokenInfo(
219
+ mintingResult.tokenId,
220
+ mintingResult.txHash,
221
+ contractInfo,
222
+ this.zipTokenData.merkleRoot,
223
+ this.zipTokenData.fileName,
224
+ options.network
225
+ );
226
+
227
+ return tokenInfo;
228
+
229
+ } catch (error) {
230
+ console.error('Error creating token metadata:', error);
231
+ return null;
232
+ }
233
+ }
234
+ }