chunktech 0.1.0 → 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/README.md +287 -130
- package/dist/crosschain.d.ts +24 -0
- package/dist/crosschain.d.ts.map +1 -0
- package/dist/crosschain.js +332 -0
- package/dist/crosschain.js.map +1 -0
- package/dist/extension-loader.d.ts +33 -0
- package/dist/extension-loader.d.ts.map +1 -0
- package/dist/extension-loader.js +299 -0
- package/dist/extension-loader.js.map +1 -0
- package/dist/extension-uploader.d.ts +69 -0
- package/dist/extension-uploader.d.ts.map +1 -0
- package/dist/extension-uploader.js +153 -0
- package/dist/extension-uploader.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +69 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChunkTech - Cross-Chain Upload
|
|
3
|
+
* Key transaction on mainnet, bulk data on L2
|
|
4
|
+
*/
|
|
5
|
+
import { createPublicClient, http } from 'viem';
|
|
6
|
+
import { mainnet, base, arbitrum, sepolia, baseSepolia, arbitrumSepolia } from 'viem/chains';
|
|
7
|
+
import { SUPPORTED_CHAINS } from './types.js';
|
|
8
|
+
import { chunkData } from './chunker.js';
|
|
9
|
+
import { sendChunks } from './sender.js';
|
|
10
|
+
import { waitForTransactions } from './tracker.js';
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Chain Registry
|
|
13
|
+
// ============================================================================
|
|
14
|
+
const CHAINS = {
|
|
15
|
+
ethereum: mainnet,
|
|
16
|
+
base: base,
|
|
17
|
+
arbitrum: arbitrum,
|
|
18
|
+
sepolia: sepolia,
|
|
19
|
+
baseSepolia: baseSepolia,
|
|
20
|
+
arbitrumSepolia: arbitrumSepolia,
|
|
21
|
+
};
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// Cross-Chain Uploader
|
|
24
|
+
// ============================================================================
|
|
25
|
+
export class CrossChainUploader {
|
|
26
|
+
keyWalletClient;
|
|
27
|
+
dataWalletClient;
|
|
28
|
+
// Using any to avoid viem's complex generic type issues
|
|
29
|
+
keyPublicClient;
|
|
30
|
+
dataPublicClient;
|
|
31
|
+
keyChain;
|
|
32
|
+
dataChain;
|
|
33
|
+
constructor(config) {
|
|
34
|
+
this.keyChain = config.keyChain;
|
|
35
|
+
this.dataChain = config.dataChain;
|
|
36
|
+
this.keyWalletClient = config.keyWalletClient;
|
|
37
|
+
this.dataWalletClient = config.dataWalletClient;
|
|
38
|
+
this.keyPublicClient = createPublicClient({
|
|
39
|
+
chain: CHAINS[config.keyChain],
|
|
40
|
+
transport: http(config.keyRpcUrl),
|
|
41
|
+
});
|
|
42
|
+
this.dataPublicClient = createPublicClient({
|
|
43
|
+
chain: CHAINS[config.dataChain],
|
|
44
|
+
transport: http(config.dataRpcUrl),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Upload data across chains - key on mainnet, chunks on L2
|
|
49
|
+
*/
|
|
50
|
+
async upload(data, options = {}) {
|
|
51
|
+
const { format = 'html', title = 'ChunkTech File', description = '', mimeType = 'application/octet-stream', onProgress, confirmations = 1, } = options;
|
|
52
|
+
// Convert input to Uint8Array
|
|
53
|
+
let bytes;
|
|
54
|
+
if (typeof data === 'string') {
|
|
55
|
+
bytes = new TextEncoder().encode(data);
|
|
56
|
+
}
|
|
57
|
+
else if (data instanceof ArrayBuffer) {
|
|
58
|
+
bytes = new Uint8Array(data);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
bytes = data;
|
|
62
|
+
}
|
|
63
|
+
// Calculate SHA256
|
|
64
|
+
const sha256 = await computeSha256(bytes);
|
|
65
|
+
// Chunk the data
|
|
66
|
+
const chunked = chunkData(bytes);
|
|
67
|
+
// Phase 1: Upload ALL chunks to L2
|
|
68
|
+
const results = await sendChunks(this.dataWalletClient, chunked.chunks, {
|
|
69
|
+
onProgress: onProgress
|
|
70
|
+
? (sent, total) => onProgress('data', sent, total)
|
|
71
|
+
: undefined,
|
|
72
|
+
});
|
|
73
|
+
const dataTxHashes = results.map((r) => r.hash);
|
|
74
|
+
// Wait for confirmations on data chain
|
|
75
|
+
if (confirmations > 0) {
|
|
76
|
+
await waitForTransactions(this.dataPublicClient, results, { confirmations });
|
|
77
|
+
}
|
|
78
|
+
// Phase 2: Create key transaction (the "unchunker") for mainnet
|
|
79
|
+
const manifest = {
|
|
80
|
+
version: 1,
|
|
81
|
+
chunkId: chunked.id,
|
|
82
|
+
sha256,
|
|
83
|
+
size: bytes.length,
|
|
84
|
+
mimeType,
|
|
85
|
+
dataChainId: SUPPORTED_CHAINS[this.dataChain].id,
|
|
86
|
+
dataChain: this.dataChain,
|
|
87
|
+
totalChunks: chunked.total,
|
|
88
|
+
dataTxHashes,
|
|
89
|
+
timestamp: Date.now(),
|
|
90
|
+
};
|
|
91
|
+
// Generate key transaction calldata
|
|
92
|
+
let keyCalldata;
|
|
93
|
+
if (format === 'html') {
|
|
94
|
+
keyCalldata = generateHtmlLoader(manifest, { title, description });
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
keyCalldata = `data:application/json;base64,${btoa(JSON.stringify(manifest))}`;
|
|
98
|
+
}
|
|
99
|
+
// Send key transaction
|
|
100
|
+
const keyTxHash = await sendKeyTransaction(this.keyWalletClient, keyCalldata);
|
|
101
|
+
if (onProgress) {
|
|
102
|
+
onProgress('key', 1, 1);
|
|
103
|
+
}
|
|
104
|
+
// Wait for confirmation on key chain
|
|
105
|
+
if (confirmations > 0) {
|
|
106
|
+
await this.keyPublicClient.waitForTransactionReceipt({
|
|
107
|
+
hash: keyTxHash,
|
|
108
|
+
confirmations,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
keyTxHash,
|
|
113
|
+
keyChainId: SUPPORTED_CHAINS[this.keyChain].id,
|
|
114
|
+
dataTxHashes,
|
|
115
|
+
dataChainId: SUPPORTED_CHAINS[this.dataChain].id,
|
|
116
|
+
chunkId: chunked.id,
|
|
117
|
+
totalChunks: chunked.total,
|
|
118
|
+
totalBytes: bytes.length,
|
|
119
|
+
sha256,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// ============================================================================
|
|
124
|
+
// HTML Loader Generator
|
|
125
|
+
// ============================================================================
|
|
126
|
+
function generateHtmlLoader(manifest, options) {
|
|
127
|
+
const { title, description } = options;
|
|
128
|
+
const html = `<!DOCTYPE html>
|
|
129
|
+
<html>
|
|
130
|
+
<head>
|
|
131
|
+
<meta charset="UTF-8">
|
|
132
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
133
|
+
<title>${escapeHtml(title)}</title>
|
|
134
|
+
<style>
|
|
135
|
+
*{margin:0;padding:0;box-sizing:border-box}
|
|
136
|
+
body{background:#0a0a0f;color:#fff;font-family:system-ui,-apple-system,sans-serif;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px}
|
|
137
|
+
.container{background:#12121a;border-radius:16px;padding:32px;max-width:480px;width:100%;box-shadow:0 20px 60px rgba(0,0,0,.5)}
|
|
138
|
+
h1{font-size:1.5rem;margin-bottom:8px;background:linear-gradient(135deg,#667eea,#764ba2);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
|
|
139
|
+
.desc{color:#888;font-size:.9rem;margin-bottom:24px}
|
|
140
|
+
.progress{background:#1a1a2e;border-radius:8px;height:8px;overflow:hidden;margin:16px 0}
|
|
141
|
+
.progress-bar{background:linear-gradient(90deg,#667eea,#764ba2);height:100%;width:0;transition:width .3s}
|
|
142
|
+
.status{color:#888;font-size:.85rem;text-align:center}
|
|
143
|
+
.meta{background:#1a1a2e;border-radius:8px;padding:16px;margin-top:24px;font-size:.8rem}
|
|
144
|
+
.meta-row{display:flex;justify-content:space-between;padding:4px 0;border-bottom:1px solid #252535}
|
|
145
|
+
.meta-row:last-child{border:none}
|
|
146
|
+
.label{color:#667eea}
|
|
147
|
+
.value{color:#aaa;font-family:monospace;font-size:.75rem;max-width:200px;overflow:hidden;text-overflow:ellipsis}
|
|
148
|
+
.badge{display:inline-block;background:#667eea;color:#fff;padding:2px 8px;border-radius:4px;font-size:.7rem;margin-right:4px}
|
|
149
|
+
.badge.l2{background:#0052ff}
|
|
150
|
+
.error{color:#ff6b6b;background:#2a1a1a;padding:12px;border-radius:8px;margin-top:16px;font-size:.85rem}
|
|
151
|
+
.download{display:none;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;padding:12px 24px;border-radius:8px;font-size:1rem;cursor:pointer;width:100%;margin-top:16px}
|
|
152
|
+
.download:hover{opacity:.9}
|
|
153
|
+
.download.show{display:block}
|
|
154
|
+
</style>
|
|
155
|
+
</head>
|
|
156
|
+
<body>
|
|
157
|
+
<div class="container">
|
|
158
|
+
<h1>${escapeHtml(title)}</h1>
|
|
159
|
+
<p class="desc">${escapeHtml(description) || 'Cross-chain file stored via ChunkTech'}</p>
|
|
160
|
+
<div><span class="badge">${getChainName(manifest.dataChainId)}</span><span class="badge l2">L2 Data</span></div>
|
|
161
|
+
<div class="progress"><div class="progress-bar" id="progress"></div></div>
|
|
162
|
+
<div class="status" id="status">Initializing...</div>
|
|
163
|
+
<div class="meta">
|
|
164
|
+
<div class="meta-row"><span class="label">Size</span><span class="value">${formatBytes(manifest.size)}</span></div>
|
|
165
|
+
<div class="meta-row"><span class="label">Chunks</span><span class="value">${manifest.totalChunks}</span></div>
|
|
166
|
+
<div class="meta-row"><span class="label">SHA256</span><span class="value">${manifest.sha256.slice(0, 16)}...</span></div>
|
|
167
|
+
<div class="meta-row"><span class="label">Type</span><span class="value">${manifest.mimeType}</span></div>
|
|
168
|
+
<div class="meta-row"><span class="label">Chain</span><span class="value">${manifest.dataChain} (${manifest.dataChainId})</span></div>
|
|
169
|
+
</div>
|
|
170
|
+
<div class="error" id="error" style="display:none"></div>
|
|
171
|
+
<button class="download" id="download">Download File</button>
|
|
172
|
+
</div>
|
|
173
|
+
<script>
|
|
174
|
+
const M=${JSON.stringify(manifest)};
|
|
175
|
+
// RPC discovery via calldata-rpc (https://github.com/chopperdaddy/calldata-rpc)
|
|
176
|
+
// Decentralized RPC endpoints hosted on IPFS via ENS
|
|
177
|
+
const TESTNET_RPC={84532:"https://sepolia.base.org",421614:"https://sepolia-rollup.arbitrum.io/rpc"};
|
|
178
|
+
|
|
179
|
+
async function getRpcUrls(chainId){
|
|
180
|
+
if(TESTNET_RPC[chainId])return[TESTNET_RPC[chainId]];
|
|
181
|
+
const endpoints=["https://rpcs.calldata.eth.limo","https://rpcs.calldata.eth.link"];
|
|
182
|
+
for(const base of endpoints){
|
|
183
|
+
try{
|
|
184
|
+
const r=await fetch(base);
|
|
185
|
+
if(r.ok){const d=await r.json();if(d[chainId]&&Array.isArray(d[chainId]))return d[chainId];}
|
|
186
|
+
}catch(e){}
|
|
187
|
+
}
|
|
188
|
+
return[];
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async function fetchChunkFromRpc(rpc,hash){
|
|
192
|
+
const r=await fetch(rpc,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",method:"eth_getTransactionByHash",params:[hash],id:1})});
|
|
193
|
+
const j=await r.json();
|
|
194
|
+
if(!j.result||!j.result.input)throw new Error("TX not found: "+hash);
|
|
195
|
+
const hex=j.result.input.slice(2);
|
|
196
|
+
const bytes=new Uint8Array(hex.length/2);
|
|
197
|
+
for(let i=0;i<hex.length;i+=2)bytes[i/2]=parseInt(hex.substr(i,2),16);
|
|
198
|
+
const str=new TextDecoder().decode(bytes);
|
|
199
|
+
const prefix="data:chunk,";
|
|
200
|
+
if(!str.startsWith(prefix))throw new Error("Invalid chunk");
|
|
201
|
+
const payload=JSON.parse(atob(str.slice(prefix.length)));
|
|
202
|
+
const binary=atob(payload.data);
|
|
203
|
+
const data=new Uint8Array(binary.length);
|
|
204
|
+
for(let i=0;i<binary.length;i++)data[i]=binary.charCodeAt(i);
|
|
205
|
+
return{part:payload.part,data};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async function fetchChunk(rpcs,hash){
|
|
209
|
+
let lastErr;
|
|
210
|
+
for(const rpc of rpcs){
|
|
211
|
+
try{return await fetchChunkFromRpc(rpc,hash);}catch(e){lastErr=e;}
|
|
212
|
+
}
|
|
213
|
+
throw lastErr||new Error("No RPCs available");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
async function load(){
|
|
217
|
+
const status=document.getElementById("status");
|
|
218
|
+
const progress=document.getElementById("progress");
|
|
219
|
+
const error=document.getElementById("error");
|
|
220
|
+
const download=document.getElementById("download");
|
|
221
|
+
status.textContent="Discovering RPC endpoints...";
|
|
222
|
+
const rpcs=await getRpcUrls(M.dataChainId);
|
|
223
|
+
if(!rpcs.length){error.textContent="No RPC endpoints for chain: "+M.dataChainId;error.style.display="block";return;}
|
|
224
|
+
const chunks=[];
|
|
225
|
+
try{
|
|
226
|
+
// Fetch ALL chunks from L2
|
|
227
|
+
for(let i=0;i<M.dataTxHashes.length;i++){
|
|
228
|
+
status.textContent="Loading chunk "+(i+1)+"/"+M.totalChunks+" from "+M.dataChain+"...";
|
|
229
|
+
const chunk=await fetchChunk(rpcs,M.dataTxHashes[i]);
|
|
230
|
+
chunks.push(chunk);
|
|
231
|
+
progress.style.width=((i+1)/M.totalChunks*100)+"%";
|
|
232
|
+
}
|
|
233
|
+
// Reassemble
|
|
234
|
+
status.textContent="Reassembling...";
|
|
235
|
+
chunks.sort((a,b)=>a.part-b.part);
|
|
236
|
+
const total=chunks.reduce((s,c)=>s+c.data.length,0);
|
|
237
|
+
const result=new Uint8Array(total);
|
|
238
|
+
let offset=0;
|
|
239
|
+
for(const c of chunks){result.set(c.data,offset);offset+=c.data.length;}
|
|
240
|
+
// Verify hash
|
|
241
|
+
const hashBuf=await crypto.subtle.digest("SHA-256",result);
|
|
242
|
+
const hash=Array.from(new Uint8Array(hashBuf)).map(b=>b.toString(16).padStart(2,"0")).join("");
|
|
243
|
+
if(hash!==M.sha256){error.textContent="Hash mismatch! Expected: "+M.sha256.slice(0,16)+"... Got: "+hash.slice(0,16)+"...";error.style.display="block";return;}
|
|
244
|
+
status.textContent="Complete! "+formatBytes(result.length)+" verified.";
|
|
245
|
+
progress.style.width="100%";
|
|
246
|
+
// Enable download
|
|
247
|
+
download.classList.add("show");
|
|
248
|
+
download.onclick=()=>{
|
|
249
|
+
const blob=new Blob([result],{type:M.mimeType});
|
|
250
|
+
const url=URL.createObjectURL(blob);
|
|
251
|
+
const a=document.createElement("a");
|
|
252
|
+
a.href=url;a.download="file";a.click();
|
|
253
|
+
URL.revokeObjectURL(url);
|
|
254
|
+
};
|
|
255
|
+
}catch(e){
|
|
256
|
+
error.textContent="Error: "+e.message;
|
|
257
|
+
error.style.display="block";
|
|
258
|
+
status.textContent="Failed";
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function formatBytes(b){if(b<1024)return b+" B";if(b<1048576)return(b/1024).toFixed(1)+" KB";return(b/1048576).toFixed(2)+" MB";}
|
|
262
|
+
load();
|
|
263
|
+
</script>
|
|
264
|
+
</body>
|
|
265
|
+
</html>`;
|
|
266
|
+
return `data:text/html;base64,${btoa(html)}`;
|
|
267
|
+
}
|
|
268
|
+
// ============================================================================
|
|
269
|
+
// Utilities
|
|
270
|
+
// ============================================================================
|
|
271
|
+
async function sendKeyTransaction(walletClient, calldata) {
|
|
272
|
+
const account = walletClient.account;
|
|
273
|
+
if (!account) {
|
|
274
|
+
throw new Error('WalletClient must have an account');
|
|
275
|
+
}
|
|
276
|
+
const hexData = stringToHex(calldata);
|
|
277
|
+
return walletClient.sendTransaction({
|
|
278
|
+
account,
|
|
279
|
+
chain: walletClient.chain,
|
|
280
|
+
to: account.address,
|
|
281
|
+
value: 0n,
|
|
282
|
+
data: hexData,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
async function computeSha256(data) {
|
|
286
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
|
287
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
288
|
+
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
289
|
+
}
|
|
290
|
+
function stringToHex(str) {
|
|
291
|
+
const bytes = new TextEncoder().encode(str);
|
|
292
|
+
return '0x' + Array.from(bytes)
|
|
293
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
294
|
+
.join('');
|
|
295
|
+
}
|
|
296
|
+
function uint8ArrayToBase64(bytes) {
|
|
297
|
+
let binary = '';
|
|
298
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
299
|
+
binary += String.fromCharCode(bytes[i]);
|
|
300
|
+
}
|
|
301
|
+
return btoa(binary);
|
|
302
|
+
}
|
|
303
|
+
function escapeHtml(str) {
|
|
304
|
+
return str
|
|
305
|
+
.replace(/&/g, '&')
|
|
306
|
+
.replace(/</g, '<')
|
|
307
|
+
.replace(/>/g, '>')
|
|
308
|
+
.replace(/"/g, '"');
|
|
309
|
+
}
|
|
310
|
+
function formatBytes(bytes) {
|
|
311
|
+
if (bytes < 1024)
|
|
312
|
+
return bytes + ' B';
|
|
313
|
+
if (bytes < 1048576)
|
|
314
|
+
return (bytes / 1024).toFixed(1) + ' KB';
|
|
315
|
+
return (bytes / 1048576).toFixed(2) + ' MB';
|
|
316
|
+
}
|
|
317
|
+
function getChainName(chainId) {
|
|
318
|
+
const names = {
|
|
319
|
+
1: 'Ethereum',
|
|
320
|
+
8453: 'Base',
|
|
321
|
+
42161: 'Arbitrum',
|
|
322
|
+
11155111: 'Sepolia',
|
|
323
|
+
84532: 'Base Sepolia',
|
|
324
|
+
421614: 'Arbitrum Sepolia',
|
|
325
|
+
};
|
|
326
|
+
return names[chainId] || `Chain ${chainId}`;
|
|
327
|
+
}
|
|
328
|
+
// ============================================================================
|
|
329
|
+
// Exports
|
|
330
|
+
// ============================================================================
|
|
331
|
+
export { generateHtmlLoader };
|
|
332
|
+
//# sourceMappingURL=crosschain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crosschain.js","sourceRoot":"","sources":["../src/crosschain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChunkTech - Extension Loader Generator
|
|
3
|
+
* Creates a self-contained inscription that downloads Chrome/Firefox extensions from Base
|
|
4
|
+
*/
|
|
5
|
+
import type { Hash } from 'viem';
|
|
6
|
+
export interface ExtensionBuild {
|
|
7
|
+
txHashes: Hash[];
|
|
8
|
+
sha256: string;
|
|
9
|
+
size: number;
|
|
10
|
+
chunks: number;
|
|
11
|
+
}
|
|
12
|
+
export interface ExtensionManifest {
|
|
13
|
+
version: number;
|
|
14
|
+
name: string;
|
|
15
|
+
extVersion: string;
|
|
16
|
+
developer: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
homepage?: string;
|
|
19
|
+
dataChainId: number;
|
|
20
|
+
dataChain: string;
|
|
21
|
+
chrome?: ExtensionBuild;
|
|
22
|
+
firefox?: ExtensionBuild;
|
|
23
|
+
timestamp: number;
|
|
24
|
+
}
|
|
25
|
+
export interface ExtensionLoaderOptions {
|
|
26
|
+
name: string;
|
|
27
|
+
extVersion: string;
|
|
28
|
+
developer: string;
|
|
29
|
+
description?: string;
|
|
30
|
+
homepage?: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function generateExtensionLoader(manifest: ExtensionManifest): string;
|
|
33
|
+
//# sourceMappingURL=extension-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension-loader.d.ts","sourceRoot":"","sources":["../src/extension-loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAMjC,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,IAAI,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,iBAAiB,GAC1B,MAAM,CAkRR"}
|