@net-protocol/storage 0.1.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/dist/index.mjs ADDED
@@ -0,0 +1,2079 @@
1
+ import { useReadContract } from 'wagmi';
2
+ import { useState, useEffect, useMemo } from 'react';
3
+ import { keccak256HashString, toBytes32, getNetContract, getPublicClient, normalizeDataOrEmpty } from '@net-protocol/core';
4
+ import { stringToHex, hexToBytes, hexToString, fromHex, decodeAbiParameters } from 'viem';
5
+ import pako from 'pako';
6
+ import { readContract } from 'viem/actions';
7
+ import useAsyncEffect from 'use-async-effect';
8
+
9
+ // src/hooks/useStorage.ts
10
+
11
+ // src/abis/storage.json
12
+ var storage_default = [
13
+ {
14
+ type: "function",
15
+ name: "bulkGet",
16
+ inputs: [
17
+ {
18
+ name: "params",
19
+ type: "tuple[]",
20
+ internalType: "struct Storage.BulkGetParams[]",
21
+ components: [
22
+ { name: "key", type: "bytes32", internalType: "bytes32" },
23
+ { name: "operator", type: "address", internalType: "address" }
24
+ ]
25
+ }
26
+ ],
27
+ outputs: [
28
+ {
29
+ name: "results",
30
+ type: "tuple[]",
31
+ internalType: "struct Storage.BulkGetResult[]",
32
+ components: [
33
+ { name: "text", type: "string", internalType: "string" },
34
+ { name: "value", type: "bytes", internalType: "bytes" }
35
+ ]
36
+ }
37
+ ],
38
+ stateMutability: "view"
39
+ },
40
+ {
41
+ type: "function",
42
+ name: "bulkGetTotalWrites",
43
+ inputs: [
44
+ {
45
+ name: "params",
46
+ type: "tuple[]",
47
+ internalType: "struct Storage.BulkGetParams[]",
48
+ components: [
49
+ { name: "key", type: "bytes32", internalType: "bytes32" },
50
+ { name: "operator", type: "address", internalType: "address" }
51
+ ]
52
+ }
53
+ ],
54
+ outputs: [
55
+ { name: "results", type: "uint256[]", internalType: "uint256[]" }
56
+ ],
57
+ stateMutability: "view"
58
+ },
59
+ {
60
+ type: "function",
61
+ name: "bulkGetValueAtIndex",
62
+ inputs: [
63
+ {
64
+ name: "params",
65
+ type: "tuple[]",
66
+ internalType: "struct Storage.BulkGetValueAtIndexParams[]",
67
+ components: [
68
+ { name: "key", type: "bytes32", internalType: "bytes32" },
69
+ {
70
+ name: "operator",
71
+ type: "address",
72
+ internalType: "address"
73
+ },
74
+ { name: "idx", type: "uint256", internalType: "uint256" }
75
+ ]
76
+ }
77
+ ],
78
+ outputs: [
79
+ {
80
+ name: "results",
81
+ type: "tuple[]",
82
+ internalType: "struct Storage.BulkGetResult[]",
83
+ components: [
84
+ { name: "text", type: "string", internalType: "string" },
85
+ { name: "value", type: "bytes", internalType: "bytes" }
86
+ ]
87
+ }
88
+ ],
89
+ stateMutability: "view"
90
+ },
91
+ {
92
+ type: "function",
93
+ name: "bulkPut",
94
+ inputs: [
95
+ {
96
+ name: "params",
97
+ type: "tuple[]",
98
+ internalType: "struct Storage.BulkPutParams[]",
99
+ components: [
100
+ { name: "key", type: "bytes32", internalType: "bytes32" },
101
+ { name: "text", type: "string", internalType: "string" },
102
+ { name: "value", type: "bytes", internalType: "bytes" }
103
+ ]
104
+ }
105
+ ],
106
+ outputs: [],
107
+ stateMutability: "nonpayable"
108
+ },
109
+ {
110
+ type: "function",
111
+ name: "get",
112
+ inputs: [
113
+ { name: "key", type: "bytes32", internalType: "bytes32" },
114
+ { name: "operator", type: "address", internalType: "address" }
115
+ ],
116
+ outputs: [
117
+ { name: "", type: "string", internalType: "string" },
118
+ { name: "", type: "bytes", internalType: "bytes" }
119
+ ],
120
+ stateMutability: "view"
121
+ },
122
+ {
123
+ type: "function",
124
+ name: "getTotalWrites",
125
+ inputs: [
126
+ { name: "key", type: "bytes32", internalType: "bytes32" },
127
+ { name: "operator", type: "address", internalType: "address" }
128
+ ],
129
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
130
+ stateMutability: "view"
131
+ },
132
+ {
133
+ type: "function",
134
+ name: "getValueAtIndex",
135
+ inputs: [
136
+ { name: "key", type: "bytes32", internalType: "bytes32" },
137
+ { name: "operator", type: "address", internalType: "address" },
138
+ { name: "idx", type: "uint256", internalType: "uint256" }
139
+ ],
140
+ outputs: [
141
+ { name: "", type: "string", internalType: "string" },
142
+ { name: "", type: "bytes", internalType: "bytes" }
143
+ ],
144
+ stateMutability: "view"
145
+ },
146
+ {
147
+ type: "function",
148
+ name: "put",
149
+ inputs: [
150
+ { name: "key", type: "bytes32", internalType: "bytes32" },
151
+ { name: "text", type: "string", internalType: "string" },
152
+ { name: "value", type: "bytes", internalType: "bytes" }
153
+ ],
154
+ outputs: [],
155
+ stateMutability: "nonpayable"
156
+ },
157
+ {
158
+ type: "event",
159
+ name: "Stored",
160
+ inputs: [
161
+ {
162
+ name: "key",
163
+ type: "bytes32",
164
+ indexed: true,
165
+ internalType: "bytes32"
166
+ },
167
+ {
168
+ name: "operator",
169
+ type: "address",
170
+ indexed: true,
171
+ internalType: "address"
172
+ }
173
+ ],
174
+ anonymous: false
175
+ }
176
+ ];
177
+
178
+ // src/abis/chunked-storage.json
179
+ var chunked_storage_default = [
180
+ {
181
+ type: "function",
182
+ name: "get",
183
+ inputs: [
184
+ { name: "key", type: "bytes32", internalType: "bytes32" },
185
+ { name: "operator", type: "address", internalType: "address" }
186
+ ],
187
+ outputs: [
188
+ { name: "", type: "string", internalType: "string" },
189
+ { name: "", type: "bytes", internalType: "bytes" }
190
+ ],
191
+ stateMutability: "view"
192
+ },
193
+ {
194
+ type: "function",
195
+ name: "getChunk",
196
+ inputs: [
197
+ { name: "key", type: "bytes32", internalType: "bytes32" },
198
+ { name: "operator", type: "address", internalType: "address" },
199
+ { name: "chunkIndex", type: "uint8", internalType: "uint8" }
200
+ ],
201
+ outputs: [
202
+ { name: "chunkData", type: "bytes", internalType: "bytes" }
203
+ ],
204
+ stateMutability: "view"
205
+ },
206
+ {
207
+ type: "function",
208
+ name: "getChunks",
209
+ inputs: [
210
+ { name: "key", type: "bytes32", internalType: "bytes32" },
211
+ { name: "operator", type: "address", internalType: "address" },
212
+ { name: "startIndex", type: "uint8", internalType: "uint8" },
213
+ { name: "endIndex", type: "uint8", internalType: "uint8" }
214
+ ],
215
+ outputs: [
216
+ { name: "chunks", type: "bytes[]", internalType: "bytes[]" }
217
+ ],
218
+ stateMutability: "view"
219
+ },
220
+ {
221
+ type: "function",
222
+ name: "getMetadata",
223
+ inputs: [
224
+ { name: "key", type: "bytes32", internalType: "bytes32" },
225
+ { name: "operator", type: "address", internalType: "address" }
226
+ ],
227
+ outputs: [
228
+ { name: "chunkCount", type: "uint8", internalType: "uint8" },
229
+ { name: "originalText", type: "string", internalType: "string" }
230
+ ],
231
+ stateMutability: "view"
232
+ },
233
+ {
234
+ type: "function",
235
+ name: "put",
236
+ inputs: [
237
+ { name: "key", type: "bytes32", internalType: "bytes32" },
238
+ { name: "text", type: "string", internalType: "string" },
239
+ { name: "chunks", type: "bytes[]", internalType: "bytes[]" }
240
+ ],
241
+ outputs: [],
242
+ stateMutability: "nonpayable"
243
+ },
244
+ {
245
+ type: "event",
246
+ name: "ChunkedStoragePut",
247
+ inputs: [
248
+ {
249
+ name: "originalKey",
250
+ type: "bytes32",
251
+ indexed: true,
252
+ internalType: "bytes32"
253
+ },
254
+ {
255
+ name: "sender",
256
+ type: "address",
257
+ indexed: true,
258
+ internalType: "address"
259
+ },
260
+ {
261
+ name: "hashedKey",
262
+ type: "bytes32",
263
+ indexed: false,
264
+ internalType: "bytes32"
265
+ }
266
+ ],
267
+ anonymous: false
268
+ },
269
+ { type: "error", name: "DataTooLarge", inputs: [] }
270
+ ];
271
+
272
+ // src/abis/chunked-storage-reader.json
273
+ var chunked_storage_reader_default = [
274
+ {
275
+ type: "function",
276
+ name: "get",
277
+ inputs: [
278
+ { name: "key", type: "bytes32", internalType: "bytes32" },
279
+ { name: "operator", type: "address", internalType: "address" }
280
+ ],
281
+ outputs: [
282
+ { name: "", type: "string", internalType: "string" },
283
+ { name: "", type: "bytes", internalType: "bytes" }
284
+ ],
285
+ stateMutability: "view"
286
+ },
287
+ {
288
+ type: "function",
289
+ name: "getChunk",
290
+ inputs: [
291
+ { name: "key", type: "bytes32", internalType: "bytes32" },
292
+ { name: "operator", type: "address", internalType: "address" },
293
+ { name: "chunkIndex", type: "uint8", internalType: "uint8" }
294
+ ],
295
+ outputs: [
296
+ { name: "chunkData", type: "bytes", internalType: "bytes" }
297
+ ],
298
+ stateMutability: "view"
299
+ },
300
+ {
301
+ type: "function",
302
+ name: "getChunkAtIndex",
303
+ inputs: [
304
+ { name: "key", type: "bytes32", internalType: "bytes32" },
305
+ { name: "operator", type: "address", internalType: "address" },
306
+ { name: "chunkIndex", type: "uint8", internalType: "uint8" },
307
+ { name: "idx", type: "uint256", internalType: "uint256" }
308
+ ],
309
+ outputs: [
310
+ { name: "chunkData", type: "bytes", internalType: "bytes" }
311
+ ],
312
+ stateMutability: "view"
313
+ },
314
+ {
315
+ type: "function",
316
+ name: "getChunks",
317
+ inputs: [
318
+ { name: "key", type: "bytes32", internalType: "bytes32" },
319
+ { name: "operator", type: "address", internalType: "address" },
320
+ { name: "startIndex", type: "uint8", internalType: "uint8" },
321
+ { name: "endIndex", type: "uint8", internalType: "uint8" }
322
+ ],
323
+ outputs: [
324
+ { name: "chunks", type: "bytes[]", internalType: "bytes[]" }
325
+ ],
326
+ stateMutability: "view"
327
+ },
328
+ {
329
+ type: "function",
330
+ name: "getChunksAtIndex",
331
+ inputs: [
332
+ { name: "key", type: "bytes32", internalType: "bytes32" },
333
+ { name: "operator", type: "address", internalType: "address" },
334
+ { name: "startIndex", type: "uint8", internalType: "uint8" },
335
+ { name: "endIndex", type: "uint8", internalType: "uint8" },
336
+ { name: "idx", type: "uint256", internalType: "uint256" }
337
+ ],
338
+ outputs: [
339
+ { name: "chunks", type: "bytes[]", internalType: "bytes[]" }
340
+ ],
341
+ stateMutability: "view"
342
+ },
343
+ {
344
+ type: "function",
345
+ name: "getMetadata",
346
+ inputs: [
347
+ { name: "key", type: "bytes32", internalType: "bytes32" },
348
+ { name: "operator", type: "address", internalType: "address" }
349
+ ],
350
+ outputs: [
351
+ { name: "chunkCount", type: "uint8", internalType: "uint8" },
352
+ { name: "originalText", type: "string", internalType: "string" }
353
+ ],
354
+ stateMutability: "view"
355
+ },
356
+ {
357
+ type: "function",
358
+ name: "getMetadataAtIndex",
359
+ inputs: [
360
+ { name: "key", type: "bytes32", internalType: "bytes32" },
361
+ { name: "operator", type: "address", internalType: "address" },
362
+ { name: "idx", type: "uint256", internalType: "uint256" }
363
+ ],
364
+ outputs: [
365
+ { name: "chunkCount", type: "uint8", internalType: "uint8" },
366
+ { name: "originalText", type: "string", internalType: "string" }
367
+ ],
368
+ stateMutability: "view"
369
+ },
370
+ {
371
+ type: "function",
372
+ name: "getTotalWrites",
373
+ inputs: [
374
+ { name: "key", type: "bytes32", internalType: "bytes32" },
375
+ { name: "operator", type: "address", internalType: "address" }
376
+ ],
377
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
378
+ stateMutability: "view"
379
+ },
380
+ {
381
+ type: "function",
382
+ name: "getValueAtIndex",
383
+ inputs: [
384
+ { name: "key", type: "bytes32", internalType: "bytes32" },
385
+ { name: "operator", type: "address", internalType: "address" },
386
+ { name: "idx", type: "uint256", internalType: "uint256" }
387
+ ],
388
+ outputs: [
389
+ { name: "", type: "string", internalType: "string" },
390
+ { name: "", type: "bytes", internalType: "bytes" }
391
+ ],
392
+ stateMutability: "view"
393
+ }
394
+ ];
395
+
396
+ // src/abis/storage-router.json
397
+ var storage_router_default = [
398
+ {
399
+ type: "function",
400
+ name: "get",
401
+ inputs: [
402
+ { name: "key", type: "bytes32", internalType: "bytes32" },
403
+ { name: "operator", type: "address", internalType: "address" }
404
+ ],
405
+ outputs: [
406
+ { name: "isChunkedStorage", type: "bool", internalType: "bool" },
407
+ { name: "text", type: "string", internalType: "string" },
408
+ { name: "data", type: "bytes", internalType: "bytes" }
409
+ ],
410
+ stateMutability: "view"
411
+ },
412
+ { type: "error", name: "StoredDataNotFound", inputs: [] }
413
+ ];
414
+
415
+ // src/abis/safe-storage-reader.json
416
+ var safe_storage_reader_default = [
417
+ {
418
+ type: "function",
419
+ name: "bulkGet",
420
+ inputs: [
421
+ {
422
+ name: "params",
423
+ type: "tuple[]",
424
+ internalType: "struct IStorage.BulkGetParams[]",
425
+ components: [
426
+ {
427
+ name: "key",
428
+ type: "bytes32",
429
+ internalType: "bytes32"
430
+ },
431
+ {
432
+ name: "operator",
433
+ type: "address",
434
+ internalType: "address"
435
+ }
436
+ ]
437
+ }
438
+ ],
439
+ outputs: [
440
+ {
441
+ name: "results",
442
+ type: "tuple[]",
443
+ internalType: "struct IStorage.BulkGetResult[]",
444
+ components: [
445
+ {
446
+ name: "text",
447
+ type: "string",
448
+ internalType: "string"
449
+ },
450
+ {
451
+ name: "value",
452
+ type: "bytes",
453
+ internalType: "bytes"
454
+ }
455
+ ]
456
+ }
457
+ ],
458
+ stateMutability: "view"
459
+ },
460
+ {
461
+ type: "function",
462
+ name: "bulkGetValueAtIndex",
463
+ inputs: [
464
+ {
465
+ name: "params",
466
+ type: "tuple[]",
467
+ internalType: "struct IStorage.BulkGetValueAtIndexParams[]",
468
+ components: [
469
+ {
470
+ name: "key",
471
+ type: "bytes32",
472
+ internalType: "bytes32"
473
+ },
474
+ {
475
+ name: "operator",
476
+ type: "address",
477
+ internalType: "address"
478
+ },
479
+ {
480
+ name: "idx",
481
+ type: "uint256",
482
+ internalType: "uint256"
483
+ }
484
+ ]
485
+ }
486
+ ],
487
+ outputs: [
488
+ {
489
+ name: "results",
490
+ type: "tuple[]",
491
+ internalType: "struct IStorage.BulkGetResult[]",
492
+ components: [
493
+ {
494
+ name: "text",
495
+ type: "string",
496
+ internalType: "string"
497
+ },
498
+ {
499
+ name: "value",
500
+ type: "bytes",
501
+ internalType: "bytes"
502
+ }
503
+ ]
504
+ }
505
+ ],
506
+ stateMutability: "view"
507
+ },
508
+ {
509
+ type: "function",
510
+ name: "get",
511
+ inputs: [
512
+ {
513
+ name: "key",
514
+ type: "bytes32",
515
+ internalType: "bytes32"
516
+ },
517
+ {
518
+ name: "operator",
519
+ type: "address",
520
+ internalType: "address"
521
+ }
522
+ ],
523
+ outputs: [
524
+ {
525
+ name: "",
526
+ type: "string",
527
+ internalType: "string"
528
+ },
529
+ {
530
+ name: "",
531
+ type: "bytes",
532
+ internalType: "bytes"
533
+ }
534
+ ],
535
+ stateMutability: "view"
536
+ },
537
+ {
538
+ type: "function",
539
+ name: "getValueAtIndex",
540
+ inputs: [
541
+ {
542
+ name: "key",
543
+ type: "bytes32",
544
+ internalType: "bytes32"
545
+ },
546
+ {
547
+ name: "operator",
548
+ type: "address",
549
+ internalType: "address"
550
+ },
551
+ {
552
+ name: "idx",
553
+ type: "uint256",
554
+ internalType: "uint256"
555
+ }
556
+ ],
557
+ outputs: [
558
+ {
559
+ name: "",
560
+ type: "string",
561
+ internalType: "string"
562
+ },
563
+ {
564
+ name: "",
565
+ type: "bytes",
566
+ internalType: "bytes"
567
+ }
568
+ ],
569
+ stateMutability: "view"
570
+ }
571
+ ];
572
+
573
+ // src/constants.ts
574
+ var STORAGE_CONTRACT = {
575
+ abi: storage_default,
576
+ address: "0x00000000db40fcb9f4466330982372e27fd7bbf5"
577
+ };
578
+ var CHUNKED_STORAGE_CONTRACT = {
579
+ abi: chunked_storage_default,
580
+ address: "0x000000A822F09aF21b1951B65223F54ea392E6C6"
581
+ };
582
+ var CHUNKED_STORAGE_READER_CONTRACT = {
583
+ abi: chunked_storage_reader_default,
584
+ address: "0x00000005210a7532787419658f6162f771be62f8"
585
+ };
586
+ var STORAGE_ROUTER_CONTRACT = {
587
+ abi: storage_router_default,
588
+ address: "0x000000C0bbc2Ca04B85E77D18053e7c38bB97939"
589
+ };
590
+ var SAFE_STORAGE_READER_CONTRACT = {
591
+ abi: safe_storage_reader_default,
592
+ address: "0x0000000d03bad401fae4935dc9cbbf8084347214"
593
+ };
594
+
595
+ // src/utils/xmlUtils.ts
596
+ function parseNetReferences(metadata) {
597
+ const regex = /<net\s+k="([^"]+)"\s+v="([^"]+)"(?:\s+i="([^"]+)")?(?:\s+o="([^"]+)")?(?:\s+s="([^"]+)")?\s*\/>/g;
598
+ const references = [];
599
+ let match;
600
+ while ((match = regex.exec(metadata)) !== null) {
601
+ references.push({
602
+ hash: match[1],
603
+ version: match[2],
604
+ index: match[3] ? parseInt(match[3], 10) : void 0,
605
+ operator: match[4]?.toLowerCase(),
606
+ source: match[5]
607
+ });
608
+ }
609
+ return references;
610
+ }
611
+ function containsXmlReferences(data) {
612
+ return /<net\s+k="[^"]+"\s+v="[^"]+"(?:\s+i="[^"]+")?(?:\s+o="[^"]+")?(?:\s+s="[^"]+")?\s*\/>/.test(
613
+ data
614
+ );
615
+ }
616
+ function detectStorageType(metadata) {
617
+ return containsXmlReferences(metadata) ? "xml" : "regular";
618
+ }
619
+ function resolveOperator(reference, defaultOperator) {
620
+ return reference.operator?.toLowerCase() || defaultOperator.toLowerCase();
621
+ }
622
+ function getReferenceKey(reference, defaultOperator) {
623
+ const operator = resolveOperator(reference, defaultOperator);
624
+ const index = reference.index !== void 0 ? `-${reference.index}` : "";
625
+ return `${reference.hash}-${operator}${index}`;
626
+ }
627
+
628
+ // src/utils/chunkUtils.ts
629
+ var CHUNK_SIZE = 20 * 1e3;
630
+ function chunkDataForStorage(data) {
631
+ try {
632
+ const dataHex = stringToHex(data);
633
+ const compressedBytes = pako.gzip(dataHex);
634
+ const dataBytes = "0x" + Buffer.from(compressedBytes).toString("hex");
635
+ const chunks = [];
636
+ const hexWithoutPrefix = dataBytes.slice(2);
637
+ for (let i = 0; i < hexWithoutPrefix.length; i += CHUNK_SIZE * 2) {
638
+ const chunk = hexWithoutPrefix.slice(i, i + CHUNK_SIZE * 2);
639
+ chunks.push("0x" + chunk);
640
+ }
641
+ if (chunks.length === 0) {
642
+ chunks.push("0x");
643
+ }
644
+ return chunks;
645
+ } catch (error) {
646
+ console.error("[chunkDataForStorage] Compression failed:", error);
647
+ throw new Error("Failed to compress data for storage");
648
+ }
649
+ }
650
+ function shouldSuggestXmlStorage(data) {
651
+ return data.length > CHUNK_SIZE || containsXmlReferences(data);
652
+ }
653
+ function getChunkCount(data) {
654
+ const dataBytes = stringToHex(data);
655
+ const hexWithoutPrefix = dataBytes.slice(2);
656
+ return Math.max(1, Math.ceil(hexWithoutPrefix.length / (CHUNK_SIZE * 2)));
657
+ }
658
+ function assembleChunks(chunks) {
659
+ try {
660
+ let assembled = chunks[0] || "0x";
661
+ for (let i = 1; i < chunks.length; i++) {
662
+ const chunk = chunks[i];
663
+ if (chunk && chunk !== "0x") {
664
+ assembled += chunk.slice(2);
665
+ }
666
+ }
667
+ const bytes = hexToBytes(assembled);
668
+ try {
669
+ const decompressed = pako.ungzip(bytes);
670
+ const hexString = Buffer.from(decompressed).toString("utf8");
671
+ const result = hexToString(hexString);
672
+ return result;
673
+ } catch (error) {
674
+ return void 0;
675
+ }
676
+ } catch (error) {
677
+ console.error("[assembleChunks] Failed to assemble chunks:", error);
678
+ throw new Error("Failed to decompress chunked data");
679
+ }
680
+ }
681
+ function isBinaryString(str) {
682
+ return str.split("").some((char) => char.charCodeAt(0) > 127);
683
+ }
684
+ function formatStorageKeyForDisplay(storageKey) {
685
+ if (storageKey.startsWith("0x") && storageKey.length === 66 && /^0x[0-9a-fA-F]{64}$/.test(storageKey)) {
686
+ try {
687
+ const decoded = fromHex(storageKey, "string");
688
+ const trimmed = decoded.replace(/\0/g, "");
689
+ if (!isBinaryString(trimmed) && trimmed.trim().length > 0) {
690
+ return {
691
+ displayText: trimmed,
692
+ isDecoded: true
693
+ };
694
+ }
695
+ } catch {
696
+ }
697
+ }
698
+ return {
699
+ displayText: storageKey,
700
+ isDecoded: false
701
+ };
702
+ }
703
+ function getStorageKeyBytes(input, keyFormat) {
704
+ if (keyFormat === "bytes32") {
705
+ return input.toLowerCase();
706
+ }
707
+ if (keyFormat === "raw") {
708
+ return input.length > 32 ? keccak256HashString(input.toLowerCase()) : toBytes32(input.toLowerCase());
709
+ }
710
+ if (input.startsWith("0x") && input.length === 66 && // 0x + 64 hex chars = bytes32
711
+ /^0x[0-9a-fA-F]{64}$/.test(input)) {
712
+ return input.toLowerCase();
713
+ }
714
+ return input.length > 32 ? keccak256HashString(input.toLowerCase()) : toBytes32(input.toLowerCase());
715
+ }
716
+ function encodeStorageKeyForUrl(key) {
717
+ return encodeURIComponent(key);
718
+ }
719
+ function generateStorageEmbedTag(params) {
720
+ const operator = params.operatorAddress.toLowerCase();
721
+ const indexAttr = params.versionIndex !== void 0 ? ` i="${params.versionIndex}"` : "";
722
+ const sourceAttr = params.isRegularStorage ? ` s="d"` : "";
723
+ return `<net k="${params.storageKeyBytes}" v="0.0.1"${indexAttr} o="${operator}"${sourceAttr} />`;
724
+ }
725
+
726
+ // src/hooks/useStorage.ts
727
+ var BATCH_SIZE = 2;
728
+ function useStorage({
729
+ chainId,
730
+ key,
731
+ operatorAddress,
732
+ enabled = true,
733
+ index,
734
+ keyFormat,
735
+ useRouter = false,
736
+ outputFormat = "hex"
737
+ }) {
738
+ const isLatestVersion = index === void 0;
739
+ const shouldUseRouter = useRouter === true && isLatestVersion;
740
+ const outputAsString = outputFormat === "string";
741
+ const storageKeyBytes = key ? getStorageKeyBytes(key, keyFormat) : void 0;
742
+ const formatData = (text, dataHex) => {
743
+ if (outputAsString) {
744
+ return [text, hexToString(dataHex)];
745
+ }
746
+ return [text, dataHex];
747
+ };
748
+ const [routerData, setRouterData] = useState();
749
+ const [routerChunkLoading, setRouterChunkLoading] = useState(false);
750
+ const [routerChunkError, setRouterChunkError] = useState();
751
+ const routerHook = useReadContract({
752
+ abi: STORAGE_ROUTER_CONTRACT.abi,
753
+ address: STORAGE_ROUTER_CONTRACT.address,
754
+ functionName: "get",
755
+ args: storageKeyBytes && operatorAddress ? [storageKeyBytes, operatorAddress] : void 0,
756
+ chainId,
757
+ query: {
758
+ enabled: shouldUseRouter && enabled && !!key && !!operatorAddress
759
+ }
760
+ });
761
+ useEffect(() => {
762
+ async function processRouterResult() {
763
+ if (!routerHook.data || routerHook.isLoading || routerHook.error) {
764
+ return;
765
+ }
766
+ const [isChunkedStorage, text, data] = routerHook.data;
767
+ if (!isChunkedStorage) {
768
+ const formatted = formatData(text, data);
769
+ setRouterData(formatted);
770
+ return;
771
+ }
772
+ setRouterChunkLoading(true);
773
+ setRouterChunkError(void 0);
774
+ try {
775
+ const [chunkCount] = decodeAbiParameters([{ type: "uint8" }], data);
776
+ if (chunkCount === 0) {
777
+ setRouterData(void 0);
778
+ return;
779
+ }
780
+ const client = getPublicClient({ chainId });
781
+ if (!client) {
782
+ throw new Error(`Chain not found for chainId: ${chainId}`);
783
+ }
784
+ const allChunks = [];
785
+ for (let start = 0; start < Number(chunkCount); start += BATCH_SIZE) {
786
+ const end = Math.min(start + BATCH_SIZE, Number(chunkCount));
787
+ const batch = await readContract(client, {
788
+ abi: CHUNKED_STORAGE_CONTRACT.abi,
789
+ address: CHUNKED_STORAGE_CONTRACT.address,
790
+ functionName: "getChunks",
791
+ args: [storageKeyBytes, operatorAddress, start, end]
792
+ });
793
+ allChunks.push(...batch);
794
+ }
795
+ const assembledString = assembleChunks(allChunks);
796
+ if (assembledString === void 0) {
797
+ setRouterData(void 0);
798
+ } else {
799
+ if (outputAsString) {
800
+ setRouterData([text, assembledString]);
801
+ } else {
802
+ const hexData = stringToHex(assembledString);
803
+ setRouterData([text, hexData]);
804
+ }
805
+ }
806
+ } catch (error) {
807
+ setRouterChunkError(error);
808
+ } finally {
809
+ setRouterChunkLoading(false);
810
+ }
811
+ }
812
+ processRouterResult();
813
+ }, [
814
+ routerHook.data,
815
+ routerHook.isLoading,
816
+ routerHook.error,
817
+ operatorAddress,
818
+ chainId,
819
+ storageKeyBytes,
820
+ outputAsString
821
+ ]);
822
+ const {
823
+ data: latestData,
824
+ isLoading: latestLoading,
825
+ error: latestError
826
+ } = useReadContract({
827
+ abi: STORAGE_CONTRACT.abi,
828
+ address: STORAGE_CONTRACT.address,
829
+ functionName: "get",
830
+ args: key && operatorAddress ? [getStorageKeyBytes(key, keyFormat), operatorAddress] : void 0,
831
+ chainId,
832
+ query: {
833
+ enabled: !shouldUseRouter && enabled && !!operatorAddress && !!key && isLatestVersion
834
+ }
835
+ });
836
+ const [historicalData, setHistoricalData] = useState(
837
+ void 0
838
+ );
839
+ const [historicalLoading, setHistoricalLoading] = useState(false);
840
+ const [historicalError, setHistoricalError] = useState();
841
+ useEffect(() => {
842
+ async function fetchHistoricalVersion() {
843
+ if (isLatestVersion || !key || !operatorAddress || !enabled) {
844
+ return;
845
+ }
846
+ setHistoricalLoading(true);
847
+ setHistoricalError(void 0);
848
+ setHistoricalData(void 0);
849
+ try {
850
+ const client = getPublicClient({ chainId });
851
+ if (!client) {
852
+ throw new Error(`Chain not found for chainId: ${chainId}`);
853
+ }
854
+ const storageKeyBytes2 = getStorageKeyBytes(
855
+ key,
856
+ keyFormat
857
+ );
858
+ try {
859
+ const metadata = await readContract(client, {
860
+ abi: CHUNKED_STORAGE_READER_CONTRACT.abi,
861
+ address: CHUNKED_STORAGE_READER_CONTRACT.address,
862
+ functionName: "getMetadataAtIndex",
863
+ args: [storageKeyBytes2, operatorAddress, index]
864
+ });
865
+ const [chunkCount, text2] = metadata;
866
+ if (chunkCount > 0) {
867
+ const chunks = await readContract(client, {
868
+ abi: CHUNKED_STORAGE_READER_CONTRACT.abi,
869
+ address: CHUNKED_STORAGE_READER_CONTRACT.address,
870
+ functionName: "getChunksAtIndex",
871
+ args: [storageKeyBytes2, operatorAddress, 0, chunkCount, index]
872
+ });
873
+ const assembledData = assembleChunks(chunks);
874
+ if (assembledData !== void 0) {
875
+ const hexData = stringToHex(assembledData);
876
+ setHistoricalData(formatData(text2, hexData));
877
+ setHistoricalLoading(false);
878
+ return;
879
+ }
880
+ }
881
+ } catch (chunkedError) {
882
+ }
883
+ const result = await readContract(client, {
884
+ abi: STORAGE_CONTRACT.abi,
885
+ address: STORAGE_CONTRACT.address,
886
+ functionName: "getValueAtIndex",
887
+ args: [storageKeyBytes2, operatorAddress, index]
888
+ });
889
+ const [text, data] = result;
890
+ setHistoricalData(formatData(text, data));
891
+ } catch (error) {
892
+ console.error(
893
+ "[useStorage] Failed to fetch historical version:",
894
+ error
895
+ );
896
+ setHistoricalError(error);
897
+ } finally {
898
+ setHistoricalLoading(false);
899
+ }
900
+ }
901
+ fetchHistoricalVersion();
902
+ }, [chainId, key, operatorAddress, index, enabled, isLatestVersion, outputAsString]);
903
+ if (!isLatestVersion) {
904
+ return {
905
+ data: historicalData,
906
+ isLoading: historicalLoading,
907
+ error: historicalError
908
+ };
909
+ }
910
+ if (shouldUseRouter) {
911
+ return {
912
+ data: routerData,
913
+ isLoading: routerHook.isLoading || routerChunkLoading,
914
+ error: routerHook.error || routerChunkError
915
+ };
916
+ }
917
+ const formattedDirectData = latestData ? formatData(latestData[0], latestData[1]) : void 0;
918
+ return {
919
+ data: formattedDirectData,
920
+ isLoading: latestLoading,
921
+ error: latestError
922
+ };
923
+ }
924
+ function useStorageForOperator({
925
+ chainId,
926
+ operatorAddress
927
+ }) {
928
+ const netContract = getNetContract(chainId);
929
+ const { data: totalCount, isLoading: isLoadingCount } = useReadContract({
930
+ abi: netContract.abi,
931
+ address: netContract.address,
932
+ functionName: "getTotalMessagesForAppUserCount",
933
+ args: [STORAGE_CONTRACT.address, operatorAddress],
934
+ chainId
935
+ });
936
+ const totalCountNumber = totalCount ? Number(totalCount) : 0;
937
+ const { data: messages, isLoading: isLoadingMessages } = useReadContract({
938
+ abi: netContract.abi,
939
+ address: netContract.address,
940
+ functionName: "getMessagesInRangeForAppUser",
941
+ args: [0, totalCountNumber, STORAGE_CONTRACT.address, operatorAddress],
942
+ chainId
943
+ });
944
+ return {
945
+ data: messages?.map((msg) => [
946
+ msg.topic,
947
+ msg.text,
948
+ Number(msg.timestamp),
949
+ msg.data
950
+ ]) || [],
951
+ isLoading: isLoadingCount || isLoadingMessages,
952
+ error: void 0
953
+ };
954
+ }
955
+ function useStorageForOperatorAndKey({
956
+ chainId,
957
+ key,
958
+ operatorAddress,
959
+ keyFormat
960
+ }) {
961
+ const storageKeyBytes = key ? getStorageKeyBytes(key, keyFormat) : void 0;
962
+ const readContractArgs = {
963
+ abi: STORAGE_CONTRACT.abi,
964
+ address: STORAGE_CONTRACT.address,
965
+ functionName: "getForOperatorAndKey",
966
+ args: storageKeyBytes ? [operatorAddress, storageKeyBytes] : void 0,
967
+ chainId,
968
+ query: {
969
+ enabled: !!key && !!operatorAddress
970
+ }
971
+ };
972
+ const { data, isLoading, error } = useReadContract(readContractArgs);
973
+ return {
974
+ data,
975
+ isLoading,
976
+ error
977
+ };
978
+ }
979
+ function useBulkStorage({
980
+ chainId,
981
+ keys,
982
+ safe = false,
983
+ keyFormat
984
+ }) {
985
+ const contract = safe ? SAFE_STORAGE_READER_CONTRACT : STORAGE_CONTRACT;
986
+ const bulkKeys = keys.map((k) => ({
987
+ key: getStorageKeyBytes(k.key, keyFormat),
988
+ operator: k.operator
989
+ }));
990
+ const readContractArgs = {
991
+ abi: contract.abi,
992
+ address: contract.address,
993
+ functionName: "bulkGet",
994
+ args: [bulkKeys],
995
+ chainId
996
+ };
997
+ const { data, isLoading, error } = useReadContract(readContractArgs);
998
+ return {
999
+ data,
1000
+ isLoading,
1001
+ error
1002
+ };
1003
+ }
1004
+ function useStorageTotalWrites({
1005
+ chainId,
1006
+ key,
1007
+ operatorAddress,
1008
+ enabled = true,
1009
+ keyFormat
1010
+ }) {
1011
+ const storageKeyBytes = key ? getStorageKeyBytes(key, keyFormat) : void 0;
1012
+ const {
1013
+ data: chunkedTotal,
1014
+ isLoading: chunkedLoading,
1015
+ error: chunkedError
1016
+ } = useReadContract({
1017
+ abi: CHUNKED_STORAGE_READER_CONTRACT.abi,
1018
+ address: CHUNKED_STORAGE_READER_CONTRACT.address,
1019
+ functionName: "getTotalWrites",
1020
+ args: storageKeyBytes && operatorAddress ? [storageKeyBytes, operatorAddress] : void 0,
1021
+ chainId,
1022
+ query: {
1023
+ enabled: enabled && !!key && !!operatorAddress
1024
+ }
1025
+ });
1026
+ const {
1027
+ data: regularTotal,
1028
+ isLoading: regularLoading,
1029
+ error: regularError
1030
+ } = useReadContract({
1031
+ abi: STORAGE_CONTRACT.abi,
1032
+ address: STORAGE_CONTRACT.address,
1033
+ functionName: "getTotalWrites",
1034
+ args: storageKeyBytes && operatorAddress ? [storageKeyBytes, operatorAddress] : void 0,
1035
+ chainId,
1036
+ query: {
1037
+ enabled: enabled && !!key && !!operatorAddress && (chunkedTotal === void 0 || Number(chunkedTotal) === 0)
1038
+ }
1039
+ });
1040
+ const chunkedTotalNumber = chunkedTotal ? Number(chunkedTotal) : 0;
1041
+ const regularTotalNumber = regularTotal ? Number(regularTotal) : 0;
1042
+ const totalWrites = chunkedTotalNumber > 0 ? chunkedTotalNumber : regularTotalNumber;
1043
+ return {
1044
+ data: totalWrites > 0 ? totalWrites : void 0,
1045
+ isLoading: chunkedLoading || regularLoading,
1046
+ error: chunkedTotalNumber === 0 && regularTotalNumber === 0 ? chunkedError || regularError : void 0
1047
+ };
1048
+ }
1049
+ var MAX_XML_DEPTH = 3;
1050
+ var CONCURRENT_XML_FETCHES = 3;
1051
+ function assembleXmlData(metadata, chunks, references) {
1052
+ let result = metadata;
1053
+ references.forEach((ref, index) => {
1054
+ const chunkData2 = chunks[index];
1055
+ if (chunkData2) {
1056
+ const indexAttr = ref.index !== void 0 ? ` i="${ref.index}"` : "";
1057
+ const operatorAttr = ref.operator ? ` o="${ref.operator}"` : "";
1058
+ const sourceAttr = ref.source ? ` s="${ref.source}"` : "";
1059
+ const xmlTag = `<net k="${ref.hash}" v="${ref.version}"${indexAttr}${operatorAttr}${sourceAttr} />`;
1060
+ result = result.replace(xmlTag, chunkData2);
1061
+ }
1062
+ });
1063
+ return result;
1064
+ }
1065
+ async function fetchFromDirectStorage(reference, operator, client) {
1066
+ const functionName = reference.index !== void 0 ? "getValueAtIndex" : "get";
1067
+ const args = reference.index !== void 0 ? [reference.hash, operator, reference.index] : [reference.hash, operator];
1068
+ const result = await readContract(client, {
1069
+ address: STORAGE_CONTRACT.address,
1070
+ abi: STORAGE_CONTRACT.abi,
1071
+ functionName,
1072
+ args
1073
+ });
1074
+ const content = hexToString(result[1] || "");
1075
+ return content;
1076
+ }
1077
+ async function fetchFromChunkedStorage(reference, operator, client) {
1078
+ const contract = CHUNKED_STORAGE_READER_CONTRACT;
1079
+ const functionName = reference.index !== void 0 ? "getMetadataAtIndex" : "getMetadata";
1080
+ const chunksFunctionName = reference.index !== void 0 ? "getChunksAtIndex" : "getChunks";
1081
+ const metadataArgs = reference.index !== void 0 ? [reference.hash, operator, reference.index] : [reference.hash, operator];
1082
+ const metadata = await readContract(client, {
1083
+ abi: contract.abi,
1084
+ address: contract.address,
1085
+ functionName,
1086
+ args: metadataArgs
1087
+ });
1088
+ const chunkCount = metadata[0];
1089
+ if (chunkCount === 0) return "";
1090
+ const chunksArgs = reference.index !== void 0 ? [reference.hash, operator, 0, chunkCount, reference.index] : [reference.hash, operator, 0, chunkCount];
1091
+ const chunks = await readContract(client, {
1092
+ abi: contract.abi,
1093
+ address: contract.address,
1094
+ functionName: chunksFunctionName,
1095
+ args: chunksArgs
1096
+ });
1097
+ const assembledResult = assembleChunks(chunks);
1098
+ const content = assembledResult || "";
1099
+ return content;
1100
+ }
1101
+ async function fetchSingleChunk(reference, defaultOperator, inheritedOperator, client) {
1102
+ const effectiveOperator = reference.operator || inheritedOperator || defaultOperator;
1103
+ if (reference.source === "d") {
1104
+ return await fetchFromDirectStorage(reference, effectiveOperator, client);
1105
+ } else {
1106
+ return await fetchFromChunkedStorage(reference, effectiveOperator, client);
1107
+ }
1108
+ }
1109
+ async function resolveXmlRecursive(content, defaultOperator, client, maxDepth, visited = /* @__PURE__ */ new Set(), inheritedOperator) {
1110
+ if (maxDepth <= 0) {
1111
+ return content;
1112
+ }
1113
+ if (!containsXmlReferences(content)) {
1114
+ return content;
1115
+ }
1116
+ const references = parseNetReferences(content);
1117
+ if (references.length === 0) {
1118
+ return content;
1119
+ }
1120
+ const resolvedChunks = [];
1121
+ for (let batchStart = 0; batchStart < references.length; batchStart += CONCURRENT_XML_FETCHES) {
1122
+ const batchEnd = Math.min(
1123
+ batchStart + CONCURRENT_XML_FETCHES,
1124
+ references.length
1125
+ );
1126
+ const batch = references.slice(batchStart, batchEnd);
1127
+ const batchResults = await Promise.all(
1128
+ batch.map(async (ref, batchIndex) => {
1129
+ const index = batchStart + batchIndex;
1130
+ const effectiveOperator = ref.operator || inheritedOperator || defaultOperator;
1131
+ const refKey = getReferenceKey(
1132
+ { ...ref, operator: effectiveOperator },
1133
+ defaultOperator
1134
+ );
1135
+ if (visited.has(refKey)) {
1136
+ console.warn(
1137
+ `[resolveXmlRecursive] Circular reference detected: ${refKey}`
1138
+ );
1139
+ return `[Circular: ${refKey}]`;
1140
+ }
1141
+ const newVisited = new Set(visited);
1142
+ newVisited.add(refKey);
1143
+ try {
1144
+ const chunkContent = await fetchSingleChunk(
1145
+ ref,
1146
+ defaultOperator,
1147
+ inheritedOperator,
1148
+ client
1149
+ );
1150
+ const resolvedContent = await resolveXmlRecursive(
1151
+ chunkContent,
1152
+ defaultOperator,
1153
+ client,
1154
+ maxDepth - 1,
1155
+ newVisited,
1156
+ effectiveOperator
1157
+ // Pass the effective operator to children
1158
+ );
1159
+ return resolvedContent;
1160
+ } catch (error) {
1161
+ console.error(
1162
+ `[resolveXmlRecursive] Failed to fetch/resolve chunk ${index}:`,
1163
+ error
1164
+ );
1165
+ return "";
1166
+ }
1167
+ })
1168
+ );
1169
+ resolvedChunks.push(...batchResults);
1170
+ }
1171
+ const assembled = assembleXmlData(content, resolvedChunks, references);
1172
+ return assembled;
1173
+ }
1174
+ function useXmlStorage({
1175
+ chainId,
1176
+ key,
1177
+ operatorAddress,
1178
+ skipXmlParsing = false,
1179
+ enabled = true,
1180
+ content,
1181
+ index,
1182
+ keyFormat,
1183
+ useRouter,
1184
+ returnFormat = "object",
1185
+ outputFormat = "hex"
1186
+ }) {
1187
+ const isPreviewMode = !!content;
1188
+ const returnAsTuple = returnFormat === "tuple";
1189
+ const outputAsString = outputFormat === "string";
1190
+ const {
1191
+ data: metadata,
1192
+ isLoading: metadataLoading,
1193
+ error: metadataError
1194
+ } = useStorage({
1195
+ chainId,
1196
+ key: key || "",
1197
+ operatorAddress,
1198
+ enabled: enabled && !isPreviewMode,
1199
+ index,
1200
+ // Pass index to useStorage for historical versions
1201
+ keyFormat,
1202
+ // Pass keyFormat through
1203
+ useRouter,
1204
+ // Pass useRouter through to enable router path
1205
+ outputFormat: "string"
1206
+ // Always get plain string from useStorage, then convert based on our outputFormat
1207
+ });
1208
+ const metadataString = useMemo(() => {
1209
+ if (skipXmlParsing) return "";
1210
+ if (isPreviewMode) return content || "";
1211
+ if (!metadata?.[1]) return "";
1212
+ return metadata[1];
1213
+ }, [skipXmlParsing, isPreviewMode, content, metadata]);
1214
+ useMemo(() => {
1215
+ if (!metadataString) return [];
1216
+ return parseNetReferences(metadataString);
1217
+ }, [metadataString]);
1218
+ const [chunks, setChunks] = useState([]);
1219
+ const [chunksLoading, setChunksLoading] = useState(false);
1220
+ const [chunksError, setChunksError] = useState();
1221
+ useAsyncEffect(async () => {
1222
+ if (skipXmlParsing || !metadataString) {
1223
+ setChunks([]);
1224
+ setChunksLoading(false);
1225
+ return;
1226
+ }
1227
+ if (!containsXmlReferences(metadataString)) {
1228
+ setChunks([]);
1229
+ setChunksLoading(false);
1230
+ return;
1231
+ }
1232
+ setChunksLoading(true);
1233
+ setChunksError(void 0);
1234
+ try {
1235
+ const client = getPublicClient({ chainId });
1236
+ if (!client) {
1237
+ throw new Error(`Chain not found for chainId: ${chainId}`);
1238
+ }
1239
+ const resolved = await resolveXmlRecursive(
1240
+ metadataString,
1241
+ operatorAddress,
1242
+ client,
1243
+ MAX_XML_DEPTH,
1244
+ /* @__PURE__ */ new Set()
1245
+ );
1246
+ setChunks([resolved]);
1247
+ } catch (error) {
1248
+ console.error("[useXmlStorage] Error in recursive resolution:", error);
1249
+ setChunksError(error);
1250
+ setChunks([]);
1251
+ } finally {
1252
+ setChunksLoading(false);
1253
+ }
1254
+ }, [metadataString, operatorAddress, chainId, skipXmlParsing]);
1255
+ const assembledData = useMemo(() => {
1256
+ if (skipXmlParsing || !metadataString || !chunks.length) return void 0;
1257
+ return chunks[0];
1258
+ }, [metadataString, chunks, skipXmlParsing]);
1259
+ const isXml = useMemo(() => {
1260
+ if (skipXmlParsing || !metadataString) return false;
1261
+ return containsXmlReferences(metadataString);
1262
+ }, [metadataString, skipXmlParsing]);
1263
+ if (returnAsTuple) {
1264
+ if (skipXmlParsing) {
1265
+ if (isPreviewMode) {
1266
+ const contentValue = content || "";
1267
+ return {
1268
+ data: contentValue ? outputAsString ? [metadata?.[0] || "", contentValue] : [
1269
+ metadata?.[0] || "",
1270
+ stringToHex(contentValue)
1271
+ ] : void 0,
1272
+ isLoading: metadataLoading,
1273
+ error: metadataError
1274
+ };
1275
+ } else {
1276
+ const dataValue = metadata?.[1];
1277
+ return {
1278
+ data: dataValue ? outputAsString ? [metadata?.[0] || "", dataValue] : [
1279
+ metadata?.[0] || "",
1280
+ stringToHex(dataValue)
1281
+ ] : void 0,
1282
+ isLoading: metadataLoading,
1283
+ error: metadataError
1284
+ };
1285
+ }
1286
+ }
1287
+ if (isXml) {
1288
+ if (!assembledData) {
1289
+ return {
1290
+ data: void 0,
1291
+ isLoading: metadataLoading || chunksLoading,
1292
+ error: metadataError || chunksError
1293
+ };
1294
+ }
1295
+ const hexData = stringToHex(assembledData);
1296
+ return {
1297
+ data: outputAsString ? [metadata?.[0] || "", assembledData] : [metadata?.[0] || "", hexData],
1298
+ isLoading: metadataLoading || chunksLoading,
1299
+ error: metadataError || chunksError
1300
+ };
1301
+ } else {
1302
+ if (!metadata) {
1303
+ return {
1304
+ data: void 0,
1305
+ isLoading: metadataLoading,
1306
+ error: metadataError
1307
+ };
1308
+ }
1309
+ const dataValue = metadata[1];
1310
+ const returnValue = dataValue ? outputAsString ? [metadata[0], dataValue] : [
1311
+ metadata[0],
1312
+ stringToHex(dataValue)
1313
+ ] : void 0;
1314
+ return {
1315
+ data: returnValue,
1316
+ isLoading: metadataLoading,
1317
+ error: metadataError
1318
+ };
1319
+ }
1320
+ }
1321
+ if (skipXmlParsing) {
1322
+ return {
1323
+ data: isPreviewMode ? content || "" : metadata?.[1] || "",
1324
+ // metadata[1] is already a plain string
1325
+ filename: metadata?.[0] || "",
1326
+ isLoading: metadataLoading,
1327
+ error: metadataError,
1328
+ isXml: false
1329
+ };
1330
+ }
1331
+ return {
1332
+ data: isXml ? assembledData : isPreviewMode ? content || "" : metadata?.[1] || "",
1333
+ // metadata[1] is already a plain string
1334
+ filename: metadata?.[0] || "",
1335
+ isLoading: metadataLoading || isXml && chunksLoading,
1336
+ error: metadataError || chunksError,
1337
+ isXml
1338
+ };
1339
+ }
1340
+ var BATCH_SIZE2 = 2;
1341
+ function useStorageFromRouter({
1342
+ chainId,
1343
+ storageKey,
1344
+ operatorAddress,
1345
+ enabled = true
1346
+ }) {
1347
+ const [assembledData, setAssembledData] = useState();
1348
+ const [isChunkLoading, setIsChunkLoading] = useState(false);
1349
+ const [chunkError, setChunkError] = useState();
1350
+ const {
1351
+ data: routerResult,
1352
+ isLoading: routerLoading,
1353
+ error: routerError
1354
+ } = useReadContract({
1355
+ abi: STORAGE_ROUTER_CONTRACT.abi,
1356
+ address: STORAGE_ROUTER_CONTRACT.address,
1357
+ functionName: "get",
1358
+ args: [storageKey, operatorAddress],
1359
+ chainId,
1360
+ query: {
1361
+ enabled: enabled && !!operatorAddress
1362
+ }
1363
+ });
1364
+ useEffect(() => {
1365
+ async function processResult() {
1366
+ if (!routerResult || routerLoading || routerError) {
1367
+ return;
1368
+ }
1369
+ const [isChunkedStorage, text, data] = routerResult;
1370
+ if (!isChunkedStorage) {
1371
+ setAssembledData([text, data]);
1372
+ return;
1373
+ }
1374
+ setIsChunkLoading(true);
1375
+ setChunkError(void 0);
1376
+ try {
1377
+ const [chunkCount] = decodeAbiParameters(
1378
+ [{ type: "uint8" }],
1379
+ data
1380
+ );
1381
+ if (chunkCount === 0) {
1382
+ setAssembledData(void 0);
1383
+ return;
1384
+ }
1385
+ const allChunks = await fetchChunksInBatches(
1386
+ Number(chunkCount),
1387
+ operatorAddress,
1388
+ chainId,
1389
+ storageKey
1390
+ );
1391
+ const assembledString = assembleChunks(allChunks);
1392
+ if (assembledString === void 0) {
1393
+ setAssembledData(void 0);
1394
+ } else {
1395
+ const hexData = stringToHex(assembledString);
1396
+ setAssembledData([text, hexData]);
1397
+ }
1398
+ } catch (error) {
1399
+ setChunkError(error);
1400
+ } finally {
1401
+ setIsChunkLoading(false);
1402
+ }
1403
+ }
1404
+ processResult();
1405
+ }, [
1406
+ routerResult,
1407
+ routerLoading,
1408
+ routerError,
1409
+ operatorAddress,
1410
+ chainId,
1411
+ storageKey
1412
+ ]);
1413
+ return {
1414
+ data: assembledData,
1415
+ isLoading: routerLoading || isChunkLoading,
1416
+ error: routerError || chunkError
1417
+ };
1418
+ }
1419
+ async function fetchChunksInBatches(chunkCount, operatorAddress, chainId, storageKey) {
1420
+ const client = getPublicClient({ chainId });
1421
+ if (!client) {
1422
+ throw new Error(`Chain not found for chainId: ${chainId}`);
1423
+ }
1424
+ const allChunks = [];
1425
+ for (let start = 0; start < chunkCount; start += BATCH_SIZE2) {
1426
+ const end = Math.min(start + BATCH_SIZE2, chunkCount);
1427
+ const batch = await readContract(client, {
1428
+ abi: CHUNKED_STORAGE_CONTRACT.abi,
1429
+ address: CHUNKED_STORAGE_CONTRACT.address,
1430
+ functionName: "getChunks",
1431
+ args: [storageKey, operatorAddress, start, end]
1432
+ });
1433
+ allChunks.push(...batch);
1434
+ }
1435
+ return allChunks;
1436
+ }
1437
+
1438
+ // src/client/storage.ts
1439
+ function getStorageReadConfig(params) {
1440
+ const { chainId, key, operator, keyFormat } = params;
1441
+ const storageKeyBytes = getStorageKeyBytes(key, keyFormat);
1442
+ return {
1443
+ abi: STORAGE_CONTRACT.abi,
1444
+ address: STORAGE_CONTRACT.address,
1445
+ functionName: "get",
1446
+ args: [storageKeyBytes, operator],
1447
+ chainId
1448
+ };
1449
+ }
1450
+ function getStorageValueAtIndexReadConfig(params) {
1451
+ const { chainId, key, operator, index, keyFormat } = params;
1452
+ const storageKeyBytes = getStorageKeyBytes(key, keyFormat);
1453
+ return {
1454
+ abi: STORAGE_CONTRACT.abi,
1455
+ address: STORAGE_CONTRACT.address,
1456
+ functionName: "getValueAtIndex",
1457
+ args: [storageKeyBytes, operator, index],
1458
+ chainId
1459
+ };
1460
+ }
1461
+ function getStorageTotalWritesReadConfig(params) {
1462
+ const { chainId, key, operator, keyFormat } = params;
1463
+ const storageKeyBytes = getStorageKeyBytes(key, keyFormat);
1464
+ return {
1465
+ abi: STORAGE_CONTRACT.abi,
1466
+ address: STORAGE_CONTRACT.address,
1467
+ functionName: "getTotalWrites",
1468
+ args: [storageKeyBytes, operator],
1469
+ chainId
1470
+ };
1471
+ }
1472
+ function getStorageBulkGetReadConfig(params) {
1473
+ const { chainId, keys, safe = false, keyFormat } = params;
1474
+ const contract = safe ? SAFE_STORAGE_READER_CONTRACT : STORAGE_CONTRACT;
1475
+ const bulkKeys = keys.map((k) => ({
1476
+ key: getStorageKeyBytes(k.key, k.keyFormat ?? keyFormat),
1477
+ operator: k.operator
1478
+ }));
1479
+ return {
1480
+ abi: contract.abi,
1481
+ address: contract.address,
1482
+ functionName: "bulkGet",
1483
+ args: [bulkKeys],
1484
+ chainId
1485
+ };
1486
+ }
1487
+ function getStorageRouterReadConfig(params) {
1488
+ const { chainId, key, operator, keyFormat } = params;
1489
+ const storageKeyBytes = getStorageKeyBytes(key, keyFormat);
1490
+ return {
1491
+ abi: STORAGE_ROUTER_CONTRACT.abi,
1492
+ address: STORAGE_ROUTER_CONTRACT.address,
1493
+ functionName: "get",
1494
+ args: [storageKeyBytes, operator],
1495
+ chainId
1496
+ };
1497
+ }
1498
+
1499
+ // src/client/chunkedStorage.ts
1500
+ function getChunkedStorageMetadataReadConfig(params) {
1501
+ const { chainId, key, operator, index, keyFormat } = params;
1502
+ const storageKeyBytes = getStorageKeyBytes(key, keyFormat);
1503
+ const functionName = index !== void 0 ? "getMetadataAtIndex" : "getMetadata";
1504
+ const args = index !== void 0 ? [storageKeyBytes, operator, index] : [storageKeyBytes, operator];
1505
+ return {
1506
+ abi: CHUNKED_STORAGE_READER_CONTRACT.abi,
1507
+ address: CHUNKED_STORAGE_READER_CONTRACT.address,
1508
+ functionName,
1509
+ args,
1510
+ chainId
1511
+ };
1512
+ }
1513
+ function getChunkedStorageChunksReadConfig(params) {
1514
+ const { chainId, key, operator, start, end, index, keyFormat } = params;
1515
+ const storageKeyBytes = getStorageKeyBytes(key, keyFormat);
1516
+ const functionName = index !== void 0 ? "getChunksAtIndex" : "getChunks";
1517
+ const args = index !== void 0 ? [storageKeyBytes, operator, start, end, index] : [storageKeyBytes, operator, start, end];
1518
+ return {
1519
+ abi: CHUNKED_STORAGE_READER_CONTRACT.abi,
1520
+ address: CHUNKED_STORAGE_READER_CONTRACT.address,
1521
+ functionName,
1522
+ args,
1523
+ chainId
1524
+ };
1525
+ }
1526
+ function getChunkedStorageTotalWritesReadConfig(params) {
1527
+ const { chainId, key, operator, keyFormat } = params;
1528
+ const storageKeyBytes = getStorageKeyBytes(key, keyFormat);
1529
+ return {
1530
+ abi: CHUNKED_STORAGE_READER_CONTRACT.abi,
1531
+ address: CHUNKED_STORAGE_READER_CONTRACT.address,
1532
+ functionName: "getTotalWrites",
1533
+ args: [storageKeyBytes, operator],
1534
+ chainId
1535
+ };
1536
+ }
1537
+ var MAX_CHUNKS = 255;
1538
+ var OPTIMAL_CHUNK_SIZE = 80 * 1e3;
1539
+ function chunkData(data, chunkSize = OPTIMAL_CHUNK_SIZE) {
1540
+ const chunks = [];
1541
+ for (let i = 0; i < data.length; i += chunkSize) {
1542
+ chunks.push(data.slice(i, i + chunkSize));
1543
+ }
1544
+ return chunks;
1545
+ }
1546
+ function generateXmlMetadata(chunkHashes, historicalIndex, operatorAddress) {
1547
+ return chunkHashes.map((hash) => {
1548
+ const operator = operatorAddress.toLowerCase();
1549
+ return `<net k="${hash}" v="0.0.1" i="${historicalIndex}" o="${operator}" />`;
1550
+ }).join("");
1551
+ }
1552
+ function generateXmlMetadataWithSource(chunkHashes, historicalIndex, operatorAddress, source) {
1553
+ return chunkHashes.map((hash) => {
1554
+ const operator = operatorAddress.toLowerCase();
1555
+ const sourceAttr = source ? ` s="${source}"` : "";
1556
+ return `<net k="${hash}" v="0.0.1" i="${historicalIndex}" o="${operator}"${sourceAttr} />`;
1557
+ }).join("");
1558
+ }
1559
+ function validateDataSize(chunks) {
1560
+ if (chunks.length === 0) {
1561
+ return { valid: false, error: "No chunks generated" };
1562
+ }
1563
+ if (chunks.length > MAX_CHUNKS) {
1564
+ return {
1565
+ valid: false,
1566
+ error: `Too many chunks: ${chunks.length} exceeds maximum of ${MAX_CHUNKS}`
1567
+ };
1568
+ }
1569
+ return { valid: true };
1570
+ }
1571
+ function computeTopLevelHash(chunkHashes) {
1572
+ return keccak256HashString(chunkHashes.join(""));
1573
+ }
1574
+ function processDataForStorage(data, operatorAddress, storageKey) {
1575
+ const chunks = chunkData(data);
1576
+ const validation = validateDataSize(chunks);
1577
+ if (!validation.valid) {
1578
+ return {
1579
+ chunks: [],
1580
+ chunkHashes: [],
1581
+ xmlMetadata: "",
1582
+ topLevelHash: "",
1583
+ valid: false,
1584
+ error: validation.error
1585
+ };
1586
+ }
1587
+ const chunkHashes = chunks.map((chunk) => keccak256HashString(chunk));
1588
+ const xmlMetadata = generateXmlMetadata(chunkHashes, 0, operatorAddress);
1589
+ const topLevelHash = storageKey || computeTopLevelHash(chunkHashes);
1590
+ return {
1591
+ chunks,
1592
+ chunkHashes,
1593
+ xmlMetadata,
1594
+ topLevelHash,
1595
+ valid: true
1596
+ };
1597
+ }
1598
+
1599
+ // src/client/StorageClient.ts
1600
+ var StorageClient = class {
1601
+ constructor(params) {
1602
+ this.client = getPublicClient({
1603
+ chainId: params.chainId,
1604
+ rpcUrl: params.overrides?.rpcUrls
1605
+ });
1606
+ this.chainId = params.chainId;
1607
+ }
1608
+ /**
1609
+ * Get storage value for a key and operator (latest version)
1610
+ */
1611
+ async get(params) {
1612
+ const config = getStorageReadConfig({
1613
+ chainId: this.chainId,
1614
+ key: params.key,
1615
+ operator: params.operator,
1616
+ keyFormat: params.keyFormat
1617
+ });
1618
+ try {
1619
+ const result = await readContract(this.client, config);
1620
+ return result;
1621
+ } catch {
1622
+ return null;
1623
+ }
1624
+ }
1625
+ /**
1626
+ * Get storage value at a specific historical index
1627
+ */
1628
+ async getValueAtIndex(params) {
1629
+ const config = getStorageValueAtIndexReadConfig({
1630
+ chainId: this.chainId,
1631
+ key: params.key,
1632
+ operator: params.operator,
1633
+ index: params.index,
1634
+ keyFormat: params.keyFormat
1635
+ });
1636
+ try {
1637
+ const result = await readContract(this.client, config);
1638
+ return result;
1639
+ } catch {
1640
+ return null;
1641
+ }
1642
+ }
1643
+ /**
1644
+ * Get total number of writes (versions) for a key-operator pair
1645
+ * Tries ChunkedStorageReader first, then Storage
1646
+ */
1647
+ async getTotalWrites(params) {
1648
+ try {
1649
+ const config = getChunkedStorageTotalWritesReadConfig({
1650
+ chainId: this.chainId,
1651
+ key: params.key,
1652
+ operator: params.operator,
1653
+ keyFormat: params.keyFormat
1654
+ });
1655
+ const count = await readContract(this.client, config);
1656
+ return Number(count);
1657
+ } catch {
1658
+ try {
1659
+ const config = getStorageTotalWritesReadConfig({
1660
+ chainId: this.chainId,
1661
+ key: params.key,
1662
+ operator: params.operator,
1663
+ keyFormat: params.keyFormat
1664
+ });
1665
+ const count = await readContract(this.client, config);
1666
+ return Number(count);
1667
+ } catch {
1668
+ return 0;
1669
+ }
1670
+ }
1671
+ }
1672
+ /**
1673
+ * Bulk get storage values
1674
+ */
1675
+ async bulkGet(params) {
1676
+ const config = getStorageBulkGetReadConfig({
1677
+ chainId: this.chainId,
1678
+ keys: params.keys,
1679
+ safe: params.safe,
1680
+ keyFormat: params.keyFormat
1681
+ });
1682
+ try {
1683
+ const results = await readContract(this.client, config);
1684
+ return results.map((r) => ({
1685
+ text: r[0],
1686
+ value: r[1]
1687
+ }));
1688
+ } catch {
1689
+ return [];
1690
+ }
1691
+ }
1692
+ /**
1693
+ * Get storage value via StorageRouter (latest version)
1694
+ * Returns data with storage type indication
1695
+ */
1696
+ async getViaRouter(params) {
1697
+ const config = getStorageRouterReadConfig({
1698
+ chainId: this.chainId,
1699
+ key: params.key,
1700
+ operator: params.operator,
1701
+ keyFormat: params.keyFormat
1702
+ });
1703
+ try {
1704
+ const result = await readContract(this.client, config);
1705
+ const [isChunkedStorage, text, data] = result;
1706
+ if (isChunkedStorage) {
1707
+ const [chunkCount] = decodeAbiParameters([{ type: "uint8" }], data);
1708
+ if (chunkCount === 0) {
1709
+ return { isChunkedStorage: true, text, data: "" };
1710
+ }
1711
+ const chunks = await this.getChunked({
1712
+ key: params.key,
1713
+ operator: params.operator,
1714
+ start: 0,
1715
+ end: Number(chunkCount),
1716
+ keyFormat: params.keyFormat
1717
+ });
1718
+ const assembled = assembleChunks(chunks);
1719
+ return {
1720
+ isChunkedStorage: true,
1721
+ text,
1722
+ data: assembled || ""
1723
+ };
1724
+ }
1725
+ return {
1726
+ isChunkedStorage: false,
1727
+ text,
1728
+ data: hexToString(data)
1729
+ };
1730
+ } catch {
1731
+ return null;
1732
+ }
1733
+ }
1734
+ /**
1735
+ * Get chunked storage metadata
1736
+ */
1737
+ async getChunkedMetadata(params) {
1738
+ const config = getChunkedStorageMetadataReadConfig({
1739
+ chainId: this.chainId,
1740
+ key: params.key,
1741
+ operator: params.operator,
1742
+ index: params.index,
1743
+ keyFormat: params.keyFormat
1744
+ });
1745
+ try {
1746
+ const result = await readContract(this.client, config);
1747
+ const [chunkCount, originalText] = result;
1748
+ return { chunkCount, originalText };
1749
+ } catch {
1750
+ return null;
1751
+ }
1752
+ }
1753
+ /**
1754
+ * Get chunked storage chunks
1755
+ */
1756
+ async getChunked(params) {
1757
+ const config = getChunkedStorageChunksReadConfig({
1758
+ chainId: this.chainId,
1759
+ key: params.key,
1760
+ operator: params.operator,
1761
+ start: params.start,
1762
+ end: params.end,
1763
+ index: params.index,
1764
+ keyFormat: params.keyFormat
1765
+ });
1766
+ try {
1767
+ const chunks = await readContract(this.client, config);
1768
+ return chunks;
1769
+ } catch {
1770
+ return [];
1771
+ }
1772
+ }
1773
+ /**
1774
+ * Get chunked storage at a specific historical index
1775
+ */
1776
+ async getChunkedAtIndex(params) {
1777
+ return this.getChunked({
1778
+ ...params,
1779
+ index: params.index
1780
+ });
1781
+ }
1782
+ /**
1783
+ * Get all storage keys for an operator using Net contract
1784
+ */
1785
+ async getForOperator(params) {
1786
+ const netContract = getNetContract(this.chainId);
1787
+ const totalCount = await readContract(this.client, {
1788
+ abi: netContract.abi,
1789
+ address: netContract.address,
1790
+ functionName: "getTotalMessagesForAppUserCount",
1791
+ args: [STORAGE_CONTRACT.address, params.operator]
1792
+ });
1793
+ const totalCountNumber = Number(totalCount);
1794
+ if (totalCountNumber === 0) {
1795
+ return [];
1796
+ }
1797
+ const messages = await readContract(this.client, {
1798
+ abi: netContract.abi,
1799
+ address: netContract.address,
1800
+ functionName: "getMessagesInRangeForAppUser",
1801
+ args: [0, totalCountNumber, STORAGE_CONTRACT.address, params.operator]
1802
+ });
1803
+ return messages.map((msg) => [
1804
+ msg.topic,
1805
+ msg.text,
1806
+ Number(msg.timestamp),
1807
+ msg.data
1808
+ ]);
1809
+ }
1810
+ /**
1811
+ * Get storage value for operator and key
1812
+ */
1813
+ async getForOperatorAndKey(params) {
1814
+ const storageKeyBytes = getStorageKeyBytes(
1815
+ params.key,
1816
+ params.keyFormat
1817
+ );
1818
+ try {
1819
+ const result = await readContract(this.client, {
1820
+ abi: STORAGE_CONTRACT.abi,
1821
+ address: STORAGE_CONTRACT.address,
1822
+ functionName: "getForOperatorAndKey",
1823
+ args: [params.operator, storageKeyBytes]
1824
+ });
1825
+ return result;
1826
+ } catch {
1827
+ return null;
1828
+ }
1829
+ }
1830
+ /**
1831
+ * Read storage data with XML resolution
1832
+ */
1833
+ async readStorageData(params) {
1834
+ let text;
1835
+ let data;
1836
+ if (params.index !== void 0) {
1837
+ const chunkedMeta = await this.getChunkedMetadata({
1838
+ key: params.key,
1839
+ operator: params.operator,
1840
+ index: params.index,
1841
+ keyFormat: params.keyFormat
1842
+ });
1843
+ if (chunkedMeta && chunkedMeta.chunkCount > 0) {
1844
+ text = chunkedMeta.originalText;
1845
+ const chunks = await this.getChunked({
1846
+ key: params.key,
1847
+ operator: params.operator,
1848
+ start: 0,
1849
+ end: chunkedMeta.chunkCount,
1850
+ index: params.index,
1851
+ keyFormat: params.keyFormat
1852
+ });
1853
+ const assembled = assembleChunks(chunks);
1854
+ data = assembled || "";
1855
+ } else {
1856
+ const result = await this.getValueAtIndex({
1857
+ key: params.key,
1858
+ operator: params.operator,
1859
+ index: params.index,
1860
+ keyFormat: params.keyFormat
1861
+ });
1862
+ if (!result) {
1863
+ throw new Error("StoredDataNotFound");
1864
+ }
1865
+ [text, data] = result;
1866
+ data = hexToString(data);
1867
+ }
1868
+ } else {
1869
+ const result = await this.getViaRouter({
1870
+ key: params.key,
1871
+ operator: params.operator,
1872
+ keyFormat: params.keyFormat
1873
+ });
1874
+ if (!result) {
1875
+ throw new Error("StoredDataNotFound");
1876
+ }
1877
+ result.isChunkedStorage;
1878
+ text = result.text;
1879
+ data = result.data;
1880
+ }
1881
+ const isXml = containsXmlReferences(data);
1882
+ if (isXml) {
1883
+ const resolvedData = await resolveXmlRecursive(
1884
+ data,
1885
+ params.operator,
1886
+ this.client,
1887
+ 3,
1888
+ // MAX_XML_DEPTH
1889
+ /* @__PURE__ */ new Set()
1890
+ );
1891
+ return { text, data: resolvedData, isXml: true };
1892
+ }
1893
+ return { text, data, isXml: false };
1894
+ }
1895
+ /**
1896
+ * Read chunked storage data with decompression
1897
+ */
1898
+ async readChunkedStorage(params) {
1899
+ const metadata = await this.getChunkedMetadata({
1900
+ key: params.key,
1901
+ operator: params.operator,
1902
+ index: params.index,
1903
+ keyFormat: params.keyFormat
1904
+ });
1905
+ if (!metadata) {
1906
+ throw new Error("ChunkedStorage metadata not found");
1907
+ }
1908
+ if (metadata.chunkCount === 0) {
1909
+ return { text: metadata.originalText, data: "" };
1910
+ }
1911
+ const chunks = await this.getChunked({
1912
+ key: params.key,
1913
+ operator: params.operator,
1914
+ start: 0,
1915
+ end: metadata.chunkCount,
1916
+ index: params.index,
1917
+ keyFormat: params.keyFormat
1918
+ });
1919
+ const assembled = assembleChunks(chunks);
1920
+ return {
1921
+ text: metadata.originalText,
1922
+ data: assembled || ""
1923
+ };
1924
+ }
1925
+ /**
1926
+ * Validate storage parameters
1927
+ */
1928
+ validateStorageParams(params) {
1929
+ if (!params.key || typeof params.key === "string" && params.key.length === 0) {
1930
+ throw new Error("Storage key cannot be empty");
1931
+ }
1932
+ if (params.chunks && params.chunks.length === 0) {
1933
+ throw new Error("Chunks array cannot be empty");
1934
+ }
1935
+ if (params.chunks && params.chunks.length > 255) {
1936
+ throw new Error(`Too many chunks: ${params.chunks.length} exceeds maximum of 255`);
1937
+ }
1938
+ }
1939
+ /**
1940
+ * Prepare transaction configs for storing XML chunks in ChunkedStorage backend.
1941
+ * Each XML chunk is compressed and chunked into 20KB ChunkedStorage chunks.
1942
+ */
1943
+ prepareXmlChunksForChunkedStorage(params) {
1944
+ const chunkedStorageHashes = [];
1945
+ const transactionConfigs = [];
1946
+ for (const xmlChunk of params.xmlChunks) {
1947
+ const chunks = chunkDataForStorage(xmlChunk);
1948
+ const chunkedHash = keccak256HashString(xmlChunk + params.operatorAddress);
1949
+ chunkedStorageHashes.push(chunkedHash);
1950
+ const config = this.prepareChunkedPut({
1951
+ key: chunkedHash,
1952
+ text: "",
1953
+ chunks
1954
+ });
1955
+ transactionConfigs.push(config);
1956
+ }
1957
+ const xmlMetadata = generateXmlMetadata(
1958
+ chunkedStorageHashes,
1959
+ 0,
1960
+ params.operatorAddress
1961
+ );
1962
+ return {
1963
+ transactionConfigs,
1964
+ chunkedStorageHashes,
1965
+ xmlMetadata
1966
+ };
1967
+ }
1968
+ /**
1969
+ * Prepare transaction config for storing a single value in Storage contract.
1970
+ */
1971
+ preparePut(params) {
1972
+ this.validateStorageParams({ key: params.key });
1973
+ const keyBytes32 = getStorageKeyBytes(params.key, params.keyFormat);
1974
+ const valueHex = normalizeDataOrEmpty(params.value);
1975
+ return {
1976
+ to: STORAGE_CONTRACT.address,
1977
+ functionName: "put",
1978
+ args: [keyBytes32, params.text, valueHex],
1979
+ abi: STORAGE_CONTRACT.abi
1980
+ };
1981
+ }
1982
+ /**
1983
+ * Prepare transaction config for storing data in ChunkedStorage contract.
1984
+ */
1985
+ prepareChunkedPut(params) {
1986
+ this.validateStorageParams({ key: params.key, chunks: params.chunks });
1987
+ const keyBytes32 = getStorageKeyBytes(params.key, params.keyFormat);
1988
+ for (const chunk of params.chunks) {
1989
+ if (!chunk.startsWith("0x")) {
1990
+ throw new Error(`Invalid chunk format: ${chunk} must be a hex string`);
1991
+ }
1992
+ }
1993
+ return {
1994
+ to: CHUNKED_STORAGE_CONTRACT.address,
1995
+ functionName: "put",
1996
+ args: [keyBytes32, params.text, params.chunks],
1997
+ abi: CHUNKED_STORAGE_CONTRACT.abi
1998
+ };
1999
+ }
2000
+ /**
2001
+ * Prepare transaction config for bulk storage operations using Storage.bulkPut.
2002
+ */
2003
+ prepareBulkPut(params) {
2004
+ if (params.entries.length === 0) {
2005
+ throw new Error("Entries array cannot be empty");
2006
+ }
2007
+ const bulkEntries = params.entries.map((entry) => {
2008
+ this.validateStorageParams({ key: entry.key });
2009
+ const keyBytes32 = getStorageKeyBytes(entry.key, params.keyFormat);
2010
+ const valueHex = normalizeDataOrEmpty(entry.value);
2011
+ return {
2012
+ key: keyBytes32,
2013
+ text: entry.text,
2014
+ value: valueHex
2015
+ };
2016
+ });
2017
+ return {
2018
+ to: STORAGE_CONTRACT.address,
2019
+ functionName: "bulkPut",
2020
+ args: [bulkEntries],
2021
+ abi: STORAGE_CONTRACT.abi
2022
+ };
2023
+ }
2024
+ /**
2025
+ * Prepare transaction configs for XML storage (multiple transactions - metadata + chunks).
2026
+ */
2027
+ prepareXmlStorage(params) {
2028
+ const result = processDataForStorage(
2029
+ params.data,
2030
+ params.operatorAddress,
2031
+ params.storageKey
2032
+ );
2033
+ if (!result.valid) {
2034
+ throw new Error(result.error || "Failed to process data for storage");
2035
+ }
2036
+ const useChunkedStorageBackend = params.useChunkedStorageBackend !== false;
2037
+ if (useChunkedStorageBackend) {
2038
+ const chunkedResult = this.prepareXmlChunksForChunkedStorage({
2039
+ xmlChunks: result.chunks,
2040
+ operatorAddress: params.operatorAddress
2041
+ });
2042
+ const metadataConfig = this.preparePut({
2043
+ key: result.topLevelHash,
2044
+ text: params.filename || "",
2045
+ value: chunkedResult.xmlMetadata,
2046
+ keyFormat: params.keyFormat
2047
+ });
2048
+ return {
2049
+ transactionConfigs: [metadataConfig, ...chunkedResult.transactionConfigs],
2050
+ topLevelHash: result.topLevelHash,
2051
+ metadata: chunkedResult.xmlMetadata
2052
+ };
2053
+ } else {
2054
+ const chunkConfigs = result.chunkHashes.map(
2055
+ (hash, index) => this.preparePut({
2056
+ key: hash,
2057
+ text: "",
2058
+ value: result.chunks[index],
2059
+ keyFormat: params.keyFormat
2060
+ })
2061
+ );
2062
+ const metadataConfig = this.preparePut({
2063
+ key: result.topLevelHash,
2064
+ text: params.filename || "",
2065
+ value: result.xmlMetadata,
2066
+ keyFormat: params.keyFormat
2067
+ });
2068
+ return {
2069
+ transactionConfigs: [metadataConfig, ...chunkConfigs],
2070
+ topLevelHash: result.topLevelHash,
2071
+ metadata: result.xmlMetadata
2072
+ };
2073
+ }
2074
+ }
2075
+ };
2076
+
2077
+ export { CHUNKED_STORAGE_CONTRACT, CHUNKED_STORAGE_READER_CONTRACT, CONCURRENT_XML_FETCHES, MAX_XML_DEPTH, SAFE_STORAGE_READER_CONTRACT, STORAGE_CONTRACT, STORAGE_ROUTER_CONTRACT, StorageClient, assembleChunks, chunkData, chunkDataForStorage, computeTopLevelHash, containsXmlReferences, detectStorageType, encodeStorageKeyForUrl, formatStorageKeyForDisplay, generateStorageEmbedTag, generateXmlMetadata, generateXmlMetadataWithSource, getChunkCount, getReferenceKey, getStorageKeyBytes, parseNetReferences, processDataForStorage, resolveOperator, resolveXmlRecursive, shouldSuggestXmlStorage, useBulkStorage, useStorage, useStorageForOperator, useStorageForOperatorAndKey, useStorageFromRouter, useStorageTotalWrites, useXmlStorage, validateDataSize };
2078
+ //# sourceMappingURL=index.mjs.map
2079
+ //# sourceMappingURL=index.mjs.map