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,486 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WalletManagerBrowser - Handles browser-specific wallet operations
|
|
3
|
+
* Manages MetaMask, Coinbase Wallet, and other browser providers
|
|
4
|
+
* Extends CoreWalletManager with browser-specific functionality
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ethers } from 'ethers';
|
|
8
|
+
import { CoreWalletManager } from '../core/WalletManager';
|
|
9
|
+
import { CONTRACT_CONFIGS, getContractConfig, isNetworkSupported, NZIP_CONTRACT_ABI } from '../core/contracts';
|
|
10
|
+
import { Logger } from '../../core/components/Logger';
|
|
11
|
+
|
|
12
|
+
// Extend Window interface for Ethereum provider
|
|
13
|
+
declare global {
|
|
14
|
+
interface Window {
|
|
15
|
+
ethereum?: any
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface WalletConfigBrowser {
|
|
20
|
+
chainId: number
|
|
21
|
+
network: string
|
|
22
|
+
address: string
|
|
23
|
+
rpcUrls: string[]
|
|
24
|
+
explorerUrl: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class WalletManagerBrowser extends CoreWalletManager {
|
|
28
|
+
private browserProvider: ethers.BrowserProvider | null = null
|
|
29
|
+
private readProvider: ethers.JsonRpcProvider | null = null
|
|
30
|
+
private contract: ethers.Contract | null = null
|
|
31
|
+
private currentConfig: WalletConfigBrowser
|
|
32
|
+
private targetChainId: number | null = null
|
|
33
|
+
|
|
34
|
+
// Dedicated RPC endpoints for read operations (to avoid rate limiting)
|
|
35
|
+
private RPC_ENDPOINTS: Record<number, string> = {
|
|
36
|
+
1: getContractConfig(1).rpcUrls[0],
|
|
37
|
+
11155111: getContractConfig(11155111).rpcUrls[0],
|
|
38
|
+
84532: getContractConfig(84532).rpcUrls[0],
|
|
39
|
+
8453: getContractConfig(8453).rpcUrls[0]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
constructor(initialChainId: number = 84532) {
|
|
43
|
+
super();
|
|
44
|
+
this.currentConfig = getContractConfig(initialChainId)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Cleanup method to dispose of providers and stop background processes
|
|
49
|
+
*/
|
|
50
|
+
public cleanup(): void {
|
|
51
|
+
Logger.log('🧹 Cleaning up browser wallet manager providers...')
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
// Clear providers to stop any ongoing background processes
|
|
55
|
+
if (this.readProvider) {
|
|
56
|
+
try {
|
|
57
|
+
(this.readProvider as any).destroy?.()
|
|
58
|
+
} catch (error) {
|
|
59
|
+
Logger.warn('Could not destroy read provider:', error)
|
|
60
|
+
}
|
|
61
|
+
this.readProvider = null
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (this.browserProvider) {
|
|
65
|
+
this.browserProvider = null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (this.contract) {
|
|
69
|
+
this.contract = null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
Logger.log('✅ Browser wallet manager cleanup completed')
|
|
73
|
+
} catch (error) {
|
|
74
|
+
Logger.warn('Error during browser wallet manager cleanup:', error)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private getNetworkName(chainId: number): string {
|
|
79
|
+
const networkNames: Record<number, string> = {
|
|
80
|
+
1: "homestead",
|
|
81
|
+
11155111: "sepolia",
|
|
82
|
+
84532: "base-sepolia",
|
|
83
|
+
8453: "base"
|
|
84
|
+
}
|
|
85
|
+
return networkNames[chainId] || `chain-${chainId}`
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Set the target network for wallet operations
|
|
90
|
+
*/
|
|
91
|
+
public setTargetNetwork(chainId: number): void {
|
|
92
|
+
if (!isNetworkSupported(chainId)) {
|
|
93
|
+
throw new Error(`Network ${chainId} is not supported for tokenization`)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
this.targetChainId = chainId
|
|
97
|
+
this.currentConfig = getContractConfig(chainId)
|
|
98
|
+
|
|
99
|
+
Logger.log(`🎯 Target network set to: ${this.currentConfig.network} (${chainId})`)
|
|
100
|
+
Logger.log(`📍 Contract address: ${this.currentConfig.address}`)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Get the current target network configuration
|
|
105
|
+
*/
|
|
106
|
+
public getCurrentConfig(): WalletConfigBrowser {
|
|
107
|
+
return this.currentConfig
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Initialize wallet with browser provider
|
|
112
|
+
*/
|
|
113
|
+
async initialize(walletAddress: string, existingProvider?: any): Promise<boolean> {
|
|
114
|
+
try {
|
|
115
|
+
// Use existing provider if available, otherwise create new one
|
|
116
|
+
if (existingProvider) {
|
|
117
|
+
Logger.log("🔄 Using existing wallet provider for tokenization")
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
this.browserProvider = new ethers.BrowserProvider(existingProvider)
|
|
121
|
+
await this.testProviderConnection(existingProvider)
|
|
122
|
+
} catch (providerError) {
|
|
123
|
+
Logger.warn("❌ Existing provider failed, falling back to window.ethereum:", providerError)
|
|
124
|
+
|
|
125
|
+
if (window.ethereum) {
|
|
126
|
+
this.browserProvider = new ethers.BrowserProvider(window.ethereum)
|
|
127
|
+
await this.testProviderConnection(window.ethereum)
|
|
128
|
+
} else {
|
|
129
|
+
throw new Error("No wallet provider available")
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
} else if (window.ethereum) {
|
|
133
|
+
Logger.log("🔄 Creating new provider from window.ethereum")
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
this.browserProvider = new ethers.BrowserProvider(window.ethereum)
|
|
137
|
+
await this.testProviderConnection(window.ethereum)
|
|
138
|
+
} catch (windowEthError: any) {
|
|
139
|
+
throw new Error(`Failed to connect to wallet: ${windowEthError.message}`)
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
throw new Error("No wallet provider found")
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Get chain ID with rate limit protection
|
|
146
|
+
let chainId: number | null = null
|
|
147
|
+
|
|
148
|
+
Logger.log("🔍 Starting network detection...")
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
Logger.log("📡 Attempting single eth_chainId call...")
|
|
152
|
+
const hexChainId = await this.browserProvider.send("eth_chainId", [])
|
|
153
|
+
chainId = parseInt(hexChainId, 16)
|
|
154
|
+
Logger.log(`✅ Network detected: Chain ${chainId}`)
|
|
155
|
+
} catch (chainIdError) {
|
|
156
|
+
Logger.warn("❌ Chain ID detection failed:", chainIdError)
|
|
157
|
+
chainId = this.currentConfig.chainId
|
|
158
|
+
Logger.log(`⚠️ Using default chain ID: ${chainId}`)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
Logger.log(`🎯 Final detected chain ID: ${chainId}`)
|
|
162
|
+
Logger.log(`🎯 Required chain ID: ${this.currentConfig.chainId}`)
|
|
163
|
+
|
|
164
|
+
// If no explicit target was set, adopt the detected network
|
|
165
|
+
if (!this.targetChainId && chainId) {
|
|
166
|
+
this.currentConfig = getContractConfig(chainId)
|
|
167
|
+
Logger.log(`🎛 Adopted current network: ${this.currentConfig.network} (${chainId})`)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Set up dedicated read provider to avoid rate limiting
|
|
171
|
+
if (chainId && this.RPC_ENDPOINTS[chainId]) {
|
|
172
|
+
try {
|
|
173
|
+
Logger.log(`🔗 Testing RPC endpoint before creating provider for chain ${chainId}...`)
|
|
174
|
+
const rpcUrl = this.RPC_ENDPOINTS[chainId]
|
|
175
|
+
|
|
176
|
+
// Test RPC endpoint with fetch first
|
|
177
|
+
const controller = new AbortController();
|
|
178
|
+
const timeout = setTimeout(() => controller.abort(), 2500)
|
|
179
|
+
const testResponse = await fetch(rpcUrl, {
|
|
180
|
+
method: 'POST',
|
|
181
|
+
headers: { 'Content-Type': 'application/json' },
|
|
182
|
+
body: JSON.stringify({ jsonrpc: '2.0', method: 'eth_chainId', params: [], id: 1 }),
|
|
183
|
+
signal: controller.signal,
|
|
184
|
+
}).catch(() => null as any)
|
|
185
|
+
clearTimeout(timeout)
|
|
186
|
+
|
|
187
|
+
if (!testResponse || !testResponse.ok) {
|
|
188
|
+
throw new Error('RPC endpoint did not respond in time')
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const testData = await testResponse.json().catch(() => null as any)
|
|
192
|
+
const actualChainId = testData && testData.result ? parseInt(testData.result, 16) : undefined
|
|
193
|
+
if (actualChainId !== chainId) {
|
|
194
|
+
throw new Error(`Chain ID mismatch: expected ${chainId}, got ${actualChainId}`)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
Logger.log(`✅ RPC endpoint test passed for chain ${chainId}`)
|
|
198
|
+
|
|
199
|
+
const networkConfig = {
|
|
200
|
+
name: this.getNetworkName(chainId),
|
|
201
|
+
chainId: chainId
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this.readProvider = new ethers.JsonRpcProvider(rpcUrl, networkConfig)
|
|
205
|
+
Logger.log(`✅ Read provider initialized successfully for ${rpcUrl}`)
|
|
206
|
+
|
|
207
|
+
} catch (readProviderError) {
|
|
208
|
+
Logger.warn("❌ Failed to set up read provider:", readProviderError)
|
|
209
|
+
this.readProvider = null
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Verify chain ID if we were able to detect it
|
|
214
|
+
if (chainId && chainId !== this.currentConfig.chainId) {
|
|
215
|
+
Logger.log(`❌ Wrong network detected. Current: Chain ${chainId}, Required: Chain ${this.currentConfig.chainId}`)
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
Logger.log(`🔄 Attempting to switch to ${this.currentConfig.network}...`)
|
|
219
|
+
await this.addAndSwitchNetwork()
|
|
220
|
+
Logger.log(`✅ Successfully switched to ${this.currentConfig.network}`)
|
|
221
|
+
|
|
222
|
+
// Re-verify the network after switching
|
|
223
|
+
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
const newNetwork = await this.browserProvider.getNetwork()
|
|
227
|
+
const newChainId = Number(newNetwork.chainId)
|
|
228
|
+
Logger.log(`🔍 Post-switch verification: Chain ${newChainId}`)
|
|
229
|
+
if (newChainId !== this.currentConfig.chainId) {
|
|
230
|
+
throw new Error(`Network switch failed. Still on Chain ${newChainId}`)
|
|
231
|
+
}
|
|
232
|
+
chainId = newChainId
|
|
233
|
+
|
|
234
|
+
// Recreate read provider for the new network
|
|
235
|
+
try {
|
|
236
|
+
if (this.readProvider) {
|
|
237
|
+
try { (this.readProvider as any).destroy?.() } catch {}
|
|
238
|
+
this.readProvider = null
|
|
239
|
+
}
|
|
240
|
+
const rpcUrl = this.RPC_ENDPOINTS[newChainId]
|
|
241
|
+
if (rpcUrl) {
|
|
242
|
+
const networkConfig = { name: this.getNetworkName(newChainId), chainId: newChainId }
|
|
243
|
+
this.readProvider = new ethers.JsonRpcProvider(rpcUrl, networkConfig)
|
|
244
|
+
Logger.log(`🔁 Read provider switched to ${rpcUrl}`)
|
|
245
|
+
}
|
|
246
|
+
} catch (rpErr) {
|
|
247
|
+
Logger.warn('Could not recreate read provider after switch:', rpErr)
|
|
248
|
+
}
|
|
249
|
+
} catch (verifyError) {
|
|
250
|
+
Logger.warn("Could not verify network after switch:", verifyError)
|
|
251
|
+
chainId = this.currentConfig.chainId
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
} catch (switchError) {
|
|
255
|
+
Logger.error("Failed to switch network:", switchError)
|
|
256
|
+
|
|
257
|
+
throw new Error(
|
|
258
|
+
`Please manually switch to ${this.currentConfig.network} in your wallet.\n\n` +
|
|
259
|
+
`Current network: Chain ${chainId}\n` +
|
|
260
|
+
`Required network: ${this.currentConfig.network} (Chain ID: ${this.currentConfig.chainId})\n\n` +
|
|
261
|
+
`In MetaMask:\n` +
|
|
262
|
+
`1. Click the network dropdown at the top\n` +
|
|
263
|
+
`2. Select "Add network" or "Custom networks"\n` +
|
|
264
|
+
`3. Add ${this.currentConfig.network} network details\n` +
|
|
265
|
+
`4. Switch to ${this.currentConfig.network}\n\n` +
|
|
266
|
+
`Network Details:\n` +
|
|
267
|
+
`• Network Name: ${this.currentConfig.network}\n` +
|
|
268
|
+
`• RPC URL: ${this.currentConfig.rpcUrls[0]}\n` +
|
|
269
|
+
`• Chain ID: ${this.currentConfig.chainId}\n` +
|
|
270
|
+
`• Currency Symbol: ETH\n` +
|
|
271
|
+
`• Block Explorer: ${this.currentConfig.explorerUrl}`
|
|
272
|
+
)
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
Logger.log(`🔗 Browser wallet manager initialized`)
|
|
277
|
+
Logger.log(`📡 Connected to ${this.currentConfig.network} (Chain ${chainId || 'unknown'})`)
|
|
278
|
+
Logger.log(`📍 Contract Address: ${this.currentConfig.address}`)
|
|
279
|
+
Logger.log(`👛 Wallet Address: ${walletAddress}`)
|
|
280
|
+
|
|
281
|
+
// Initialize contract with the actual contract address
|
|
282
|
+
try {
|
|
283
|
+
const signer = await this.browserProvider.getSigner()
|
|
284
|
+
this.contract = new ethers.Contract(this.currentConfig.address, NZIP_CONTRACT_ABI, signer)
|
|
285
|
+
|
|
286
|
+
// Test the contract connection by checking if it has code
|
|
287
|
+
try {
|
|
288
|
+
const providerForRead = this.readProvider || this.browserProvider
|
|
289
|
+
const code = await providerForRead.getCode(this.currentConfig.address)
|
|
290
|
+
if (code === '0x') {
|
|
291
|
+
Logger.warn(`⚠️ No contract code found at ${this.currentConfig.address}. Contract may not be deployed on this network.`)
|
|
292
|
+
} else {
|
|
293
|
+
Logger.log(`✅ Contract verified at ${this.currentConfig.address}`)
|
|
294
|
+
}
|
|
295
|
+
} catch (codeError) {
|
|
296
|
+
Logger.warn("Could not verify contract code:", codeError)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
} catch (signerError) {
|
|
300
|
+
Logger.error("Failed to get signer or initialize contract:", signerError)
|
|
301
|
+
throw new Error("Could not connect to wallet. Please ensure your wallet is unlocked and connected.")
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return true
|
|
305
|
+
} catch (error) {
|
|
306
|
+
Logger.error("Browser wallet manager initialization failed:", error)
|
|
307
|
+
|
|
308
|
+
if (error instanceof Error) {
|
|
309
|
+
if (error.message.includes("No wallet provider found")) {
|
|
310
|
+
throw new Error("No crypto wallet detected. Please install MetaMask, Coinbase Wallet, or another Web3 wallet.")
|
|
311
|
+
} else if (error.message.includes("Please switch to")) {
|
|
312
|
+
throw error
|
|
313
|
+
} else if (error.message.includes("Could not connect to wallet")) {
|
|
314
|
+
throw error
|
|
315
|
+
} else {
|
|
316
|
+
throw new Error(`Wallet connection failed: ${error.message}`)
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
throw error
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Get the contract instance
|
|
326
|
+
*/
|
|
327
|
+
public getContract(): ethers.Contract | null {
|
|
328
|
+
return this.contract
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Get the browser provider instance
|
|
333
|
+
*/
|
|
334
|
+
public getBrowserProvider(): ethers.BrowserProvider | null {
|
|
335
|
+
return this.browserProvider
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Override parent method to return browser provider
|
|
340
|
+
*/
|
|
341
|
+
public getWallet(): ethers.Wallet | null {
|
|
342
|
+
// Browser doesn't have direct wallet access, return null
|
|
343
|
+
return null
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Get the read provider instance
|
|
348
|
+
*/
|
|
349
|
+
public getReadProvider(): ethers.JsonRpcProvider | null {
|
|
350
|
+
return this.readProvider
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Override parent method to check browser provider
|
|
355
|
+
*/
|
|
356
|
+
public isReady(): boolean {
|
|
357
|
+
return this.browserProvider !== null
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Override parent method to check read provider
|
|
362
|
+
*/
|
|
363
|
+
public isOnline(): boolean {
|
|
364
|
+
return this.readProvider !== null || this.browserProvider !== null
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
private async addAndSwitchNetwork(): Promise<void> {
|
|
368
|
+
if (!window.ethereum) {
|
|
369
|
+
throw new Error("Ethereum provider not found")
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
try {
|
|
373
|
+
// First try to switch to the network (in case it already exists)
|
|
374
|
+
await window.ethereum.request({
|
|
375
|
+
method: "wallet_switchEthereumChain",
|
|
376
|
+
params: [
|
|
377
|
+
{
|
|
378
|
+
chainId: `0x${this.currentConfig.chainId.toString(16)}`,
|
|
379
|
+
},
|
|
380
|
+
],
|
|
381
|
+
})
|
|
382
|
+
|
|
383
|
+
Logger.log(`✅ Successfully switched to existing ${this.currentConfig.network}`)
|
|
384
|
+
|
|
385
|
+
} catch (switchError: any) {
|
|
386
|
+
// If switching failed, the network might not exist, so try to add it
|
|
387
|
+
if (switchError.code === 4902) {
|
|
388
|
+
Logger.log(`➕ Network not found, adding ${this.currentConfig.network}...`)
|
|
389
|
+
|
|
390
|
+
try {
|
|
391
|
+
await window.ethereum.request({
|
|
392
|
+
method: "wallet_addEthereumChain",
|
|
393
|
+
params: [
|
|
394
|
+
{
|
|
395
|
+
chainId: `0x${this.currentConfig.chainId.toString(16)}`,
|
|
396
|
+
chainName: this.currentConfig.network,
|
|
397
|
+
nativeCurrency: {
|
|
398
|
+
name: "ETH",
|
|
399
|
+
symbol: "ETH",
|
|
400
|
+
decimals: 18,
|
|
401
|
+
},
|
|
402
|
+
rpcUrls: this.currentConfig.rpcUrls,
|
|
403
|
+
blockExplorerUrls: [
|
|
404
|
+
this.currentConfig.explorerUrl,
|
|
405
|
+
],
|
|
406
|
+
},
|
|
407
|
+
],
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
Logger.log(`✅ Successfully added and switched to ${this.currentConfig.network}`)
|
|
411
|
+
|
|
412
|
+
} catch (addError: any) {
|
|
413
|
+
Logger.error("Failed to add network:", addError)
|
|
414
|
+
|
|
415
|
+
if (addError.code === 4001) {
|
|
416
|
+
throw new Error("User rejected the network addition request. Please manually add Base Sepolia network to your wallet.")
|
|
417
|
+
} else {
|
|
418
|
+
throw new Error(`Failed to add ${this.currentConfig.network} network: ${addError.message}`)
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
} else if (switchError.code === 4001) {
|
|
422
|
+
throw new Error("User rejected the network switch request. Please manually switch to Base Sepolia in your wallet.")
|
|
423
|
+
} else {
|
|
424
|
+
Logger.error("Network switch failed:", switchError)
|
|
425
|
+
throw new Error(`Failed to switch to ${this.currentConfig.network}: ${switchError.message}`)
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
private async testProviderConnection(provider: any): Promise<void> {
|
|
431
|
+
try {
|
|
432
|
+
await provider.request({ method: 'eth_chainId' })
|
|
433
|
+
Logger.log("✅ Provider connection successful (eth_chainId)")
|
|
434
|
+
} catch (error: any) {
|
|
435
|
+
Logger.warn("❌ Provider connection failed (eth_chainId):", error)
|
|
436
|
+
throw new Error(`Could not establish connection to wallet: ${error.message}`)
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// ===== Explorer URL Generation Methods =====
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Generate block explorer URL for a transaction
|
|
444
|
+
*/
|
|
445
|
+
public getExplorerUrl(transactionHash: string): string {
|
|
446
|
+
return `${this.currentConfig.explorerUrl}/tx/${transactionHash}`
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Generate block explorer URL for a contract
|
|
451
|
+
*/
|
|
452
|
+
public getContractExplorerUrl(): string {
|
|
453
|
+
return `${this.currentConfig.explorerUrl}/address/${this.currentConfig.address}`
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Generate block explorer URL for a token
|
|
458
|
+
* Uses the contract address page where users can search for specific token IDs
|
|
459
|
+
*/
|
|
460
|
+
public getTokenExplorerUrl(tokenId: string): string {
|
|
461
|
+
return `${this.currentConfig.explorerUrl}/address/${this.currentConfig.address}#readContract`
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Generate block explorer URL for a specific token ID
|
|
466
|
+
* Some explorers support direct token URLs
|
|
467
|
+
*/
|
|
468
|
+
public getTokenDirectUrl(tokenId: string): string {
|
|
469
|
+
// This varies by explorer, but most support this pattern
|
|
470
|
+
return `${this.currentConfig.explorerUrl}/token/${this.currentConfig.address}?a=${tokenId}`
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Generate block explorer URL for an address
|
|
475
|
+
*/
|
|
476
|
+
public getAddressExplorerUrl(address: string): string {
|
|
477
|
+
return `${this.currentConfig.explorerUrl}/address/${address}`
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Generate block explorer URL for a block
|
|
482
|
+
*/
|
|
483
|
+
public getBlockExplorerUrl(blockNumber: string | number): string {
|
|
484
|
+
return `${this.currentConfig.explorerUrl}/block/${blockNumber}`
|
|
485
|
+
}
|
|
486
|
+
}
|