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.
- package/README.md +400 -0
- package/contracts/Lock.sol +34 -0
- package/contracts/bytecode.txt +1 -0
- package/contracts/compile-contract.js +168 -0
- package/contracts/deploy/deploy-both-contracts.js +286 -0
- package/contracts/deploy/deploy-enhanced-contract.js +197 -0
- package/contracts/deploy/deploy-private-contract.js +190 -0
- package/contracts/deploy/deploy-public-clean.js +1063 -0
- package/contracts/deploy/deploy-public-contract.js +1107 -0
- package/contracts/deployment.config.example.js +25 -0
- package/contracts/remix-compile.js +222 -0
- package/contracts/setup-deployment.js +51 -0
- package/contracts/src/NZIP-NFT-Private.sol +350 -0
- package/contracts/src/NZIP-NFT.sol +265 -0
- package/contracts/src/ZipFileNFT-DEPRECATED-6field.sol +260 -0
- package/contracts/src/ZipFileNFT-DEPRECATED-Enhanced.sol +289 -0
- package/dist/browser/CertificateGeneratorBrowser.d.ts +75 -0
- package/dist/browser/CertificateGeneratorBrowser.js +433 -0
- package/dist/browser/TokenVerifierBrowser.d.ts +76 -0
- package/dist/browser/TokenVerifierBrowser.js +299 -0
- package/dist/browser/ZipKitBrowser.d.ts +18 -0
- package/dist/browser/ZipKitBrowser.js +250 -0
- package/dist/browser/ZipKitStampBrowser.d.ts +2 -0
- package/dist/browser/ZipKitStampBrowser.js +12 -0
- package/dist/browser-index.d.ts +21 -0
- package/dist/browser-index.js +58 -0
- package/dist/browser.d.ts +21 -0
- package/dist/browser.js +58 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +76 -0
- package/dist/server/blockchain/CertificateToken.d.ts +48 -0
- package/dist/server/blockchain/CertificateToken.js +386 -0
- package/dist/server/blockchain/NFTMinter.d.ts +41 -0
- package/dist/server/blockchain/NFTMinter.js +323 -0
- package/dist/server/blockchain/TokenQuerier.d.ts +31 -0
- package/dist/server/blockchain/TokenQuerier.js +259 -0
- package/dist/server/blockchain/TokenVerifier.d.ts +20 -0
- package/dist/server/blockchain/TokenVerifier.js +395 -0
- package/dist/server/blockchain/WalletAnalyzer.d.ts +81 -0
- package/dist/server/blockchain/WalletAnalyzer.js +356 -0
- package/dist/server/blockchain/WalletFormatter.d.ts +39 -0
- package/dist/server/blockchain/WalletFormatter.js +196 -0
- package/dist/server/blockchain/WalletManager.d.ts +46 -0
- package/dist/server/blockchain/WalletManager.js +294 -0
- package/dist/server/blockchain/ZipMetadata.d.ts +27 -0
- package/dist/server/blockchain/ZipMetadata.js +131 -0
- package/dist/server/blockchain/ZipTokenProcessor.d.ts +44 -0
- package/dist/server/blockchain/ZipTokenProcessor.js +204 -0
- package/dist/server/blockchain/constants.d.ts +102 -0
- package/dist/server/blockchain/constants.js +968 -0
- package/dist/server/blockchain/index.d.ts +9 -0
- package/dist/server/blockchain/index.js +44 -0
- package/dist/server/blockchain/test-certificate.d.ts +8 -0
- package/dist/server/blockchain/test-certificate.js +100 -0
- package/dist/server/blockchain/types.d.ts +69 -0
- package/dist/server/blockchain/types.js +51 -0
- package/dist/server/platform/server/ZipKitServer.d.ts +105 -0
- package/dist/server/platform/server/ZipKitServer.js +437 -0
- package/dist/server/platform/servercomponents/ZipKitOTS.d.ts +91 -0
- package/dist/server/platform/servercomponents/ZipKitOTS.js +271 -0
- package/dist/shared/ZipEntry.d.ts +131 -0
- package/dist/shared/ZipEntry.js +686 -0
- package/dist/shared/ZipKit.d.ts +249 -0
- package/dist/shared/ZipKit.js +789 -0
- package/dist/shared/components/CertificateOTS.d.ts +15 -0
- package/dist/shared/components/CertificateOTS.js +116 -0
- package/dist/shared/components/FileSys.d.ts +2 -0
- package/dist/shared/components/FileSys.js +113 -0
- package/dist/shared/components/HashAccumulator.d.ts +55 -0
- package/dist/shared/components/HashAccumulator.js +100 -0
- package/dist/shared/components/Support.d.ts +63 -0
- package/dist/shared/components/Support.js +70 -0
- package/dist/shared/components/Util.d.ts +21 -0
- package/dist/shared/components/Util.js +115 -0
- package/dist/shared/components/ZipCrypto.d.ts +3 -0
- package/dist/shared/components/ZipCrypto.js +78 -0
- package/dist/shared/components/merkleTree.d.ts +66 -0
- package/dist/shared/components/merkleTree.js +136 -0
- package/dist/shared/constants/Errors.d.ts +53 -0
- package/dist/shared/constants/Errors.js +69 -0
- package/dist/shared/constants/Headers.d.ts +167 -0
- package/dist/shared/constants/Headers.js +191 -0
- package/dist/shared/types/index.d.ts +21 -0
- package/dist/shared/types/index.js +3 -0
- package/dist/shared/types.d.ts +33 -0
- package/dist/shared/types.js +8 -0
- package/dist/shared/version.d.ts +4 -0
- package/dist/shared/version.js +7 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/index.js +3 -0
- package/examples/unzip-token.ts +488 -0
- package/examples/zip-token.ts +604 -0
- package/package.json +117 -0
- package/src/browser/CertificateGeneratorBrowser.ts +498 -0
- package/src/browser/TokenVerifierBrowser.ts +344 -0
- package/src/browser/ZipKitBrowser.ts +242 -0
- package/src/browser/ZipKitStampBrowser.ts +9 -0
- package/src/browser-index.ts +36 -0
- package/src/index.ts +48 -0
- package/src/server/blockchain/CertificateToken.ts +444 -0
- package/src/server/blockchain/NFTMinter.ts +357 -0
- package/src/server/blockchain/TokenQuerier.ts +287 -0
- package/src/server/blockchain/TokenVerifier.ts +453 -0
- package/src/server/blockchain/WalletAnalyzer.ts +397 -0
- package/src/server/blockchain/WalletFormatter.ts +206 -0
- package/src/server/blockchain/WalletManager.ts +294 -0
- package/src/server/blockchain/ZipMetadata.ts +117 -0
- package/src/server/blockchain/ZipTokenProcessor.ts +234 -0
- package/src/server/blockchain/constants.ts +969 -0
- package/src/server/blockchain/index.ts +42 -0
- package/src/server/blockchain/test-certificate.ts +137 -0
- package/src/server/blockchain/types.ts +134 -0
- package/src/server/platform/server/ZipKitServer.ts +459 -0
- package/src/server/platform/servercomponents/ZipKitOTS.ts +313 -0
- package/src/server/platform/servercomponents/opentimestamps.d.ts +23 -0
- package/src/shared/ZipEntry.ts +767 -0
- package/src/shared/ZipKit.ts +899 -0
- package/src/shared/components/CertificateOTS.ts +132 -0
- package/src/shared/components/FileSys.ts +87 -0
- package/src/shared/components/HashAccumulator.ts +113 -0
- package/src/shared/components/Support.ts +77 -0
- package/src/shared/components/Util.ts +113 -0
- package/src/shared/components/ZipCrypto.ts +91 -0
- package/src/shared/components/merkleTree.ts +162 -0
- package/src/shared/constants/Errors.ts +82 -0
- package/src/shared/constants/Headers.ts +203 -0
- package/src/shared/types/index.ts +25 -0
- package/src/shared/types/modules.d.ts +22 -0
- package/src/shared/types/opentimestamps.d.ts +23 -0
- package/src/shared/types.d.ts +8 -0
- package/src/shared/types.ts +43 -0
- package/src/shared/version.ts +4 -0
- package/src/types/index.ts +25 -0
- package/src/types/modules.d.ts +22 -0
- package/src/types/opentimestamps.d.ts +23 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
const { ethers } = require('ethers');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Deployment script for both NZIP NFT contracts
|
|
7
|
+
*
|
|
8
|
+
* This script deploys:
|
|
9
|
+
* 1. NZIP-NFT.sol (Public contract with universal verification)
|
|
10
|
+
* 2. NZIP-NFT-Private.sol (Private contract with owner-only verification)
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* 1. Compile both contracts in Remix or using solc
|
|
14
|
+
* 2. Copy the bytecode and ABI for both contracts into this script
|
|
15
|
+
* 3. Run: node deploy-both-contracts.js
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// =============================================================================
|
|
19
|
+
// CONFIGURATION
|
|
20
|
+
// =============================================================================
|
|
21
|
+
|
|
22
|
+
const NETWORK_CONFIG = {
|
|
23
|
+
// Base Sepolia (Testnet)
|
|
24
|
+
84532: {
|
|
25
|
+
name: "Base Sepolia",
|
|
26
|
+
rpcUrl: "https://sepolia.base.org",
|
|
27
|
+
explorerUrl: "https://sepolia.basescan.org",
|
|
28
|
+
chainId: 84532
|
|
29
|
+
},
|
|
30
|
+
// Base Mainnet
|
|
31
|
+
8453: {
|
|
32
|
+
name: "Base Mainnet",
|
|
33
|
+
rpcUrl: "https://mainnet.base.org",
|
|
34
|
+
explorerUrl: "https://basescan.org",
|
|
35
|
+
chainId: 8453
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Configuration - Load from environment variables or config file
|
|
40
|
+
function loadConfig() {
|
|
41
|
+
let config = {};
|
|
42
|
+
|
|
43
|
+
// Try to load from deployment.config.js first
|
|
44
|
+
try {
|
|
45
|
+
config = require('../../deployment.config.js');
|
|
46
|
+
console.log('๐ Loaded configuration from deployment.config.js');
|
|
47
|
+
} catch (err) {
|
|
48
|
+
console.log('๐ No deployment.config.js found, using environment variables');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Environment variables override config file
|
|
52
|
+
const CHAIN_ID = process.env.CHAIN_ID ? parseInt(process.env.CHAIN_ID) : (config.CHAIN_ID || 84532);
|
|
53
|
+
const PRIVATE_KEY = process.env.PRIVATE_KEY || config.PRIVATE_KEY;
|
|
54
|
+
|
|
55
|
+
return { CHAIN_ID, PRIVATE_KEY, EXISTING_CONTRACT: config.EXISTING_CONTRACT };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Default to Base Sepolia for testing
|
|
59
|
+
const { CHAIN_ID, PRIVATE_KEY, EXISTING_CONTRACT } = loadConfig();
|
|
60
|
+
|
|
61
|
+
// =============================================================================
|
|
62
|
+
// CONTRACT BYTECODE AND ABI (REPLACE WITH COMPILED CONTRACT DATA)
|
|
63
|
+
// =============================================================================
|
|
64
|
+
|
|
65
|
+
// TODO: Replace with actual compiled bytecode from Remix/solc
|
|
66
|
+
const PUBLIC_CONTRACT_BYTECODE = "0x608060405234801561001057600080fd5b50..."; // REPLACE ME
|
|
67
|
+
const PRIVATE_CONTRACT_BYTECODE = "0x608060405234801561001057600080fd5b50..."; // REPLACE ME
|
|
68
|
+
|
|
69
|
+
// TODO: Replace with actual compiled ABI from Remix/solc
|
|
70
|
+
const PUBLIC_CONTRACT_ABI = [
|
|
71
|
+
// REPLACE WITH ACTUAL ABI FROM NZIP-NFT.sol
|
|
72
|
+
"constructor()",
|
|
73
|
+
"function publicMintZipFile(string memory fileName, string memory merkleRootHash, uint256 creationTimestamp, string memory ipfsHash, string memory tokenURI) public returns (uint256)",
|
|
74
|
+
"function getZipFileInfo(uint256 tokenId) external view returns (tuple(string fileName, string merkleRootHash, string ipfsHash, address creator, uint256 creationTimestamp, uint256 tokenizationTime, uint256 blockNumber, bytes32 blockHash))",
|
|
75
|
+
"function totalSupply() public view returns (uint256)"
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
const PRIVATE_CONTRACT_ABI = [
|
|
79
|
+
// REPLACE WITH ACTUAL ABI FROM NZIP-NFT-Private.sol
|
|
80
|
+
"constructor()",
|
|
81
|
+
"function publicMintZipFile(string memory fileName, string memory merkleRootHash, uint256 creationTimestamp, string memory ipfsHash, string memory tokenURI) public returns (uint256)",
|
|
82
|
+
"function getZipFileInfo(uint256 tokenId) external view returns (tuple(string fileName, string merkleRootHash, string ipfsHash, address creator, uint256 creationTimestamp, uint256 tokenizationTime, uint256 blockNumber, bytes32 blockHash))",
|
|
83
|
+
"function authorizeVerifier(uint256 tokenId, address authorizedAddress, bool authorized) external",
|
|
84
|
+
"function totalSupply() public view returns (uint256)"
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
// =============================================================================
|
|
88
|
+
// DEPLOYMENT FUNCTIONS
|
|
89
|
+
// =============================================================================
|
|
90
|
+
|
|
91
|
+
async function deployContract(contractName, bytecode, abi, signer) {
|
|
92
|
+
console.log(`\n๐ Deploying ${contractName}...`);
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
// Create contract factory
|
|
96
|
+
const contractFactory = new ethers.ContractFactory(abi, bytecode, signer);
|
|
97
|
+
|
|
98
|
+
// Estimate gas for deployment
|
|
99
|
+
const gasEstimate = await contractFactory.estimateDeployment();
|
|
100
|
+
console.log(`โฝ Estimated gas: ${gasEstimate.toString()}`);
|
|
101
|
+
|
|
102
|
+
// Deploy the contract
|
|
103
|
+
const contract = await contractFactory.deploy();
|
|
104
|
+
console.log(`๐ Transaction hash: ${contract.deploymentTransaction().hash}`);
|
|
105
|
+
console.log(`โณ Waiting for confirmation...`);
|
|
106
|
+
|
|
107
|
+
// Wait for deployment to be mined
|
|
108
|
+
await contract.waitForDeployment();
|
|
109
|
+
const address = await contract.getAddress();
|
|
110
|
+
|
|
111
|
+
console.log(`โ
${contractName} deployed successfully!`);
|
|
112
|
+
console.log(`๐ Contract address: ${address}`);
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
address,
|
|
116
|
+
transactionHash: contract.deploymentTransaction().hash,
|
|
117
|
+
contract
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error(`โ Failed to deploy ${contractName}:`, error);
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function deployBothContracts() {
|
|
127
|
+
console.log('๐ฏ NZIP NFT Contracts Deployment');
|
|
128
|
+
console.log('=======================================');
|
|
129
|
+
|
|
130
|
+
// Validate configuration
|
|
131
|
+
if (!PRIVATE_KEY) {
|
|
132
|
+
throw new Error('โ PRIVATE_KEY environment variable is required');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (!NETWORK_CONFIG[CHAIN_ID]) {
|
|
136
|
+
throw new Error(`โ Unsupported chain ID: ${CHAIN_ID}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const networkConfig = NETWORK_CONFIG[CHAIN_ID];
|
|
140
|
+
console.log(`๐ Network: ${networkConfig.name}`);
|
|
141
|
+
console.log(`๐ RPC URL: ${networkConfig.rpcUrl}`);
|
|
142
|
+
console.log(`๐ Explorer: ${networkConfig.explorerUrl}`);
|
|
143
|
+
|
|
144
|
+
// Validate contract data
|
|
145
|
+
if (PUBLIC_CONTRACT_BYTECODE.length < 10 || PRIVATE_CONTRACT_BYTECODE.length < 10) {
|
|
146
|
+
throw new Error('โ Contract bytecode not provided. Please compile contracts and update the script.');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
// Initialize provider and wallet
|
|
151
|
+
console.log('\n๐ Initializing wallet...');
|
|
152
|
+
const provider = new ethers.JsonRpcProvider(networkConfig.rpcUrl);
|
|
153
|
+
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
|
|
154
|
+
|
|
155
|
+
console.log(`๐ Deployer address: ${wallet.address}`);
|
|
156
|
+
|
|
157
|
+
// Check balance
|
|
158
|
+
const balance = await provider.getBalance(wallet.address);
|
|
159
|
+
const balanceEth = ethers.formatEther(balance);
|
|
160
|
+
console.log(`๐ฐ Balance: ${balanceEth} ETH`);
|
|
161
|
+
|
|
162
|
+
if (parseFloat(balanceEth) < 0.01) {
|
|
163
|
+
console.warn('โ ๏ธ Low balance detected. Make sure you have enough ETH for deployment.');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Deploy both contracts
|
|
167
|
+
const deploymentResults = {};
|
|
168
|
+
|
|
169
|
+
// Deploy Public Contract
|
|
170
|
+
const publicResult = await deployContract(
|
|
171
|
+
"NZIP NFT (Public)",
|
|
172
|
+
PUBLIC_CONTRACT_BYTECODE,
|
|
173
|
+
PUBLIC_CONTRACT_ABI,
|
|
174
|
+
wallet
|
|
175
|
+
);
|
|
176
|
+
deploymentResults.public = publicResult;
|
|
177
|
+
|
|
178
|
+
// Deploy Private Contract
|
|
179
|
+
const privateResult = await deployContract(
|
|
180
|
+
"NZIP NFT (Private)",
|
|
181
|
+
PRIVATE_CONTRACT_BYTECODE,
|
|
182
|
+
PRIVATE_CONTRACT_ABI,
|
|
183
|
+
wallet
|
|
184
|
+
);
|
|
185
|
+
deploymentResults.private = privateResult;
|
|
186
|
+
|
|
187
|
+
// Test basic functionality
|
|
188
|
+
console.log('\n๐งช Testing deployed contracts...');
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
const publicSupply = await deploymentResults.public.contract.totalSupply();
|
|
192
|
+
const privateSupply = await deploymentResults.private.contract.totalSupply();
|
|
193
|
+
|
|
194
|
+
console.log(`โ
Public contract total supply: ${publicSupply}`);
|
|
195
|
+
console.log(`โ
Private contract total supply: ${privateSupply}`);
|
|
196
|
+
} catch (testError) {
|
|
197
|
+
console.warn('โ ๏ธ Contract testing failed (this may be expected):', testError.message);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Generate deployment summary
|
|
201
|
+
const summary = {
|
|
202
|
+
network: networkConfig.name,
|
|
203
|
+
chainId: CHAIN_ID,
|
|
204
|
+
deployerAddress: wallet.address,
|
|
205
|
+
deployedAt: new Date().toISOString(),
|
|
206
|
+
contracts: {
|
|
207
|
+
public: {
|
|
208
|
+
name: "NZIP NFT (Public)",
|
|
209
|
+
address: deploymentResults.public.address,
|
|
210
|
+
transactionHash: deploymentResults.public.transactionHash,
|
|
211
|
+
explorerUrl: `${networkConfig.explorerUrl}/address/${deploymentResults.public.address}`,
|
|
212
|
+
txExplorerUrl: `${networkConfig.explorerUrl}/tx/${deploymentResults.public.transactionHash}`
|
|
213
|
+
},
|
|
214
|
+
private: {
|
|
215
|
+
name: "NZIP NFT (Private)",
|
|
216
|
+
address: deploymentResults.private.address,
|
|
217
|
+
transactionHash: deploymentResults.private.transactionHash,
|
|
218
|
+
explorerUrl: `${networkConfig.explorerUrl}/address/${deploymentResults.private.address}`,
|
|
219
|
+
txExplorerUrl: `${networkConfig.explorerUrl}/tx/${deploymentResults.private.transactionHash}`
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// Save deployment info
|
|
225
|
+
const deploymentFile = `deployment-${networkConfig.name.toLowerCase().replace(' ', '-')}-${Date.now()}.json`;
|
|
226
|
+
fs.writeFileSync(deploymentFile, JSON.stringify(summary, null, 2));
|
|
227
|
+
|
|
228
|
+
// Display final summary
|
|
229
|
+
console.log('\n๐ DEPLOYMENT COMPLETE!');
|
|
230
|
+
console.log('=======================================');
|
|
231
|
+
console.log(`๐ Deployment summary saved to: ${deploymentFile}`);
|
|
232
|
+
console.log('\n๐ Contract Addresses:');
|
|
233
|
+
console.log(`๐ Public Contract: ${summary.contracts.public.address}`);
|
|
234
|
+
console.log(`๐ Private Contract: ${summary.contracts.private.address}`);
|
|
235
|
+
|
|
236
|
+
console.log('\n๐ Explorer Links:');
|
|
237
|
+
console.log(`๐ Public Contract: ${summary.contracts.public.explorerUrl}`);
|
|
238
|
+
console.log(`๐ Private Contract: ${summary.contracts.private.explorerUrl}`);
|
|
239
|
+
|
|
240
|
+
console.log('\n๐ Transaction Links:');
|
|
241
|
+
console.log(`๐ Public TX: ${summary.contracts.public.txExplorerUrl}`);
|
|
242
|
+
console.log(`๐ Private TX: ${summary.contracts.private.txExplorerUrl}`);
|
|
243
|
+
|
|
244
|
+
console.log('\nโ๏ธ Next Steps:');
|
|
245
|
+
console.log('1. Verify contracts on the block explorer');
|
|
246
|
+
console.log('2. Update portal configuration with new contract addresses');
|
|
247
|
+
console.log('3. Update neozipkit package with new ABIs');
|
|
248
|
+
console.log('4. Test minting functionality');
|
|
249
|
+
|
|
250
|
+
console.log('\n๐ง Portal Configuration Updates Needed:');
|
|
251
|
+
console.log('File: apps/portal/src/lib/tokenization.ts');
|
|
252
|
+
console.log(`- Update CONTRACT_CONFIG.contractAddress to: "${summary.contracts.public.address}"`);
|
|
253
|
+
console.log('\nFile: apps/portal/src/services/nftTokenService.ts');
|
|
254
|
+
console.log('- Add private contract configuration if needed');
|
|
255
|
+
|
|
256
|
+
return summary;
|
|
257
|
+
|
|
258
|
+
} catch (error) {
|
|
259
|
+
console.error('\nโ Deployment failed:', error);
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// =============================================================================
|
|
265
|
+
// MAIN EXECUTION
|
|
266
|
+
// =============================================================================
|
|
267
|
+
|
|
268
|
+
if (require.main === module) {
|
|
269
|
+
// Only run if this file is executed directly
|
|
270
|
+
deployBothContracts()
|
|
271
|
+
.then((summary) => {
|
|
272
|
+
console.log('\nโ
All deployments completed successfully!');
|
|
273
|
+
process.exit(0);
|
|
274
|
+
})
|
|
275
|
+
.catch((error) => {
|
|
276
|
+
console.error('\nโ Deployment process failed:', error);
|
|
277
|
+
process.exit(1);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Export for use in other scripts
|
|
282
|
+
module.exports = {
|
|
283
|
+
deployBothContracts,
|
|
284
|
+
deployContract,
|
|
285
|
+
NETWORK_CONFIG
|
|
286
|
+
};
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
const { ethers } = require('ethers');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
// Contract deployment configuration
|
|
6
|
+
const DEPLOYMENT_CONFIG = {
|
|
7
|
+
networks: {
|
|
8
|
+
'base-sepolia': {
|
|
9
|
+
name: 'Base Sepolia',
|
|
10
|
+
chainId: 84532,
|
|
11
|
+
rpcUrl: 'https://sepolia.base.org',
|
|
12
|
+
explorerUrl: 'https://sepolia.basescan.org'
|
|
13
|
+
},
|
|
14
|
+
'base-mainnet': {
|
|
15
|
+
name: 'Base Mainnet',
|
|
16
|
+
chainId: 8453,
|
|
17
|
+
rpcUrl: 'https://mainnet.base.org',
|
|
18
|
+
explorerUrl: 'https://basescan.org'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Contract source (you'll need to compile this or use Remix)
|
|
24
|
+
const CONTRACT_SOURCE = `
|
|
25
|
+
// SPDX-License-Identifier: MIT
|
|
26
|
+
pragma solidity ^0.8.19;
|
|
27
|
+
|
|
28
|
+
// NOTE: This script expects the compiled contract bytecode and ABI
|
|
29
|
+
// Compile ZipFileNFT-Enhanced.sol using Remix, Hardhat, or Foundry
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
async function deployEnhancedContract(networkName = 'base-sepolia', privateKey = null) {
|
|
33
|
+
try {
|
|
34
|
+
console.log('๐ Starting Enhanced NZIP Contract Deployment');
|
|
35
|
+
console.log('='.repeat(50));
|
|
36
|
+
|
|
37
|
+
const network = DEPLOYMENT_CONFIG.networks[networkName];
|
|
38
|
+
if (!network) {
|
|
39
|
+
throw new Error(`Network ${networkName} not supported. Available: ${Object.keys(DEPLOYMENT_CONFIG.networks).join(', ')}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log(`๐ก Network: ${network.name} (Chain ID: ${network.chainId})`);
|
|
43
|
+
console.log(`๐ RPC URL: ${network.rpcUrl}`);
|
|
44
|
+
|
|
45
|
+
// Setup provider and wallet
|
|
46
|
+
const provider = new ethers.JsonRpcProvider(network.rpcUrl);
|
|
47
|
+
|
|
48
|
+
if (!privateKey) {
|
|
49
|
+
privateKey = process.env.DEPLOYER_PRIVATE_KEY;
|
|
50
|
+
if (!privateKey) {
|
|
51
|
+
throw new Error('Please provide DEPLOYER_PRIVATE_KEY environment variable or pass privateKey parameter');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const wallet = new ethers.Wallet(privateKey, provider);
|
|
56
|
+
const deployerAddress = await wallet.getAddress();
|
|
57
|
+
|
|
58
|
+
console.log(`๐ Deployer Address: ${deployerAddress}`);
|
|
59
|
+
|
|
60
|
+
// Check balance
|
|
61
|
+
const balance = await provider.getBalance(deployerAddress);
|
|
62
|
+
const balanceInEth = ethers.formatEther(balance);
|
|
63
|
+
console.log(`๐ฐ Deployer Balance: ${balanceInEth} ETH`);
|
|
64
|
+
|
|
65
|
+
if (parseFloat(balanceInEth) < 0.01) {
|
|
66
|
+
console.warn('โ ๏ธ Low balance detected. You may need more ETH for deployment.');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Contract bytecode and ABI (these need to be compiled first)
|
|
70
|
+
console.log('๐ Loading contract artifacts...');
|
|
71
|
+
|
|
72
|
+
// NOTE: You'll need to replace these with actual compiled contract data
|
|
73
|
+
const contractBytecode = "0x608060405234801561001057600080fd5b50..." // Replace with actual bytecode
|
|
74
|
+
const contractABI = [
|
|
75
|
+
// Replace with actual ABI from compilation
|
|
76
|
+
"constructor()",
|
|
77
|
+
"function publicMintZipFile(string memory fileName, string memory merkleRootHash, uint256 creationTimestamp, string memory ipfsHash, string memory tokenURI) public returns (uint256)",
|
|
78
|
+
"function getZipFileInfo(uint256 tokenId) external view returns (tuple(string fileName, string merkleRootHash, string ipfsHash, address creator, uint256 creationTimestamp, uint256 tokenizationTime, uint256 blockNumber, bytes32 blockHash))"
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
// Create contract factory
|
|
82
|
+
const contractFactory = new ethers.ContractFactory(contractABI, contractBytecode, wallet);
|
|
83
|
+
|
|
84
|
+
// Estimate gas
|
|
85
|
+
console.log('โฝ Estimating deployment gas...');
|
|
86
|
+
const deploymentGas = await contractFactory.getDeployTransaction().gasLimit;
|
|
87
|
+
|
|
88
|
+
const gasPrice = await provider.getFeeData();
|
|
89
|
+
const estimatedCost = deploymentGas * gasPrice.gasPrice;
|
|
90
|
+
const costInEth = ethers.formatEther(estimatedCost);
|
|
91
|
+
|
|
92
|
+
console.log(`๐ Estimated Gas: ${deploymentGas.toString()}`);
|
|
93
|
+
console.log(`๐ฐ Estimated Cost: ${costInEth} ETH`);
|
|
94
|
+
|
|
95
|
+
// Deploy contract
|
|
96
|
+
console.log('๐๏ธ Deploying Enhanced NZIP Contract...');
|
|
97
|
+
console.log('โณ Please wait for deployment confirmation...');
|
|
98
|
+
|
|
99
|
+
const contract = await contractFactory.deploy();
|
|
100
|
+
|
|
101
|
+
console.log(`๐ Transaction Hash: ${contract.deploymentTransaction().hash}`);
|
|
102
|
+
console.log('โณ Waiting for deployment confirmation...');
|
|
103
|
+
|
|
104
|
+
// Wait for deployment
|
|
105
|
+
await contract.waitForDeployment();
|
|
106
|
+
const contractAddress = await contract.getAddress();
|
|
107
|
+
|
|
108
|
+
console.log('โ
Contract Deployed Successfully!');
|
|
109
|
+
console.log('='.repeat(50));
|
|
110
|
+
console.log(`๐ Contract Address: ${contractAddress}`);
|
|
111
|
+
console.log(`๐ Explorer: ${network.explorerUrl}/address/${contractAddress}`);
|
|
112
|
+
console.log(`๐ Transaction: ${network.explorerUrl}/tx/${contract.deploymentTransaction().hash}`);
|
|
113
|
+
|
|
114
|
+
// Verify deployment
|
|
115
|
+
console.log('๐ Verifying deployment...');
|
|
116
|
+
try {
|
|
117
|
+
const code = await provider.getCode(contractAddress);
|
|
118
|
+
if (code !== '0x') {
|
|
119
|
+
console.log('โ
Contract code verified on blockchain');
|
|
120
|
+
} else {
|
|
121
|
+
console.log('โ No contract code found at address');
|
|
122
|
+
}
|
|
123
|
+
} catch (error) {
|
|
124
|
+
console.log('โ ๏ธ Could not verify contract code:', error.message);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Generate deployment summary
|
|
128
|
+
const deploymentSummary = {
|
|
129
|
+
network: network.name,
|
|
130
|
+
chainId: network.chainId,
|
|
131
|
+
contractAddress: contractAddress,
|
|
132
|
+
transactionHash: contract.deploymentTransaction().hash,
|
|
133
|
+
deployerAddress: deployerAddress,
|
|
134
|
+
blockNumber: contract.deploymentTransaction().blockNumber,
|
|
135
|
+
gasUsed: deploymentGas.toString(),
|
|
136
|
+
deploymentTime: new Date().toISOString(),
|
|
137
|
+
explorerUrl: `${network.explorerUrl}/address/${contractAddress}`
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Save deployment info
|
|
141
|
+
const deploymentFile = `deployment-${networkName}-${Date.now()}.json`;
|
|
142
|
+
fs.writeFileSync(deploymentFile, JSON.stringify(deploymentSummary, null, 2));
|
|
143
|
+
console.log(`๐ Deployment info saved to: ${deploymentFile}`);
|
|
144
|
+
|
|
145
|
+
// Update portal configuration instructions
|
|
146
|
+
console.log('\n๐ง Next Steps:');
|
|
147
|
+
console.log('1. Update portal configuration:');
|
|
148
|
+
console.log(` - File: apps/portal/src/lib/tokenization.ts`);
|
|
149
|
+
console.log(` - Update contractAddress: "${contractAddress}"`);
|
|
150
|
+
console.log('\n2. Update server configuration:');
|
|
151
|
+
console.log(` - File: apps/portal/src/services/nftTokenService.ts`);
|
|
152
|
+
console.log(` - Update NZIP_CONTRACT_ADDRESSES[${network.chainId}]: "${contractAddress}"`);
|
|
153
|
+
console.log('\n3. Update neozipkit configuration:');
|
|
154
|
+
console.log(` - Files: packages/neozipkit/server-components/blockchain/*.ts`);
|
|
155
|
+
console.log(` - Update contract addresses to: "${contractAddress}"`);
|
|
156
|
+
|
|
157
|
+
return deploymentSummary;
|
|
158
|
+
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.error('โ Deployment failed:', error);
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Helper function to compile contract (requires solc)
|
|
166
|
+
async function compileContract() {
|
|
167
|
+
console.log('๐จ Compiling Enhanced NZIP Contract...');
|
|
168
|
+
|
|
169
|
+
// This is a placeholder - you'll need to implement actual compilation
|
|
170
|
+
// or use external tools like Remix, Hardhat, or Foundry
|
|
171
|
+
|
|
172
|
+
console.log('๐ Please compile ZipFileNFT-Enhanced.sol using:');
|
|
173
|
+
console.log(' - Remix IDE (https://remix.ethereum.org)');
|
|
174
|
+
console.log(' - Hardhat: npx hardhat compile');
|
|
175
|
+
console.log(' - Foundry: forge build');
|
|
176
|
+
console.log(' - Solc: solc --optimize --bin --abi ZipFileNFT-Enhanced.sol');
|
|
177
|
+
|
|
178
|
+
throw new Error('Contract compilation not implemented. Please compile manually and update bytecode/ABI in this script.');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Main execution
|
|
182
|
+
if (require.main === module) {
|
|
183
|
+
const args = process.argv.slice(2);
|
|
184
|
+
const networkName = args[0] || 'base-sepolia';
|
|
185
|
+
|
|
186
|
+
deployEnhancedContract(networkName)
|
|
187
|
+
.then((result) => {
|
|
188
|
+
console.log('\n๐ Deployment completed successfully!');
|
|
189
|
+
process.exit(0);
|
|
190
|
+
})
|
|
191
|
+
.catch((error) => {
|
|
192
|
+
console.error('\n๐ฅ Deployment failed:', error.message);
|
|
193
|
+
process.exit(1);
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
module.exports = { deployEnhancedContract, DEPLOYMENT_CONFIG };
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
const { deployContract, NETWORK_CONFIG } = require('./deploy-both-contracts');
|
|
2
|
+
const { ethers } = require('ethers');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Deployment script for NZIP NFT Private Contract Only
|
|
7
|
+
*
|
|
8
|
+
* This script deploys only the private NZIP-NFT-Private.sol contract
|
|
9
|
+
* Usage: node deploy-private-contract.js
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// Configuration - Load from environment variables or config file
|
|
13
|
+
function loadConfig() {
|
|
14
|
+
let config = {};
|
|
15
|
+
|
|
16
|
+
// Try to load from deployment.config.js first
|
|
17
|
+
try {
|
|
18
|
+
config = require('../deployment.config.js');
|
|
19
|
+
console.log('๐ Loaded configuration from deployment.config.js');
|
|
20
|
+
} catch (err) {
|
|
21
|
+
console.log('๐ No deployment.config.js found, using environment variables');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Environment variables override config file
|
|
25
|
+
const CHAIN_ID = process.env.CHAIN_ID ? parseInt(process.env.CHAIN_ID) : (config.CHAIN_ID || 84532);
|
|
26
|
+
const PRIVATE_KEY = process.env.PRIVATE_KEY || config.PRIVATE_KEY;
|
|
27
|
+
|
|
28
|
+
return { CHAIN_ID, PRIVATE_KEY, EXISTING_CONTRACT: config.EXISTING_CONTRACT };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const { CHAIN_ID, PRIVATE_KEY, EXISTING_CONTRACT } = loadConfig();
|
|
32
|
+
|
|
33
|
+
// TODO: Replace with actual compiled bytecode and ABI from NZIP-NFT-Private.sol
|
|
34
|
+
const CONTRACT_BYTECODE = "0x608060405234801561001057600080fd5b50..."; // REPLACE ME
|
|
35
|
+
const CONTRACT_ABI = [
|
|
36
|
+
// REPLACE WITH ACTUAL ABI FROM NZIP-NFT-Private.sol
|
|
37
|
+
"constructor()",
|
|
38
|
+
"function publicMintZipFile(string memory fileName, string memory merkleRootHash, uint256 creationTimestamp, string memory ipfsHash, string memory tokenURI) public returns (uint256)",
|
|
39
|
+
"function getZipFileInfo(uint256 tokenId) external view returns (tuple(string fileName, string merkleRootHash, string ipfsHash, address creator, uint256 creationTimestamp, uint256 tokenizationTime, uint256 blockNumber, bytes32 blockHash))",
|
|
40
|
+
"function getPublicTokenInfo(uint256 tokenId) external view returns (string memory fileName, address creator, uint256 tokenizationTime, uint256 blockNumber)",
|
|
41
|
+
"function verifyZipFile(uint256 tokenId, string memory providedMerkleRoot) external view returns (bool isValid)",
|
|
42
|
+
"function authorizeVerifier(uint256 tokenId, address authorizedAddress, bool authorized) external",
|
|
43
|
+
"function isAuthorizedVerifier(uint256 tokenId, address verifierAddress) external view returns (bool)",
|
|
44
|
+
"function getBlockchainMetadata(uint256 tokenId) external view returns (uint256 blockNumber, bytes32 blockHash, uint256 tokenizationTime)",
|
|
45
|
+
"function getTokensByOwner(address owner) external view returns (uint256[] memory)",
|
|
46
|
+
"function totalSupply() public view returns (uint256)"
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
async function deployPrivateContract() {
|
|
50
|
+
console.log('๐ NZIP NFT Private Contract Deployment');
|
|
51
|
+
console.log('======================================');
|
|
52
|
+
|
|
53
|
+
// Validate configuration
|
|
54
|
+
if (!PRIVATE_KEY) {
|
|
55
|
+
throw new Error('โ PRIVATE_KEY environment variable is required');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!NETWORK_CONFIG[CHAIN_ID]) {
|
|
59
|
+
throw new Error(`โ Unsupported chain ID: ${CHAIN_ID}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const networkConfig = NETWORK_CONFIG[CHAIN_ID];
|
|
63
|
+
console.log(`๐ Network: ${networkConfig.name}`);
|
|
64
|
+
console.log(`๐ RPC URL: ${networkConfig.rpcUrl}`);
|
|
65
|
+
console.log(`๐ Explorer: ${networkConfig.explorerUrl}`);
|
|
66
|
+
|
|
67
|
+
// Validate contract data
|
|
68
|
+
if (CONTRACT_BYTECODE.length < 10) {
|
|
69
|
+
throw new Error('โ Contract bytecode not provided. Please compile NZIP-NFT-Private.sol and update the script.');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
// Initialize provider and wallet
|
|
74
|
+
console.log('\n๐ Initializing wallet...');
|
|
75
|
+
const provider = new ethers.JsonRpcProvider(networkConfig.rpcUrl);
|
|
76
|
+
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
|
|
77
|
+
|
|
78
|
+
console.log(`๐ Deployer address: ${wallet.address}`);
|
|
79
|
+
|
|
80
|
+
// Check balance
|
|
81
|
+
const balance = await provider.getBalance(wallet.address);
|
|
82
|
+
const balanceEth = ethers.formatEther(balance);
|
|
83
|
+
console.log(`๐ฐ Balance: ${balanceEth} ETH`);
|
|
84
|
+
|
|
85
|
+
if (parseFloat(balanceEth) < 0.01) {
|
|
86
|
+
console.warn('โ ๏ธ Low balance detected. Make sure you have enough ETH for deployment.');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Deploy contract
|
|
90
|
+
const result = await deployContract(
|
|
91
|
+
"NZIP NFT (Private)",
|
|
92
|
+
CONTRACT_BYTECODE,
|
|
93
|
+
CONTRACT_ABI,
|
|
94
|
+
wallet
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
// Test basic functionality
|
|
98
|
+
console.log('\n๐งช Testing deployed contract...');
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
const totalSupply = await result.contract.totalSupply();
|
|
102
|
+
console.log(`โ
Contract total supply: ${totalSupply}`);
|
|
103
|
+
} catch (testError) {
|
|
104
|
+
console.warn('โ ๏ธ Contract testing failed:', testError.message);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Generate deployment summary
|
|
108
|
+
const summary = {
|
|
109
|
+
network: networkConfig.name,
|
|
110
|
+
chainId: CHAIN_ID,
|
|
111
|
+
deployerAddress: wallet.address,
|
|
112
|
+
deployedAt: new Date().toISOString(),
|
|
113
|
+
contract: {
|
|
114
|
+
name: "NZIP NFT (Private)",
|
|
115
|
+
type: "private",
|
|
116
|
+
address: result.address,
|
|
117
|
+
transactionHash: result.transactionHash,
|
|
118
|
+
explorerUrl: `${networkConfig.explorerUrl}/address/${result.address}`,
|
|
119
|
+
txExplorerUrl: `${networkConfig.explorerUrl}/tx/${result.transactionHash}`,
|
|
120
|
+
features: [
|
|
121
|
+
"Owner-only verification",
|
|
122
|
+
"Private blockchain metadata access",
|
|
123
|
+
"8-field enhanced structure",
|
|
124
|
+
"Selective authorization system",
|
|
125
|
+
"Privacy-conscious events",
|
|
126
|
+
"Owner dashboard support"
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// Save deployment info
|
|
132
|
+
const deploymentFile = `deployment-private-${networkConfig.name.toLowerCase().replace(' ', '-')}-${Date.now()}.json`;
|
|
133
|
+
fs.writeFileSync(deploymentFile, JSON.stringify(summary, null, 2));
|
|
134
|
+
|
|
135
|
+
// Display final summary
|
|
136
|
+
console.log('\n๐ PRIVATE CONTRACT DEPLOYMENT COMPLETE!');
|
|
137
|
+
console.log('=======================================');
|
|
138
|
+
console.log(`๐ Deployment summary saved to: ${deploymentFile}`);
|
|
139
|
+
console.log(`๐ Contract Address: ${summary.contract.address}`);
|
|
140
|
+
console.log(`๐ Explorer Link: ${summary.contract.explorerUrl}`);
|
|
141
|
+
console.log(`๐ Transaction Link: ${summary.contract.txExplorerUrl}`);
|
|
142
|
+
|
|
143
|
+
console.log('\nโจ Contract Features:');
|
|
144
|
+
summary.contract.features.forEach(feature => {
|
|
145
|
+
console.log(` ๐ ${feature}`);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
console.log('\n๐ Privacy Features:');
|
|
149
|
+
console.log(' โข Only token owners can verify their tokens');
|
|
150
|
+
console.log(' โข Sensitive data (merkle root, IPFS hash) stored privately');
|
|
151
|
+
console.log(' โข Owners can authorize specific addresses for verification');
|
|
152
|
+
console.log(' โข Events do not expose sensitive information');
|
|
153
|
+
console.log(' โข Public functions only reveal safe metadata');
|
|
154
|
+
|
|
155
|
+
console.log('\nโ๏ธ Next Steps:');
|
|
156
|
+
console.log('1. Verify contract on the block explorer');
|
|
157
|
+
console.log('2. Update portal configuration for private contracts:');
|
|
158
|
+
console.log(` - File: apps/portal/src/services/nftTokenService.ts`);
|
|
159
|
+
console.log(` - Add private contract configuration`);
|
|
160
|
+
console.log('3. Test minting and authorization functionality');
|
|
161
|
+
console.log('4. Deploy public contract if needed for comparison');
|
|
162
|
+
|
|
163
|
+
console.log('\n๐ Usage Examples:');
|
|
164
|
+
console.log('โข Mint a private token: contract.publicMintZipFile(...)');
|
|
165
|
+
console.log('โข Authorize verifier: contract.authorizeVerifier(tokenId, address, true)');
|
|
166
|
+
console.log('โข Verify as owner: contract.verifyZipFile(tokenId, merkleRoot)');
|
|
167
|
+
console.log('โข Get owner tokens: contract.getTokensByOwner(ownerAddress)');
|
|
168
|
+
|
|
169
|
+
return summary;
|
|
170
|
+
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.error('\nโ Deployment failed:', error);
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Main execution
|
|
178
|
+
if (require.main === module) {
|
|
179
|
+
deployPrivateContract()
|
|
180
|
+
.then((summary) => {
|
|
181
|
+
console.log('\nโ
Private contract deployment completed successfully!');
|
|
182
|
+
process.exit(0);
|
|
183
|
+
})
|
|
184
|
+
.catch((error) => {
|
|
185
|
+
console.error('\nโ Private contract deployment failed:', error);
|
|
186
|
+
process.exit(1);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
module.exports = { deployPrivateContract };
|