neozipkit 0.1.1 → 0.2.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 +52 -105
- package/contracts/INTEGRATION.md +338 -0
- package/contracts/NETWORKS.md +156 -0
- package/contracts/README.md +152 -0
- package/{src/server/blockchain → contracts}/constants.ts +5 -22
- package/contracts/deploy-bytecode.mjs +94 -0
- package/dist/blockchain/ZipKitMinter.d.ts +106 -0
- package/dist/blockchain/ZipKitMinter.js +347 -0
- package/dist/blockchain/ZipKitNFT.d.ts +3 -0
- package/dist/blockchain/ZipKitNFT.js +7 -0
- package/dist/blockchain/ZipKitOTS.d.ts +135 -0
- package/dist/blockchain/ZipKitOTS.js +564 -0
- package/dist/blockchain/ZipKitVerifier.d.ts +69 -0
- package/dist/blockchain/ZipKitVerifier.js +289 -0
- package/dist/{server/blockchain/WalletAnalyzer.d.ts → blockchain/ZipKitWallet.d.ts} +31 -43
- package/dist/{server/blockchain/WalletAnalyzer.js → blockchain/ZipKitWallet.js} +193 -161
- package/dist/blockchain/contracts.d.ts +14 -0
- package/dist/blockchain/contracts.js +77 -0
- package/dist/blockchain/index.d.ts +7 -0
- package/dist/blockchain/index.js +50 -0
- package/dist/{server/blockchain → blockchain}/types.d.ts +12 -34
- package/dist/{server/blockchain → blockchain}/types.js +1 -22
- package/dist/browser-index.d.ts +0 -3
- package/dist/browser-index.js +4 -5
- package/dist/browser.d.ts +0 -3
- package/dist/browser.js +4 -5
- package/dist/index.d.ts +8 -15
- package/dist/index.js +12 -24
- package/dist/server/{platform/server/ZipKitServer.d.ts → ZipKitServer.d.ts} +4 -35
- package/dist/server/{platform/server/ZipKitServer.js → ZipKitServer.js} +55 -182
- package/dist/shared/ZipEntry.js +1 -1
- package/dist/shared/ZipKit.d.ts +0 -6
- package/dist/shared/ZipKit.js +1 -18
- package/dist/shared/types.js +2 -2
- package/dist/shared/version.d.ts +2 -4
- package/dist/shared/version.js +4 -5
- package/package.json +13 -3
- package/src/blockchain/README.md +229 -0
- package/src/blockchain/ZipKitMinter.ts +470 -0
- package/src/blockchain/ZipKitNFT.ts +12 -0
- package/src/blockchain/ZipKitOTS.ts +622 -0
- package/src/blockchain/ZipKitVerifier.ts +382 -0
- package/src/blockchain/ZipKitWallet.ts +338 -0
- package/src/blockchain/contracts.ts +88 -0
- package/src/blockchain/index.ts +61 -0
- package/src/blockchain/types.ts +91 -0
- package/src/browser/{TokenVerifierBrowser.ts → TokenVerifierBrowser.ts-remove} +1 -1
- package/src/browser-index.ts +3 -3
- package/src/index.ts +10 -17
- package/src/server/README.md +25 -0
- package/src/server/ZipKitServer.ts +305 -0
- package/src/shared/ZipEntry.ts +1 -1
- package/src/shared/ZipKit.ts +1 -19
- package/src/shared/types.ts +3 -3
- package/src/shared/version.ts +3 -4
- package/src/types/modules.d.ts +11 -1
- package/contracts/Lock.sol +0 -34
- package/contracts/compile-contract.js +0 -168
- package/contracts/deploy/deploy-both-contracts.js +0 -286
- package/contracts/deploy/deploy-enhanced-contract.js +0 -197
- package/contracts/deploy/deploy-private-contract.js +0 -190
- package/contracts/deploy/deploy-public-clean.js +0 -1063
- package/contracts/deploy/deploy-public-contract.js +0 -1107
- package/contracts/deployment.config.example.js +0 -25
- package/contracts/remix-compile.js +0 -222
- package/contracts/setup-deployment.js +0 -51
- package/contracts/src/ZipFileNFT-DEPRECATED-6field.sol +0 -260
- package/contracts/src/ZipFileNFT-DEPRECATED-Enhanced.sol +0 -289
- package/dist/browser/CertificateGeneratorBrowser.d.ts +0 -75
- package/dist/browser/CertificateGeneratorBrowser.js +0 -433
- package/dist/browser/TokenVerifierBrowser.d.ts +0 -76
- package/dist/browser/TokenVerifierBrowser.js +0 -299
- package/dist/server/blockchain/NFTMinter.d.ts +0 -41
- package/dist/server/blockchain/NFTMinter.js +0 -323
- package/dist/server/blockchain/TokenQuerier.d.ts +0 -31
- package/dist/server/blockchain/TokenQuerier.js +0 -259
- package/dist/server/blockchain/TokenVerifier.d.ts +0 -20
- package/dist/server/blockchain/TokenVerifier.js +0 -395
- package/dist/server/blockchain/WalletFormatter.d.ts +0 -39
- package/dist/server/blockchain/WalletFormatter.js +0 -196
- package/dist/server/blockchain/WalletManager.d.ts +0 -46
- package/dist/server/blockchain/WalletManager.js +0 -294
- package/dist/server/blockchain/ZipMetadata.d.ts +0 -27
- package/dist/server/blockchain/ZipMetadata.js +0 -131
- package/dist/server/blockchain/ZipTokenProcessor.d.ts +0 -44
- package/dist/server/blockchain/ZipTokenProcessor.js +0 -204
- package/dist/server/blockchain/constants.d.ts +0 -102
- package/dist/server/blockchain/constants.js +0 -968
- package/dist/server/blockchain/index.d.ts +0 -9
- package/dist/server/blockchain/index.js +0 -44
- package/dist/server/blockchain/test-certificate.d.ts +0 -8
- package/dist/server/blockchain/test-certificate.js +0 -100
- package/dist/server/platform/servercomponents/ZipKitOTS.d.ts +0 -91
- package/dist/server/platform/servercomponents/ZipKitOTS.js +0 -271
- package/examples/unzip-token.ts +0 -488
- package/examples/zip-token.ts +0 -604
- package/src/server/blockchain/NFTMinter.ts +0 -357
- package/src/server/blockchain/TokenQuerier.ts +0 -287
- package/src/server/blockchain/TokenVerifier.ts +0 -453
- package/src/server/blockchain/WalletAnalyzer.ts +0 -397
- package/src/server/blockchain/WalletFormatter.ts +0 -206
- package/src/server/blockchain/WalletManager.ts +0 -294
- package/src/server/blockchain/ZipMetadata.ts +0 -117
- package/src/server/blockchain/ZipTokenProcessor.ts +0 -234
- package/src/server/blockchain/index.ts +0 -42
- package/src/server/blockchain/test-certificate.ts +0 -137
- package/src/server/blockchain/types.ts +0 -134
- package/src/server/platform/server/ZipKitServer.ts +0 -459
- package/src/server/platform/servercomponents/ZipKitOTS.ts +0 -313
- package/src/server/platform/servercomponents/opentimestamps.d.ts +0 -23
- /package/contracts/{bytecode.txt → NZIP-NFT-bytecode.txt} +0 -0
- /package/dist/{server/blockchain → blockchain}/CertificateToken.d.ts +0 -0
- /package/dist/{server/blockchain → blockchain}/CertificateToken.js +0 -0
- /package/src/{server/blockchain → blockchain}/CertificateToken.ts +0 -0
- /package/src/browser/{CertificateGeneratorBrowser.ts → CertificateGeneratorBrowser.ts-remove} +0 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as readline from 'readline';
|
|
4
|
+
import { ethers } from 'ethers';
|
|
5
|
+
import { WalletSetupResult, WalletInfo, NetworkConfig, NETWORKS, MintingOptions } from './types';
|
|
6
|
+
|
|
7
|
+
export interface CommonTokenConfig { address: string; name: string; symbol: string; type: 'ERC20' | 'ERC721'; }
|
|
8
|
+
export interface TokenInfo { address: string; name: string; symbol: string; balance: string; decimals?: number; type: 'ERC20' | 'ERC721' | 'NZIP'; }
|
|
9
|
+
export interface WalletBasicInfo { ethBalance: string; transactionCount: number; networkName: string; chainId: bigint; latestBlock: number; }
|
|
10
|
+
export interface TokenScanResult { foundTokens: number[]; searchMethod: 'recent-events' | 'iteration' | 'common-ids' | 'none'; }
|
|
11
|
+
export interface NZipTokenDetails { tokenId: string; merkleRootHash: string; fileName: string; timestamp: number; tokenURI?: string; creator: string; creationTimestamp: number; tokenizationTime: number; ipfsHash?: string; }
|
|
12
|
+
|
|
13
|
+
const NZIP_CONTRACT_ABI = [
|
|
14
|
+
"function getZipFileInfo(uint256 tokenId) view returns (tuple(string fileName, string merkleRootHash, uint256 creationTimestamp, string ipfsHash, uint256 tokenizationTime, address creator))",
|
|
15
|
+
"function ownerOf(uint256 tokenId) view returns (address)",
|
|
16
|
+
"function name() view returns (string)",
|
|
17
|
+
"function symbol() view returns (string)",
|
|
18
|
+
"function totalSupply() view returns (uint256)",
|
|
19
|
+
"function getTokensByMerkleRoot(string merkleRootHash) view returns (uint256[])",
|
|
20
|
+
"event ZipFileTokenized(uint256 indexed tokenId, address indexed creator, string fileName, string merkleRootHash, uint256 creationTimestamp, string ipfsHash)"
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const ERC20_ABI = [
|
|
24
|
+
"function balanceOf(address owner) view returns (uint256)",
|
|
25
|
+
"function name() view returns (string)",
|
|
26
|
+
"function symbol() view returns (string)",
|
|
27
|
+
"function decimals() view returns (uint8)"
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const ERC721_ABI = [
|
|
31
|
+
"function balanceOf(address owner) view returns (uint256)",
|
|
32
|
+
"function name() view returns (string)",
|
|
33
|
+
"function symbol() view returns (string)",
|
|
34
|
+
"function tokenOfOwnerByIndex(address owner, uint256 index) view returns (uint256)"
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
export class ZipKitWallet {
|
|
38
|
+
private wallet: ethers.Wallet | null = null;
|
|
39
|
+
private provider: ethers.JsonRpcProvider | null = null;
|
|
40
|
+
|
|
41
|
+
private async promptUser(question: string): Promise<string> {
|
|
42
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
43
|
+
return new Promise<string>((resolve) => {
|
|
44
|
+
rl.question(question, (answer: string) => { rl.close(); resolve(answer.trim()); });
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private findExistingWallets(): string[] {
|
|
49
|
+
const walletFiles: string[] = [];
|
|
50
|
+
const currentDir = process.cwd();
|
|
51
|
+
const walletDir = path.join(currentDir, 'wallet');
|
|
52
|
+
const walletFileNames = ['neozip-wallet.json'];
|
|
53
|
+
for (const fileName of walletFileNames) {
|
|
54
|
+
const filePath = path.join(currentDir, fileName);
|
|
55
|
+
if (fs.existsSync(filePath)) walletFiles.push(filePath);
|
|
56
|
+
}
|
|
57
|
+
if (fs.existsSync(walletDir)) {
|
|
58
|
+
for (const fileName of walletFileNames) {
|
|
59
|
+
const filePath = path.join(walletDir, fileName);
|
|
60
|
+
if (fs.existsSync(filePath)) walletFiles.push(filePath);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return walletFiles;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private loadWalletFromFile(filePath: string): string | null {
|
|
67
|
+
try {
|
|
68
|
+
const content = fs.readFileSync(filePath, 'utf8').trim();
|
|
69
|
+
try {
|
|
70
|
+
const walletData = JSON.parse(content);
|
|
71
|
+
if (walletData.privateKey) {
|
|
72
|
+
console.log(`Found wallet file: ${filePath}`);
|
|
73
|
+
console.log(`Wallet address: ${walletData.address}`);
|
|
74
|
+
return walletData.privateKey;
|
|
75
|
+
}
|
|
76
|
+
} catch {
|
|
77
|
+
if (content.startsWith('0x') && content.length === 66) {
|
|
78
|
+
console.log(`Found private key file: ${filePath}`);
|
|
79
|
+
return content;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.warn(`Could not read wallet file ${filePath}:`, error);
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async setupWallet(options: MintingOptions): Promise<WalletSetupResult> {
|
|
90
|
+
try {
|
|
91
|
+
const networkConfig = NETWORKS[options.network] || NETWORKS['base-sepolia'];
|
|
92
|
+
let privateKey: string;
|
|
93
|
+
if ((options as any).wallet) {
|
|
94
|
+
const val = (options as any).wallet as string;
|
|
95
|
+
if (fs.existsSync(val)) {
|
|
96
|
+
const loaded = this.loadWalletFromFile(val);
|
|
97
|
+
if (!loaded) throw new Error(`Could not load valid private key from ${val}`);
|
|
98
|
+
privateKey = loaded;
|
|
99
|
+
} else {
|
|
100
|
+
privateKey = val;
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
const existing = this.findExistingWallets();
|
|
104
|
+
if (existing.length > 0) {
|
|
105
|
+
const selected = existing[0];
|
|
106
|
+
const relativePath = path.relative(process.cwd(), selected);
|
|
107
|
+
console.log(`Using existing wallet: ${relativePath}`);
|
|
108
|
+
const loaded = this.loadWalletFromFile(selected);
|
|
109
|
+
if (!loaded) throw new Error(`Could not load valid private key from ${selected}`);
|
|
110
|
+
privateKey = loaded;
|
|
111
|
+
} else {
|
|
112
|
+
console.log('No existing wallet found. Creating new wallet...');
|
|
113
|
+
privateKey = await this.createNewWallet();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
this.wallet = new ethers.Wallet(privateKey);
|
|
118
|
+
console.log(`Using wallet: ${this.wallet.address}`);
|
|
119
|
+
const ok = await this.connectToNetwork(networkConfig, (options as any).mintToken === true);
|
|
120
|
+
if (!ok) {
|
|
121
|
+
return { wallet: null, provider: null, success: false, message: `Failed to connect to ${networkConfig.name} network. Blockchain operations require network connectivity.` };
|
|
122
|
+
}
|
|
123
|
+
return { wallet: this.wallet, provider: this.provider, success: true, message: `Wallet setup successful for ${networkConfig.name}` };
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error('Error setting up wallet:', error);
|
|
126
|
+
return { wallet: null, provider: null, success: false, message: `Wallet setup failed: ${error instanceof Error ? error.message : String(error)}` };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private async createNewWallet(): Promise<string> {
|
|
131
|
+
console.log('Creating a new wallet...');
|
|
132
|
+
const newWallet = ethers.Wallet.createRandom();
|
|
133
|
+
const walletInfo: WalletInfo = { address: newWallet.address, privateKey: newWallet.privateKey, mnemonic: newWallet.mnemonic?.phrase || "" };
|
|
134
|
+
const walletDir = path.join(process.cwd(), 'wallet');
|
|
135
|
+
if (!fs.existsSync(walletDir)) fs.mkdirSync(walletDir, { recursive: true });
|
|
136
|
+
const walletFilePath = path.join(walletDir, 'neozip-wallet.json');
|
|
137
|
+
fs.writeFileSync(walletFilePath, JSON.stringify(walletInfo, null, 2));
|
|
138
|
+
console.log(`New wallet created and saved to ${walletFilePath}`);
|
|
139
|
+
console.log(`Wallet address: ${newWallet.address}`);
|
|
140
|
+
console.log(`IMPORTANT: Please fund this wallet with BASE to use for minting NFTs!`);
|
|
141
|
+
return newWallet.privateKey;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private async connectToNetwork(networkConfig: NetworkConfig, mintToken: boolean): Promise<boolean> {
|
|
145
|
+
try {
|
|
146
|
+
console.log(`Attempting to connect to ${networkConfig.name} network...`);
|
|
147
|
+
this.provider = new ethers.JsonRpcProvider(networkConfig.rpcUrl);
|
|
148
|
+
let networkTimedOut = false;
|
|
149
|
+
const networkTimeout = setTimeout(() => { networkTimedOut = true; console.error("Network connection timeout"); }, 5000);
|
|
150
|
+
await Promise.race([
|
|
151
|
+
this.provider.getNetwork(),
|
|
152
|
+
new Promise((_, reject) => setTimeout(() => { if (networkTimedOut) reject(new Error("Network connection timeout")); }, 5100))
|
|
153
|
+
]);
|
|
154
|
+
clearTimeout(networkTimeout);
|
|
155
|
+
if (this.wallet) {
|
|
156
|
+
this.wallet = this.wallet.connect(this.provider);
|
|
157
|
+
const balance = await this.provider.getBalance(this.wallet.address);
|
|
158
|
+
const balanceEth = ethers.formatEther(balance);
|
|
159
|
+
console.log(`Wallet balance: ${balanceEth} ETH`);
|
|
160
|
+
const minBalance = 0.0001;
|
|
161
|
+
if (parseFloat(balanceEth) < minBalance && mintToken) {
|
|
162
|
+
console.error(`ERROR: Insufficient balance (${balanceEth} ETH). Minimum required: ${minBalance} ETH`);
|
|
163
|
+
console.error('Get testnet ETH from: https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet');
|
|
164
|
+
throw new Error(`Insufficient balance for minting. Current: ${balanceEth} ETH, Required: ${minBalance} ETH`);
|
|
165
|
+
} else if (mintToken) {
|
|
166
|
+
console.log(`✅ Sufficient balance for token minting`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
console.log(`✅ Successfully connected to ${networkConfig.name}`);
|
|
170
|
+
return true;
|
|
171
|
+
} catch (networkError: unknown) {
|
|
172
|
+
const errorMessage = networkError instanceof Error ? networkError.message : String(networkError);
|
|
173
|
+
console.error(`Failed to connect to ${networkConfig.name} network: ${errorMessage}`);
|
|
174
|
+
this.provider = null;
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
getWallet(): ethers.Wallet | null { return this.wallet; }
|
|
180
|
+
getProvider(): ethers.JsonRpcProvider | null { return this.provider; }
|
|
181
|
+
isReady(): boolean { return this.wallet !== null; }
|
|
182
|
+
isOnline(): boolean { return this.provider !== null; }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export class WalletAnalyzer {
|
|
186
|
+
private provider: ethers.JsonRpcProvider;
|
|
187
|
+
constructor(provider: ethers.JsonRpcProvider) { this.provider = provider; }
|
|
188
|
+
|
|
189
|
+
async getWalletBasics(address: string): Promise<WalletBasicInfo> {
|
|
190
|
+
const balance = await this.provider.getBalance(address);
|
|
191
|
+
const ethBalance = ethers.formatEther(balance);
|
|
192
|
+
const txCount = await this.provider.getTransactionCount(address);
|
|
193
|
+
const network = await this.provider.getNetwork();
|
|
194
|
+
const latestBlock = await this.provider.getBlockNumber();
|
|
195
|
+
return { ethBalance, transactionCount: txCount, networkName: network.name, chainId: network.chainId, latestBlock };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async scanForNZipTokens(contractAddress: string, ownerAddress: string): Promise<TokenScanResult> {
|
|
199
|
+
const contract = new ethers.Contract(contractAddress, NZIP_CONTRACT_ABI, this.provider);
|
|
200
|
+
let foundTokens: number[] = [];
|
|
201
|
+
let searchMethod: TokenScanResult['searchMethod'] = 'none';
|
|
202
|
+
try {
|
|
203
|
+
const latestBlock = await this.provider.getBlockNumber();
|
|
204
|
+
const startBlock = Math.max(0, latestBlock - 50000);
|
|
205
|
+
const filter = contract.filters.ZipFileTokenized(null, ownerAddress);
|
|
206
|
+
const events = await contract.queryFilter(filter, startBlock, 'latest');
|
|
207
|
+
for (const event of events) {
|
|
208
|
+
if ('args' in event && event.args && (event as any).args.tokenId) {
|
|
209
|
+
const tokenId = Number((event as any).args.tokenId);
|
|
210
|
+
if (!foundTokens.includes(tokenId)) foundTokens.push(tokenId);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (foundTokens.length > 0) { return { foundTokens, searchMethod: 'recent-events' }; }
|
|
214
|
+
} catch {}
|
|
215
|
+
try {
|
|
216
|
+
const totalSupply = await contract.totalSupply();
|
|
217
|
+
const maxCheck = Math.min(Number(totalSupply), 50);
|
|
218
|
+
for (let tokenId = 0; tokenId < maxCheck; tokenId++) {
|
|
219
|
+
try {
|
|
220
|
+
const owner = await contract.ownerOf(tokenId);
|
|
221
|
+
if (owner.toLowerCase() === ownerAddress.toLowerCase()) foundTokens.push(tokenId);
|
|
222
|
+
} catch {}
|
|
223
|
+
}
|
|
224
|
+
if (foundTokens.length > 0) return { foundTokens, searchMethod: 'iteration' };
|
|
225
|
+
} catch {}
|
|
226
|
+
const commonTokenIds = Array.from({length: 20}, (_, i) => i);
|
|
227
|
+
for (const tokenId of commonTokenIds) {
|
|
228
|
+
try {
|
|
229
|
+
const owner = await contract.ownerOf(tokenId);
|
|
230
|
+
if (owner.toLowerCase() === ownerAddress.toLowerCase()) foundTokens.push(tokenId);
|
|
231
|
+
} catch {}
|
|
232
|
+
}
|
|
233
|
+
return { foundTokens, searchMethod: foundTokens.length > 0 ? 'common-ids' : 'none' };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
async getNZipTokenDetails(contractAddress: string, tokenIds: number[]): Promise<NZipTokenDetails[]> {
|
|
237
|
+
const contract = new ethers.Contract(contractAddress, NZIP_CONTRACT_ABI, this.provider);
|
|
238
|
+
const tokenDetails: NZipTokenDetails[] = [];
|
|
239
|
+
for (const tokenId of tokenIds) {
|
|
240
|
+
try {
|
|
241
|
+
const zipInfo = await contract.getZipFileInfo(tokenId);
|
|
242
|
+
tokenDetails.push({
|
|
243
|
+
tokenId: tokenId.toString(),
|
|
244
|
+
merkleRootHash: zipInfo.merkleRootHash,
|
|
245
|
+
fileName: zipInfo.fileName,
|
|
246
|
+
timestamp: Number(zipInfo.creationTimestamp),
|
|
247
|
+
creator: zipInfo.creator,
|
|
248
|
+
creationTimestamp: Number(zipInfo.creationTimestamp),
|
|
249
|
+
tokenizationTime: Number(zipInfo.tokenizationTime),
|
|
250
|
+
ipfsHash: zipInfo.ipfsHash || undefined
|
|
251
|
+
});
|
|
252
|
+
} catch (error) {
|
|
253
|
+
console.error(`Error fetching details for token ${tokenId}:`, error);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return tokenDetails;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async getContractInfo(contractAddress: string): Promise<{name: string, symbol: string, totalSupply: string} | null> {
|
|
260
|
+
try {
|
|
261
|
+
const contract = new ethers.Contract(contractAddress, NZIP_CONTRACT_ABI, this.provider);
|
|
262
|
+
const [name, symbol, totalSupply] = await Promise.all([contract.name(), contract.symbol(), contract.totalSupply()]);
|
|
263
|
+
return { name, symbol, totalSupply: totalSupply.toString() };
|
|
264
|
+
} catch { return null; }
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
async checkERC20Tokens(ownerAddress: string, tokenConfigs: CommonTokenConfig[]): Promise<TokenInfo[]> {
|
|
268
|
+
const foundTokens: TokenInfo[] = [];
|
|
269
|
+
for (const tokenConfig of tokenConfigs.filter(t => t.type === 'ERC20')) {
|
|
270
|
+
try {
|
|
271
|
+
const contract = new ethers.Contract(tokenConfig.address, ERC20_ABI, this.provider);
|
|
272
|
+
const balance = await contract.balanceOf(ownerAddress);
|
|
273
|
+
if (balance > 0) {
|
|
274
|
+
let name = tokenConfig.name, symbol = tokenConfig.symbol, decimals = 18;
|
|
275
|
+
try { [name, symbol, decimals] = await Promise.all([contract.name(), contract.symbol(), contract.decimals()]); } catch {}
|
|
276
|
+
const formattedBalance = ethers.formatUnits(balance, decimals);
|
|
277
|
+
foundTokens.push({ address: tokenConfig.address, name, symbol, balance: formattedBalance, decimals, type: 'ERC20' });
|
|
278
|
+
}
|
|
279
|
+
} catch {}
|
|
280
|
+
}
|
|
281
|
+
return foundTokens;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
async checkNFTCollections(ownerAddress: string, nftConfigs: CommonTokenConfig[]): Promise<TokenInfo[]> {
|
|
285
|
+
const foundNFTs: TokenInfo[] = [];
|
|
286
|
+
for (const nftConfig of nftConfigs) {
|
|
287
|
+
try {
|
|
288
|
+
const contract = new ethers.Contract(nftConfig.address, ERC721_ABI, this.provider);
|
|
289
|
+
const balance = await contract.balanceOf(ownerAddress);
|
|
290
|
+
if (balance > 0) {
|
|
291
|
+
let name = nftConfig.name, symbol = nftConfig.symbol;
|
|
292
|
+
try { [name, symbol] = await Promise.all([contract.name(), contract.symbol()]); } catch {}
|
|
293
|
+
foundNFTs.push({ address: nftConfig.address, name, symbol, balance: balance.toString(), type: 'ERC721' });
|
|
294
|
+
}
|
|
295
|
+
} catch {}
|
|
296
|
+
}
|
|
297
|
+
return foundNFTs;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
static detectNZipContract(): string | undefined {
|
|
301
|
+
const deploymentPath = path.join(process.cwd(), 'zipfile-nft-deployment.json');
|
|
302
|
+
if (fs.existsSync(deploymentPath)) {
|
|
303
|
+
try { const deploymentInfo = JSON.parse(fs.readFileSync(deploymentPath, 'utf8')); if (deploymentInfo.address) return deploymentInfo.address; } catch {}
|
|
304
|
+
}
|
|
305
|
+
return undefined;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
static getCommonTokens(network: string): CommonTokenConfig[] {
|
|
309
|
+
const commonTokens: Record<string, CommonTokenConfig[]> = {
|
|
310
|
+
'base-sepolia': [
|
|
311
|
+
{ address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e', name: 'USD Coin', symbol: 'USDC', type: 'ERC20' },
|
|
312
|
+
{ address: '0x4200000000000000000000000000000000000006', name: 'Wrapped Ether', symbol: 'WETH', type: 'ERC20' },
|
|
313
|
+
{ address: '0xE4aB69C077896252FAFBD49EFD26B5D171A32410', name: 'Coinbase Wrapped Staked ETH', symbol: 'cbETH', type: 'ERC20' },
|
|
314
|
+
],
|
|
315
|
+
'base': [
|
|
316
|
+
{ address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', name: 'USD Coin', symbol: 'USDC', type: 'ERC20' },
|
|
317
|
+
{ address: '0x4200000000000000000000000000000000000006', name: 'Wrapped Ether', symbol: 'WETH', type: 'ERC20' },
|
|
318
|
+
{ address: '0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb', name: 'Dai Stablecoin', symbol: 'DAI', type: 'ERC20' },
|
|
319
|
+
{ address: '0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22', name: 'Coinbase Wrapped Staked ETH', symbol: 'cbETH', type: 'ERC20' },
|
|
320
|
+
{ address: '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA', name: 'USD Base Coin', symbol: 'USDbC', type: 'ERC20' },
|
|
321
|
+
]
|
|
322
|
+
};
|
|
323
|
+
return commonTokens[network] || [];
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
static getCommonNFTs(network: string): CommonTokenConfig[] {
|
|
327
|
+
const commonNFTs: Record<string, CommonTokenConfig[]> = {
|
|
328
|
+
'base-sepolia': [ ],
|
|
329
|
+
'base': [
|
|
330
|
+
{ address: '0x1234567890123456789012345678901234567890', name: 'Base Punks', symbol: 'BPUNK', type: 'ERC721' },
|
|
331
|
+
{ address: '0x0987654321098765432109876543210987654321', name: 'Base Bears', symbol: 'BBEAR', type: 'ERC721' },
|
|
332
|
+
]
|
|
333
|
+
};
|
|
334
|
+
return commonNFTs[network] || [];
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Contract addresses and configurations for different networks
|
|
2
|
+
|
|
3
|
+
export interface ContractConfig {
|
|
4
|
+
address: string
|
|
5
|
+
network: string
|
|
6
|
+
chainId: number
|
|
7
|
+
explorerUrl: string
|
|
8
|
+
rpcUrls: string[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// NZIP NFT Contract configurations by network
|
|
12
|
+
export const CONTRACT_CONFIGS: Record<number, ContractConfig> = {
|
|
13
|
+
// Base Sepolia (Primary testnet)
|
|
14
|
+
84532: {
|
|
15
|
+
address: '0xFD76a5d420704F34d84b0767961835c43D7b30a8', // Production contract v2.0
|
|
16
|
+
network: 'Base Sepolia',
|
|
17
|
+
chainId: 84532,
|
|
18
|
+
explorerUrl: 'https://sepolia.basescan.org',
|
|
19
|
+
rpcUrls: [
|
|
20
|
+
'https://sepolia.base.org',
|
|
21
|
+
'https://base-sepolia.g.alchemy.com/v2/demo',
|
|
22
|
+
'https://base-sepolia-rpc.publicnode.com'
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
// Base Mainnet (Production)
|
|
27
|
+
8453: {
|
|
28
|
+
address: '0x2716c4609fD97DaEdF429BC4B4Ec2faa81e2cC60',
|
|
29
|
+
network: 'Base Mainnet',
|
|
30
|
+
chainId: 8453,
|
|
31
|
+
explorerUrl: 'https://basescan.org',
|
|
32
|
+
rpcUrls: [
|
|
33
|
+
'https://mainnet.base.org',
|
|
34
|
+
'https://base.drpc.org',
|
|
35
|
+
'https://base.gateway.tenderly.co'
|
|
36
|
+
]
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
// Ethereum Sepolia (Testnet) - disabled until NZIP is deployed
|
|
40
|
+
// 11155111: {
|
|
41
|
+
// address: '0x0000000000000000000000000000000000000000',
|
|
42
|
+
// network: 'Sepolia Testnet',
|
|
43
|
+
// chainId: 11155111,
|
|
44
|
+
// explorerUrl: 'https://sepolia.etherscan.io',
|
|
45
|
+
// rpcUrls: []
|
|
46
|
+
// },
|
|
47
|
+
|
|
48
|
+
// Ethereum Mainnet (Production) - disabled until NZIP is deployed
|
|
49
|
+
// 1: {
|
|
50
|
+
// address: '0x0000000000000000000000000000000000000000',
|
|
51
|
+
// network: 'Ethereum Mainnet',
|
|
52
|
+
// chainId: 1,
|
|
53
|
+
// explorerUrl: 'https://etherscan.io',
|
|
54
|
+
// rpcUrls: []
|
|
55
|
+
// }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Contract ABI (same for all networks)
|
|
59
|
+
export const NZIP_CONTRACT_ABI = [
|
|
60
|
+
"function publicMintZipFile(string memory fileName, string memory merkleRootHash, uint256 creationTimestamp, string memory ipfsHash, string memory metadataURI) public returns (uint256)",
|
|
61
|
+
"function totalSupply() external view returns (uint256)",
|
|
62
|
+
"function getTokensByMerkleRoot(string memory merkleRoot) external view returns (uint256[])",
|
|
63
|
+
"function getZipFileInfo(uint256 tokenId) external view returns (tuple(string fileName, string merkleRootHash, string ipfsHash, address creator, uint256 creationTimestamp, uint256 tokenizationTime, uint256 blockNumber))",
|
|
64
|
+
"function ownerOf(uint256 tokenId) external view returns (address)",
|
|
65
|
+
"function balanceOf(address owner) external view returns (uint256)",
|
|
66
|
+
"function isZipFileTokenized(string memory merkleRootHash, uint256 creationTimestamp) external view returns (bool exists, uint256 tokenId)",
|
|
67
|
+
"function verifyZipFile(uint256 tokenId, string memory providedMerkleRoot) external view returns (bool isValid)",
|
|
68
|
+
"function getVersion() external pure returns (string memory)",
|
|
69
|
+
"event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)",
|
|
70
|
+
"event ZipFileTokenized(uint256 indexed tokenId, address indexed creator, string fileName, string merkleRootHash, uint256 creationTimestamp, string ipfsHash, uint256 tokenizationTime, uint256 blockNumber)"
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
// Default configuration (Base Sepolia for development)
|
|
74
|
+
export const DEFAULT_NETWORK = 84532
|
|
75
|
+
export const CURRENT_DEPLOYMENT = CONTRACT_CONFIGS[DEFAULT_NETWORK]
|
|
76
|
+
|
|
77
|
+
// Helper functions
|
|
78
|
+
export const getContractConfig = (chainId: number): ContractConfig => {
|
|
79
|
+
return CONTRACT_CONFIGS[chainId] || CURRENT_DEPLOYMENT
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const getSupportedNetworks = (): number[] => {
|
|
83
|
+
return Object.keys(CONTRACT_CONFIGS).map(Number)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const isNetworkSupported = (chainId: number): boolean => {
|
|
87
|
+
return chainId in CONTRACT_CONFIGS
|
|
88
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Export all types
|
|
2
|
+
export * from './types';
|
|
3
|
+
|
|
4
|
+
export {
|
|
5
|
+
ZipKitMinter,
|
|
6
|
+
MintingOptions,
|
|
7
|
+
MintingResult,
|
|
8
|
+
DuplicateCheckResult,
|
|
9
|
+
TokenInfo,
|
|
10
|
+
WalletInfo,
|
|
11
|
+
validatePrivateKey
|
|
12
|
+
} from './ZipKitMinter';
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
ZipKitVerifier,
|
|
16
|
+
VerificationOptions,
|
|
17
|
+
VerificationResult
|
|
18
|
+
} from './ZipKitVerifier';
|
|
19
|
+
|
|
20
|
+
export { TokenMetadata } from './types';
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
NZIP_CONTRACT_ABI,
|
|
24
|
+
CONTRACT_CONFIGS,
|
|
25
|
+
CURRENT_DEPLOYMENT,
|
|
26
|
+
DEFAULT_NETWORK,
|
|
27
|
+
getContractConfig,
|
|
28
|
+
getSupportedNetworks,
|
|
29
|
+
isNetworkSupported
|
|
30
|
+
} from './contracts';
|
|
31
|
+
|
|
32
|
+
// Export wallet management and analysis (combined under ZipKitWallet)
|
|
33
|
+
export {
|
|
34
|
+
ZipKitWallet,
|
|
35
|
+
WalletAnalyzer,
|
|
36
|
+
NZipTokenDetails,
|
|
37
|
+
WalletBasicInfo,
|
|
38
|
+
TokenScanResult,
|
|
39
|
+
CommonTokenConfig
|
|
40
|
+
} from './ZipKitWallet';
|
|
41
|
+
|
|
42
|
+
// Export OpenTimestamps utilities
|
|
43
|
+
export {
|
|
44
|
+
createTimestamp,
|
|
45
|
+
deserializeOts,
|
|
46
|
+
parseVerifyResult,
|
|
47
|
+
createCertificateOts,
|
|
48
|
+
upgradeOTS,
|
|
49
|
+
createOtsMetadataEntry,
|
|
50
|
+
bufferToArrayBuffer,
|
|
51
|
+
getOtsEntry,
|
|
52
|
+
getOtsBuffer,
|
|
53
|
+
getMerkleRootSafe,
|
|
54
|
+
verifyOts,
|
|
55
|
+
verifyOtsZip,
|
|
56
|
+
// Export interfaces
|
|
57
|
+
TimestampResult,
|
|
58
|
+
TimestampInfo,
|
|
59
|
+
DeserializeOtsResult,
|
|
60
|
+
OtsVerifyResult
|
|
61
|
+
} from './ZipKitOTS';
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { Wallet, JsonRpcProvider } from 'ethers';
|
|
2
|
+
|
|
3
|
+
// Wallet and network types
|
|
4
|
+
export interface WalletInfo {
|
|
5
|
+
address: string;
|
|
6
|
+
privateKey: string;
|
|
7
|
+
mnemonic: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface NetworkConfig {
|
|
11
|
+
name: string;
|
|
12
|
+
rpcUrl: string;
|
|
13
|
+
chainId: number;
|
|
14
|
+
explorerUrl: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface WalletSetupResult {
|
|
18
|
+
wallet: Wallet | null;
|
|
19
|
+
provider: JsonRpcProvider | null;
|
|
20
|
+
success: boolean;
|
|
21
|
+
message?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface MintingResult {
|
|
25
|
+
success: boolean;
|
|
26
|
+
message: string;
|
|
27
|
+
tokenId?: string;
|
|
28
|
+
txHash?: string;
|
|
29
|
+
creationTimestamp?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface MintingOptions {
|
|
33
|
+
wallet?: string;
|
|
34
|
+
network: string;
|
|
35
|
+
mintToken: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Canonical token metadata used across minting, verification, and ZIP embedding
|
|
39
|
+
export interface TokenMetadata {
|
|
40
|
+
// Core identifiers
|
|
41
|
+
tokenId: string;
|
|
42
|
+
contractAddress: string;
|
|
43
|
+
network: string;
|
|
44
|
+
merkleRoot: string;
|
|
45
|
+
|
|
46
|
+
// Optional chain info
|
|
47
|
+
networkChainId?: number;
|
|
48
|
+
transactionHash?: string;
|
|
49
|
+
blockNumber?: number;
|
|
50
|
+
|
|
51
|
+
// Names and timestamps (support both archiveName/fileName and mintedAt/mintDate)
|
|
52
|
+
fileName?: string;
|
|
53
|
+
archiveName?: string;
|
|
54
|
+
mintedAt?: string;
|
|
55
|
+
mintDate?: string;
|
|
56
|
+
creationTimestamp?: number;
|
|
57
|
+
|
|
58
|
+
// Optional content link
|
|
59
|
+
ipfsHash?: string;
|
|
60
|
+
|
|
61
|
+
// Versioning
|
|
62
|
+
version?: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Network configuration
|
|
66
|
+
export const NETWORKS: Record<string, NetworkConfig> = {
|
|
67
|
+
'base': {
|
|
68
|
+
name: 'Base Mainnet',
|
|
69
|
+
rpcUrl: 'https://mainnet.base.org',
|
|
70
|
+
chainId: 8453,
|
|
71
|
+
explorerUrl: 'https://basescan.org'
|
|
72
|
+
},
|
|
73
|
+
'base-sepolia': {
|
|
74
|
+
name: 'Base Sepolia',
|
|
75
|
+
rpcUrl: 'https://sepolia.base.org',
|
|
76
|
+
chainId: 84532,
|
|
77
|
+
explorerUrl: 'https://sepolia.basescan.org'
|
|
78
|
+
},
|
|
79
|
+
'base-goerli': {
|
|
80
|
+
name: 'Base Goerli',
|
|
81
|
+
rpcUrl: 'https://goerli.base.org',
|
|
82
|
+
chainId: 84531,
|
|
83
|
+
explorerUrl: 'https://goerli.basescan.org'
|
|
84
|
+
},
|
|
85
|
+
'localhost': {
|
|
86
|
+
name: 'Localhost',
|
|
87
|
+
rpcUrl: 'http://localhost:8545',
|
|
88
|
+
chainId: 31337,
|
|
89
|
+
explorerUrl: 'http://localhost:8545'
|
|
90
|
+
}
|
|
91
|
+
};
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import ZipKitBrowser from './ZipKitBrowser';
|
|
8
8
|
import { ZipEntry } from '../shared/ZipKit';
|
|
9
9
|
import { TOKENIZED_METADATA } from '../shared/constants/Headers';
|
|
10
|
-
import { NZIP_CONTRACT_ABI, CURRENT_DEPLOYMENT } from '../
|
|
10
|
+
import { NZIP_CONTRACT_ABI, CURRENT_DEPLOYMENT } from '../blockchain/constants';
|
|
11
11
|
|
|
12
12
|
// Token types (adapted for browser)
|
|
13
13
|
export interface NZipTokenInfo {
|
package/src/browser-index.ts
CHANGED
|
@@ -12,9 +12,9 @@ export default ZipKit;
|
|
|
12
12
|
|
|
13
13
|
// Browser-only exports
|
|
14
14
|
export { default as ZipKitBrowser } from './browser/ZipKitBrowser';
|
|
15
|
-
export { CertificateGeneratorBrowser } from './browser/CertificateGeneratorBrowser';
|
|
16
|
-
export { TokenVerificationResult, checkForTokenization as checkForTokenizationBrowser, NZipTokenInfo } from './browser/TokenVerifierBrowser';
|
|
17
|
-
export type { TokenVerificationOptions } from './browser/TokenVerifierBrowser';
|
|
15
|
+
// export { CertificateGeneratorBrowser } from './browser/CertificateGeneratorBrowser';
|
|
16
|
+
// export { TokenVerificationResult, checkForTokenization as checkForTokenizationBrowser, NZipTokenInfo } from './browser/TokenVerifierBrowser';
|
|
17
|
+
// export type { TokenVerificationOptions } from './browser/TokenVerifierBrowser';
|
|
18
18
|
|
|
19
19
|
// Shared component exports
|
|
20
20
|
export { default as HashAccumulator } from './shared/components/HashAccumulator';
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
// NeoZipKit - Unified Package Exports
|
|
3
3
|
// =============================================================================
|
|
4
4
|
|
|
5
|
+
// Type and constant exports
|
|
6
|
+
export * from './shared/types';
|
|
7
|
+
export * from './shared/constants/Headers';
|
|
8
|
+
export * from './shared/constants/Errors';
|
|
9
|
+
export * from './shared/version';
|
|
10
|
+
export { NEOZIPKIT_VERSION, NEOZIPKIT_RELEASE_DATE } from './shared/version';
|
|
11
|
+
|
|
5
12
|
// Core shared exports
|
|
6
13
|
import ZipKit from './shared/ZipKit';
|
|
7
14
|
export { ZipEntry, Errors, CMP_METHOD, TIMESTAMP_METADATA, TIMESTAMP_SUBMITTED } from './shared/ZipKit';
|
|
@@ -12,33 +19,19 @@ export default ZipKit;
|
|
|
12
19
|
|
|
13
20
|
// Browser-only exports
|
|
14
21
|
export { default as ZipKitBrowser } from './browser/ZipKitBrowser';
|
|
15
|
-
export { CertificateGeneratorBrowser } from './browser/CertificateGeneratorBrowser';
|
|
16
|
-
export { TokenVerificationResult, checkForTokenization as checkForTokenizationBrowser, NZipTokenInfo } from './browser/TokenVerifierBrowser';
|
|
17
|
-
export type { TokenVerificationOptions } from './browser/TokenVerifierBrowser';
|
|
18
22
|
|
|
19
23
|
// Server-only exports (now included in main build)
|
|
20
|
-
export { default as ZipKitServer } from './server/
|
|
21
|
-
export {
|
|
24
|
+
export { default as ZipKitServer } from './server/ZipKitServer';
|
|
25
|
+
export { createTimestamp } from './blockchain/ZipKitOTS';
|
|
22
26
|
|
|
23
27
|
// Blockchain exports
|
|
24
|
-
export * from './
|
|
25
|
-
export { checkForTokenization as checkForTokenizationServer } from './server/blockchain/TokenVerifier';
|
|
26
|
-
export { NFTMinter } from './server/blockchain/NFTMinter';
|
|
27
|
-
export { WalletAnalyzer } from './server/blockchain/WalletAnalyzer';
|
|
28
|
-
export { WalletManager } from './server/blockchain/WalletManager';
|
|
29
|
-
export { ZipTokenProcessor } from './server/blockchain/ZipTokenProcessor';
|
|
28
|
+
export * from './blockchain';
|
|
30
29
|
|
|
31
30
|
// Shared component exports
|
|
32
31
|
export { default as HashAccumulator } from './shared/components/HashAccumulator';
|
|
33
32
|
export * from './shared/components/Util';
|
|
34
33
|
export * from './shared/components/Support';
|
|
35
34
|
|
|
36
|
-
// Type and constant exports
|
|
37
|
-
export * from './shared/types';
|
|
38
|
-
export * from './shared/constants/Headers';
|
|
39
|
-
export * from './shared/constants/Errors';
|
|
40
|
-
export * from './shared/version';
|
|
41
|
-
|
|
42
35
|
// Platform-specific conditional exports
|
|
43
36
|
export const PlatformUtils = {
|
|
44
37
|
// Browser detection
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
### Server APIs
|
|
2
|
+
|
|
3
|
+
#### ZipKitServer
|
|
4
|
+
- `loadZipFile(path)`
|
|
5
|
+
- Open or create a ZIP for writing; prepares entries for add/update operations.
|
|
6
|
+
- `loadUnzipFile(path)`
|
|
7
|
+
- Open an existing ZIP for reading/extraction; throws on missing files.
|
|
8
|
+
- `addFile(path, freshen?, update?)`
|
|
9
|
+
- Add a new entry or update an existing one (respects freshen/update flags).
|
|
10
|
+
- `addFiles(paths[], freshen?, update?)`
|
|
11
|
+
- Batch add/update using `addFile` logic.
|
|
12
|
+
- `createZip(path, options)`
|
|
13
|
+
- Write all staged entries to disk (no OpenTimestamps metadata).
|
|
14
|
+
- `createZipOTS(path, options)`
|
|
15
|
+
- Write entries to disk and embed OpenTimestamps (OTS) metadata using the Merkle root.
|
|
16
|
+
- `deleteFiles(paths[])`
|
|
17
|
+
- Delete entries by filename and rebuild central directory.
|
|
18
|
+
- `upgradeOTS(zipPath, upgradedOts)`
|
|
19
|
+
- Replace OTS metadata in an existing archive with upgraded OTS bytes.
|
|
20
|
+
|
|
21
|
+
Notes:
|
|
22
|
+
- All read/write callbacks use Node Buffers. Ensure files exist on disk during `createZip*` flows.
|
|
23
|
+
|
|
24
|
+
For OpenTimestamps utilities, see `src/blockchain/ZipKitOTS.ts`.
|
|
25
|
+
|