neozip-cli 0.75.0-beta → 0.75.1-beta

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.
@@ -0,0 +1,240 @@
1
+ "use strict";
2
+ /**
3
+ * CommentManager - Handles archive and file comments for ZIP files
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.CommentManager = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const readline = __importStar(require("readline"));
42
+ class CommentManager {
43
+ static setArchiveComment(zip, comment) {
44
+ try {
45
+ if (zip && typeof zip.setZipComment === 'function') {
46
+ zip.setZipComment(comment);
47
+ return true;
48
+ }
49
+ return false;
50
+ }
51
+ catch (error) {
52
+ console.error('Error setting archive comment:', error);
53
+ return false;
54
+ }
55
+ }
56
+ static getArchiveComment(zip) {
57
+ try {
58
+ if (zip && typeof zip.getZipComment === 'function') {
59
+ return zip.getZipComment();
60
+ }
61
+ return null;
62
+ }
63
+ catch (error) {
64
+ console.error('Error getting archive comment:', error);
65
+ return null;
66
+ }
67
+ }
68
+ static setFileComment(entry, comment) {
69
+ try {
70
+ if (entry && typeof entry.comment !== 'undefined') {
71
+ entry.comment = comment;
72
+ return true;
73
+ }
74
+ return false;
75
+ }
76
+ catch (error) {
77
+ console.error('Error setting file comment:', error);
78
+ return false;
79
+ }
80
+ }
81
+ static getFileComment(entry) {
82
+ try {
83
+ if (entry && typeof entry.comment !== 'undefined') {
84
+ return entry.comment || null;
85
+ }
86
+ return null;
87
+ }
88
+ catch (error) {
89
+ console.error('Error getting file comment:', error);
90
+ return null;
91
+ }
92
+ }
93
+ static async readCommentsFromFile(filePath) {
94
+ try {
95
+ if (!fs.existsSync(filePath)) {
96
+ return { success: false, error: `Comment file not found: ${filePath}` };
97
+ }
98
+ const content = fs.readFileSync(filePath, 'utf8');
99
+ const lines = content.split('\n');
100
+ let archiveComment = '';
101
+ const fileComments = {};
102
+ let currentFile = '';
103
+ let currentComment = '';
104
+ for (const line of lines) {
105
+ const trimmedLine = line.trim();
106
+ if (!trimmedLine) {
107
+ if (currentFile && currentComment) {
108
+ fileComments[currentFile] = currentComment.trim();
109
+ currentFile = '';
110
+ currentComment = '';
111
+ }
112
+ continue;
113
+ }
114
+ if (trimmedLine.includes(':')) {
115
+ if (currentFile && currentComment) {
116
+ fileComments[currentFile] = currentComment.trim();
117
+ }
118
+ const colonIndex = trimmedLine.indexOf(':');
119
+ currentFile = trimmedLine.substring(0, colonIndex).trim();
120
+ currentComment = trimmedLine.substring(colonIndex + 1).trim();
121
+ }
122
+ else {
123
+ if (currentFile) {
124
+ currentComment += (currentComment ? '\n' : '') + trimmedLine;
125
+ }
126
+ else {
127
+ archiveComment += (archiveComment ? '\n' : '') + trimmedLine;
128
+ }
129
+ }
130
+ }
131
+ if (currentFile && currentComment) {
132
+ fileComments[currentFile] = currentComment.trim();
133
+ }
134
+ return {
135
+ success: true,
136
+ archiveComment: archiveComment || undefined,
137
+ fileComments: Object.keys(fileComments).length > 0 ? fileComments : undefined
138
+ };
139
+ }
140
+ catch (error) {
141
+ return {
142
+ success: false,
143
+ error: `Error reading comment file: ${error instanceof Error ? error.message : String(error)}`
144
+ };
145
+ }
146
+ }
147
+ static async promptForArchiveComment() {
148
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
149
+ return new Promise((resolve) => {
150
+ rl.question('Enter archive comment (press Enter twice to finish):\n', (comment) => {
151
+ const lines = [comment];
152
+ const readLine = () => {
153
+ rl.question('', (line) => {
154
+ if (line.trim() === '') {
155
+ rl.close();
156
+ resolve(lines.join('\n').trim());
157
+ }
158
+ else {
159
+ lines.push(line);
160
+ readLine();
161
+ }
162
+ });
163
+ };
164
+ readLine();
165
+ });
166
+ });
167
+ }
168
+ static async promptForFileComments(filenames) {
169
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
170
+ const fileComments = {};
171
+ for (const filename of filenames) {
172
+ const comment = await new Promise((resolve) => {
173
+ rl.question(`Enter comment for ${filename}: `, (input) => resolve(input.trim()));
174
+ });
175
+ if (comment)
176
+ fileComments[filename] = comment;
177
+ }
178
+ rl.close();
179
+ return fileComments;
180
+ }
181
+ static async promptForFileCommentsOnly(filenames) {
182
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
183
+ const fileComments = {};
184
+ for (const filename of filenames) {
185
+ const comment = await new Promise((resolve) => {
186
+ rl.question(`Enter comment for ${filename}: `, (input) => resolve(input.trim()));
187
+ });
188
+ if (comment)
189
+ fileComments[filename] = comment;
190
+ }
191
+ rl.close();
192
+ return fileComments;
193
+ }
194
+ static applyComments(zip, entries, options) {
195
+ try {
196
+ let success = true;
197
+ const errors = [];
198
+ if (options.archiveComment) {
199
+ if (!this.setArchiveComment(zip, options.archiveComment)) {
200
+ success = false;
201
+ errors.push('Failed to set archive comment');
202
+ }
203
+ }
204
+ if (options.fileComments) {
205
+ for (const [filename, comment] of Object.entries(options.fileComments)) {
206
+ const entry = entries.find((e) => e.filename === filename);
207
+ if (entry) {
208
+ if (!this.setFileComment(entry, comment)) {
209
+ success = false;
210
+ errors.push(`Failed to set comment for ${filename}`);
211
+ }
212
+ }
213
+ else {
214
+ success = false;
215
+ errors.push(`File not found: ${filename}`);
216
+ }
217
+ }
218
+ }
219
+ return { success, archiveComment: options.archiveComment, fileComments: options.fileComments, error: errors.length > 0 ? errors.join('; ') : undefined };
220
+ }
221
+ catch (error) {
222
+ return { success: false, error: `Error applying comments: ${error instanceof Error ? error.message : String(error)}` };
223
+ }
224
+ }
225
+ static applyFileCommentToEntry(entry, filename, fileComments) {
226
+ try {
227
+ if (fileComments[filename]) {
228
+ return this.setFileComment(entry, fileComments[filename]);
229
+ }
230
+ return true;
231
+ }
232
+ catch (error) {
233
+ console.error(`Error applying file comment to ${filename}:`, error);
234
+ return false;
235
+ }
236
+ }
237
+ }
238
+ exports.CommentManager = CommentManager;
239
+ exports.default = CommentManager;
240
+ //# sourceMappingURL=CommentManager.js.map
@@ -0,0 +1,387 @@
1
+ "use strict";
2
+ /**
3
+ * Blockchain-related functions for NeoZip CLI
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.isSupportedNetwork = isSupportedNetwork;
40
+ exports.getWalletPasskey = getWalletPasskey;
41
+ exports.addTokenMetaToZip = addTokenMetaToZip;
42
+ exports.handleTokenMinting = handleTokenMinting;
43
+ const neozipkit_1 = require("neozipkit");
44
+ const blockchain_1 = require("neozipkit/blockchain");
45
+ const ConfigStore_1 = require("../config/ConfigStore");
46
+ const readline = __importStar(require("readline"));
47
+ /**
48
+ * Check if the network is supported (uses nameAliases from CONTRACT_CONFIGS)
49
+ */
50
+ function isSupportedNetwork(network) {
51
+ return (0, blockchain_1.getChainIdByName)(network) !== null;
52
+ }
53
+ /**
54
+ * Check if the required wallet passkey is available and valid
55
+ * Priority: CLI arg > wallet.json > ENV var
56
+ * @param cliWalletKey - Optional wallet key from CLI
57
+ * @param showError - Whether to show error messages (default: true)
58
+ */
59
+ function getWalletPasskey(cliWalletKey, showError = true) {
60
+ // Get config with CLI wallet key taking precedence
61
+ const config = ConfigStore_1.ConfigStore.getConfig(cliWalletKey);
62
+ const passkey = config.walletKey;
63
+ if (!passkey) {
64
+ if (showError) {
65
+ console.error('❌ Error: Wallet private key is required for blockchain operations');
66
+ console.error('');
67
+ console.error(' Option 1 (Recommended): Run interactive setup');
68
+ console.error(' $ neozip init');
69
+ console.error('');
70
+ console.error(' Option 2: Use command-line flag');
71
+ console.error(' $ neozip -b -w 0x... <archive> <files>');
72
+ console.error('');
73
+ console.error(' Option 3: Set environment variable');
74
+ console.error(' $ export NEOZIP_WALLET_PASSKEY="0x..."');
75
+ console.error('');
76
+ console.error(' Get testnet ETH from: https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet');
77
+ }
78
+ return null;
79
+ }
80
+ // Validate the private key format
81
+ if (!(0, blockchain_1.validatePrivateKey)(passkey)) {
82
+ if (showError) {
83
+ console.error('❌ Error: Invalid private key format');
84
+ console.error(' Private key should be a 64-character hex string starting with 0x');
85
+ console.error(' Example: 0x1234567890abcdef...');
86
+ }
87
+ return null;
88
+ }
89
+ return passkey;
90
+ }
91
+ /**
92
+ * Add token metadata to ZIP file using the constant
93
+ */
94
+ async function addTokenMetaToZip(zip, tokenMeta) {
95
+ const tokenContent = JSON.stringify(tokenMeta, null, 2);
96
+ const tokenBuffer = Buffer.from(tokenContent, 'utf8');
97
+ const tokenPath = neozipkit_1.TOKENIZED_METADATA;
98
+ // Create new token entry
99
+ const tokenEntry = zip.createZipEntry(tokenPath);
100
+ tokenEntry.timeDateDOS = tokenEntry.setDateTime(new Date());
101
+ tokenEntry.compressedSize = tokenBuffer.length;
102
+ tokenEntry.uncompressedSize = tokenBuffer.length;
103
+ tokenEntry.cmpMethod = 0; // STORED
104
+ tokenEntry.crc = (0, neozipkit_1.crc32)(tokenBuffer);
105
+ tokenEntry.fileBuffer = tokenBuffer;
106
+ tokenEntry.isUpdated = true;
107
+ console.log('✅ Token metadata prepared for ZIP');
108
+ console.log(`📄 Token content:\n${tokenContent}`);
109
+ return tokenEntry;
110
+ }
111
+ /**
112
+ * Prompt user for action when minting timeout/error occurs
113
+ */
114
+ async function promptForMintingTimeoutAction(networkConfig, currentRpcIndex, nonInteractive) {
115
+ if (nonInteractive) {
116
+ return 'exit';
117
+ }
118
+ const rpcUrls = networkConfig.rpcUrls || [];
119
+ const hasMoreRpcs = currentRpcIndex + 1 < rpcUrls.length;
120
+ console.log('\n⏱️ Minting timeout/error occurred');
121
+ console.log(` Current RPC: ${rpcUrls[currentRpcIndex] || 'unknown'}`);
122
+ if (hasMoreRpcs) {
123
+ console.log(` ${rpcUrls.length - currentRpcIndex - 1} more RPC URL(s) available`);
124
+ }
125
+ const rl = readline.createInterface({
126
+ input: process.stdin,
127
+ output: process.stdout
128
+ });
129
+ return new Promise((resolve) => {
130
+ console.log('\nChoose an option:');
131
+ console.log(' 1. Retry minting with same RPC');
132
+ if (hasMoreRpcs) {
133
+ console.log(' 2. Try next RPC URL');
134
+ }
135
+ console.log(' 3. Exit (continue without token metadata)');
136
+ rl.question('Enter your choice (1-3): ', (answer) => {
137
+ rl.close();
138
+ const choice = answer.trim();
139
+ if (choice === '1') {
140
+ resolve('retry');
141
+ }
142
+ else if (choice === '2' && hasMoreRpcs) {
143
+ resolve('next-rpc');
144
+ }
145
+ else if (choice === '3') {
146
+ resolve('exit');
147
+ }
148
+ else {
149
+ // Invalid choice, default to exit
150
+ console.log('Invalid choice, exiting...');
151
+ resolve('exit');
152
+ }
153
+ });
154
+ });
155
+ }
156
+ /**
157
+ * Handle token minting process with retry logic and RPC switching
158
+ */
159
+ async function handleTokenMinting(initialMinter, zip, nonInteractive = false, initialRpcUrlIndex = 0) {
160
+ // Get network config from minter
161
+ const networkConfig = initialMinter.networkConfig;
162
+ const network = initialMinter.networkConfig?.network || 'unknown';
163
+ const merkleRoot = initialMinter.merkleRoot;
164
+ const walletPrivateKey = initialMinter.wallet?.privateKey;
165
+ const debug = initialMinter.debug;
166
+ const verbose = process.env.NEOZIP_VERBOSE === 'true';
167
+ let currentRpcIndex = initialRpcUrlIndex;
168
+ let maxRetries = 3; // Maximum retries per RPC
169
+ let retryCount = 0;
170
+ let minter = null;
171
+ // Cleanup helper
172
+ const cleanup = () => {
173
+ if (minter) {
174
+ try {
175
+ minter.destroy();
176
+ }
177
+ catch (error) {
178
+ // Ignore cleanup errors
179
+ }
180
+ }
181
+ };
182
+ try {
183
+ while (true) {
184
+ try {
185
+ // Cleanup previous minter if switching RPCs
186
+ if (minter && minter !== initialMinter) {
187
+ cleanup();
188
+ }
189
+ // Create new minter with current RPC index (or reuse initial if first attempt)
190
+ if (currentRpcIndex === initialRpcUrlIndex && retryCount === 0) {
191
+ minter = initialMinter;
192
+ }
193
+ else {
194
+ // ZipkitMinter uses getChainIdByName internally which handles all nameAliases
195
+ // So we can pass the original network name directly
196
+ minter = new neozipkit_1.ZipkitMinter(merkleRoot, {
197
+ network: network,
198
+ walletPrivateKey: walletPrivateKey,
199
+ verbose: verbose,
200
+ debug: debug,
201
+ rpcUrlIndex: currentRpcIndex
202
+ });
203
+ }
204
+ console.log('\n⏳ Minting token on blockchain...');
205
+ // Enable debug logging
206
+ const debugMode = debug || process.env.NEOZIP_DEBUG === 'true' || process.env.NEOZIP_VERBOSE === 'true';
207
+ if (debugMode) {
208
+ console.log('[DEBUG] Starting completeMinting()...');
209
+ if (networkConfig) {
210
+ console.log('[DEBUG] Network:', networkConfig.network || 'unknown');
211
+ console.log('[DEBUG] Chain ID:', networkConfig.chainId || 'unknown');
212
+ console.log('[DEBUG] Contract Address:', networkConfig.address || 'unknown');
213
+ console.log('[DEBUG] RPC URL:', networkConfig.rpcUrls?.[currentRpcIndex] || 'unknown');
214
+ console.log('[DEBUG] Explorer URL:', networkConfig.explorerUrl || 'unknown');
215
+ }
216
+ }
217
+ // Complete the minting process
218
+ const mintResult = await minter.completeMinting();
219
+ if (mintResult.mintingResult.success) {
220
+ console.log(`✅ Token minted successfully!`);
221
+ console.log(` Token ID: ${mintResult.tokenMetadata?.tokenId}`);
222
+ console.log(` Transaction: ${mintResult.tokenMetadata?.transactionHash}`);
223
+ console.log(` Contract: ${mintResult.tokenMetadata?.contractAddress}`);
224
+ // Create TokenMetadata from minting result
225
+ if (mintResult.tokenMetadata) {
226
+ // Determine contract version: v2.11+ has version in config, prior versions are "unknown"
227
+ const versionStr = networkConfig?.version || '0';
228
+ const versionNum = parseFloat(versionStr);
229
+ const contractVersion = versionNum >= 2.11 ? versionStr : 'unknown';
230
+ const tokenMeta = {
231
+ contractVersion: contractVersion,
232
+ tokenId: mintResult.tokenMetadata.tokenId,
233
+ contractAddress: mintResult.tokenMetadata.contractAddress,
234
+ network: mintResult.tokenMetadata.network,
235
+ networkChainId: mintResult.tokenMetadata.networkChainId || networkConfig?.chainId || 84532,
236
+ transactionHash: mintResult.tokenMetadata.transactionHash,
237
+ merkleRoot: mintResult.tokenMetadata.merkleRoot,
238
+ encryptedHash: mintResult.tokenMetadata.encryptedHash, // Currently unused, but preserve if present
239
+ mintedAt: mintResult.tokenMetadata.mintDate
240
+ };
241
+ // Cleanup before returning
242
+ if (minter !== initialMinter) {
243
+ cleanup();
244
+ }
245
+ return { success: true, tokenInfo: tokenMeta, entry: null };
246
+ }
247
+ }
248
+ else {
249
+ // Minting failed - check if it's a retryable error
250
+ const errorMessage = mintResult.mintingResult.message ||
251
+ mintResult.mintingResult.error ||
252
+ 'Unknown minting error';
253
+ // Check if this is a timeout or retryable error
254
+ const isTimeout = errorMessage.toLowerCase().includes('timeout');
255
+ const isNetworkError = errorMessage.toLowerCase().includes('network') ||
256
+ errorMessage.toLowerCase().includes('connection') ||
257
+ errorMessage.toLowerCase().includes('rpc') ||
258
+ errorMessage.toLowerCase().includes('failed to connect');
259
+ const isRetryable = isTimeout || isNetworkError;
260
+ if (isRetryable && !nonInteractive && networkConfig) {
261
+ // Display the error first
262
+ console.log(`❌ ${errorMessage}`);
263
+ console.log(` Network: ${networkConfig.network}`);
264
+ console.log(` RPC URL: ${networkConfig.rpcUrls[currentRpcIndex] || 'unknown'}`);
265
+ console.log(` Contract: ${networkConfig.address}`);
266
+ // Prompt user for action
267
+ const action = await promptForMintingTimeoutAction(networkConfig, currentRpcIndex, nonInteractive);
268
+ if (action === 'exit') {
269
+ // User chose to exit - continue without token metadata
270
+ if (minter !== initialMinter) {
271
+ cleanup();
272
+ }
273
+ return { success: false };
274
+ }
275
+ else if (action === 'retry') {
276
+ // Retry with same RPC
277
+ retryCount++;
278
+ if (retryCount >= maxRetries) {
279
+ console.log(`\n❌ Maximum retries (${maxRetries}) reached for current RPC`);
280
+ if (minter !== initialMinter) {
281
+ cleanup();
282
+ }
283
+ return { success: false };
284
+ }
285
+ console.log(`\n🔄 Retrying minting (attempt ${retryCount + 1}/${maxRetries})...`);
286
+ continue;
287
+ }
288
+ else if (action === 'next-rpc') {
289
+ // Try next RPC URL
290
+ currentRpcIndex++;
291
+ retryCount = 0; // Reset retry count for new RPC
292
+ if (currentRpcIndex >= networkConfig.rpcUrls.length) {
293
+ console.log('\n❌ No more RPC URLs available');
294
+ if (minter !== initialMinter) {
295
+ cleanup();
296
+ }
297
+ return { success: false };
298
+ }
299
+ console.log(`\n🔄 Trying next RPC URL (${currentRpcIndex + 1}/${networkConfig.rpcUrls.length})...`);
300
+ continue;
301
+ }
302
+ }
303
+ else {
304
+ // Not retryable or non-interactive - show error and return
305
+ console.error(`❌ Token minting failed!`);
306
+ if (mintResult.mintingResult.error) {
307
+ console.error(` Error: ${mintResult.mintingResult.error}`);
308
+ }
309
+ if (mintResult.mintingResult.message) {
310
+ console.error(` Message: ${mintResult.mintingResult.message}`);
311
+ }
312
+ if (minter !== initialMinter) {
313
+ cleanup();
314
+ }
315
+ return { success: false };
316
+ }
317
+ }
318
+ }
319
+ catch (error) {
320
+ // Handle unexpected errors
321
+ const errorMessage = error instanceof Error ? error.message : String(error);
322
+ const isTimeout = errorMessage.toLowerCase().includes('timeout');
323
+ const isNetworkError = errorMessage.toLowerCase().includes('network') ||
324
+ errorMessage.toLowerCase().includes('connection') ||
325
+ errorMessage.toLowerCase().includes('rpc') ||
326
+ errorMessage.toLowerCase().includes('failed to connect');
327
+ const isRetryable = isTimeout || isNetworkError;
328
+ if (isRetryable && !nonInteractive && networkConfig) {
329
+ // Display the error first
330
+ console.log(`❌ Minting error: ${errorMessage}`);
331
+ console.log(` Network: ${networkConfig.network}`);
332
+ console.log(` RPC URL: ${networkConfig.rpcUrls[currentRpcIndex] || 'unknown'}`);
333
+ console.log(` Contract: ${networkConfig.address}`);
334
+ const action = await promptForMintingTimeoutAction(networkConfig, currentRpcIndex, nonInteractive);
335
+ if (action === 'exit') {
336
+ if (minter && minter !== initialMinter) {
337
+ cleanup();
338
+ }
339
+ return { success: false };
340
+ }
341
+ else if (action === 'retry') {
342
+ retryCount++;
343
+ if (retryCount >= maxRetries) {
344
+ if (minter && minter !== initialMinter) {
345
+ cleanup();
346
+ }
347
+ return { success: false };
348
+ }
349
+ console.log(`\n🔄 Retrying minting (attempt ${retryCount + 1}/${maxRetries})...`);
350
+ continue;
351
+ }
352
+ else if (action === 'next-rpc') {
353
+ currentRpcIndex++;
354
+ retryCount = 0;
355
+ if (currentRpcIndex >= networkConfig.rpcUrls.length) {
356
+ if (minter && minter !== initialMinter) {
357
+ cleanup();
358
+ }
359
+ return { success: false };
360
+ }
361
+ console.log(`\n🔄 Trying next RPC URL (${currentRpcIndex + 1}/${networkConfig.rpcUrls.length})...`);
362
+ continue;
363
+ }
364
+ }
365
+ else {
366
+ // Not retryable or non-interactive - show error and return
367
+ console.error(`❌ Token minting error: ${errorMessage}`);
368
+ if (error instanceof Error && error.stack && debug) {
369
+ console.error(` Stack trace: ${error.stack}`);
370
+ }
371
+ if (minter && minter !== initialMinter) {
372
+ cleanup();
373
+ }
374
+ return { success: false };
375
+ }
376
+ }
377
+ }
378
+ }
379
+ finally {
380
+ // Ensure cleanup of any minter we created (but not the initial one)
381
+ if (minter && minter !== initialMinter) {
382
+ cleanup();
383
+ }
384
+ }
385
+ return { success: false };
386
+ }
387
+ //# sourceMappingURL=blockchain.js.map