@shelby-protocol/cli 0.0.20 → 0.0.22
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/bin/entry.js +1838 -1289
- package/package.json +3 -3
package/bin/entry.js
CHANGED
|
@@ -505,196 +505,279 @@ import { Command } from "@commander-js/extra-typings";
|
|
|
505
505
|
|
|
506
506
|
// package.json
|
|
507
507
|
var name = "@shelby-protocol/cli";
|
|
508
|
-
var version = "0.0.
|
|
508
|
+
var version = "0.0.22";
|
|
509
509
|
|
|
510
510
|
// src/commands/account.tsx
|
|
511
511
|
import readline from "readline";
|
|
512
512
|
import { Account as Account3, AptosApiError as AptosApiError2, Ed25519PrivateKey as Ed25519PrivateKey4 } from "@aptos-labs/ts-sdk";
|
|
513
513
|
import { Option } from "@commander-js/extra-typings";
|
|
514
514
|
|
|
515
|
-
// ../../packages/sdk/dist/chunk-
|
|
516
|
-
import { AptosConfig, Network } from "@aptos-labs/ts-sdk";
|
|
517
|
-
var getAptosConfig = (config) => {
|
|
518
|
-
if (config.aptos) {
|
|
519
|
-
return new AptosConfig(config.aptos);
|
|
520
|
-
}
|
|
521
|
-
let aptosConfig;
|
|
522
|
-
switch (config.network) {
|
|
523
|
-
case "local":
|
|
524
|
-
aptosConfig = new AptosConfig({
|
|
525
|
-
network: Network.LOCAL
|
|
526
|
-
});
|
|
527
|
-
break;
|
|
528
|
-
case "shelbynet":
|
|
529
|
-
aptosConfig = new AptosConfig({
|
|
530
|
-
network: Network.SHELBYNET,
|
|
531
|
-
clientConfig: {
|
|
532
|
-
API_KEY: config.apiKey
|
|
533
|
-
}
|
|
534
|
-
});
|
|
535
|
-
break;
|
|
536
|
-
default:
|
|
537
|
-
throw new Error(`Unsupported network: ${config.network}`);
|
|
538
|
-
}
|
|
539
|
-
return aptosConfig;
|
|
540
|
-
};
|
|
541
|
-
|
|
542
|
-
// ../../packages/sdk/dist/chunk-EH4NYOCS.mjs
|
|
543
|
-
import { Network as Network2 } from "@aptos-labs/ts-sdk";
|
|
544
|
-
var NetworkToShelbyRPCBaseUrl = {
|
|
545
|
-
[Network2.SHELBYNET]: "https://api.shelbynet.shelby.xyz/shelby",
|
|
546
|
-
[Network2.DEVNET]: void 0,
|
|
547
|
-
[Network2.TESTNET]: void 0,
|
|
548
|
-
[Network2.MAINNET]: void 0,
|
|
549
|
-
[Network2.LOCAL]: void 0,
|
|
550
|
-
[Network2.CUSTOM]: void 0
|
|
551
|
-
};
|
|
552
|
-
var NetworkToShelbyBlobIndexerBaseUrl = {
|
|
553
|
-
[Network2.SHELBYNET]: "https://api.shelbynet.aptoslabs.com/nocode/v1/public/cmforrguw0042s601fn71f9l2/v1/graphql",
|
|
554
|
-
[Network2.DEVNET]: void 0,
|
|
555
|
-
[Network2.TESTNET]: void 0,
|
|
556
|
-
[Network2.MAINNET]: void 0,
|
|
557
|
-
[Network2.LOCAL]: void 0,
|
|
558
|
-
[Network2.CUSTOM]: void 0
|
|
559
|
-
};
|
|
560
|
-
var SHELBY_DEPLOYER = "0xc63d6a5efb0080a6029403131715bd4971e1149f7cc099aac69bb0069b3ddbf5";
|
|
561
|
-
var MICROPAYMENTS_DEPLOYER = "0xb42ac038b6dae86f6171e28e297aab9555ce09909445ec579e4ffe6b8d4d63bf";
|
|
562
|
-
var SHELBYUSD_TOKEN_NAME = "ShelbyUSD";
|
|
563
|
-
var SHELBYUSD_FA_METADATA_ADDRESS = "0x1b18363a9f1fe5e6ebf247daba5cc1c18052bb232efdc4c50f556053922d98e1";
|
|
564
|
-
|
|
565
|
-
// ../../packages/sdk/dist/chunk-NEBSHEBE.mjs
|
|
566
|
-
import {
|
|
567
|
-
AccountAddress,
|
|
568
|
-
Aptos,
|
|
569
|
-
Hex
|
|
570
|
-
} from "@aptos-labs/ts-sdk";
|
|
571
|
-
|
|
572
|
-
// ../../packages/sdk/dist/chunk-4MG4XGY4.mjs
|
|
515
|
+
// ../../packages/sdk/dist/chunk-OGKZ575S.mjs
|
|
573
516
|
import {
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
}
|
|
580
|
-
var
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
message ?? "Client has stale channel state. Use the returned micropayment to reset local state."
|
|
589
|
-
);
|
|
590
|
-
this.name = "StaleChannelStateError";
|
|
591
|
-
this.storedMicropayment = storedMicropayment;
|
|
592
|
-
}
|
|
593
|
-
/**
|
|
594
|
-
* Returns the stored micropayment as a base64-encoded string.
|
|
595
|
-
*/
|
|
596
|
-
toBase64() {
|
|
597
|
-
const bytes = this.storedMicropayment.bcsToBytes();
|
|
598
|
-
const binaryString = Array.from(
|
|
599
|
-
bytes,
|
|
600
|
-
(byte) => String.fromCharCode(byte)
|
|
601
|
-
).join("");
|
|
602
|
-
return btoa(binaryString);
|
|
603
|
-
}
|
|
604
|
-
/**
|
|
605
|
-
* Creates a StaleChannelStateError from a base64-encoded micropayment string.
|
|
606
|
-
*/
|
|
607
|
-
static fromBase64(base64, message) {
|
|
608
|
-
const binaryString = atob(base64);
|
|
609
|
-
const bytes = Uint8Array.from(binaryString, (char) => char.charCodeAt(0));
|
|
610
|
-
const micropayment = SenderBuiltMicropayment.deserialize(bytes);
|
|
611
|
-
return new _StaleChannelStateError(micropayment, message);
|
|
517
|
+
createDecoder,
|
|
518
|
+
createEncoder
|
|
519
|
+
} from "@shelby-protocol/clay-codes";
|
|
520
|
+
function getTotalChunks(config) {
|
|
521
|
+
return config.erasure_n;
|
|
522
|
+
}
|
|
523
|
+
var ClayErasureCodingProvider = class _ClayErasureCodingProvider {
|
|
524
|
+
config;
|
|
525
|
+
encoderCache;
|
|
526
|
+
decoderCache;
|
|
527
|
+
lastFunction;
|
|
528
|
+
constructor(config) {
|
|
529
|
+
this.config = config;
|
|
530
|
+
this.lastFunction = "none";
|
|
612
531
|
}
|
|
613
|
-
};
|
|
614
|
-
var SenderBuiltMicropayment = class _SenderBuiltMicropayment {
|
|
615
532
|
/**
|
|
616
|
-
*
|
|
617
|
-
*/
|
|
618
|
-
micropayment;
|
|
619
|
-
/**
|
|
620
|
-
* The sender's signature.
|
|
533
|
+
* Static factory method to create an initialized ClayErasureCodingProvider
|
|
621
534
|
*/
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
535
|
+
static async create(config) {
|
|
536
|
+
const provider = new _ClayErasureCodingProvider(config);
|
|
537
|
+
[provider.encoderCache, provider.decoderCache] = await Promise.all([
|
|
538
|
+
createEncoder({
|
|
539
|
+
n: getTotalChunks(config),
|
|
540
|
+
k: config.erasure_k,
|
|
541
|
+
d: config.erasure_d,
|
|
542
|
+
chunkSizeBytes: config.chunkSizeBytes
|
|
543
|
+
}),
|
|
544
|
+
createDecoder({
|
|
545
|
+
n: getTotalChunks(config),
|
|
546
|
+
k: config.erasure_k,
|
|
547
|
+
d: config.erasure_d,
|
|
548
|
+
chunkSizeBytes: config.chunkSizeBytes,
|
|
549
|
+
erasedChunksMask: 0
|
|
550
|
+
// No chunks erased initially; will be reconfigured on decode
|
|
551
|
+
})
|
|
552
|
+
]);
|
|
553
|
+
return provider;
|
|
635
554
|
}
|
|
636
|
-
|
|
637
|
-
|
|
555
|
+
encode(data) {
|
|
556
|
+
const { erasure_k, chunkSizeBytes } = this.config;
|
|
557
|
+
if (!this.encoderCache) {
|
|
558
|
+
throw new Error("Encoder cache is missing");
|
|
559
|
+
}
|
|
560
|
+
const systematicCapacity = erasure_k * chunkSizeBytes;
|
|
561
|
+
if (data.byteLength > systematicCapacity) {
|
|
562
|
+
throw new Error(
|
|
563
|
+
`Data size ${data.byteLength} bytes exceeds systematic capacity ${systematicCapacity} bytes (erasure_k=${erasure_k} * chunkSizeBytes=${chunkSizeBytes}).`
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
if (this.requiresPadding(data.length)) {
|
|
567
|
+
throw new Error(
|
|
568
|
+
`Data size ${data.length} bytes does not match systematic capacity ${systematicCapacity} bytes (erasure_k=${erasure_k} * chunkSizeBytes=${chunkSizeBytes}). Provide pre-padded data before encoding.`
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
this.lastFunction = "encoded";
|
|
572
|
+
return this.encoderCache.erasureCode(data);
|
|
638
573
|
}
|
|
639
|
-
|
|
640
|
-
|
|
574
|
+
decode(available, config) {
|
|
575
|
+
if (!this.decoderCache) {
|
|
576
|
+
throw new Error("Decoder cache is missing");
|
|
577
|
+
}
|
|
578
|
+
const { erasure_k, chunkSizeBytes } = this.config;
|
|
579
|
+
if (available.length < erasure_k) {
|
|
580
|
+
throw new Error(
|
|
581
|
+
`Insufficient available chunks: need at least ${erasure_k}, received ${available.length}.`
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
for (let i = 0; i < available.length; i++) {
|
|
585
|
+
const chunk = available[i];
|
|
586
|
+
if (chunk.length !== chunkSizeBytes) {
|
|
587
|
+
throw new Error(
|
|
588
|
+
`Chunk ${i} size ${chunk.length} bytes does not match expected chunkSizeBytes ${chunkSizeBytes}.`
|
|
589
|
+
);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
this.lastFunction = "decoded";
|
|
593
|
+
return this.decoderCache.decode(available, config);
|
|
641
594
|
}
|
|
642
|
-
|
|
643
|
-
|
|
595
|
+
getChunkMerkleRoots() {
|
|
596
|
+
if (this.decoderCache && this.lastFunction === "decoded")
|
|
597
|
+
return this.decoderCache.getChunkMerkleRoots();
|
|
598
|
+
if (this.encoderCache && this.lastFunction === "encoded")
|
|
599
|
+
return this.encoderCache.getChunkMerkleRoots();
|
|
600
|
+
throw new Error(
|
|
601
|
+
"You must call encode or decode before calling getChunkMerkleRoots"
|
|
602
|
+
);
|
|
644
603
|
}
|
|
645
604
|
/**
|
|
646
|
-
*
|
|
647
|
-
*
|
|
648
|
-
*
|
|
605
|
+
* Determines if data can be erasure coded as-is or requires padding.
|
|
606
|
+
*
|
|
607
|
+
* Data can be erasure coded without padding if its size exactly matches
|
|
608
|
+
* the total systematic data capacity (k * chunkSizeBytes).
|
|
609
|
+
*
|
|
610
|
+
* @param dataSize - Size of the data in bytes
|
|
611
|
+
* @returns true if data needs padding, false if it can be coded as-is
|
|
649
612
|
*/
|
|
650
|
-
|
|
651
|
-
const
|
|
652
|
-
const
|
|
653
|
-
|
|
654
|
-
const senderSignature = AccountAuthenticator.deserialize(deserializer);
|
|
655
|
-
return new _SenderBuiltMicropayment(micropayment, senderSignature);
|
|
613
|
+
requiresPadding(dataSize) {
|
|
614
|
+
const { erasure_k, chunkSizeBytes } = this.config;
|
|
615
|
+
const systematicCapacity = erasure_k * chunkSizeBytes;
|
|
616
|
+
return dataSize !== systematicCapacity;
|
|
656
617
|
}
|
|
657
618
|
};
|
|
658
619
|
|
|
659
|
-
// ../../
|
|
660
|
-
var
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
620
|
+
// ../../packages/sdk/dist/chunk-JTXYKO3U.mjs
|
|
621
|
+
var CHUNK_SIZE_PARAMS = {
|
|
622
|
+
[
|
|
623
|
+
"ChunkSet10MiB_Chunk1MiB"
|
|
624
|
+
/* ChunkSet10MiB_Chunk1MiB */
|
|
625
|
+
]: {
|
|
626
|
+
// 1MiB
|
|
627
|
+
chunkSizeBytes: 1 * 1024 * 1024,
|
|
628
|
+
// 10MiB
|
|
629
|
+
chunksetSizeBytes: 10 * 1024 * 1024
|
|
630
|
+
},
|
|
631
|
+
[
|
|
632
|
+
"ChunkSet2MiB_Chunk1MiB"
|
|
633
|
+
/* ChunkSet2MiB_Chunk1MiB */
|
|
634
|
+
]: {
|
|
635
|
+
// 1MiB
|
|
636
|
+
chunkSizeBytes: 1 * 1024 * 1024,
|
|
637
|
+
// 2MiB
|
|
638
|
+
chunksetSizeBytes: 2 * 1024 * 1024
|
|
676
639
|
}
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
640
|
+
};
|
|
641
|
+
var DEFAULT_CHUNK_SIZE_BYTES = CHUNK_SIZE_PARAMS[
|
|
642
|
+
"ChunkSet10MiB_Chunk1MiB"
|
|
643
|
+
/* ChunkSet10MiB_Chunk1MiB */
|
|
644
|
+
].chunkSizeBytes;
|
|
645
|
+
var DEFAULT_CHUNKSET_SIZE_BYTES = CHUNK_SIZE_PARAMS[
|
|
646
|
+
"ChunkSet10MiB_Chunk1MiB"
|
|
647
|
+
/* ChunkSet10MiB_Chunk1MiB */
|
|
648
|
+
].chunksetSizeBytes;
|
|
649
|
+
var ERASURE_CODE_AND_CHUNK_MAPPING = {
|
|
650
|
+
[
|
|
651
|
+
"ClayCode_16Total_10Data_13Helper"
|
|
652
|
+
/* ClayCode_16Total_10Data_13Helper */
|
|
653
|
+
]: {
|
|
654
|
+
...CHUNK_SIZE_PARAMS.ChunkSet10MiB_Chunk1MiB
|
|
655
|
+
},
|
|
656
|
+
[
|
|
657
|
+
"ClayCode_4Total_2Data_3Helper"
|
|
658
|
+
/* ClayCode_4Total_2Data_3Helper */
|
|
659
|
+
]: {
|
|
660
|
+
...CHUNK_SIZE_PARAMS.ChunkSet2MiB_Chunk1MiB
|
|
691
661
|
}
|
|
692
|
-
}
|
|
662
|
+
};
|
|
693
663
|
|
|
694
|
-
// ../../
|
|
695
|
-
var
|
|
696
|
-
|
|
697
|
-
|
|
664
|
+
// ../../packages/sdk/dist/chunk-AUQDI5BS.mjs
|
|
665
|
+
var ERASURE_CODE_PARAMS = {
|
|
666
|
+
[
|
|
667
|
+
"ClayCode_16Total_10Data_13Helper"
|
|
668
|
+
/* ClayCode_16Total_10Data_13Helper */
|
|
669
|
+
]: {
|
|
670
|
+
// total chunks (data + parity)
|
|
671
|
+
erasure_n: 16,
|
|
672
|
+
// data chunks
|
|
673
|
+
erasure_k: 10,
|
|
674
|
+
// helper nodes
|
|
675
|
+
erasure_d: 13,
|
|
676
|
+
// enum index
|
|
677
|
+
enumIndex: 0
|
|
678
|
+
},
|
|
679
|
+
[
|
|
680
|
+
"ClayCode_4Total_2Data_3Helper"
|
|
681
|
+
/* ClayCode_4Total_2Data_3Helper */
|
|
682
|
+
]: {
|
|
683
|
+
// total chunks (data + parity)
|
|
684
|
+
erasure_n: 4,
|
|
685
|
+
// data chunks
|
|
686
|
+
erasure_k: 2,
|
|
687
|
+
// helper nodes
|
|
688
|
+
erasure_d: 3,
|
|
689
|
+
// enum index
|
|
690
|
+
enumIndex: 1
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
var DEFAULT_ERASURE_N = ERASURE_CODE_PARAMS[
|
|
694
|
+
"ClayCode_16Total_10Data_13Helper"
|
|
695
|
+
/* ClayCode_16Total_10Data_13Helper */
|
|
696
|
+
].erasure_n;
|
|
697
|
+
var DEFAULT_ERASURE_K = ERASURE_CODE_PARAMS[
|
|
698
|
+
"ClayCode_16Total_10Data_13Helper"
|
|
699
|
+
/* ClayCode_16Total_10Data_13Helper */
|
|
700
|
+
].erasure_k;
|
|
701
|
+
var DEFAULT_ERASURE_D = ERASURE_CODE_PARAMS[
|
|
702
|
+
"ClayCode_16Total_10Data_13Helper"
|
|
703
|
+
/* ClayCode_16Total_10Data_13Helper */
|
|
704
|
+
].erasure_d;
|
|
705
|
+
var DEFAULT_ERASURE_M = DEFAULT_ERASURE_N - DEFAULT_ERASURE_K;
|
|
706
|
+
|
|
707
|
+
// ../../packages/sdk/dist/chunk-HPPMI7DC.mjs
|
|
708
|
+
function defaultErasureCodingConfig() {
|
|
709
|
+
console.log(
|
|
710
|
+
`default erasure coding, with env: ${process.env.SHELBY_ENCODING}`
|
|
711
|
+
);
|
|
712
|
+
const encoding = Number(process.env.SHELBY_ENCODING) || 0;
|
|
713
|
+
if (encoding === 0) {
|
|
714
|
+
console.log("getting default erasure coding (16,10,13)");
|
|
715
|
+
return erasureCodingConfig16Total10Data13Helper();
|
|
716
|
+
}
|
|
717
|
+
console.log("getting default erasure coding (4,2,3)");
|
|
718
|
+
return erasureCodingConfig4Total2Data3Helper();
|
|
719
|
+
}
|
|
720
|
+
function erasureCodingConfig16Total10Data13Helper() {
|
|
721
|
+
return erasureCodingConfig(
|
|
722
|
+
"ClayCode_16Total_10Data_13Helper"
|
|
723
|
+
/* ClayCode_16Total_10Data_13Helper */
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
function erasureCodingConfig4Total2Data3Helper() {
|
|
727
|
+
return erasureCodingConfig(
|
|
728
|
+
"ClayCode_4Total_2Data_3Helper"
|
|
729
|
+
/* ClayCode_4Total_2Data_3Helper */
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
function erasureCodingConfig(encodingScheme) {
|
|
733
|
+
return {
|
|
734
|
+
erasure_n: ERASURE_CODE_PARAMS[encodingScheme].erasure_n,
|
|
735
|
+
erasure_k: ERASURE_CODE_PARAMS[encodingScheme].erasure_k,
|
|
736
|
+
erasure_d: ERASURE_CODE_PARAMS[encodingScheme].erasure_d,
|
|
737
|
+
chunkSizeBytes: DEFAULT_CHUNK_SIZE_BYTES,
|
|
738
|
+
enumIndex: ERASURE_CODE_PARAMS[encodingScheme].enumIndex
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// ../../node_modules/.pnpm/tslib@2.8.1/node_modules/tslib/tslib.es6.mjs
|
|
743
|
+
var __assign = function() {
|
|
744
|
+
__assign = Object.assign || function __assign2(t) {
|
|
745
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
746
|
+
s = arguments[i];
|
|
747
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
748
|
+
}
|
|
749
|
+
return t;
|
|
750
|
+
};
|
|
751
|
+
return __assign.apply(this, arguments);
|
|
752
|
+
};
|
|
753
|
+
|
|
754
|
+
// ../../node_modules/.pnpm/graphql@16.11.0/node_modules/graphql/jsutils/devAssert.mjs
|
|
755
|
+
function devAssert(condition, message) {
|
|
756
|
+
const booleanCondition = Boolean(condition);
|
|
757
|
+
if (!booleanCondition) {
|
|
758
|
+
throw new Error(message);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// ../../node_modules/.pnpm/graphql@16.11.0/node_modules/graphql/jsutils/isObjectLike.mjs
|
|
763
|
+
function isObjectLike(value) {
|
|
764
|
+
return typeof value == "object" && value !== null;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// ../../node_modules/.pnpm/graphql@16.11.0/node_modules/graphql/jsutils/invariant.mjs
|
|
768
|
+
function invariant(condition, message) {
|
|
769
|
+
const booleanCondition = Boolean(condition);
|
|
770
|
+
if (!booleanCondition) {
|
|
771
|
+
throw new Error(
|
|
772
|
+
message != null ? message : "Unexpected invariant triggered."
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// ../../node_modules/.pnpm/graphql@16.11.0/node_modules/graphql/language/location.mjs
|
|
778
|
+
var LineRegExp = /\r\n|[\n\r]/g;
|
|
779
|
+
function getLocation(source, position) {
|
|
780
|
+
let lastLineStart = 0;
|
|
698
781
|
let line = 1;
|
|
699
782
|
for (const match of source.body.matchAll(LineRegExp)) {
|
|
700
783
|
typeof match.index === "number" || invariant(false);
|
|
@@ -3855,7 +3938,7 @@ var extras = {
|
|
|
3855
3938
|
gql["default"] = gql;
|
|
3856
3939
|
var lib_default = gql;
|
|
3857
3940
|
|
|
3858
|
-
// ../../packages/sdk/dist/chunk-
|
|
3941
|
+
// ../../packages/sdk/dist/chunk-KJ24NKPH.mjs
|
|
3859
3942
|
var GetBlobsDocument = lib_default`
|
|
3860
3943
|
query getBlobs($where: blobs_bool_exp, $orderBy: [blobs_order_by!], $limit: Int, $offset: Int) {
|
|
3861
3944
|
blobs(where: $where, order_by: $orderBy, limit: $limit, offset: $offset) {
|
|
@@ -3909,6 +3992,40 @@ var GetBlobActivitiesCountDocument = lib_default`
|
|
|
3909
3992
|
}
|
|
3910
3993
|
}
|
|
3911
3994
|
`;
|
|
3995
|
+
var GetPlacementGroupSlotsDocument = lib_default`
|
|
3996
|
+
query getPlacementGroupSlots($where: placement_group_slots_bool_exp, $orderBy: [placement_group_slots_order_by!], $limit: Int, $offset: Int) {
|
|
3997
|
+
placement_group_slots(
|
|
3998
|
+
where: $where
|
|
3999
|
+
order_by: $orderBy
|
|
4000
|
+
limit: $limit
|
|
4001
|
+
offset: $offset
|
|
4002
|
+
) {
|
|
4003
|
+
placement_group
|
|
4004
|
+
slot_index
|
|
4005
|
+
storage_provider
|
|
4006
|
+
status
|
|
4007
|
+
updated_at
|
|
4008
|
+
}
|
|
4009
|
+
}
|
|
4010
|
+
`;
|
|
4011
|
+
var GetPlacementGroupSlotsCountDocument = lib_default`
|
|
4012
|
+
query getPlacementGroupSlotsCount($where: placement_group_slots_bool_exp) {
|
|
4013
|
+
placement_group_slots_aggregate(where: $where) {
|
|
4014
|
+
aggregate {
|
|
4015
|
+
count
|
|
4016
|
+
}
|
|
4017
|
+
}
|
|
4018
|
+
}
|
|
4019
|
+
`;
|
|
4020
|
+
var GetProcessorStatusDocument = lib_default`
|
|
4021
|
+
query getProcessorStatus {
|
|
4022
|
+
processor_status {
|
|
4023
|
+
last_success_version
|
|
4024
|
+
last_transaction_timestamp
|
|
4025
|
+
last_updated
|
|
4026
|
+
}
|
|
4027
|
+
}
|
|
4028
|
+
`;
|
|
3912
4029
|
var defaultWrapper = (action, _operationName, _operationType, _variables) => action();
|
|
3913
4030
|
function getSdk(client, withWrapper = defaultWrapper) {
|
|
3914
4031
|
return {
|
|
@@ -3923,12 +4040,86 @@ function getSdk(client, withWrapper = defaultWrapper) {
|
|
|
3923
4040
|
},
|
|
3924
4041
|
getBlobActivitiesCount(variables, requestHeaders, signal) {
|
|
3925
4042
|
return withWrapper((wrappedRequestHeaders) => client.request({ document: GetBlobActivitiesCountDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getBlobActivitiesCount", "query", variables);
|
|
4043
|
+
},
|
|
4044
|
+
getPlacementGroupSlots(variables, requestHeaders, signal) {
|
|
4045
|
+
return withWrapper((wrappedRequestHeaders) => client.request({ document: GetPlacementGroupSlotsDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getPlacementGroupSlots", "query", variables);
|
|
4046
|
+
},
|
|
4047
|
+
getPlacementGroupSlotsCount(variables, requestHeaders, signal) {
|
|
4048
|
+
return withWrapper((wrappedRequestHeaders) => client.request({ document: GetPlacementGroupSlotsCountDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getPlacementGroupSlotsCount", "query", variables);
|
|
4049
|
+
},
|
|
4050
|
+
getProcessorStatus(variables, requestHeaders, signal) {
|
|
4051
|
+
return withWrapper((wrappedRequestHeaders) => client.request({ document: GetProcessorStatusDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getProcessorStatus", "query", variables);
|
|
3926
4052
|
}
|
|
3927
4053
|
};
|
|
3928
4054
|
}
|
|
3929
4055
|
|
|
3930
|
-
// ../../packages/sdk/dist/chunk-
|
|
3931
|
-
import {
|
|
4056
|
+
// ../../packages/sdk/dist/chunk-AABBONAF.mjs
|
|
4057
|
+
import { AptosConfig } from "@aptos-labs/ts-sdk";
|
|
4058
|
+
var getAptosConfig = (config) => {
|
|
4059
|
+
const baseFaucetConfig = config.faucet?.authToken ? { AUTH_TOKEN: config.faucet.authToken } : void 0;
|
|
4060
|
+
if (config.aptos) {
|
|
4061
|
+
return new AptosConfig({
|
|
4062
|
+
// Spread user's aptos config first
|
|
4063
|
+
...config.aptos,
|
|
4064
|
+
// Network from top-level is authoritative - cannot be overridden
|
|
4065
|
+
network: config.network,
|
|
4066
|
+
// Merge clientConfig with API_KEY default
|
|
4067
|
+
clientConfig: {
|
|
4068
|
+
API_KEY: config.apiKey,
|
|
4069
|
+
...config.aptos.clientConfig
|
|
4070
|
+
},
|
|
4071
|
+
// Merge faucetConfig: aptos config first, then base authToken (authoritative)
|
|
4072
|
+
faucetConfig: {
|
|
4073
|
+
...config.aptos.faucetConfig,
|
|
4074
|
+
...baseFaucetConfig
|
|
4075
|
+
}
|
|
4076
|
+
});
|
|
4077
|
+
}
|
|
4078
|
+
return new AptosConfig({
|
|
4079
|
+
network: config.network,
|
|
4080
|
+
clientConfig: {
|
|
4081
|
+
API_KEY: config.apiKey
|
|
4082
|
+
},
|
|
4083
|
+
faucetConfig: baseFaucetConfig
|
|
4084
|
+
});
|
|
4085
|
+
};
|
|
4086
|
+
|
|
4087
|
+
// ../../packages/sdk/dist/chunk-4ZOFT75Q.mjs
|
|
4088
|
+
import { Network } from "@aptos-labs/ts-sdk";
|
|
4089
|
+
var NetworkToShelbyRPCBaseUrl = {
|
|
4090
|
+
[Network.SHELBYNET]: "https://api.shelbynet.shelby.xyz/shelby",
|
|
4091
|
+
[Network.NETNA]: void 0,
|
|
4092
|
+
[Network.DEVNET]: void 0,
|
|
4093
|
+
[Network.TESTNET]: "https://api.testnet.shelby.xyz/shelby",
|
|
4094
|
+
[Network.MAINNET]: void 0,
|
|
4095
|
+
[Network.LOCAL]: void 0,
|
|
4096
|
+
[Network.CUSTOM]: void 0
|
|
4097
|
+
};
|
|
4098
|
+
var NetworkToShelbyBlobIndexerBaseUrl = {
|
|
4099
|
+
[Network.SHELBYNET]: "https://api.shelbynet.aptoslabs.com/nocode/v1/public/cmforrguw0042s601fn71f9l2/v1/graphql",
|
|
4100
|
+
[Network.NETNA]: void 0,
|
|
4101
|
+
[Network.DEVNET]: void 0,
|
|
4102
|
+
[Network.TESTNET]: "https://api.testnet.aptoslabs.com/nocode/v1/public/cmlfqs5wt00qrs601zt5s4kfj/v1/graphql",
|
|
4103
|
+
[Network.MAINNET]: void 0,
|
|
4104
|
+
[Network.LOCAL]: void 0,
|
|
4105
|
+
[Network.CUSTOM]: void 0
|
|
4106
|
+
};
|
|
4107
|
+
var NetworkToGasStationBaseUrl = {
|
|
4108
|
+
[Network.SHELBYNET]: "https://api.shelbynet.shelby.xyz/gs/v1",
|
|
4109
|
+
[Network.NETNA]: void 0,
|
|
4110
|
+
[Network.DEVNET]: void 0,
|
|
4111
|
+
[Network.TESTNET]: "https://api.testnet.shelby.xyz/gs/v1",
|
|
4112
|
+
[Network.MAINNET]: void 0,
|
|
4113
|
+
[Network.LOCAL]: void 0,
|
|
4114
|
+
[Network.CUSTOM]: void 0
|
|
4115
|
+
};
|
|
4116
|
+
var SHELBY_DEPLOYER = "0xc63d6a5efb0080a6029403131715bd4971e1149f7cc099aac69bb0069b3ddbf5";
|
|
4117
|
+
var MICROPAYMENTS_DEPLOYER = "0xb42ac038b6dae86f6171e28e297aab9555ce09909445ec579e4ffe6b8d4d63bf";
|
|
4118
|
+
var SHELBYUSD_TOKEN_NAME = "ShelbyUSD";
|
|
4119
|
+
var SHELBYUSD_FA_METADATA_ADDRESS = "0x1b18363a9f1fe5e6ebf247daba5cc1c18052bb232efdc4c50f556053922d98e1";
|
|
4120
|
+
|
|
4121
|
+
// ../../packages/sdk/dist/chunk-CGYJLKBU.mjs
|
|
4122
|
+
import { Network as Network2 } from "@aptos-labs/ts-sdk";
|
|
3932
4123
|
|
|
3933
4124
|
// ../../node_modules/.pnpm/graphql-request@7.2.0_graphql@16.11.0/node_modules/graphql-request/build/legacy/classes/ClientError.js
|
|
3934
4125
|
var ClientError = class _ClientError extends Error {
|
|
@@ -4442,21 +4633,21 @@ var parseRequestArgs = (documentOrOptions, variables, requestHeaders) => {
|
|
|
4442
4633
|
};
|
|
4443
4634
|
};
|
|
4444
4635
|
|
|
4445
|
-
// ../../packages/sdk/dist/chunk-
|
|
4636
|
+
// ../../packages/sdk/dist/chunk-CGYJLKBU.mjs
|
|
4446
4637
|
function createShelbyIndexerClient(baseUrl, options) {
|
|
4447
4638
|
const graphqlClient = new GraphQLClient(baseUrl, options);
|
|
4448
4639
|
return getSdk(graphqlClient);
|
|
4449
4640
|
}
|
|
4450
4641
|
function getShelbyIndexerClient(config) {
|
|
4451
|
-
const aptosConfig =
|
|
4642
|
+
const aptosConfig = getAptosConfig(config);
|
|
4452
4643
|
let { apiKey: indexerApiKey, baseUrl } = config.indexer ?? {};
|
|
4453
4644
|
if (!baseUrl) {
|
|
4454
4645
|
switch (aptosConfig?.network) {
|
|
4455
4646
|
// TODO: Add endpoints for core networks
|
|
4456
|
-
case
|
|
4457
|
-
case
|
|
4458
|
-
case
|
|
4459
|
-
case
|
|
4647
|
+
case Network2.MAINNET:
|
|
4648
|
+
case Network2.TESTNET:
|
|
4649
|
+
case Network2.DEVNET:
|
|
4650
|
+
case Network2.SHELBYNET:
|
|
4460
4651
|
baseUrl = NetworkToShelbyBlobIndexerBaseUrl[aptosConfig.network];
|
|
4461
4652
|
break;
|
|
4462
4653
|
}
|
|
@@ -4475,96 +4666,14 @@ function getShelbyIndexerClient(config) {
|
|
|
4475
4666
|
});
|
|
4476
4667
|
}
|
|
4477
4668
|
|
|
4478
|
-
// ../../packages/sdk/dist/chunk-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
/* ChunkSet10MiB_Chunk1MiB */
|
|
4483
|
-
]: {
|
|
4484
|
-
// 1MiB
|
|
4485
|
-
chunkSizeBytes: 1 * 1024 * 1024,
|
|
4486
|
-
// 10MiB
|
|
4487
|
-
chunksetSizeBytes: 10 * 1024 * 1024
|
|
4488
|
-
}
|
|
4489
|
-
};
|
|
4490
|
-
var DEFAULT_CHUNK_SIZE_BYTES = CHUNK_SIZE_PARAMS[
|
|
4491
|
-
"ChunkSet10MiB_Chunk1MiB"
|
|
4492
|
-
/* ChunkSet10MiB_Chunk1MiB */
|
|
4493
|
-
].chunkSizeBytes;
|
|
4494
|
-
var DEFAULT_CHUNKSET_SIZE_BYTES = CHUNK_SIZE_PARAMS[
|
|
4495
|
-
"ChunkSet10MiB_Chunk1MiB"
|
|
4496
|
-
/* ChunkSet10MiB_Chunk1MiB */
|
|
4497
|
-
].chunksetSizeBytes;
|
|
4498
|
-
var ERASURE_CODE_AND_CHUNK_MAPPING = {
|
|
4499
|
-
[
|
|
4500
|
-
"ClayCode_16Total_10Data_13Helper"
|
|
4501
|
-
/* ClayCode_16Total_10Data_13Helper */
|
|
4502
|
-
]: {
|
|
4503
|
-
...CHUNK_SIZE_PARAMS.ChunkSet10MiB_Chunk1MiB
|
|
4504
|
-
}
|
|
4505
|
-
};
|
|
4506
|
-
|
|
4507
|
-
// ../../packages/sdk/dist/chunk-LZSIZJYR.mjs
|
|
4508
|
-
var ERASURE_CODE_PARAMS = {
|
|
4509
|
-
[
|
|
4510
|
-
"ClayCode_16Total_10Data_13Helper"
|
|
4511
|
-
/* ClayCode_16Total_10Data_13Helper */
|
|
4512
|
-
]: {
|
|
4513
|
-
// total chunks (data + parity)
|
|
4514
|
-
erasure_n: 16,
|
|
4515
|
-
// data chunks
|
|
4516
|
-
erasure_k: 10,
|
|
4517
|
-
// helper nodes
|
|
4518
|
-
erasure_d: 13
|
|
4519
|
-
}
|
|
4669
|
+
// ../../packages/sdk/dist/chunk-OTBLZL2S.mjs
|
|
4670
|
+
import { AccountAddress } from "@aptos-labs/ts-sdk";
|
|
4671
|
+
var createBlobKey = (params) => {
|
|
4672
|
+
return `@${AccountAddress.from(params.account).toStringLongWithoutPrefix()}/${params.blobName}`;
|
|
4520
4673
|
};
|
|
4521
|
-
var DEFAULT_ERASURE_N = ERASURE_CODE_PARAMS[
|
|
4522
|
-
"ClayCode_16Total_10Data_13Helper"
|
|
4523
|
-
/* ClayCode_16Total_10Data_13Helper */
|
|
4524
|
-
].erasure_n;
|
|
4525
|
-
var DEFAULT_ERASURE_K = ERASURE_CODE_PARAMS[
|
|
4526
|
-
"ClayCode_16Total_10Data_13Helper"
|
|
4527
|
-
/* ClayCode_16Total_10Data_13Helper */
|
|
4528
|
-
].erasure_k;
|
|
4529
|
-
var DEFAULT_ERASURE_D = ERASURE_CODE_PARAMS[
|
|
4530
|
-
"ClayCode_16Total_10Data_13Helper"
|
|
4531
|
-
/* ClayCode_16Total_10Data_13Helper */
|
|
4532
|
-
].erasure_d;
|
|
4533
|
-
var DEFAULT_ERASURE_M = DEFAULT_ERASURE_N - DEFAULT_ERASURE_K;
|
|
4534
|
-
|
|
4535
|
-
// ../../packages/sdk/dist/chunk-W5NRGZEP.mjs
|
|
4536
|
-
import { AccountAddress as AccountAddress2 } from "@aptos-labs/ts-sdk";
|
|
4537
|
-
import { z } from "zod";
|
|
4538
|
-
var BlobNameSchema = z.string().min(1, "Blob name path parameter cannot be empty.").max(1024, "Blob name cannot exceed 1024 characters.").refine((name2) => !name2.endsWith("/"), {
|
|
4539
|
-
message: "Blob name cannot end with a slash"
|
|
4540
|
-
});
|
|
4541
|
-
|
|
4542
|
-
// ../../packages/sdk/dist/chunk-I6NG5GNL.mjs
|
|
4543
|
-
function sleep(ms) {
|
|
4544
|
-
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
4545
|
-
}
|
|
4546
|
-
|
|
4547
|
-
// ../../packages/sdk/dist/chunk-IE6LYVIA.mjs
|
|
4548
|
-
import { z as z2 } from "zod";
|
|
4549
|
-
var StartMultipartUploadResponseSchema = z2.object({
|
|
4550
|
-
uploadId: z2.string()
|
|
4551
|
-
});
|
|
4552
|
-
var UploadPartResponseSchema = z2.object({
|
|
4553
|
-
success: z2.literal(true)
|
|
4554
|
-
});
|
|
4555
|
-
var CompleteMultipartUploadResponseSchema = z2.object({
|
|
4556
|
-
success: z2.literal(true)
|
|
4557
|
-
});
|
|
4558
|
-
var RPCErrorResponseSchema = z2.object({
|
|
4559
|
-
error: z2.string()
|
|
4560
|
-
});
|
|
4561
|
-
var StaleMicropaymentErrorResponseSchema = z2.object({
|
|
4562
|
-
error: z2.string().optional(),
|
|
4563
|
-
storedMicropayment: z2.string().optional()
|
|
4564
|
-
});
|
|
4565
4674
|
|
|
4566
4675
|
// ../../packages/sdk/dist/chunk-4JZO2D7T.mjs
|
|
4567
|
-
import { Hex
|
|
4676
|
+
import { Hex } from "@aptos-labs/ts-sdk";
|
|
4568
4677
|
async function* readInChunks(input, chunkSize) {
|
|
4569
4678
|
let idx = 0;
|
|
4570
4679
|
if (isReadableStream(input)) {
|
|
@@ -4624,7 +4733,7 @@ function zeroPadBytes(buffer, desiredLength) {
|
|
|
4624
4733
|
return paddedBuffer;
|
|
4625
4734
|
}
|
|
4626
4735
|
async function concatHashes(parts) {
|
|
4627
|
-
const chunks = parts.map((part) =>
|
|
4736
|
+
const chunks = parts.map((part) => Hex.fromHexInput(part).toUint8Array());
|
|
4628
4737
|
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
|
|
4629
4738
|
const combined = new Uint8Array(totalLength);
|
|
4630
4739
|
let offset = 0;
|
|
@@ -4632,7 +4741,7 @@ async function concatHashes(parts) {
|
|
|
4632
4741
|
combined.set(chunk, offset);
|
|
4633
4742
|
offset += chunk.byteLength;
|
|
4634
4743
|
}
|
|
4635
|
-
return
|
|
4744
|
+
return Hex.fromHexInput(
|
|
4636
4745
|
new Uint8Array(await crypto.subtle.digest("SHA-256", combined))
|
|
4637
4746
|
);
|
|
4638
4747
|
}
|
|
@@ -4653,730 +4762,466 @@ function getBlobNameSuffix(blobName) {
|
|
|
4653
4762
|
return parts.slice(1).join("/") || "";
|
|
4654
4763
|
}
|
|
4655
4764
|
|
|
4656
|
-
// ../../packages/sdk/dist/chunk-
|
|
4657
|
-
import {
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
* @param config.network - The Shelby network to use.
|
|
4673
|
-
*
|
|
4674
|
-
* @example
|
|
4675
|
-
* ```typescript
|
|
4676
|
-
* const client = new ShelbyRPCClient({
|
|
4677
|
-
* network: Network.SHELBYNET,
|
|
4678
|
-
* apiKey: "AG-***",
|
|
4679
|
-
* });
|
|
4680
|
-
* ```
|
|
4681
|
-
*/
|
|
4682
|
-
constructor(config) {
|
|
4683
|
-
this.baseUrl = config.rpc?.baseUrl ?? NetworkToShelbyRPCBaseUrl.shelbynet;
|
|
4684
|
-
this.apiKey = config.apiKey ?? config.rpc?.apiKey;
|
|
4685
|
-
this.rpcConfig = config.rpc ?? {};
|
|
4686
|
-
this.indexer = getShelbyIndexerClient(config);
|
|
4765
|
+
// ../../packages/sdk/dist/chunk-2WEX3K7C.mjs
|
|
4766
|
+
import { Hex as Hex2 } from "@aptos-labs/ts-sdk";
|
|
4767
|
+
import { z } from "zod";
|
|
4768
|
+
var COMMITMENT_SCHEMA_VERSION = "1.3";
|
|
4769
|
+
var ChunksetCommitmentSchema = z.object({
|
|
4770
|
+
// Chunkset root (vector commitment of child chunks)
|
|
4771
|
+
chunkset_root: z.string(),
|
|
4772
|
+
// the size is known statically from the current configuration
|
|
4773
|
+
chunk_commitments: z.array(z.string())
|
|
4774
|
+
}).refine(
|
|
4775
|
+
(data) => {
|
|
4776
|
+
return data.chunk_commitments.length === DEFAULT_ERASURE_K + DEFAULT_ERASURE_M;
|
|
4777
|
+
},
|
|
4778
|
+
{
|
|
4779
|
+
message: `Chunkset must have exactly ${DEFAULT_ERASURE_K + DEFAULT_ERASURE_M} chunks (ERASURE_K + ERASURE_M = ${DEFAULT_ERASURE_K} + ${DEFAULT_ERASURE_M})`,
|
|
4780
|
+
path: ["chunk_commitments"]
|
|
4687
4781
|
}
|
|
4688
|
-
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
buildRequestUrl(
|
|
4693
|
-
`/v1/multipart-uploads/${uploadId}/parts/${partIdx}`,
|
|
4694
|
-
this.baseUrl
|
|
4695
|
-
),
|
|
4696
|
-
{
|
|
4697
|
-
method: "PUT",
|
|
4698
|
-
headers: {
|
|
4699
|
-
"Content-Type": "application/octet-stream",
|
|
4700
|
-
...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
|
|
4701
|
-
},
|
|
4702
|
-
body: partData
|
|
4703
|
-
}
|
|
4704
|
-
);
|
|
4705
|
-
if (partResponse.ok) return;
|
|
4706
|
-
if (i < nRetries - 1) {
|
|
4707
|
-
const delay = 2 ** i * 100;
|
|
4708
|
-
await sleep(delay);
|
|
4709
|
-
}
|
|
4710
|
-
}
|
|
4711
|
-
throw new Error(`Failed to upload part ${partIdx}.`);
|
|
4782
|
+
);
|
|
4783
|
+
function expectedTotalChunksets(rawSize, chunksetSize = DEFAULT_CHUNKSET_SIZE_BYTES) {
|
|
4784
|
+
if (chunksetSize <= 0) {
|
|
4785
|
+
throw new Error("chunksetSize must be positive");
|
|
4712
4786
|
}
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4787
|
+
if (rawSize === 0) return 1;
|
|
4788
|
+
return Math.ceil(rawSize / chunksetSize);
|
|
4789
|
+
}
|
|
4790
|
+
var BlobCommitmentsSchema = z.object({
|
|
4791
|
+
schema_version: z.string(),
|
|
4792
|
+
raw_data_size: z.number(),
|
|
4793
|
+
// FIXME I am not sure about this being here, or if it should be somewhere else
|
|
4794
|
+
blob_merkle_root: z.string(),
|
|
4795
|
+
chunkset_commitments: z.array(ChunksetCommitmentSchema)
|
|
4796
|
+
}).refine(
|
|
4797
|
+
(data) => {
|
|
4798
|
+
return expectedTotalChunksets(data.raw_data_size) === data.chunkset_commitments.length;
|
|
4799
|
+
},
|
|
4800
|
+
{
|
|
4801
|
+
message: "Total chunkset count mismatches with raw data size",
|
|
4802
|
+
// FIXME put more details in here
|
|
4803
|
+
path: ["chunkset_commitments"]
|
|
4804
|
+
}
|
|
4805
|
+
);
|
|
4806
|
+
async function generateMerkleRoot(leafHashes) {
|
|
4807
|
+
if (!leafHashes.length) {
|
|
4808
|
+
throw new Error(
|
|
4809
|
+
"An empty array cannot be used to construct a Merkle tree."
|
|
4728
4810
|
);
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4811
|
+
}
|
|
4812
|
+
const zeroArray = new Uint8Array(leafHashes[0].toUint8Array().length);
|
|
4813
|
+
const zeroBytes = Hex2.fromHexInput(zeroArray);
|
|
4814
|
+
let currentLeaves = leafHashes;
|
|
4815
|
+
while (currentLeaves.length > 1) {
|
|
4816
|
+
if (currentLeaves.length % 2 !== 0) {
|
|
4817
|
+
currentLeaves.push(zeroBytes);
|
|
4818
|
+
}
|
|
4819
|
+
const nextLeaves = [];
|
|
4820
|
+
for (let i = 0; i < currentLeaves.length; i += 2) {
|
|
4821
|
+
nextLeaves.push(
|
|
4822
|
+
await concatHashes([
|
|
4823
|
+
currentLeaves[i].toUint8Array(),
|
|
4824
|
+
currentLeaves[i + 1].toUint8Array()
|
|
4825
|
+
])
|
|
4737
4826
|
);
|
|
4738
4827
|
}
|
|
4739
|
-
|
|
4740
|
-
|
|
4828
|
+
currentLeaves = nextLeaves;
|
|
4829
|
+
}
|
|
4830
|
+
return currentLeaves[0];
|
|
4831
|
+
}
|
|
4832
|
+
async function generateChunksetCommitments(shouldPad, chunksetIdx, chunksetData, expectedChunksetSize, provider, onChunk) {
|
|
4833
|
+
const { erasure_n } = provider.config;
|
|
4834
|
+
const chunksetPayload = shouldPad ? zeroPadBytes(chunksetData, expectedChunksetSize) : validatePrePaddedChunkset(
|
|
4835
|
+
chunksetData,
|
|
4836
|
+
expectedChunksetSize,
|
|
4837
|
+
chunksetIdx
|
|
4838
|
+
);
|
|
4839
|
+
const { chunks } = provider.encode(chunksetPayload);
|
|
4840
|
+
if (chunks.length !== erasure_n) {
|
|
4841
|
+
throw new Error(
|
|
4842
|
+
`Erasure provider produced ${chunks.length} chunks, expected ${erasure_n}.`
|
|
4741
4843
|
);
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
await
|
|
4748
|
-
onProgress?.({
|
|
4749
|
-
partIdx,
|
|
4750
|
-
totalParts,
|
|
4751
|
-
partBytes: partData.length,
|
|
4752
|
-
uploadedBytes: end,
|
|
4753
|
-
totalBytes: blobData.length
|
|
4754
|
-
});
|
|
4844
|
+
}
|
|
4845
|
+
const chunkRoots = provider.getChunkMerkleRoots();
|
|
4846
|
+
let chunkIdx = 0;
|
|
4847
|
+
for (const chunkData of chunks) {
|
|
4848
|
+
if (onChunk !== void 0) {
|
|
4849
|
+
await onChunk(chunksetIdx, chunkIdx, chunkData);
|
|
4755
4850
|
}
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4851
|
+
chunkIdx += 1;
|
|
4852
|
+
}
|
|
4853
|
+
const a = await generateMerkleRoot(
|
|
4854
|
+
chunkRoots.map((a2) => Hex2.fromHexInput(a2))
|
|
4855
|
+
);
|
|
4856
|
+
const entry = {
|
|
4857
|
+
chunkset_root: a.toString(),
|
|
4858
|
+
chunk_commitments: chunkRoots.map(
|
|
4859
|
+
(chunk) => Hex2.fromHexInput(chunk).toString()
|
|
4860
|
+
)
|
|
4861
|
+
};
|
|
4862
|
+
return { h: a, entry };
|
|
4863
|
+
}
|
|
4864
|
+
async function generateCommitments(provider, fullData, onChunk, options) {
|
|
4865
|
+
const expectedChunksetSize = provider.config.chunkSizeBytes * provider.config.erasure_k;
|
|
4866
|
+
const shouldPad = options?.pad ?? true;
|
|
4867
|
+
const chunksetCommitments = [];
|
|
4868
|
+
const chunksetCommitmentHashes = [];
|
|
4869
|
+
let rawDataSize = 0;
|
|
4870
|
+
const chunksetGen = readInChunks(fullData, expectedChunksetSize);
|
|
4871
|
+
for await (const [chunksetIdx, chunksetData] of chunksetGen) {
|
|
4872
|
+
rawDataSize += chunksetData.length;
|
|
4873
|
+
const { h, entry } = await generateChunksetCommitments(
|
|
4874
|
+
shouldPad,
|
|
4875
|
+
chunksetIdx,
|
|
4876
|
+
chunksetData,
|
|
4877
|
+
expectedChunksetSize,
|
|
4878
|
+
provider,
|
|
4879
|
+
onChunk
|
|
4880
|
+
);
|
|
4881
|
+
chunksetCommitments.push(entry);
|
|
4882
|
+
chunksetCommitmentHashes.push(h);
|
|
4883
|
+
}
|
|
4884
|
+
if (rawDataSize === 0) {
|
|
4885
|
+
const zeroChunkset = new Uint8Array(expectedChunksetSize);
|
|
4886
|
+
const { h, entry } = await generateChunksetCommitments(
|
|
4887
|
+
shouldPad,
|
|
4888
|
+
0,
|
|
4889
|
+
zeroChunkset,
|
|
4890
|
+
expectedChunksetSize,
|
|
4891
|
+
provider,
|
|
4892
|
+
onChunk
|
|
4893
|
+
);
|
|
4894
|
+
chunksetCommitments.push(entry);
|
|
4895
|
+
chunksetCommitmentHashes.push(h);
|
|
4896
|
+
}
|
|
4897
|
+
return {
|
|
4898
|
+
schema_version: COMMITMENT_SCHEMA_VERSION,
|
|
4899
|
+
raw_data_size: rawDataSize,
|
|
4900
|
+
blob_merkle_root: (await generateMerkleRoot(chunksetCommitmentHashes)).toString(),
|
|
4901
|
+
chunkset_commitments: chunksetCommitments
|
|
4902
|
+
};
|
|
4903
|
+
}
|
|
4904
|
+
function validatePrePaddedChunkset(chunkset, expectedSize, chunksetIdx) {
|
|
4905
|
+
if (chunkset.byteLength !== expectedSize) {
|
|
4906
|
+
throw new Error(
|
|
4907
|
+
`Chunkset ${chunksetIdx} has size ${chunkset.byteLength} bytes but expected ${expectedSize} bytes. Enable padding or supply pre-padded data before calling generateCommitments.`
|
|
4768
4908
|
);
|
|
4769
|
-
if (!completeResponse.ok) {
|
|
4770
|
-
let errorBodyText = "Could not read error body";
|
|
4771
|
-
try {
|
|
4772
|
-
errorBodyText = await completeResponse.text();
|
|
4773
|
-
} catch (_e) {
|
|
4774
|
-
}
|
|
4775
|
-
throw new Error(
|
|
4776
|
-
`Failed to complete multipart upload! status: ${completeResponse.status}, body: ${errorBodyText}`
|
|
4777
|
-
);
|
|
4778
|
-
}
|
|
4779
4909
|
}
|
|
4910
|
+
return chunkset;
|
|
4911
|
+
}
|
|
4912
|
+
|
|
4913
|
+
// ../../packages/sdk/dist/chunk-SRV4YWFH.mjs
|
|
4914
|
+
import {
|
|
4915
|
+
AccountAddress as AccountAddress2,
|
|
4916
|
+
Aptos,
|
|
4917
|
+
Hex as Hex3,
|
|
4918
|
+
U32
|
|
4919
|
+
} from "@aptos-labs/ts-sdk";
|
|
4920
|
+
var MissingTransactionSubmitterError = class extends Error {
|
|
4921
|
+
constructor() {
|
|
4922
|
+
super(
|
|
4923
|
+
"USD sponsorship (usdSponsor) requires a transaction submitter to be configured. The sponsored transaction is a multi-agent transaction that must be co-signed by the sponsor. Configure a transaction submitter via aptos.pluginSettings.TRANSACTION_SUBMITTER that routes transactions to a service (like a gas station) capable of providing the sponsor's signature."
|
|
4924
|
+
);
|
|
4925
|
+
this.name = "MissingTransactionSubmitterError";
|
|
4926
|
+
}
|
|
4927
|
+
};
|
|
4928
|
+
var ShelbyBlobClient = class _ShelbyBlobClient {
|
|
4929
|
+
aptos;
|
|
4930
|
+
deployer;
|
|
4931
|
+
indexer;
|
|
4932
|
+
defaultOptions;
|
|
4780
4933
|
/**
|
|
4781
|
-
*
|
|
4782
|
-
*
|
|
4783
|
-
* Uses multipart upload for efficient handling of large files.
|
|
4934
|
+
* The ShelbyBlobClient is used to interact with the Shelby contract on the Aptos blockchain. This
|
|
4935
|
+
* includes functions for registering blob commitments and retrieving blob metadata.
|
|
4784
4936
|
*
|
|
4785
|
-
* @param
|
|
4786
|
-
* @param
|
|
4787
|
-
* @param
|
|
4937
|
+
* @param config - The client configuration object.
|
|
4938
|
+
* @param config.network - The Shelby network to use.
|
|
4939
|
+
* @param defaultOptions - Optional default options for blob operations.
|
|
4788
4940
|
*
|
|
4789
4941
|
* @example
|
|
4790
4942
|
* ```typescript
|
|
4791
|
-
* const
|
|
4792
|
-
*
|
|
4793
|
-
*
|
|
4794
|
-
*
|
|
4795
|
-
*
|
|
4796
|
-
*
|
|
4943
|
+
* const blobClient = new ShelbyBlobClient({
|
|
4944
|
+
* aptos: {
|
|
4945
|
+
* network: Network.SHELBYNET,
|
|
4946
|
+
* clientConfig: {
|
|
4947
|
+
* API_KEY: "AG-***",
|
|
4948
|
+
* },
|
|
4949
|
+
* },
|
|
4797
4950
|
* });
|
|
4798
4951
|
* ```
|
|
4952
|
+
*
|
|
4953
|
+
* @example
|
|
4954
|
+
* ```typescript
|
|
4955
|
+
* // With default options for USD sponsorship
|
|
4956
|
+
* const blobClient = new ShelbyBlobClient(
|
|
4957
|
+
* {
|
|
4958
|
+
* network: Network.SHELBYNET,
|
|
4959
|
+
* aptos: {
|
|
4960
|
+
* pluginSettings: {
|
|
4961
|
+
* TRANSACTION_SUBMITTER: myGasStationSubmitter,
|
|
4962
|
+
* },
|
|
4963
|
+
* },
|
|
4964
|
+
* },
|
|
4965
|
+
* {
|
|
4966
|
+
* usdSponsor: { feePayerAddress: sponsorAddress },
|
|
4967
|
+
* }
|
|
4968
|
+
* );
|
|
4969
|
+
* ```
|
|
4799
4970
|
*/
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
params.blobData,
|
|
4806
|
-
void 0,
|
|
4807
|
-
params.onProgress
|
|
4808
|
-
);
|
|
4971
|
+
constructor(config, defaultOptions) {
|
|
4972
|
+
this.aptos = new Aptos(getAptosConfig(config));
|
|
4973
|
+
this.deployer = config.deployer ?? AccountAddress2.fromString(SHELBY_DEPLOYER);
|
|
4974
|
+
this.indexer = getShelbyIndexerClient(config);
|
|
4975
|
+
this.defaultOptions = defaultOptions ?? {};
|
|
4809
4976
|
}
|
|
4810
|
-
// FIXME make this possible to stream in put ^^^
|
|
4811
4977
|
/**
|
|
4812
|
-
*
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4978
|
+
* Merges method-level options with default options, giving precedence to method-level values.
|
|
4979
|
+
*/
|
|
4980
|
+
mergeOptions(options) {
|
|
4981
|
+
return {
|
|
4982
|
+
build: options?.build ?? this.defaultOptions.build,
|
|
4983
|
+
submit: options?.submit ?? this.defaultOptions.submit,
|
|
4984
|
+
usdSponsor: options?.usdSponsor ?? this.defaultOptions.usdSponsor,
|
|
4985
|
+
chunksetSizeBytes: options?.chunksetSizeBytes ?? this.defaultOptions.chunksetSizeBytes
|
|
4986
|
+
};
|
|
4987
|
+
}
|
|
4988
|
+
/**
|
|
4989
|
+
* Validates that if USD sponsorship is requested, a transaction submitter is
|
|
4990
|
+
* configured as well. Checks both the client-level and method-level transaction
|
|
4991
|
+
* submitter configurations. Throws MissingTransactionSubmitterError if usdSponsor is
|
|
4992
|
+
* provided without a transaction submitter.
|
|
4993
|
+
*/
|
|
4994
|
+
validateUsdSponsorConfig(usdSponsor, submit) {
|
|
4995
|
+
if (!usdSponsor) {
|
|
4996
|
+
return;
|
|
4997
|
+
}
|
|
4998
|
+
const hasClientSubmitter = this.aptos.config.getTransactionSubmitter();
|
|
4999
|
+
const hasMethodSubmitter = submit?.transactionSubmitter !== void 0 && submit?.transactionSubmitter !== null;
|
|
5000
|
+
if (!hasClientSubmitter && !hasMethodSubmitter) {
|
|
5001
|
+
throw new MissingTransactionSubmitterError();
|
|
5002
|
+
}
|
|
5003
|
+
}
|
|
5004
|
+
/**
|
|
5005
|
+
* Retrieves the blob metadata from the blockchain. If it does not exist,
|
|
5006
|
+
* returns `undefined`.
|
|
4821
5007
|
*
|
|
4822
|
-
* @
|
|
4823
|
-
*
|
|
4824
|
-
* @
|
|
4825
|
-
* @throws StaleChannelStateError if the micropayment is stale (server has newer state).
|
|
5008
|
+
* @param params.account - The account namespace the blob is stored in (e.g. "0x1")
|
|
5009
|
+
* @param params.name - The name of the blob (e.g. "foo/bar")
|
|
5010
|
+
* @returns The blob metadata.
|
|
4826
5011
|
*
|
|
4827
5012
|
* @example
|
|
4828
5013
|
* ```typescript
|
|
4829
|
-
*
|
|
4830
|
-
*
|
|
4831
|
-
*
|
|
4832
|
-
* blobName: "documents/report.pdf"
|
|
4833
|
-
* });
|
|
4834
|
-
*
|
|
4835
|
-
* // Download partial content (bytes 100-199)
|
|
4836
|
-
* const partial = await client.getBlob({
|
|
4837
|
-
* account: AccountAddress.from("0x1"),
|
|
4838
|
-
* blobName: "large-file.bin",
|
|
4839
|
-
* range: { start: 100, end: 199 }
|
|
4840
|
-
* });
|
|
4841
|
-
*
|
|
4842
|
-
* // Download with micropayment
|
|
4843
|
-
* const blob = await client.getBlob({
|
|
4844
|
-
* account: AccountAddress.from("0x1"),
|
|
4845
|
-
* blobName: "documents/report.pdf",
|
|
4846
|
-
* micropayment: senderBuiltMicropayment
|
|
5014
|
+
* const metadata = await client.getBlobMetadata({
|
|
5015
|
+
* account: AccountAddress.fromString("0x1"),
|
|
5016
|
+
* name: "foo/bar.txt",
|
|
4847
5017
|
* });
|
|
4848
5018
|
* ```
|
|
4849
5019
|
*/
|
|
4850
|
-
async
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
if (end === void 0) {
|
|
4862
|
-
headers.set("Range", `bytes=${start}-`);
|
|
4863
|
-
} else {
|
|
4864
|
-
if (end < start) {
|
|
4865
|
-
throw new Error("Range end cannot be less than start.");
|
|
5020
|
+
async getBlobMetadata(params) {
|
|
5021
|
+
try {
|
|
5022
|
+
const rawMetadata = await this.aptos.view({
|
|
5023
|
+
payload: {
|
|
5024
|
+
function: `${this.deployer.toString()}::blob_metadata::get_blob_metadata`,
|
|
5025
|
+
functionArguments: [
|
|
5026
|
+
createBlobKey({
|
|
5027
|
+
account: params.account,
|
|
5028
|
+
blobName: params.name
|
|
5029
|
+
})
|
|
5030
|
+
]
|
|
4866
5031
|
}
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
if (this.apiKey) {
|
|
4871
|
-
headers.set("Authorization", `Bearer ${this.apiKey}`);
|
|
4872
|
-
}
|
|
4873
|
-
if (params.micropayment) {
|
|
4874
|
-
const bytes = params.micropayment.bcsToBytes();
|
|
4875
|
-
const binaryString = Array.from(
|
|
4876
|
-
bytes,
|
|
4877
|
-
(byte) => String.fromCharCode(byte)
|
|
4878
|
-
).join("");
|
|
4879
|
-
headers.set(MICROPAYMENT_HEADER, btoa(binaryString));
|
|
4880
|
-
}
|
|
4881
|
-
const response = await fetch(url, { headers });
|
|
4882
|
-
if (response.status === 409) {
|
|
4883
|
-
let json;
|
|
4884
|
-
try {
|
|
4885
|
-
json = await response.json();
|
|
4886
|
-
} catch {
|
|
4887
|
-
throw new Error(
|
|
4888
|
-
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
4889
|
-
);
|
|
5032
|
+
});
|
|
5033
|
+
if (!rawMetadata?.[0]?.vec?.[0]) {
|
|
5034
|
+
return void 0;
|
|
4890
5035
|
}
|
|
4891
|
-
const
|
|
4892
|
-
|
|
5036
|
+
const metadata = rawMetadata[0].vec[0];
|
|
5037
|
+
let encoding;
|
|
5038
|
+
if (metadata.encoding.__variant__ === "ClayCode_16Total_10Data_13Helper") {
|
|
5039
|
+
console.log("read blob metadata with ClayCode_16Total_10Data_13Helper");
|
|
5040
|
+
encoding = {
|
|
5041
|
+
variant: "clay",
|
|
5042
|
+
...ERASURE_CODE_PARAMS[metadata.encoding.__variant__],
|
|
5043
|
+
...ERASURE_CODE_AND_CHUNK_MAPPING[metadata.encoding.__variant__]
|
|
5044
|
+
};
|
|
5045
|
+
} else if (metadata.encoding.__variant__ === "ClayCode_4Total_2Data_3Helper") {
|
|
5046
|
+
console.log("read blob metadata with ClayCode_4Total_2Data_3Helper");
|
|
5047
|
+
encoding = {
|
|
5048
|
+
variant: "clay",
|
|
5049
|
+
...ERASURE_CODE_PARAMS[metadata.encoding.__variant__],
|
|
5050
|
+
...ERASURE_CODE_AND_CHUNK_MAPPING[metadata.encoding.__variant__]
|
|
5051
|
+
};
|
|
5052
|
+
} else {
|
|
4893
5053
|
throw new Error(
|
|
4894
|
-
|
|
5054
|
+
"Could not parse encoding from Shelby Smart Contract, this SDK is out of date."
|
|
4895
5055
|
);
|
|
4896
5056
|
}
|
|
4897
|
-
|
|
4898
|
-
|
|
4899
|
-
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
5057
|
+
return {
|
|
5058
|
+
blobMerkleRoot: Hex3.fromHexInput(
|
|
5059
|
+
metadata.blob_commitment
|
|
5060
|
+
).toUint8Array(),
|
|
5061
|
+
owner: AccountAddress2.fromString(metadata.owner),
|
|
5062
|
+
name: params.name,
|
|
5063
|
+
blobNameSuffix: getBlobNameSuffix(params.name),
|
|
5064
|
+
size: Number(metadata.blob_size),
|
|
5065
|
+
encoding,
|
|
5066
|
+
expirationMicros: Number(metadata.expiration_micros),
|
|
5067
|
+
creationMicros: Number(metadata.creation_micros),
|
|
5068
|
+
sliceAddress: AccountAddress2.fromString(metadata.slice.inner),
|
|
5069
|
+
isWritten: metadata.is_written
|
|
5070
|
+
};
|
|
5071
|
+
} catch (error) {
|
|
5072
|
+
if (error instanceof Error && // Depending on the network, the error message may show up differently.
|
|
5073
|
+
(error.message?.includes("sub_status: Some(404)") || error.message?.includes("EBLOB_NOT_FOUND"))) {
|
|
5074
|
+
return void 0;
|
|
4903
5075
|
}
|
|
4904
|
-
throw
|
|
4905
|
-
errorBody.error ?? `Failed to download blob: ${response.status} ${response.statusText}`
|
|
4906
|
-
);
|
|
4907
|
-
}
|
|
4908
|
-
if (!response.ok) {
|
|
4909
|
-
throw new Error(
|
|
4910
|
-
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
4911
|
-
);
|
|
4912
|
-
}
|
|
4913
|
-
if (!response.body) {
|
|
4914
|
-
throw new Error("Response body is null");
|
|
4915
|
-
}
|
|
4916
|
-
const contentLengthHeader = response.headers.get("content-length");
|
|
4917
|
-
if (contentLengthHeader === null) {
|
|
4918
|
-
throw new Error(
|
|
4919
|
-
"Response did not have content-length header, which is required"
|
|
4920
|
-
);
|
|
4921
|
-
}
|
|
4922
|
-
const expectedContentLength = Number.parseInt(contentLengthHeader, 10);
|
|
4923
|
-
if (Number.isNaN(expectedContentLength)) {
|
|
4924
|
-
throw new Error(
|
|
4925
|
-
`Invalid content-length header received: ${contentLengthHeader}`
|
|
4926
|
-
);
|
|
5076
|
+
throw error;
|
|
4927
5077
|
}
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
4937
|
-
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
controller.error(error);
|
|
4956
|
-
});
|
|
4957
|
-
}
|
|
4958
|
-
return pump();
|
|
4959
|
-
}
|
|
5078
|
+
}
|
|
5079
|
+
/**
|
|
5080
|
+
* Retrieves all the blobs and their metadata for an account from the
|
|
5081
|
+
* blockchain.
|
|
5082
|
+
*
|
|
5083
|
+
* @param params.account - The account namespace the blobs are stored in (e.g. "0x1")
|
|
5084
|
+
* @param params.pagination (optional) - The pagination options.
|
|
5085
|
+
* @param params.orderBy (optional) - The order by clause to sort the blobs by.
|
|
5086
|
+
* @returns The blob metadata for all the blobs for the account.
|
|
5087
|
+
*
|
|
5088
|
+
* @example
|
|
5089
|
+
* ```typescript
|
|
5090
|
+
* // BlobMetadata[]
|
|
5091
|
+
* const blobs = await client.getAccountBlobs({
|
|
5092
|
+
* account: AccountAddress.fromString("0x1"),
|
|
5093
|
+
* });
|
|
5094
|
+
* ```
|
|
5095
|
+
*/
|
|
5096
|
+
getAccountBlobs(params) {
|
|
5097
|
+
const { where, ...rest } = params;
|
|
5098
|
+
return this.getBlobs({
|
|
5099
|
+
where: {
|
|
5100
|
+
...where,
|
|
5101
|
+
owner: { _eq: AccountAddress2.from(params.account).toString() }
|
|
5102
|
+
},
|
|
5103
|
+
pagination: rest.pagination,
|
|
5104
|
+
orderBy: rest.orderBy
|
|
4960
5105
|
});
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
5106
|
+
}
|
|
5107
|
+
/**
|
|
5108
|
+
* Retrieves blobs and their metadata from the blockchain.
|
|
5109
|
+
*
|
|
5110
|
+
* @param params.where (optional) - The where clause to filter the blobs by.
|
|
5111
|
+
* @param params.pagination (optional) - The pagination options.
|
|
5112
|
+
* @param params.orderBy (optional) - The order by clause to sort the blobs by.
|
|
5113
|
+
* @returns The blob metadata for all the blobs that match the where clause.
|
|
5114
|
+
*
|
|
5115
|
+
* @example
|
|
5116
|
+
* ```typescript
|
|
5117
|
+
* // BlobMetadata[]
|
|
5118
|
+
* const blobs = await client.getBlobs({
|
|
5119
|
+
* where: { owner: { _eq: AccountAddress.fromString("0x1").toString() } },
|
|
5120
|
+
* });
|
|
5121
|
+
* ```
|
|
5122
|
+
*/
|
|
5123
|
+
async getBlobs(params = {}) {
|
|
5124
|
+
const { limit, offset } = params.pagination ?? {};
|
|
5125
|
+
const { orderBy, where } = params;
|
|
5126
|
+
const currentMicros = String(Date.now() * 1e3);
|
|
5127
|
+
const defaultActiveFilter = {
|
|
5128
|
+
expires_at: { _gte: currentMicros },
|
|
5129
|
+
is_deleted: { _eq: "0" }
|
|
4966
5130
|
};
|
|
5131
|
+
const finalWhere = where !== void 0 ? { ...defaultActiveFilter, ...where } : defaultActiveFilter;
|
|
5132
|
+
const { blobs } = await this.indexer.getBlobs({
|
|
5133
|
+
where: finalWhere,
|
|
5134
|
+
limit,
|
|
5135
|
+
offset,
|
|
5136
|
+
orderBy
|
|
5137
|
+
});
|
|
5138
|
+
return blobs.map(
|
|
5139
|
+
(blob) => ({
|
|
5140
|
+
owner: AccountAddress2.from(blob.owner),
|
|
5141
|
+
name: blob.blob_name,
|
|
5142
|
+
blobNameSuffix: getBlobNameSuffix(blob.blob_name),
|
|
5143
|
+
blobMerkleRoot: Hex3.fromHexInput(blob.blob_commitment).toUint8Array(),
|
|
5144
|
+
size: Number(blob.size),
|
|
5145
|
+
// TODO: Add encoding when supported in NCI
|
|
5146
|
+
encoding: {
|
|
5147
|
+
variant: "clay",
|
|
5148
|
+
...ERASURE_CODE_PARAMS.ClayCode_16Total_10Data_13Helper,
|
|
5149
|
+
...ERASURE_CODE_AND_CHUNK_MAPPING.ClayCode_16Total_10Data_13Helper
|
|
5150
|
+
},
|
|
5151
|
+
expirationMicros: Number(blob.expires_at),
|
|
5152
|
+
creationMicros: Number(blob.created_at),
|
|
5153
|
+
sliceAddress: AccountAddress2.from(blob.slice_address),
|
|
5154
|
+
isWritten: Boolean(Number(blob.is_written)),
|
|
5155
|
+
isDeleted: Boolean(Number(blob.is_deleted))
|
|
5156
|
+
})
|
|
5157
|
+
);
|
|
4967
5158
|
}
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
if (rawSize === 0) return 1;
|
|
4999
|
-
return Math.ceil(rawSize / chunksetSize);
|
|
5000
|
-
}
|
|
5001
|
-
var BlobCommitmentsSchema = z3.object({
|
|
5002
|
-
schema_version: z3.string(),
|
|
5003
|
-
raw_data_size: z3.number(),
|
|
5004
|
-
// FIXME I am not sure about this being here, or if it should be somewhere else
|
|
5005
|
-
blob_merkle_root: z3.string(),
|
|
5006
|
-
chunkset_commitments: z3.array(ChunksetCommitmentSchema)
|
|
5007
|
-
}).refine(
|
|
5008
|
-
(data) => {
|
|
5009
|
-
return expectedTotalChunksets(data.raw_data_size) === data.chunkset_commitments.length;
|
|
5010
|
-
},
|
|
5011
|
-
{
|
|
5012
|
-
message: "Total chunkset count mismatches with raw data size",
|
|
5013
|
-
// FIXME put more details in here
|
|
5014
|
-
path: ["chunkset_commitments"]
|
|
5015
|
-
}
|
|
5016
|
-
);
|
|
5017
|
-
async function generateMerkleRoot(leafHashes) {
|
|
5018
|
-
if (!leafHashes.length) {
|
|
5019
|
-
throw new Error(
|
|
5020
|
-
"An empty array cannot be used to construct a Merkle tree."
|
|
5021
|
-
);
|
|
5022
|
-
}
|
|
5023
|
-
const zeroArray = new Uint8Array(leafHashes[0].toUint8Array().length);
|
|
5024
|
-
const zeroBytes = Hex4.fromHexInput(zeroArray);
|
|
5025
|
-
let currentLeaves = leafHashes;
|
|
5026
|
-
while (currentLeaves.length > 1) {
|
|
5027
|
-
if (currentLeaves.length % 2 !== 0) {
|
|
5028
|
-
currentLeaves.push(zeroBytes);
|
|
5029
|
-
}
|
|
5030
|
-
const nextLeaves = [];
|
|
5031
|
-
for (let i = 0; i < currentLeaves.length; i += 2) {
|
|
5032
|
-
nextLeaves.push(
|
|
5033
|
-
await concatHashes([
|
|
5034
|
-
currentLeaves[i].toUint8Array(),
|
|
5035
|
-
currentLeaves[i + 1].toUint8Array()
|
|
5036
|
-
])
|
|
5037
|
-
);
|
|
5038
|
-
}
|
|
5039
|
-
currentLeaves = nextLeaves;
|
|
5040
|
-
}
|
|
5041
|
-
return currentLeaves[0];
|
|
5042
|
-
}
|
|
5043
|
-
async function generateChunksetCommitments(shouldPad, chunksetIdx, chunksetData, expectedChunksetSize, provider, onChunk) {
|
|
5044
|
-
const { erasure_n } = provider.config;
|
|
5045
|
-
const chunksetPayload = shouldPad ? zeroPadBytes(chunksetData, expectedChunksetSize) : validatePrePaddedChunkset(
|
|
5046
|
-
chunksetData,
|
|
5047
|
-
expectedChunksetSize,
|
|
5048
|
-
chunksetIdx
|
|
5049
|
-
);
|
|
5050
|
-
const { chunks } = provider.encode(chunksetPayload);
|
|
5051
|
-
if (chunks.length !== erasure_n) {
|
|
5052
|
-
throw new Error(
|
|
5053
|
-
`Erasure provider produced ${chunks.length} chunks, expected ${erasure_n}.`
|
|
5054
|
-
);
|
|
5055
|
-
}
|
|
5056
|
-
const chunkRoots = provider.getChunkMerkleRoots();
|
|
5057
|
-
let chunkIdx = 0;
|
|
5058
|
-
for (const chunkData of chunks) {
|
|
5059
|
-
if (onChunk !== void 0) {
|
|
5060
|
-
await onChunk(chunksetIdx, chunkIdx, chunkData);
|
|
5061
|
-
}
|
|
5062
|
-
chunkIdx += 1;
|
|
5063
|
-
}
|
|
5064
|
-
const a = await generateMerkleRoot(
|
|
5065
|
-
chunkRoots.map((a2) => Hex4.fromHexInput(a2))
|
|
5066
|
-
);
|
|
5067
|
-
const entry = {
|
|
5068
|
-
chunkset_root: a.toString(),
|
|
5069
|
-
chunk_commitments: chunkRoots.map(
|
|
5070
|
-
(chunk) => Hex4.fromHexInput(chunk).toString()
|
|
5071
|
-
)
|
|
5072
|
-
};
|
|
5073
|
-
return { h: a, entry };
|
|
5074
|
-
}
|
|
5075
|
-
async function generateCommitments(provider, fullData, onChunk, options) {
|
|
5076
|
-
const expectedChunksetSize = DEFAULT_CHUNKSET_SIZE_BYTES;
|
|
5077
|
-
const shouldPad = options?.pad ?? true;
|
|
5078
|
-
const chunksetCommitments = [];
|
|
5079
|
-
const chunksetCommitmentHashes = [];
|
|
5080
|
-
let rawDataSize = 0;
|
|
5081
|
-
const chunksetGen = readInChunks(fullData, expectedChunksetSize);
|
|
5082
|
-
for await (const [chunksetIdx, chunksetData] of chunksetGen) {
|
|
5083
|
-
rawDataSize += chunksetData.length;
|
|
5084
|
-
const { h, entry } = await generateChunksetCommitments(
|
|
5085
|
-
shouldPad,
|
|
5086
|
-
chunksetIdx,
|
|
5087
|
-
chunksetData,
|
|
5088
|
-
expectedChunksetSize,
|
|
5089
|
-
provider,
|
|
5090
|
-
onChunk
|
|
5091
|
-
);
|
|
5092
|
-
chunksetCommitments.push(entry);
|
|
5093
|
-
chunksetCommitmentHashes.push(h);
|
|
5094
|
-
}
|
|
5095
|
-
if (rawDataSize === 0) {
|
|
5096
|
-
const zeroChunkset = new Uint8Array(expectedChunksetSize);
|
|
5097
|
-
const { h, entry } = await generateChunksetCommitments(
|
|
5098
|
-
shouldPad,
|
|
5099
|
-
0,
|
|
5100
|
-
zeroChunkset,
|
|
5101
|
-
expectedChunksetSize,
|
|
5102
|
-
provider,
|
|
5103
|
-
onChunk
|
|
5104
|
-
);
|
|
5105
|
-
chunksetCommitments.push(entry);
|
|
5106
|
-
chunksetCommitmentHashes.push(h);
|
|
5107
|
-
}
|
|
5108
|
-
return {
|
|
5109
|
-
schema_version: COMMITMENT_SCHEMA_VERSION,
|
|
5110
|
-
raw_data_size: rawDataSize,
|
|
5111
|
-
blob_merkle_root: (await generateMerkleRoot(chunksetCommitmentHashes)).toString(),
|
|
5112
|
-
chunkset_commitments: chunksetCommitments
|
|
5113
|
-
};
|
|
5114
|
-
}
|
|
5115
|
-
function validatePrePaddedChunkset(chunkset, expectedSize, chunksetIdx) {
|
|
5116
|
-
if (chunkset.byteLength !== expectedSize) {
|
|
5117
|
-
throw new Error(
|
|
5118
|
-
`Chunkset ${chunksetIdx} has size ${chunkset.byteLength} bytes but expected ${expectedSize} bytes. Enable padding or supply pre-padded data before calling generateCommitments.`
|
|
5159
|
+
async getBlobActivities(params) {
|
|
5160
|
+
const { limit, offset } = params.pagination ?? {};
|
|
5161
|
+
const { orderBy, where } = params;
|
|
5162
|
+
const { blob_activities } = await this.indexer.getBlobActivities({
|
|
5163
|
+
where,
|
|
5164
|
+
limit,
|
|
5165
|
+
offset,
|
|
5166
|
+
orderBy
|
|
5167
|
+
});
|
|
5168
|
+
const activityTypeMapping = {
|
|
5169
|
+
[`${this.deployer.toStringLong()}::blob_metadata::BlobRegisteredEvent`]: "register_blob",
|
|
5170
|
+
[`${this.deployer.toStringLong()}::blob_metadata::BlobDeletedEvent`]: "delete_blob",
|
|
5171
|
+
[`${this.deployer.toStringLong()}::blob_metadata::BlobExpirationExtendedEvent`]: "extend_blob_expiration",
|
|
5172
|
+
[`${this.deployer.toStringLong()}::blob_metadata::BlobWrittenEvent`]: "write_blob"
|
|
5173
|
+
};
|
|
5174
|
+
return blob_activities.map(
|
|
5175
|
+
(activity) => ({
|
|
5176
|
+
blobName: activity.blob_name,
|
|
5177
|
+
accountAddress: AccountAddress2.from(
|
|
5178
|
+
activity.blob_name.substring(1, 65)
|
|
5179
|
+
),
|
|
5180
|
+
type: activityTypeMapping[activity.event_type] ?? "unknown",
|
|
5181
|
+
eventType: activity.event_type,
|
|
5182
|
+
eventIndex: Number(activity.event_index),
|
|
5183
|
+
transactionHash: activity.transaction_hash,
|
|
5184
|
+
// Using Number here in JS is technically not okay because txn version can be
|
|
5185
|
+
// as large as u64::MAX, but it should be fine for a long while.
|
|
5186
|
+
transactionVersion: Number(activity.transaction_version),
|
|
5187
|
+
timestamp: `${activity.timestamp}Z`
|
|
5188
|
+
})
|
|
5119
5189
|
);
|
|
5120
5190
|
}
|
|
5121
|
-
return chunkset;
|
|
5122
|
-
}
|
|
5123
|
-
|
|
5124
|
-
// ../../packages/sdk/dist/chunk-JWVMZ2Y7.mjs
|
|
5125
|
-
import {
|
|
5126
|
-
AccountAddress as AccountAddress5,
|
|
5127
|
-
Aptos as Aptos2,
|
|
5128
|
-
AptosConfig as AptosConfig2,
|
|
5129
|
-
Hex as Hex5,
|
|
5130
|
-
MoveVector,
|
|
5131
|
-
U32
|
|
5132
|
-
} from "@aptos-labs/ts-sdk";
|
|
5133
|
-
var ShelbyBlobClient = class _ShelbyBlobClient {
|
|
5134
|
-
aptos;
|
|
5135
|
-
deployer;
|
|
5136
|
-
indexer;
|
|
5137
5191
|
/**
|
|
5138
|
-
*
|
|
5139
|
-
* includes functions for registering blob commitments and retrieving blob metadata.
|
|
5192
|
+
* Retrieves the total number of blobs from the blockchain.
|
|
5140
5193
|
*
|
|
5141
|
-
* @param
|
|
5142
|
-
* @
|
|
5194
|
+
* @param params.where (optional) - The where clause to filter the blobs by.
|
|
5195
|
+
* @returns The total number of blobs.
|
|
5143
5196
|
*
|
|
5144
5197
|
* @example
|
|
5145
5198
|
* ```typescript
|
|
5146
|
-
* const
|
|
5147
|
-
* aptos: {
|
|
5148
|
-
* network: Network.SHELBYNET,
|
|
5149
|
-
* clientConfig: {
|
|
5150
|
-
* API_KEY: "AG-***",
|
|
5151
|
-
* },
|
|
5152
|
-
* },
|
|
5153
|
-
* });
|
|
5199
|
+
* const count = await client.getBlobsCount();
|
|
5154
5200
|
* ```
|
|
5155
5201
|
*/
|
|
5156
|
-
|
|
5157
|
-
const
|
|
5158
|
-
const
|
|
5159
|
-
|
|
5160
|
-
clientConfig: {
|
|
5161
|
-
...baseAptosConfig.clientConfig,
|
|
5162
|
-
// Only use top-level apiKey if no API_KEY is already provided in Aptos settings
|
|
5163
|
-
API_KEY: baseAptosConfig.clientConfig?.API_KEY ?? config.apiKey
|
|
5164
|
-
}
|
|
5165
|
-
});
|
|
5166
|
-
this.aptos = new Aptos2(aptosConfig);
|
|
5167
|
-
this.deployer = config.deployer ?? AccountAddress5.fromString(SHELBY_DEPLOYER);
|
|
5168
|
-
this.indexer = getShelbyIndexerClient(config);
|
|
5202
|
+
async getBlobsCount(params) {
|
|
5203
|
+
const { where } = params;
|
|
5204
|
+
const { blobs_aggregate } = await this.indexer.getBlobsCount({ where });
|
|
5205
|
+
return blobs_aggregate?.aggregate?.count ?? 0;
|
|
5169
5206
|
}
|
|
5170
5207
|
/**
|
|
5171
|
-
* Retrieves the blob
|
|
5172
|
-
* returns `undefined`.
|
|
5208
|
+
* Retrieves the total number of blob activities from the blockchain.
|
|
5173
5209
|
*
|
|
5174
|
-
* @param params.
|
|
5175
|
-
* @
|
|
5176
|
-
* @returns The blob metadata.
|
|
5210
|
+
* @param params.where (optional) - The where clause to filter the blob activities by.
|
|
5211
|
+
* @returns The total number of blob activities.
|
|
5177
5212
|
*
|
|
5178
5213
|
* @example
|
|
5179
5214
|
* ```typescript
|
|
5180
|
-
* const
|
|
5181
|
-
* account: AccountAddress.fromString("0x1"),
|
|
5182
|
-
* name: "foo/bar.txt",
|
|
5183
|
-
* });
|
|
5215
|
+
* const count = await client.getBlobActivitiesCount();
|
|
5184
5216
|
* ```
|
|
5185
5217
|
*/
|
|
5186
|
-
async
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
function: `${this.deployer.toString()}::blob_metadata::get_blob_metadata`,
|
|
5191
|
-
functionArguments: [
|
|
5192
|
-
createBlobKey({
|
|
5193
|
-
account: params.account,
|
|
5194
|
-
blobName: params.name
|
|
5195
|
-
})
|
|
5196
|
-
]
|
|
5197
|
-
}
|
|
5198
|
-
});
|
|
5199
|
-
if (!rawMetadata?.[0]?.vec?.[0]) {
|
|
5200
|
-
return void 0;
|
|
5201
|
-
}
|
|
5202
|
-
const metadata = rawMetadata[0].vec[0];
|
|
5203
|
-
let encoding;
|
|
5204
|
-
if (metadata.encoding.__variant__ === "ClayCode_16Total_10Data_13Helper") {
|
|
5205
|
-
encoding = {
|
|
5206
|
-
variant: "clay",
|
|
5207
|
-
...ERASURE_CODE_PARAMS[metadata.encoding.__variant__],
|
|
5208
|
-
...ERASURE_CODE_AND_CHUNK_MAPPING[metadata.encoding.__variant__]
|
|
5209
|
-
};
|
|
5210
|
-
} else {
|
|
5211
|
-
throw new Error(
|
|
5212
|
-
"Could not parse encoding from Shelby Smart Contract, this SDK is out of date."
|
|
5213
|
-
);
|
|
5214
|
-
}
|
|
5215
|
-
return {
|
|
5216
|
-
blobMerkleRoot: Hex5.fromHexInput(
|
|
5217
|
-
metadata.blob_commitment
|
|
5218
|
-
).toUint8Array(),
|
|
5219
|
-
owner: AccountAddress5.fromString(metadata.owner),
|
|
5220
|
-
name: params.name,
|
|
5221
|
-
blobNameSuffix: getBlobNameSuffix(params.name),
|
|
5222
|
-
size: Number(metadata.blob_size),
|
|
5223
|
-
encoding,
|
|
5224
|
-
expirationMicros: Number(metadata.expiration_micros),
|
|
5225
|
-
creationMicros: Number(metadata.creation_micros),
|
|
5226
|
-
sliceAddress: AccountAddress5.fromString(metadata.slice.inner),
|
|
5227
|
-
isWritten: metadata.is_written
|
|
5228
|
-
};
|
|
5229
|
-
} catch (error) {
|
|
5230
|
-
if (error instanceof Error && // Depending on the network, the error message may show up differently.
|
|
5231
|
-
(error.message?.includes("sub_status: Some(404)") || error.message?.includes("EBLOB_NOT_FOUND"))) {
|
|
5232
|
-
return void 0;
|
|
5233
|
-
}
|
|
5234
|
-
throw error;
|
|
5235
|
-
}
|
|
5218
|
+
async getBlobActivitiesCount(params) {
|
|
5219
|
+
const { where } = params;
|
|
5220
|
+
const { blob_activities_aggregate } = await this.indexer.getBlobActivitiesCount({ where });
|
|
5221
|
+
return blob_activities_aggregate?.aggregate?.count ?? 0;
|
|
5236
5222
|
}
|
|
5237
5223
|
/**
|
|
5238
|
-
*
|
|
5239
|
-
* blockchain.
|
|
5240
|
-
*
|
|
5241
|
-
* @param params.account - The account namespace the blobs are stored in (e.g. "0x1")
|
|
5242
|
-
* @param params.pagination (optional) - The pagination options.
|
|
5243
|
-
* @param params.orderBy (optional) - The order by clause to sort the blobs by.
|
|
5244
|
-
* @returns The blob metadata for all the blobs for the account.
|
|
5245
|
-
*
|
|
5246
|
-
* @example
|
|
5247
|
-
* ```typescript
|
|
5248
|
-
* // BlobMetadata[]
|
|
5249
|
-
* const blobs = await client.getAccountBlobs({
|
|
5250
|
-
* account: AccountAddress.fromString("0x1"),
|
|
5251
|
-
* });
|
|
5252
|
-
* ```
|
|
5253
|
-
*/
|
|
5254
|
-
getAccountBlobs(params) {
|
|
5255
|
-
const { where, ...rest } = params;
|
|
5256
|
-
return this.getBlobs({
|
|
5257
|
-
where: {
|
|
5258
|
-
...where ?? {},
|
|
5259
|
-
owner: { _eq: AccountAddress5.from(params.account).toString() }
|
|
5260
|
-
},
|
|
5261
|
-
pagination: rest.pagination,
|
|
5262
|
-
orderBy: rest.orderBy
|
|
5263
|
-
});
|
|
5264
|
-
}
|
|
5265
|
-
/**
|
|
5266
|
-
* Retrieves blobs and their metadata from the blockchain.
|
|
5267
|
-
*
|
|
5268
|
-
* @param params.where (optional) - The where clause to filter the blobs by.
|
|
5269
|
-
* @param params.pagination (optional) - The pagination options.
|
|
5270
|
-
* @param params.orderBy (optional) - The order by clause to sort the blobs by.
|
|
5271
|
-
* @returns The blob metadata for all the blobs that match the where clause.
|
|
5272
|
-
*
|
|
5273
|
-
* @example
|
|
5274
|
-
* ```typescript
|
|
5275
|
-
* // BlobMetadata[]
|
|
5276
|
-
* const blobs = await client.getBlobs({
|
|
5277
|
-
* where: { owner: { _eq: AccountAddress.fromString("0x1").toString() } },
|
|
5278
|
-
* });
|
|
5279
|
-
* ```
|
|
5280
|
-
*/
|
|
5281
|
-
async getBlobs(params = {}) {
|
|
5282
|
-
const { limit, offset } = params.pagination ?? {};
|
|
5283
|
-
const { orderBy, where } = params;
|
|
5284
|
-
const currentMicros = Date.now() * 1e3;
|
|
5285
|
-
const defaultActiveFilter = {
|
|
5286
|
-
expires_at: { _gte: currentMicros },
|
|
5287
|
-
is_deleted: { _eq: "0" }
|
|
5288
|
-
};
|
|
5289
|
-
const finalWhere = where !== void 0 ? { ...defaultActiveFilter, ...where } : defaultActiveFilter;
|
|
5290
|
-
const { blobs } = await this.indexer.getBlobs({
|
|
5291
|
-
where: finalWhere,
|
|
5292
|
-
limit,
|
|
5293
|
-
offset,
|
|
5294
|
-
orderBy
|
|
5295
|
-
});
|
|
5296
|
-
return blobs.map(
|
|
5297
|
-
(blob) => ({
|
|
5298
|
-
owner: AccountAddress5.from(blob.owner),
|
|
5299
|
-
name: blob.blob_name,
|
|
5300
|
-
blobNameSuffix: getBlobNameSuffix(blob.blob_name),
|
|
5301
|
-
blobMerkleRoot: Hex5.fromHexInput(blob.blob_commitment).toUint8Array(),
|
|
5302
|
-
size: Number(blob.size),
|
|
5303
|
-
// TODO: Add encoding when supported in NCI
|
|
5304
|
-
encoding: {
|
|
5305
|
-
variant: "clay",
|
|
5306
|
-
...ERASURE_CODE_PARAMS.ClayCode_16Total_10Data_13Helper,
|
|
5307
|
-
...ERASURE_CODE_AND_CHUNK_MAPPING.ClayCode_16Total_10Data_13Helper
|
|
5308
|
-
},
|
|
5309
|
-
expirationMicros: Number(blob.expires_at),
|
|
5310
|
-
creationMicros: Number(blob.created_at),
|
|
5311
|
-
sliceAddress: AccountAddress5.from(blob.slice_address),
|
|
5312
|
-
isWritten: Boolean(Number(blob.is_written))
|
|
5313
|
-
})
|
|
5314
|
-
);
|
|
5315
|
-
}
|
|
5316
|
-
async getBlobActivities(params) {
|
|
5317
|
-
const { limit, offset } = params.pagination ?? {};
|
|
5318
|
-
const { orderBy, where } = params;
|
|
5319
|
-
const { blob_activities } = await this.indexer.getBlobActivities({
|
|
5320
|
-
where,
|
|
5321
|
-
limit,
|
|
5322
|
-
offset,
|
|
5323
|
-
orderBy
|
|
5324
|
-
});
|
|
5325
|
-
const activityTypeMapping = {
|
|
5326
|
-
[`${this.deployer.toStringLong()}::blob_metadata::BlobRegisteredEvent`]: "register_blob",
|
|
5327
|
-
[`${this.deployer.toStringLong()}::blob_metadata::BlobDeletedEvent`]: "delete_blob",
|
|
5328
|
-
[`${this.deployer.toStringLong()}::blob_metadata::BlobExpirationExtendedEvent`]: "extend_blob_expiration",
|
|
5329
|
-
[`${this.deployer.toStringLong()}::blob_metadata::BlobWrittenEvent`]: "write_blob"
|
|
5330
|
-
};
|
|
5331
|
-
return blob_activities.map(
|
|
5332
|
-
(activity) => ({
|
|
5333
|
-
blobName: activity.blob_name,
|
|
5334
|
-
accountAddress: AccountAddress5.from(
|
|
5335
|
-
activity.blob_name.substring(1, 65)
|
|
5336
|
-
),
|
|
5337
|
-
type: activityTypeMapping[activity.event_type] ?? "unknown",
|
|
5338
|
-
eventType: activity.event_type,
|
|
5339
|
-
eventIndex: activity.event_index,
|
|
5340
|
-
transactionHash: activity.transaction_hash,
|
|
5341
|
-
transactionVersion: activity.transaction_version,
|
|
5342
|
-
timestamp: activity.timestamp
|
|
5343
|
-
})
|
|
5344
|
-
);
|
|
5345
|
-
}
|
|
5346
|
-
/**
|
|
5347
|
-
* Retrieves the total number of blobs from the blockchain.
|
|
5348
|
-
*
|
|
5349
|
-
* @param params.where (optional) - The where clause to filter the blobs by.
|
|
5350
|
-
* @returns The total number of blobs.
|
|
5351
|
-
*
|
|
5352
|
-
* @example
|
|
5353
|
-
* ```typescript
|
|
5354
|
-
* const count = await client.getBlobsCount();
|
|
5355
|
-
* ```
|
|
5356
|
-
*/
|
|
5357
|
-
async getBlobsCount(params) {
|
|
5358
|
-
const { where } = params;
|
|
5359
|
-
const { blobs_aggregate } = await this.indexer.getBlobsCount({ where });
|
|
5360
|
-
return blobs_aggregate?.aggregate?.count ?? 0;
|
|
5361
|
-
}
|
|
5362
|
-
/**
|
|
5363
|
-
* Retrieves the total number of blob activities from the blockchain.
|
|
5364
|
-
*
|
|
5365
|
-
* @param params.where (optional) - The where clause to filter the blob activities by.
|
|
5366
|
-
* @returns The total number of blob activities.
|
|
5367
|
-
*
|
|
5368
|
-
* @example
|
|
5369
|
-
* ```typescript
|
|
5370
|
-
* const count = await client.getBlobActivitiesCount();
|
|
5371
|
-
* ```
|
|
5372
|
-
*/
|
|
5373
|
-
async getBlobActivitiesCount(params) {
|
|
5374
|
-
const { where } = params;
|
|
5375
|
-
const { blob_activities_aggregate } = await this.indexer.getBlobActivitiesCount({ where });
|
|
5376
|
-
return blob_activities_aggregate?.aggregate?.count ?? 0;
|
|
5377
|
-
}
|
|
5378
|
-
/**
|
|
5379
|
-
* Registers a blob on the blockchain by writing its merkle root and metadata.
|
|
5224
|
+
* Registers a blob on the blockchain by writing its merkle root and metadata.
|
|
5380
5225
|
*
|
|
5381
5226
|
* @param params.account - The account that is signing and paying for the transaction.
|
|
5382
5227
|
* @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
|
|
@@ -5404,9 +5249,12 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
|
|
|
5404
5249
|
* ```
|
|
5405
5250
|
*/
|
|
5406
5251
|
async registerBlob(params) {
|
|
5407
|
-
const
|
|
5408
|
-
|
|
5409
|
-
|
|
5252
|
+
const options = this.mergeOptions(params.options);
|
|
5253
|
+
this.validateUsdSponsorConfig(options.usdSponsor, options.submit);
|
|
5254
|
+
const config = params.config ?? defaultErasureCodingConfig();
|
|
5255
|
+
const chunksetSize = config.chunkSizeBytes * config.erasure_k;
|
|
5256
|
+
const buildArgs = {
|
|
5257
|
+
...options.build,
|
|
5410
5258
|
data: _ShelbyBlobClient.createRegisterBlobPayload({
|
|
5411
5259
|
deployer: this.deployer,
|
|
5412
5260
|
account: params.account.accountAddress,
|
|
@@ -5414,14 +5262,21 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
|
|
|
5414
5262
|
blobSize: params.size,
|
|
5415
5263
|
blobMerkleRoot: params.blobMerkleRoot,
|
|
5416
5264
|
numChunksets: expectedTotalChunksets(params.size, chunksetSize),
|
|
5417
|
-
expirationMicros: params.expirationMicros
|
|
5265
|
+
expirationMicros: params.expirationMicros,
|
|
5266
|
+
useSponsoredUsdVariant: options.usdSponsor !== void 0,
|
|
5267
|
+
encoding: config.enumIndex
|
|
5418
5268
|
}),
|
|
5419
5269
|
sender: params.account.accountAddress
|
|
5420
|
-
}
|
|
5270
|
+
};
|
|
5271
|
+
const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
|
|
5272
|
+
...buildArgs,
|
|
5273
|
+
secondarySignerAddresses: [options.usdSponsor.feePayerAddress]
|
|
5274
|
+
}) : await this.aptos.transaction.build.simple(buildArgs);
|
|
5421
5275
|
return {
|
|
5422
5276
|
transaction: await this.aptos.signAndSubmitTransaction({
|
|
5423
5277
|
signer: params.account,
|
|
5424
|
-
transaction
|
|
5278
|
+
transaction,
|
|
5279
|
+
...options.submit
|
|
5425
5280
|
})
|
|
5426
5281
|
};
|
|
5427
5282
|
}
|
|
@@ -5580,9 +5435,12 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
|
|
|
5580
5435
|
* ```
|
|
5581
5436
|
*/
|
|
5582
5437
|
async batchRegisterBlobs(params) {
|
|
5583
|
-
const
|
|
5584
|
-
|
|
5585
|
-
|
|
5438
|
+
const options = this.mergeOptions(params.options);
|
|
5439
|
+
this.validateUsdSponsorConfig(options.usdSponsor, options.submit);
|
|
5440
|
+
const config = params.config ?? defaultErasureCodingConfig();
|
|
5441
|
+
const chunksetSize = config.chunkSizeBytes * config.erasure_k;
|
|
5442
|
+
const buildArgs = {
|
|
5443
|
+
...options.build,
|
|
5586
5444
|
sender: params.account.accountAddress,
|
|
5587
5445
|
data: _ShelbyBlobClient.createBatchRegisterBlobsPayload({
|
|
5588
5446
|
deployer: this.deployer,
|
|
@@ -5593,298 +5451,863 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
|
|
|
5593
5451
|
blobSize: blob.blobSize,
|
|
5594
5452
|
blobMerkleRoot: blob.blobMerkleRoot,
|
|
5595
5453
|
numChunksets: expectedTotalChunksets(blob.blobSize, chunksetSize)
|
|
5596
|
-
}))
|
|
5454
|
+
})),
|
|
5455
|
+
useSponsoredUsdVariant: options.usdSponsor !== void 0,
|
|
5456
|
+
encoding: config.enumIndex
|
|
5457
|
+
})
|
|
5458
|
+
};
|
|
5459
|
+
const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
|
|
5460
|
+
...buildArgs,
|
|
5461
|
+
secondarySignerAddresses: [options.usdSponsor.feePayerAddress]
|
|
5462
|
+
}) : await this.aptos.transaction.build.simple(buildArgs);
|
|
5463
|
+
return {
|
|
5464
|
+
transaction: await this.aptos.signAndSubmitTransaction({
|
|
5465
|
+
signer: params.account,
|
|
5466
|
+
transaction,
|
|
5467
|
+
...options.submit
|
|
5597
5468
|
})
|
|
5469
|
+
};
|
|
5470
|
+
}
|
|
5471
|
+
/**
|
|
5472
|
+
* Creates a transaction payload to register a blob on the blockchain.
|
|
5473
|
+
* This is a static helper method for constructing the Move function call payload.
|
|
5474
|
+
*
|
|
5475
|
+
* @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
|
|
5476
|
+
* @param params.account - The account that will own the blob.
|
|
5477
|
+
* @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
|
|
5478
|
+
* @param params.blobSize - The size of the blob in bytes.
|
|
5479
|
+
* @param params.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
|
|
5480
|
+
* @param params.expirationMicros - The expiration time of the blob in microseconds.
|
|
5481
|
+
* @param params.numChunksets - The total number of chunksets in the blob.
|
|
5482
|
+
*
|
|
5483
|
+
* @returns An Aptos transaction payload data object for the register_blob Move function.
|
|
5484
|
+
*
|
|
5485
|
+
* @see https://github.com/shelby/shelby/blob/e08e84742cf2b80ad8bb7227deb3013398076d53/move/shelby_contract/sources/global_metadata.move#L357
|
|
5486
|
+
*/
|
|
5487
|
+
static createRegisterBlobPayload(params) {
|
|
5488
|
+
const functionName = params.useSponsoredUsdVariant ? "register_blob_with_sponsor" : "register_blob";
|
|
5489
|
+
return {
|
|
5490
|
+
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
|
|
5491
|
+
functionArguments: [
|
|
5492
|
+
params.blobName,
|
|
5493
|
+
params.expirationMicros,
|
|
5494
|
+
Hex3.fromHexString(params.blobMerkleRoot).toUint8Array(),
|
|
5495
|
+
params.numChunksets,
|
|
5496
|
+
params.blobSize,
|
|
5497
|
+
// TODO
|
|
5498
|
+
0,
|
|
5499
|
+
// payment tier
|
|
5500
|
+
params.encoding
|
|
5501
|
+
]
|
|
5502
|
+
};
|
|
5503
|
+
}
|
|
5504
|
+
/**
|
|
5505
|
+
* Creates a transaction payload to register multiple blobs on the blockchain.
|
|
5506
|
+
* This is a static helper method for constructing the Move function call payload.
|
|
5507
|
+
*
|
|
5508
|
+
* @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
|
|
5509
|
+
* @param params.account - The account that will own the blobs.
|
|
5510
|
+
* @param params.expirationMicros - The expiration time of the blobs in microseconds.
|
|
5511
|
+
* @param params.blobs - The blobs to register.
|
|
5512
|
+
* @param params.blobs.blobName - The name/path of the blob (e.g. "foo/bar.txt").
|
|
5513
|
+
* @param params.blobs.blobSize - The size of the blob in bytes.
|
|
5514
|
+
* @param params.blobs.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
|
|
5515
|
+
* @param params.blobs.numChunksets - The total number of chunksets in the blob.
|
|
5516
|
+
*
|
|
5517
|
+
* @returns An Aptos transaction payload data object for the register_multiple_blobs Move function.
|
|
5518
|
+
*
|
|
5519
|
+
* @see https://github.com/shelby/shelby/blob/e08e84742cf2b80ad8bb7227deb3013398076d53/move/shelby_contract/sources/global_metadata.move#L357
|
|
5520
|
+
*/
|
|
5521
|
+
static createBatchRegisterBlobsPayload(params) {
|
|
5522
|
+
const functionName = params.useSponsoredUsdVariant ? "register_multiple_blobs_with_sponsor" : "register_multiple_blobs";
|
|
5523
|
+
const blobNames = [];
|
|
5524
|
+
const blobMerkleRoots = [];
|
|
5525
|
+
const blobNumChunksets = [];
|
|
5526
|
+
const blobSizes = [];
|
|
5527
|
+
params.blobs.forEach((blob) => {
|
|
5528
|
+
blobNames.push(blob.blobName);
|
|
5529
|
+
blobMerkleRoots.push(
|
|
5530
|
+
Hex3.fromHexString(blob.blobMerkleRoot).toUint8Array()
|
|
5531
|
+
);
|
|
5532
|
+
blobNumChunksets.push(blob.numChunksets);
|
|
5533
|
+
blobSizes.push(blob.blobSize);
|
|
5534
|
+
});
|
|
5535
|
+
return {
|
|
5536
|
+
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
|
|
5537
|
+
functionArguments: [
|
|
5538
|
+
blobNames,
|
|
5539
|
+
params.expirationMicros,
|
|
5540
|
+
blobMerkleRoots,
|
|
5541
|
+
blobNumChunksets,
|
|
5542
|
+
blobSizes,
|
|
5543
|
+
// TODO
|
|
5544
|
+
0,
|
|
5545
|
+
// payment tier
|
|
5546
|
+
params.encoding
|
|
5547
|
+
]
|
|
5548
|
+
};
|
|
5549
|
+
}
|
|
5550
|
+
/**
|
|
5551
|
+
* Creates a transaction payload to delete a blob on the blockchain.
|
|
5552
|
+
* This is a static helper method for constructing the Move function call payload.
|
|
5553
|
+
*
|
|
5554
|
+
* @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
|
|
5555
|
+
* @param params.blobName - The blob name (e.g. "bar.txt", without the account address prefix).
|
|
5556
|
+
*
|
|
5557
|
+
* @returns An Aptos transaction payload data object for the delete_blob Move function.
|
|
5558
|
+
*
|
|
5559
|
+
* @see https://github.com/shelby/shelby/blob/64e9d7b4f0005e586faeb1e4085c79159234b6b6/move/shelby_contract/sources/global_metadata.move#L616
|
|
5560
|
+
*/
|
|
5561
|
+
static createDeleteBlobPayload(params) {
|
|
5562
|
+
return {
|
|
5563
|
+
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_blob`,
|
|
5564
|
+
functionArguments: [params.blobName]
|
|
5565
|
+
};
|
|
5566
|
+
}
|
|
5567
|
+
/**
|
|
5568
|
+
* Creates a transaction payload to delete multiple blobs on the blockchain.
|
|
5569
|
+
* This is a static helper method for constructing the Move function call payload.
|
|
5570
|
+
*
|
|
5571
|
+
* **Note:** This function requires the `delete_multiple_blobs` entry function
|
|
5572
|
+
* which will be deployed to the smart contract on 2026-02-04. Using this
|
|
5573
|
+
* function before that date will result in a transaction failure.
|
|
5574
|
+
*
|
|
5575
|
+
* This operation is atomic: if any blob deletion fails (e.g., blob not found),
|
|
5576
|
+
* the entire transaction fails and no blobs are deleted.
|
|
5577
|
+
*
|
|
5578
|
+
* @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
|
|
5579
|
+
* @param params.blobNames - Array of blob name suffixes without the account address prefix
|
|
5580
|
+
* (e.g. ["foo/bar.txt", "baz.txt"], NOT ["0x1/foo/bar.txt"]). The account address
|
|
5581
|
+
* prefix is automatically derived from the transaction sender.
|
|
5582
|
+
*
|
|
5583
|
+
* @returns An Aptos transaction payload data object for the delete_multiple_blobs Move function.
|
|
5584
|
+
*
|
|
5585
|
+
* @see https://github.com/shelby/shelby/blob/main/move/shelby_contract/sources/blob_metadata.move
|
|
5586
|
+
*/
|
|
5587
|
+
static createDeleteMultipleBlobsPayload(params) {
|
|
5588
|
+
return {
|
|
5589
|
+
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_multiple_blobs`,
|
|
5590
|
+
functionArguments: [params.blobNames]
|
|
5591
|
+
};
|
|
5592
|
+
}
|
|
5593
|
+
static createChunksetAcknowledgementsPayload(params) {
|
|
5594
|
+
const ackBitMask = params.storageProviderAcks.reduce(
|
|
5595
|
+
(acc, ack) => acc | 1 << ack.slot,
|
|
5596
|
+
0
|
|
5597
|
+
);
|
|
5598
|
+
return {
|
|
5599
|
+
function: `${SHELBY_DEPLOYER}::blob_metadata::add_chunkset_acknowledgements`,
|
|
5600
|
+
functionArguments: [
|
|
5601
|
+
createBlobKey({
|
|
5602
|
+
account: params.blobOwner,
|
|
5603
|
+
blobName: params.blobName
|
|
5604
|
+
}),
|
|
5605
|
+
params.chunksetIdx,
|
|
5606
|
+
params.creationMicros,
|
|
5607
|
+
new U32(Number(ackBitMask)),
|
|
5608
|
+
params.storageProviderAcks.map((ack) => ack.signature)
|
|
5609
|
+
]
|
|
5610
|
+
};
|
|
5611
|
+
}
|
|
5612
|
+
};
|
|
5613
|
+
|
|
5614
|
+
// ../../packages/sdk/dist/chunk-MV6FNYAU.mjs
|
|
5615
|
+
import {
|
|
5616
|
+
AccountAddress as AccountAddress3,
|
|
5617
|
+
Aptos as Aptos2,
|
|
5618
|
+
Hex as Hex4
|
|
5619
|
+
} from "@aptos-labs/ts-sdk";
|
|
5620
|
+
function parseStorageProviderState(raw) {
|
|
5621
|
+
switch (raw.__variant__) {
|
|
5622
|
+
case "Active":
|
|
5623
|
+
return {
|
|
5624
|
+
variant: "Active",
|
|
5625
|
+
quota: raw.quota.value,
|
|
5626
|
+
stakeAtStartOfStakingEpoch: raw.stake_at_start_of_staking_epoch,
|
|
5627
|
+
faulty: raw.faulty,
|
|
5628
|
+
leaving: raw.leaving
|
|
5629
|
+
};
|
|
5630
|
+
case "Waitlisted":
|
|
5631
|
+
return {
|
|
5632
|
+
variant: "Waitlisted"
|
|
5633
|
+
};
|
|
5634
|
+
case "Frozen":
|
|
5635
|
+
return {
|
|
5636
|
+
variant: "Frozen",
|
|
5637
|
+
frozenReason: raw.frozen_reason,
|
|
5638
|
+
frozenFrom: raw.frozen_from,
|
|
5639
|
+
frozenTill: raw.frozen_till
|
|
5640
|
+
};
|
|
5641
|
+
}
|
|
5642
|
+
}
|
|
5643
|
+
var ShelbyMetadataClient = class {
|
|
5644
|
+
aptos;
|
|
5645
|
+
deployer;
|
|
5646
|
+
/**
|
|
5647
|
+
* The ShelbyMetadataClient is used to interact with the Shelby contract on the Aptos blockchain. This
|
|
5648
|
+
* includes functions like gathering basic details about the Shelby system, including storage provider information.
|
|
5649
|
+
*
|
|
5650
|
+
* @param config.aptos.config - The Aptos config.
|
|
5651
|
+
* @param config.shelbyDeployer - The deployer account address of the Shelby contract. If not provided, the default deployer address will be used.
|
|
5652
|
+
*
|
|
5653
|
+
* @example
|
|
5654
|
+
* ```typescript
|
|
5655
|
+
* const aptos = new Aptos(new AptosConfig({ network: Network.TESTNET }));
|
|
5656
|
+
* const metadataClient = new ShelbyMetadataClient({ aptos });
|
|
5657
|
+
* ```
|
|
5658
|
+
*/
|
|
5659
|
+
constructor(config) {
|
|
5660
|
+
this.aptos = new Aptos2(getAptosConfig(config));
|
|
5661
|
+
this.deployer = config.deployer ?? AccountAddress3.fromString(SHELBY_DEPLOYER);
|
|
5662
|
+
}
|
|
5663
|
+
/**
|
|
5664
|
+
* Retrieves storage provider list from the blockchain.
|
|
5665
|
+
*
|
|
5666
|
+
* @returns A list of storage providers, or empty array if none exist.
|
|
5667
|
+
*
|
|
5668
|
+
* @example
|
|
5669
|
+
* ```typescript
|
|
5670
|
+
* const spList = await client.getStorageProviders();
|
|
5671
|
+
* ```
|
|
5672
|
+
*/
|
|
5673
|
+
async getStorageProviders() {
|
|
5674
|
+
try {
|
|
5675
|
+
const rawMetadata = await this.aptos.view({
|
|
5676
|
+
payload: {
|
|
5677
|
+
function: `${this.deployer.toString()}::storage_provider_registry::get_all_storage_providers`,
|
|
5678
|
+
functionArguments: []
|
|
5679
|
+
}
|
|
5680
|
+
});
|
|
5681
|
+
const metadata = rawMetadata[0];
|
|
5682
|
+
return metadata.map((provider) => ({
|
|
5683
|
+
address: AccountAddress3.fromString(provider.address),
|
|
5684
|
+
ipAddress: provider.ip_address,
|
|
5685
|
+
port: provider.port,
|
|
5686
|
+
blsPublicKey: Hex4.fromHexInput(provider.bls_public_key).toUint8Array(),
|
|
5687
|
+
failureDomain: provider.failure_domain,
|
|
5688
|
+
state: parseStorageProviderState(provider.state)
|
|
5689
|
+
}));
|
|
5690
|
+
} catch (error) {
|
|
5691
|
+
if (error instanceof Error && // Depending on the network, the error message may show up differently.
|
|
5692
|
+
error.message?.includes("sub_status: Some(404)")) {
|
|
5693
|
+
return [];
|
|
5694
|
+
}
|
|
5695
|
+
throw error;
|
|
5696
|
+
}
|
|
5697
|
+
}
|
|
5698
|
+
/**
|
|
5699
|
+
* Retrieves the list of placement group addresses.
|
|
5700
|
+
*
|
|
5701
|
+
* @returns The placement group address list, or an empty array if none exist.
|
|
5702
|
+
*
|
|
5703
|
+
* @example
|
|
5704
|
+
* ```typescript
|
|
5705
|
+
* const pgList = await client.getPlacementGroupAddresses();
|
|
5706
|
+
* ```
|
|
5707
|
+
*/
|
|
5708
|
+
async getPlacementGroupAddresses() {
|
|
5709
|
+
try {
|
|
5710
|
+
const pgSizeMetadata = await this.aptos.view({
|
|
5711
|
+
payload: {
|
|
5712
|
+
function: `${this.deployer.toString()}::placement_group_registry::get_number_of_placement_groups`,
|
|
5713
|
+
functionArguments: []
|
|
5714
|
+
}
|
|
5715
|
+
});
|
|
5716
|
+
const finalPlacementGroupIndex = pgSizeMetadata[0] - 1;
|
|
5717
|
+
const addressMetadataArray = await this.aptos.view({
|
|
5718
|
+
payload: {
|
|
5719
|
+
function: `${this.deployer.toString()}::placement_group_registry::get_placement_group_addresses`,
|
|
5720
|
+
functionArguments: [0, finalPlacementGroupIndex]
|
|
5721
|
+
}
|
|
5722
|
+
});
|
|
5723
|
+
const metadata = addressMetadataArray[0];
|
|
5724
|
+
return metadata.map((pg) => AccountAddress3.fromString(pg));
|
|
5725
|
+
} catch (error) {
|
|
5726
|
+
if (error instanceof Error && // Depending on the network, the error message may show up differently.
|
|
5727
|
+
(error.message?.includes("sub_status: Some(404)") || error.message?.includes("E_PLACEMENT_GROUP_NOT_FOUND"))) {
|
|
5728
|
+
return [];
|
|
5729
|
+
}
|
|
5730
|
+
throw error;
|
|
5731
|
+
}
|
|
5732
|
+
}
|
|
5733
|
+
/**
|
|
5734
|
+
* Retrieves the list of slice addresses.
|
|
5735
|
+
*
|
|
5736
|
+
* @returns The slice group list, or an empty array if none exist.
|
|
5737
|
+
*
|
|
5738
|
+
* @example
|
|
5739
|
+
* ```typescript
|
|
5740
|
+
* const pgList = await client.getSliceAddresses();
|
|
5741
|
+
* ```
|
|
5742
|
+
*/
|
|
5743
|
+
async getSliceAddresses() {
|
|
5744
|
+
try {
|
|
5745
|
+
const sliceSizeMetadata = await this.aptos.view({
|
|
5746
|
+
payload: {
|
|
5747
|
+
function: `${this.deployer.toString()}::slice_registry::get_number_of_slices`,
|
|
5748
|
+
functionArguments: []
|
|
5749
|
+
}
|
|
5750
|
+
});
|
|
5751
|
+
const finalSliceIndex = sliceSizeMetadata[0] - 1;
|
|
5752
|
+
const addressMetadataArray = await this.aptos.view({
|
|
5753
|
+
payload: {
|
|
5754
|
+
function: `${this.deployer.toString()}::slice_registry::get_slice_addresses`,
|
|
5755
|
+
functionArguments: [0, finalSliceIndex]
|
|
5756
|
+
}
|
|
5757
|
+
});
|
|
5758
|
+
const metadata = addressMetadataArray[0];
|
|
5759
|
+
return metadata.map((slice) => AccountAddress3.fromString(slice));
|
|
5760
|
+
} catch (error) {
|
|
5761
|
+
if (error instanceof Error && // Depending on the network, the error message may show up differently.
|
|
5762
|
+
(error.message?.includes("sub_status: Some(404)") || error.message?.includes("E_SLICE_NOT_FOUND"))) {
|
|
5763
|
+
return [];
|
|
5764
|
+
}
|
|
5765
|
+
throw error;
|
|
5766
|
+
}
|
|
5767
|
+
}
|
|
5768
|
+
/**
|
|
5769
|
+
* Retrieves the storage providers assigned to a slice, through a placement group.
|
|
5770
|
+
*
|
|
5771
|
+
* @param params.account - The address of the slice account.
|
|
5772
|
+
* @returns The list of storage providers for the slice, or an empty array if none exist.
|
|
5773
|
+
*
|
|
5774
|
+
* @example
|
|
5775
|
+
* ```typescript
|
|
5776
|
+
* const pgInfo = await client.getStorageProvidersForSlice();
|
|
5777
|
+
* ```
|
|
5778
|
+
*/
|
|
5779
|
+
async getStorageProvidersForSlice(params) {
|
|
5780
|
+
const sliceMetadata = await this.aptos.view({
|
|
5781
|
+
payload: {
|
|
5782
|
+
function: `${this.deployer.toString()}::slice::get_slice_info`,
|
|
5783
|
+
functionArguments: [params.account.toString()]
|
|
5784
|
+
}
|
|
5785
|
+
});
|
|
5786
|
+
const placementGroupAddress = sliceMetadata[0].placement_group_assignments[0].placement_group_address;
|
|
5787
|
+
const rawMetadata = await this.aptos.view({
|
|
5788
|
+
payload: {
|
|
5789
|
+
function: `${this.deployer.toString()}::placement_group::get_placement_group_info`,
|
|
5790
|
+
functionArguments: [placementGroupAddress]
|
|
5791
|
+
}
|
|
5792
|
+
});
|
|
5793
|
+
const members = rawMetadata[0].members;
|
|
5794
|
+
const keys = members.flatMap((m) => {
|
|
5795
|
+
const active = m.active?.vec.map((a) => a.address) ?? [];
|
|
5796
|
+
const others = m.others?.data.map((o) => o.key) ?? [];
|
|
5797
|
+
return [...active, ...others];
|
|
5798
|
+
});
|
|
5799
|
+
return keys.map((k) => AccountAddress3.fromString(k));
|
|
5800
|
+
}
|
|
5801
|
+
};
|
|
5802
|
+
|
|
5803
|
+
// ../../packages/sdk/dist/chunk-4MG4XGY4.mjs
|
|
5804
|
+
import {
|
|
5805
|
+
AccountAuthenticator,
|
|
5806
|
+
Deserializer,
|
|
5807
|
+
Hex as Hex5,
|
|
5808
|
+
MultiAgentTransaction,
|
|
5809
|
+
Serializer
|
|
5810
|
+
} from "@aptos-labs/ts-sdk";
|
|
5811
|
+
var StaleChannelStateError = class _StaleChannelStateError extends Error {
|
|
5812
|
+
/**
|
|
5813
|
+
* The last valid micropayment stored by the server.
|
|
5814
|
+
* Clients can use this to reset their local channel state.
|
|
5815
|
+
*/
|
|
5816
|
+
storedMicropayment;
|
|
5817
|
+
constructor(storedMicropayment, message) {
|
|
5818
|
+
super(
|
|
5819
|
+
message ?? "Client has stale channel state. Use the returned micropayment to reset local state."
|
|
5820
|
+
);
|
|
5821
|
+
this.name = "StaleChannelStateError";
|
|
5822
|
+
this.storedMicropayment = storedMicropayment;
|
|
5823
|
+
}
|
|
5824
|
+
/**
|
|
5825
|
+
* Returns the stored micropayment as a base64-encoded string.
|
|
5826
|
+
*/
|
|
5827
|
+
toBase64() {
|
|
5828
|
+
const bytes = this.storedMicropayment.bcsToBytes();
|
|
5829
|
+
const binaryString = Array.from(
|
|
5830
|
+
bytes,
|
|
5831
|
+
(byte) => String.fromCharCode(byte)
|
|
5832
|
+
).join("");
|
|
5833
|
+
return btoa(binaryString);
|
|
5834
|
+
}
|
|
5835
|
+
/**
|
|
5836
|
+
* Creates a StaleChannelStateError from a base64-encoded micropayment string.
|
|
5837
|
+
*/
|
|
5838
|
+
static fromBase64(base64, message) {
|
|
5839
|
+
const binaryString = atob(base64);
|
|
5840
|
+
const bytes = Uint8Array.from(binaryString, (char) => char.charCodeAt(0));
|
|
5841
|
+
const micropayment = SenderBuiltMicropayment.deserialize(bytes);
|
|
5842
|
+
return new _StaleChannelStateError(micropayment, message);
|
|
5843
|
+
}
|
|
5844
|
+
};
|
|
5845
|
+
var SenderBuiltMicropayment = class _SenderBuiltMicropayment {
|
|
5846
|
+
/**
|
|
5847
|
+
* The actual micropayment transaction. It is built with the receiver address as fee payer and also requires a signature from the receiver to submit.
|
|
5848
|
+
*/
|
|
5849
|
+
micropayment;
|
|
5850
|
+
/**
|
|
5851
|
+
* The sender's signature.
|
|
5852
|
+
*/
|
|
5853
|
+
senderSignature;
|
|
5854
|
+
constructor(micropayment, senderSignature) {
|
|
5855
|
+
this.micropayment = micropayment;
|
|
5856
|
+
this.senderSignature = senderSignature;
|
|
5857
|
+
}
|
|
5858
|
+
serialize(serializer) {
|
|
5859
|
+
this.micropayment.serialize(serializer);
|
|
5860
|
+
this.senderSignature.serialize(serializer);
|
|
5861
|
+
}
|
|
5862
|
+
bcsToBytes() {
|
|
5863
|
+
const serializer = new Serializer();
|
|
5864
|
+
this.serialize(serializer);
|
|
5865
|
+
return serializer.toUint8Array();
|
|
5866
|
+
}
|
|
5867
|
+
bcsToHex() {
|
|
5868
|
+
return Hex5.fromHexInput(this.bcsToBytes());
|
|
5869
|
+
}
|
|
5870
|
+
toStringWithoutPrefix() {
|
|
5871
|
+
return this.bcsToHex().toStringWithoutPrefix();
|
|
5872
|
+
}
|
|
5873
|
+
toString() {
|
|
5874
|
+
return this.bcsToHex().toString();
|
|
5875
|
+
}
|
|
5876
|
+
/**
|
|
5877
|
+
* Deserializes a SenderBuiltMicropayment from BCS bytes.
|
|
5878
|
+
* @param bytes - The bytes to deserialize from (Uint8Array or hex string).
|
|
5879
|
+
* @returns A new SenderBuiltMicropayment instance.
|
|
5880
|
+
*/
|
|
5881
|
+
static deserialize(bytes) {
|
|
5882
|
+
const bytesArray = typeof bytes === "string" ? Hex5.fromHexInput(bytes).toUint8Array() : bytes;
|
|
5883
|
+
const deserializer = new Deserializer(bytesArray);
|
|
5884
|
+
const micropayment = MultiAgentTransaction.deserialize(deserializer);
|
|
5885
|
+
const senderSignature = AccountAuthenticator.deserialize(deserializer);
|
|
5886
|
+
return new _SenderBuiltMicropayment(micropayment, senderSignature);
|
|
5887
|
+
}
|
|
5888
|
+
};
|
|
5889
|
+
|
|
5890
|
+
// ../../packages/sdk/dist/chunk-I6NG5GNL.mjs
|
|
5891
|
+
function sleep(ms) {
|
|
5892
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
5893
|
+
}
|
|
5894
|
+
|
|
5895
|
+
// ../../packages/sdk/dist/chunk-IE6LYVIA.mjs
|
|
5896
|
+
import { z as z2 } from "zod";
|
|
5897
|
+
var StartMultipartUploadResponseSchema = z2.object({
|
|
5898
|
+
uploadId: z2.string()
|
|
5899
|
+
});
|
|
5900
|
+
var UploadPartResponseSchema = z2.object({
|
|
5901
|
+
success: z2.literal(true)
|
|
5902
|
+
});
|
|
5903
|
+
var CompleteMultipartUploadResponseSchema = z2.object({
|
|
5904
|
+
success: z2.literal(true)
|
|
5905
|
+
});
|
|
5906
|
+
var RPCErrorResponseSchema = z2.object({
|
|
5907
|
+
error: z2.string()
|
|
5908
|
+
});
|
|
5909
|
+
var StaleMicropaymentErrorResponseSchema = z2.object({
|
|
5910
|
+
error: z2.string().optional(),
|
|
5911
|
+
storedMicropayment: z2.string().optional()
|
|
5912
|
+
});
|
|
5913
|
+
|
|
5914
|
+
// ../../packages/sdk/dist/chunk-Z4FZ7W6L.mjs
|
|
5915
|
+
import { z as z3 } from "zod";
|
|
5916
|
+
var BlobNameSchema = z3.string().min(1, "Blob name path parameter cannot be empty.").max(1024, "Blob name cannot exceed 1024 characters.").refine((name2) => !name2.endsWith("/"), {
|
|
5917
|
+
message: "Blob name cannot end with a slash"
|
|
5918
|
+
});
|
|
5919
|
+
|
|
5920
|
+
// ../../packages/sdk/dist/chunk-PJVWGMVI.mjs
|
|
5921
|
+
import { AccountAddress as AccountAddress4 } from "@aptos-labs/ts-sdk";
|
|
5922
|
+
var MICROPAYMENT_HEADER = "X-Shelby-Micropayment";
|
|
5923
|
+
function encodeURIComponentKeepSlashes(str) {
|
|
5924
|
+
return encodeURIComponent(str).replace(/%2F/g, "/");
|
|
5925
|
+
}
|
|
5926
|
+
function validateTotalBytes(totalBytes) {
|
|
5927
|
+
if (!Number.isInteger(totalBytes) || totalBytes < 0) {
|
|
5928
|
+
throw new Error("totalBytes must be a non-negative integer");
|
|
5929
|
+
}
|
|
5930
|
+
}
|
|
5931
|
+
function getErrorCode(error) {
|
|
5932
|
+
if (typeof error === "object" && error !== null && "code" in error && typeof error.code === "string") {
|
|
5933
|
+
return error.code;
|
|
5934
|
+
}
|
|
5935
|
+
if (error instanceof Error) {
|
|
5936
|
+
const match = error.message.match(/\bE[A-Z0-9_]+\b/);
|
|
5937
|
+
return match?.[0];
|
|
5938
|
+
}
|
|
5939
|
+
return void 0;
|
|
5940
|
+
}
|
|
5941
|
+
var ShelbyRPCClient = class {
|
|
5942
|
+
baseUrl;
|
|
5943
|
+
apiKey;
|
|
5944
|
+
rpcConfig;
|
|
5945
|
+
indexer;
|
|
5946
|
+
/**
|
|
5947
|
+
* Creates a new ShelbyRPCClient for interacting with Shelby RPC nodes.
|
|
5948
|
+
* This client handles blob storage operations including upload and download.
|
|
5949
|
+
*
|
|
5950
|
+
* @param config - The client configuration object.
|
|
5951
|
+
* @param config.network - The Shelby network to use.
|
|
5952
|
+
*
|
|
5953
|
+
* @example
|
|
5954
|
+
* ```typescript
|
|
5955
|
+
* const client = new ShelbyRPCClient({
|
|
5956
|
+
* network: Network.SHELBYNET,
|
|
5957
|
+
* apiKey: "AG-***",
|
|
5958
|
+
* });
|
|
5959
|
+
* ```
|
|
5960
|
+
*/
|
|
5961
|
+
constructor(config) {
|
|
5962
|
+
this.baseUrl = config.rpc?.baseUrl ?? NetworkToShelbyRPCBaseUrl.shelbynet;
|
|
5963
|
+
this.apiKey = config.apiKey ?? config.rpc?.apiKey;
|
|
5964
|
+
this.rpcConfig = config.rpc ?? {};
|
|
5965
|
+
this.indexer = getShelbyIndexerClient(config);
|
|
5966
|
+
}
|
|
5967
|
+
async #uploadPart(uploadId, partIdx, partData) {
|
|
5968
|
+
const nRetries = 5;
|
|
5969
|
+
let lastResponse;
|
|
5970
|
+
let lastError;
|
|
5971
|
+
const partUrl = buildRequestUrl(
|
|
5972
|
+
`/v1/multipart-uploads/${uploadId}/parts/${partIdx}`,
|
|
5973
|
+
this.baseUrl
|
|
5974
|
+
);
|
|
5975
|
+
for (let i = 0; i < nRetries; ++i) {
|
|
5976
|
+
try {
|
|
5977
|
+
lastResponse = await fetch(partUrl, {
|
|
5978
|
+
method: "PUT",
|
|
5979
|
+
headers: {
|
|
5980
|
+
"Content-Type": "application/octet-stream",
|
|
5981
|
+
...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
|
|
5982
|
+
},
|
|
5983
|
+
body: partData
|
|
5984
|
+
});
|
|
5985
|
+
lastError = void 0;
|
|
5986
|
+
} catch (error) {
|
|
5987
|
+
lastError = error;
|
|
5988
|
+
if (i < nRetries - 1) {
|
|
5989
|
+
const delay = 2 ** i * 100;
|
|
5990
|
+
await sleep(delay);
|
|
5991
|
+
continue;
|
|
5992
|
+
}
|
|
5993
|
+
break;
|
|
5994
|
+
}
|
|
5995
|
+
if (lastResponse.ok) return;
|
|
5996
|
+
if (i < nRetries - 1) {
|
|
5997
|
+
const delay = 2 ** i * 100;
|
|
5998
|
+
await sleep(delay);
|
|
5999
|
+
}
|
|
6000
|
+
}
|
|
6001
|
+
if (lastError !== void 0) {
|
|
6002
|
+
const errorCode = getErrorCode(lastError);
|
|
6003
|
+
const errorMessage = lastError instanceof Error ? lastError.message : String(lastError);
|
|
6004
|
+
throw new Error(
|
|
6005
|
+
`Failed to upload part ${partIdx} for multipart upload ${uploadId} after ${nRetries} attempts. The connection to the Shelby RPC endpoint was interrupted while sending data${errorCode ? ` (${errorCode})` : ""}. Endpoint: ${partUrl.toString()}, partBytes: ${partData.length}. Last error: ${errorMessage}`,
|
|
6006
|
+
{ cause: lastError }
|
|
6007
|
+
);
|
|
6008
|
+
}
|
|
6009
|
+
const errorBody = await lastResponse?.text().catch(() => "");
|
|
6010
|
+
throw new Error(
|
|
6011
|
+
`Failed to upload part ${partIdx} for multipart upload ${uploadId} after ${nRetries} attempts. status: ${lastResponse?.status}, body: ${errorBody}`
|
|
6012
|
+
);
|
|
6013
|
+
}
|
|
6014
|
+
async #putBlobMultipart(account, blobName, blobData, totalBytes, partSize = 5 * 1024 * 1024, onProgress) {
|
|
6015
|
+
validateTotalBytes(totalBytes);
|
|
6016
|
+
const startResponse = await fetch(
|
|
6017
|
+
buildRequestUrl("/v1/multipart-uploads", this.baseUrl),
|
|
6018
|
+
{
|
|
6019
|
+
method: "POST",
|
|
6020
|
+
headers: {
|
|
6021
|
+
"Content-Type": "application/json",
|
|
6022
|
+
...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
|
|
6023
|
+
},
|
|
6024
|
+
body: JSON.stringify({
|
|
6025
|
+
rawAccount: account.toString(),
|
|
6026
|
+
rawBlobName: blobName,
|
|
6027
|
+
rawPartSize: partSize
|
|
6028
|
+
})
|
|
6029
|
+
}
|
|
6030
|
+
);
|
|
6031
|
+
if (!startResponse.ok) {
|
|
6032
|
+
let errorBodyText = "Could not read error body";
|
|
6033
|
+
try {
|
|
6034
|
+
errorBodyText = await startResponse.text();
|
|
6035
|
+
} catch (_e) {
|
|
6036
|
+
}
|
|
6037
|
+
throw new Error(
|
|
6038
|
+
`Failed to start multipart upload! status: ${startResponse.status}, body: ${errorBodyText}`
|
|
6039
|
+
);
|
|
6040
|
+
}
|
|
6041
|
+
const { uploadId } = StartMultipartUploadResponseSchema.parse(
|
|
6042
|
+
await startResponse.json()
|
|
6043
|
+
);
|
|
6044
|
+
const totalParts = Math.ceil(totalBytes / partSize);
|
|
6045
|
+
let uploadedBytes = 0;
|
|
6046
|
+
for await (const [partIdx, partData] of readInChunks(blobData, partSize)) {
|
|
6047
|
+
await this.#uploadPart(uploadId, partIdx, partData);
|
|
6048
|
+
uploadedBytes += partData.length;
|
|
6049
|
+
onProgress?.({
|
|
6050
|
+
phase: "uploading",
|
|
6051
|
+
partIdx,
|
|
6052
|
+
totalParts,
|
|
6053
|
+
partBytes: partData.length,
|
|
6054
|
+
uploadedBytes,
|
|
6055
|
+
totalBytes
|
|
6056
|
+
});
|
|
6057
|
+
}
|
|
6058
|
+
if (uploadedBytes !== totalBytes) {
|
|
6059
|
+
throw new Error(
|
|
6060
|
+
`Uploaded bytes (${uploadedBytes}) did not match declared totalBytes (${totalBytes})`
|
|
6061
|
+
);
|
|
6062
|
+
}
|
|
6063
|
+
const finalPartIdx = totalParts > 0 ? totalParts - 1 : 0;
|
|
6064
|
+
onProgress?.({
|
|
6065
|
+
phase: "finalizing",
|
|
6066
|
+
partIdx: finalPartIdx,
|
|
6067
|
+
totalParts,
|
|
6068
|
+
// no part uploaded in this phase
|
|
6069
|
+
partBytes: 0,
|
|
6070
|
+
uploadedBytes: totalBytes,
|
|
6071
|
+
totalBytes
|
|
5598
6072
|
});
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
static createRegisterBlobPayload(params) {
|
|
5623
|
-
return {
|
|
5624
|
-
function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::register_blob`,
|
|
5625
|
-
functionArguments: [
|
|
5626
|
-
params.blobName,
|
|
5627
|
-
params.expirationMicros,
|
|
5628
|
-
MoveVector.U8(params.blobMerkleRoot),
|
|
5629
|
-
params.numChunksets,
|
|
5630
|
-
params.blobSize,
|
|
5631
|
-
// TODO
|
|
5632
|
-
0,
|
|
5633
|
-
// payment tier
|
|
5634
|
-
0
|
|
5635
|
-
// encoding
|
|
5636
|
-
]
|
|
5637
|
-
};
|
|
6073
|
+
const completeResponse = await fetch(
|
|
6074
|
+
buildRequestUrl(
|
|
6075
|
+
`/v1/multipart-uploads/${uploadId}/complete`,
|
|
6076
|
+
this.baseUrl
|
|
6077
|
+
),
|
|
6078
|
+
{
|
|
6079
|
+
method: "POST",
|
|
6080
|
+
headers: {
|
|
6081
|
+
"Content-Type": "application/json",
|
|
6082
|
+
...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
|
|
6083
|
+
}
|
|
6084
|
+
}
|
|
6085
|
+
);
|
|
6086
|
+
if (!completeResponse.ok) {
|
|
6087
|
+
let errorBodyText = "Could not read error body";
|
|
6088
|
+
try {
|
|
6089
|
+
errorBodyText = await completeResponse.text();
|
|
6090
|
+
} catch (_e) {
|
|
6091
|
+
}
|
|
6092
|
+
throw new Error(
|
|
6093
|
+
`Failed to complete multipart upload! status: ${completeResponse.status}, body: ${errorBodyText}`
|
|
6094
|
+
);
|
|
6095
|
+
}
|
|
5638
6096
|
}
|
|
5639
6097
|
/**
|
|
5640
|
-
*
|
|
5641
|
-
* This
|
|
6098
|
+
* Uploads blob data to the Shelby RPC node for storage by storage providers.
|
|
6099
|
+
* This method should be called after blob commitments have been registered on the blockchain.
|
|
6100
|
+
* Uses multipart upload for efficient handling of large files.
|
|
5642
6101
|
*
|
|
5643
|
-
* @param params.
|
|
5644
|
-
* @param params.
|
|
5645
|
-
* @param params.
|
|
5646
|
-
* @param params.
|
|
5647
|
-
* @param params.blobs.blobName - The name/path of the blob (e.g. "foo/bar.txt").
|
|
5648
|
-
* @param params.blobs.blobSize - The size of the blob in bytes.
|
|
5649
|
-
* @param params.blobs.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
|
|
5650
|
-
* @param params.blobs.numChunksets - The total number of chunksets in the blob.
|
|
6102
|
+
* @param params.account - The account that owns the blob.
|
|
6103
|
+
* @param params.blobName - The name/path of the blob (e.g. "folder/file.txt").
|
|
6104
|
+
* @param params.blobData - The raw blob data as a Uint8Array or ReadableStream.
|
|
6105
|
+
* @param params.totalBytes - Total byte length. Required for streams; optional for Uint8Array.
|
|
5651
6106
|
*
|
|
5652
|
-
* @
|
|
6107
|
+
* @example
|
|
6108
|
+
* ```typescript
|
|
6109
|
+
* const blobData = new TextEncoder().encode("Hello, world!");
|
|
5653
6110
|
*
|
|
5654
|
-
*
|
|
6111
|
+
* await client.putBlob({
|
|
6112
|
+
* account: AccountAddress.from("0x1"),
|
|
6113
|
+
* blobName: "greetings/hello.txt",
|
|
6114
|
+
* blobData,
|
|
6115
|
+
* });
|
|
6116
|
+
* ```
|
|
5655
6117
|
*/
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
}
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
6118
|
+
async putBlob(params) {
|
|
6119
|
+
BlobNameSchema.parse(params.blobName);
|
|
6120
|
+
let totalBytes;
|
|
6121
|
+
if (params.blobData instanceof Uint8Array) {
|
|
6122
|
+
totalBytes = params.totalBytes ?? params.blobData.length;
|
|
6123
|
+
if (totalBytes !== params.blobData.length) {
|
|
6124
|
+
throw new Error(
|
|
6125
|
+
"totalBytes must match blobData.length when blobData is a Uint8Array"
|
|
6126
|
+
);
|
|
6127
|
+
}
|
|
6128
|
+
} else {
|
|
6129
|
+
if (params.totalBytes === void 0) {
|
|
6130
|
+
throw new Error(
|
|
6131
|
+
"totalBytes is required when blobData is a ReadableStream"
|
|
6132
|
+
);
|
|
6133
|
+
}
|
|
6134
|
+
totalBytes = params.totalBytes;
|
|
6135
|
+
}
|
|
6136
|
+
validateTotalBytes(totalBytes);
|
|
6137
|
+
await this.#putBlobMultipart(
|
|
6138
|
+
params.account,
|
|
6139
|
+
params.blobName,
|
|
6140
|
+
params.blobData,
|
|
6141
|
+
totalBytes,
|
|
6142
|
+
void 0,
|
|
6143
|
+
params.onProgress
|
|
6144
|
+
);
|
|
5680
6145
|
}
|
|
5681
6146
|
/**
|
|
5682
|
-
*
|
|
5683
|
-
*
|
|
5684
|
-
*
|
|
5685
|
-
* @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
|
|
5686
|
-
* @param params.blobName - The blob name (e.g. "bar.txt", without the account address prefix).
|
|
5687
|
-
*
|
|
5688
|
-
* @returns An Aptos transaction payload data object for the delete_blob Move function.
|
|
6147
|
+
* Downloads a blob from the Shelby RPC node.
|
|
6148
|
+
* Returns a streaming response with validation to ensure data integrity.
|
|
5689
6149
|
*
|
|
5690
|
-
* @
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
};
|
|
5697
|
-
}
|
|
5698
|
-
/**
|
|
5699
|
-
* Creates a transaction payload to delete multiple blobs on the blockchain.
|
|
5700
|
-
* This is a static helper method for constructing the Move function call payload.
|
|
6150
|
+
* @param params.account - The account that owns the blob.
|
|
6151
|
+
* @param params.blobName - The name/path of the blob (e.g. "folder/file.txt").
|
|
6152
|
+
* @param params.range - Optional byte range for partial downloads.
|
|
6153
|
+
* @param params.range.start - Starting byte position (inclusive).
|
|
6154
|
+
* @param params.range.end - Ending byte position (inclusive, optional).
|
|
6155
|
+
* @param params.micropayment - Optional micropayment to attach to the request.
|
|
5701
6156
|
*
|
|
5702
|
-
*
|
|
5703
|
-
* which will be deployed to the smart contract on 2026-02-04. Using this
|
|
5704
|
-
* function before that date will result in a transaction failure.
|
|
6157
|
+
* @returns A ShelbyBlob object containing the account, name, readable stream, and content length.
|
|
5705
6158
|
*
|
|
5706
|
-
*
|
|
5707
|
-
* the
|
|
6159
|
+
* @throws Error if the download fails or content length doesn't match.
|
|
6160
|
+
* @throws StaleChannelStateError if the micropayment is stale (server has newer state).
|
|
5708
6161
|
*
|
|
5709
|
-
* @
|
|
5710
|
-
*
|
|
5711
|
-
*
|
|
5712
|
-
*
|
|
6162
|
+
* @example
|
|
6163
|
+
* ```typescript
|
|
6164
|
+
* // Download entire blob
|
|
6165
|
+
* const blob = await client.getBlob({
|
|
6166
|
+
* account: AccountAddress.from("0x1"),
|
|
6167
|
+
* blobName: "documents/report.pdf"
|
|
6168
|
+
* });
|
|
5713
6169
|
*
|
|
5714
|
-
*
|
|
6170
|
+
* // Download partial content (bytes 100-199)
|
|
6171
|
+
* const partial = await client.getBlob({
|
|
6172
|
+
* account: AccountAddress.from("0x1"),
|
|
6173
|
+
* blobName: "large-file.bin",
|
|
6174
|
+
* range: { start: 100, end: 199 }
|
|
6175
|
+
* });
|
|
5715
6176
|
*
|
|
5716
|
-
*
|
|
6177
|
+
* // Download with micropayment
|
|
6178
|
+
* const blob = await client.getBlob({
|
|
6179
|
+
* account: AccountAddress.from("0x1"),
|
|
6180
|
+
* blobName: "documents/report.pdf",
|
|
6181
|
+
* micropayment: senderBuiltMicropayment
|
|
6182
|
+
* });
|
|
6183
|
+
* ```
|
|
5717
6184
|
*/
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
const ackBitMask = params.storageProviderAcks.reduce(
|
|
5726
|
-
(acc, ack) => acc | 1 << ack.slot,
|
|
5727
|
-
0
|
|
6185
|
+
async getBlob(params) {
|
|
6186
|
+
BlobNameSchema.parse(params.blobName);
|
|
6187
|
+
const url = buildRequestUrl(
|
|
6188
|
+
`/v1/blobs/${params.account.toString()}/${encodeURIComponentKeepSlashes(
|
|
6189
|
+
params.blobName
|
|
6190
|
+
)}`,
|
|
6191
|
+
this.baseUrl
|
|
5728
6192
|
);
|
|
5729
|
-
const
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
signatures
|
|
5741
|
-
]
|
|
5742
|
-
};
|
|
5743
|
-
}
|
|
5744
|
-
};
|
|
5745
|
-
|
|
5746
|
-
// ../../packages/sdk/dist/chunk-UCDAABAS.mjs
|
|
5747
|
-
import {
|
|
5748
|
-
createDecoder,
|
|
5749
|
-
createEncoder
|
|
5750
|
-
} from "@shelby-protocol/clay-codes";
|
|
5751
|
-
function getTotalChunks(config) {
|
|
5752
|
-
return config.erasure_n;
|
|
5753
|
-
}
|
|
5754
|
-
var ClayErasureCodingProvider = class _ClayErasureCodingProvider {
|
|
5755
|
-
config;
|
|
5756
|
-
encoderCache;
|
|
5757
|
-
decoderCache;
|
|
5758
|
-
lastFunction;
|
|
5759
|
-
constructor(config) {
|
|
5760
|
-
this.config = config;
|
|
5761
|
-
this.lastFunction = "none";
|
|
5762
|
-
}
|
|
5763
|
-
/**
|
|
5764
|
-
* Static factory method to create an initialized ClayErasureCodingProvider
|
|
5765
|
-
*/
|
|
5766
|
-
static async create(options) {
|
|
5767
|
-
const config = buildClayConfig({
|
|
5768
|
-
erasure_n: options?.erasure_n ?? DEFAULT_ERASURE_N,
|
|
5769
|
-
erasure_k: options?.erasure_k ?? DEFAULT_ERASURE_K,
|
|
5770
|
-
erasure_d: options?.erasure_d ?? DEFAULT_ERASURE_D,
|
|
5771
|
-
chunkSizeBytes: options?.chunkSizeBytes ?? DEFAULT_CHUNK_SIZE_BYTES
|
|
5772
|
-
});
|
|
5773
|
-
const provider = new _ClayErasureCodingProvider(config);
|
|
5774
|
-
[provider.encoderCache, provider.decoderCache] = await Promise.all([
|
|
5775
|
-
createEncoder({
|
|
5776
|
-
n: getTotalChunks(config),
|
|
5777
|
-
k: config.erasure_k,
|
|
5778
|
-
d: config.erasure_d,
|
|
5779
|
-
chunkSizeBytes: config.chunkSizeBytes
|
|
5780
|
-
}),
|
|
5781
|
-
createDecoder({
|
|
5782
|
-
n: getTotalChunks(config),
|
|
5783
|
-
k: config.erasure_k,
|
|
5784
|
-
d: config.erasure_d,
|
|
5785
|
-
chunkSizeBytes: config.chunkSizeBytes,
|
|
5786
|
-
erasedChunksMask: 0
|
|
5787
|
-
// No chunks erased initially; will be reconfigured on decode
|
|
5788
|
-
})
|
|
5789
|
-
]);
|
|
5790
|
-
return provider;
|
|
5791
|
-
}
|
|
5792
|
-
encode(data) {
|
|
5793
|
-
const { erasure_k, chunkSizeBytes } = this.config;
|
|
5794
|
-
if (!this.encoderCache) {
|
|
5795
|
-
throw new Error("Encoder cache is missing");
|
|
6193
|
+
const headers = new Headers();
|
|
6194
|
+
if (params.range !== void 0) {
|
|
6195
|
+
const { start, end } = params.range;
|
|
6196
|
+
if (end === void 0) {
|
|
6197
|
+
headers.set("Range", `bytes=${start}-`);
|
|
6198
|
+
} else {
|
|
6199
|
+
if (end < start) {
|
|
6200
|
+
throw new Error("Range end cannot be less than start.");
|
|
6201
|
+
}
|
|
6202
|
+
headers.set("Range", `bytes=${start}-${end}`);
|
|
6203
|
+
}
|
|
5796
6204
|
}
|
|
5797
|
-
|
|
5798
|
-
|
|
6205
|
+
if (this.apiKey) {
|
|
6206
|
+
headers.set("Authorization", `Bearer ${this.apiKey}`);
|
|
6207
|
+
}
|
|
6208
|
+
if (params.micropayment) {
|
|
6209
|
+
const bytes = params.micropayment.bcsToBytes();
|
|
6210
|
+
const binaryString = Array.from(
|
|
6211
|
+
bytes,
|
|
6212
|
+
(byte) => String.fromCharCode(byte)
|
|
6213
|
+
).join("");
|
|
6214
|
+
headers.set(MICROPAYMENT_HEADER, btoa(binaryString));
|
|
6215
|
+
}
|
|
6216
|
+
const response = await fetch(url, { headers });
|
|
6217
|
+
if (response.status === 409) {
|
|
6218
|
+
let json;
|
|
6219
|
+
try {
|
|
6220
|
+
json = await response.json();
|
|
6221
|
+
} catch {
|
|
6222
|
+
throw new Error(
|
|
6223
|
+
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
6224
|
+
);
|
|
6225
|
+
}
|
|
6226
|
+
const parseResult = StaleMicropaymentErrorResponseSchema.safeParse(json);
|
|
6227
|
+
if (!parseResult.success) {
|
|
6228
|
+
throw new Error(
|
|
6229
|
+
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
6230
|
+
);
|
|
6231
|
+
}
|
|
6232
|
+
const errorBody = parseResult.data;
|
|
6233
|
+
if (errorBody.storedMicropayment) {
|
|
6234
|
+
throw StaleChannelStateError.fromBase64(
|
|
6235
|
+
errorBody.storedMicropayment,
|
|
6236
|
+
errorBody.error
|
|
6237
|
+
);
|
|
6238
|
+
}
|
|
5799
6239
|
throw new Error(
|
|
5800
|
-
|
|
6240
|
+
errorBody.error ?? `Failed to download blob: ${response.status} ${response.statusText}`
|
|
5801
6241
|
);
|
|
5802
6242
|
}
|
|
5803
|
-
if (
|
|
6243
|
+
if (!response.ok) {
|
|
5804
6244
|
throw new Error(
|
|
5805
|
-
`
|
|
6245
|
+
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
5806
6246
|
);
|
|
5807
6247
|
}
|
|
5808
|
-
|
|
5809
|
-
|
|
5810
|
-
}
|
|
5811
|
-
decode(available, config) {
|
|
5812
|
-
if (!this.decoderCache) {
|
|
5813
|
-
throw new Error("Decoder cache is missing");
|
|
6248
|
+
if (!response.body) {
|
|
6249
|
+
throw new Error("Response body is null");
|
|
5814
6250
|
}
|
|
5815
|
-
const
|
|
5816
|
-
if (
|
|
6251
|
+
const contentLengthHeader = response.headers.get("content-length");
|
|
6252
|
+
if (contentLengthHeader === null) {
|
|
5817
6253
|
throw new Error(
|
|
5818
|
-
|
|
6254
|
+
"Response did not have content-length header, which is required"
|
|
5819
6255
|
);
|
|
5820
6256
|
}
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
);
|
|
5827
|
-
}
|
|
6257
|
+
const expectedContentLength = Number.parseInt(contentLengthHeader, 10);
|
|
6258
|
+
if (Number.isNaN(expectedContentLength)) {
|
|
6259
|
+
throw new Error(
|
|
6260
|
+
`Invalid content-length header received: ${contentLengthHeader}`
|
|
6261
|
+
);
|
|
5828
6262
|
}
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
6263
|
+
const validatingStream = new ReadableStream({
|
|
6264
|
+
start(controller) {
|
|
6265
|
+
const maybeReader = response.body?.getReader();
|
|
6266
|
+
if (!maybeReader) {
|
|
6267
|
+
controller.error(new Error("Response body reader is unavailable"));
|
|
6268
|
+
return;
|
|
6269
|
+
}
|
|
6270
|
+
const reader = maybeReader;
|
|
6271
|
+
let bytesReceived = 0;
|
|
6272
|
+
function pump() {
|
|
6273
|
+
return reader.read().then(({ done, value }) => {
|
|
6274
|
+
if (done) {
|
|
6275
|
+
if (bytesReceived !== expectedContentLength) {
|
|
6276
|
+
controller.error(
|
|
6277
|
+
new Error(
|
|
6278
|
+
`Downloaded data size (${bytesReceived} bytes) does not match content-length header (${expectedContentLength} bytes). This might indicate a partial or corrupted download.`
|
|
6279
|
+
)
|
|
6280
|
+
);
|
|
6281
|
+
return;
|
|
6282
|
+
}
|
|
6283
|
+
controller.close();
|
|
6284
|
+
return;
|
|
6285
|
+
}
|
|
6286
|
+
bytesReceived += value.byteLength;
|
|
6287
|
+
controller.enqueue(value);
|
|
6288
|
+
return pump();
|
|
6289
|
+
}).catch((error) => {
|
|
6290
|
+
controller.error(error);
|
|
6291
|
+
});
|
|
6292
|
+
}
|
|
6293
|
+
return pump();
|
|
6294
|
+
}
|
|
6295
|
+
});
|
|
6296
|
+
return {
|
|
6297
|
+
account: AccountAddress4.from(params.account),
|
|
6298
|
+
name: params.blobName,
|
|
6299
|
+
readable: validatingStream,
|
|
6300
|
+
contentLength: expectedContentLength
|
|
6301
|
+
};
|
|
5854
6302
|
}
|
|
5855
6303
|
};
|
|
5856
|
-
function buildClayConfig(input) {
|
|
5857
|
-
const { erasure_n, erasure_k, erasure_d, chunkSizeBytes } = input;
|
|
5858
|
-
if (erasure_n <= 0)
|
|
5859
|
-
throw new Error("erasure_n (total number of chunks) must be > 0");
|
|
5860
|
-
if (erasure_k <= 0)
|
|
5861
|
-
throw new Error("erasure_k (number of data chunks) must be > 0");
|
|
5862
|
-
if (erasure_k >= erasure_n)
|
|
5863
|
-
throw new Error(
|
|
5864
|
-
`erasure_k (${erasure_k}) must be < erasure_n (${erasure_n})`
|
|
5865
|
-
);
|
|
5866
|
-
if (erasure_d <= erasure_k)
|
|
5867
|
-
throw new Error(
|
|
5868
|
-
`erasure_d (${erasure_d}) must be > erasure_k (${erasure_k})`
|
|
5869
|
-
);
|
|
5870
|
-
if (erasure_d >= erasure_n)
|
|
5871
|
-
throw new Error(
|
|
5872
|
-
`erasure_d (${erasure_d}) must be < erasure_n (${erasure_n})`
|
|
5873
|
-
);
|
|
5874
|
-
if (chunkSizeBytes <= 0) throw new Error("chunkSizeBytes must be > 0");
|
|
5875
|
-
return {
|
|
5876
|
-
erasure_n,
|
|
5877
|
-
erasure_k,
|
|
5878
|
-
erasure_d,
|
|
5879
|
-
chunkSizeBytes
|
|
5880
|
-
};
|
|
5881
|
-
}
|
|
5882
6304
|
|
|
5883
|
-
// ../../packages/sdk/dist/chunk-
|
|
6305
|
+
// ../../packages/sdk/dist/chunk-7PN65RDX.mjs
|
|
5884
6306
|
import {
|
|
5885
|
-
AccountAddress as
|
|
6307
|
+
AccountAddress as AccountAddress5,
|
|
5886
6308
|
Aptos as Aptos3,
|
|
5887
6309
|
DEFAULT_TXN_TIMEOUT_SEC,
|
|
6310
|
+
Network as Network3,
|
|
5888
6311
|
TransactionResponseType
|
|
5889
6312
|
} from "@aptos-labs/ts-sdk";
|
|
5890
6313
|
|
|
@@ -6025,13 +6448,17 @@ function validateConcurrency(concurrency) {
|
|
|
6025
6448
|
}
|
|
6026
6449
|
}
|
|
6027
6450
|
|
|
6028
|
-
// ../../packages/sdk/dist/chunk-
|
|
6451
|
+
// ../../packages/sdk/dist/chunk-7PN65RDX.mjs
|
|
6029
6452
|
var ShelbyClient = class {
|
|
6030
6453
|
/**
|
|
6031
6454
|
* The coordination client is used to interact with the Aptos blockchain which handles the commitments
|
|
6032
6455
|
* and metadata for blobs.
|
|
6033
6456
|
*/
|
|
6034
6457
|
coordination;
|
|
6458
|
+
/**
|
|
6459
|
+
* The metadata client is used for protocol-level metadata queries.
|
|
6460
|
+
*/
|
|
6461
|
+
metadata;
|
|
6035
6462
|
/**
|
|
6036
6463
|
* The RPC client is used to interact with the Shelby RPC node which can be responsible for storing,
|
|
6037
6464
|
* confirming, and retrieving blobs from the storage layer.
|
|
@@ -6083,6 +6510,7 @@ var ShelbyClient = class {
|
|
|
6083
6510
|
this.config = config;
|
|
6084
6511
|
this.aptos = new Aptos3(getAptosConfig(config));
|
|
6085
6512
|
this.coordination = new ShelbyBlobClient(config);
|
|
6513
|
+
this.metadata = new ShelbyMetadataClient(config);
|
|
6086
6514
|
this.rpc = new ShelbyRPCClient(config);
|
|
6087
6515
|
this._provider = provider;
|
|
6088
6516
|
}
|
|
@@ -6092,7 +6520,9 @@ var ShelbyClient = class {
|
|
|
6092
6520
|
*/
|
|
6093
6521
|
async getProvider() {
|
|
6094
6522
|
if (!this._provider) {
|
|
6095
|
-
this._provider = await ClayErasureCodingProvider.create(
|
|
6523
|
+
this._provider = await ClayErasureCodingProvider.create(
|
|
6524
|
+
defaultErasureCodingConfig()
|
|
6525
|
+
);
|
|
6096
6526
|
}
|
|
6097
6527
|
return this._provider;
|
|
6098
6528
|
}
|
|
@@ -6107,6 +6537,11 @@ var ShelbyClient = class {
|
|
|
6107
6537
|
* This method handles the complete upload flow including commitment generation,
|
|
6108
6538
|
* blockchain registration, and storage upload.
|
|
6109
6539
|
*
|
|
6540
|
+
* Note: This method accepts only `Uint8Array` and buffers the entire blob in memory.
|
|
6541
|
+
* For streaming uploads of large files (e.g. >2 GiB), orchestrate the steps manually
|
|
6542
|
+
* using `generateCommitments()`, `coordination.registerBlob()`, and `rpc.putBlob()`
|
|
6543
|
+
* with a `ReadableStream`.
|
|
6544
|
+
*
|
|
6110
6545
|
* @param params.blobData - The raw data to upload as a Uint8Array.
|
|
6111
6546
|
* @param params.signer - The account that signs and pays for the transaction.
|
|
6112
6547
|
* @param params.blobName - The name/path of the blob (e.g. "folder/file.txt").
|
|
@@ -6144,6 +6579,7 @@ var ShelbyClient = class {
|
|
|
6144
6579
|
blobMerkleRoot: blobCommitments.blob_merkle_root,
|
|
6145
6580
|
size: params.blobData.length,
|
|
6146
6581
|
expirationMicros: params.expirationMicros,
|
|
6582
|
+
config: provider.config,
|
|
6147
6583
|
options: params.options
|
|
6148
6584
|
});
|
|
6149
6585
|
await this.coordination.aptos.waitForTransaction({
|
|
@@ -6161,6 +6597,11 @@ var ShelbyClient = class {
|
|
|
6161
6597
|
* This method handles the complete upload flow including commitment generation,
|
|
6162
6598
|
* blockchain registration, and storage upload.
|
|
6163
6599
|
*
|
|
6600
|
+
* Note: This method accepts only `Uint8Array` and buffers each blob in memory.
|
|
6601
|
+
* For streaming uploads of large files, orchestrate the steps manually using
|
|
6602
|
+
* `generateCommitments()`, `coordination.registerBlob()`, and `rpc.putBlob()`
|
|
6603
|
+
* with a `ReadableStream`.
|
|
6604
|
+
*
|
|
6164
6605
|
* @param params.blobs - The blobs to upload.
|
|
6165
6606
|
* @param params.blobs.blobData - The raw data to upload as a Uint8Array.
|
|
6166
6607
|
* @param params.blobs.blobName - The name/path of the blob (e.g. "folder/file.txt").
|
|
@@ -6219,6 +6660,7 @@ var ShelbyClient = class {
|
|
|
6219
6660
|
blobSize: blob.blobData.length,
|
|
6220
6661
|
blobMerkleRoot: blobCommitments[index].blob_merkle_root
|
|
6221
6662
|
})),
|
|
6663
|
+
config: provider.config,
|
|
6222
6664
|
options: params.options
|
|
6223
6665
|
});
|
|
6224
6666
|
await this.coordination.aptos.waitForTransaction({
|
|
@@ -6276,21 +6718,29 @@ var ShelbyClient = class {
|
|
|
6276
6718
|
* ```
|
|
6277
6719
|
*/
|
|
6278
6720
|
async fundAccountWithShelbyUSD(params) {
|
|
6721
|
+
if (this.config.network === Network3.TESTNET) {
|
|
6722
|
+
throw new Error(
|
|
6723
|
+
`ShelbyUSD cannot be minted programmatically on ${Network3.TESTNET}. Please use the faucet at https://docs.shelby.xyz/apis/faucet/shelbyusd instead.`
|
|
6724
|
+
);
|
|
6725
|
+
}
|
|
6279
6726
|
const { address, amount } = params;
|
|
6280
6727
|
try {
|
|
6281
|
-
const faucet = this.config.faucet ?? "https://faucet.shelbynet.shelby.xyz/fund?asset=shelbyusd";
|
|
6728
|
+
const faucet = this.config.faucet?.baseUrl ?? "https://faucet.shelbynet.shelby.xyz/fund?asset=shelbyusd";
|
|
6729
|
+
const authToken = this.config.faucet?.authToken;
|
|
6282
6730
|
const response = await fetch(`${faucet}`, {
|
|
6283
6731
|
method: "POST",
|
|
6284
6732
|
body: JSON.stringify({
|
|
6285
|
-
address:
|
|
6733
|
+
address: AccountAddress5.from(address).toString(),
|
|
6286
6734
|
amount
|
|
6287
6735
|
}),
|
|
6288
6736
|
headers: {
|
|
6289
|
-
"Content-Type": "application/json"
|
|
6737
|
+
"Content-Type": "application/json",
|
|
6738
|
+
...authToken ? { Authorization: `Bearer ${authToken}` } : {}
|
|
6290
6739
|
}
|
|
6291
6740
|
});
|
|
6292
6741
|
if (!response.ok) {
|
|
6293
|
-
|
|
6742
|
+
const errorBody = await response.text();
|
|
6743
|
+
throw new Error(`Failed to fund account: ${errorBody}`);
|
|
6294
6744
|
}
|
|
6295
6745
|
const json = await response.json();
|
|
6296
6746
|
const res = await this.aptos.waitForTransaction({
|
|
@@ -6334,22 +6784,41 @@ var ShelbyClient = class {
|
|
|
6334
6784
|
}
|
|
6335
6785
|
};
|
|
6336
6786
|
|
|
6337
|
-
// ../../packages/sdk/dist/chunk-
|
|
6787
|
+
// ../../packages/sdk/dist/chunk-ZEDD2MPU.mjs
|
|
6338
6788
|
var ShelbyNodeClient = class extends ShelbyClient {
|
|
6339
6789
|
};
|
|
6340
6790
|
|
|
6791
|
+
// ../../packages/sdk/dist/chunk-7P6ASYW6.mjs
|
|
6792
|
+
var __defProp2 = Object.defineProperty;
|
|
6793
|
+
var __export = (target, all) => {
|
|
6794
|
+
for (var name2 in all)
|
|
6795
|
+
__defProp2(target, name2, { get: all[name2], enumerable: true });
|
|
6796
|
+
};
|
|
6797
|
+
|
|
6798
|
+
// ../../packages/sdk/dist/chunk-A4IG6GSE.mjs
|
|
6799
|
+
var testUtil_exports = {};
|
|
6800
|
+
__export(testUtil_exports, {
|
|
6801
|
+
makeChunk: () => makeChunk
|
|
6802
|
+
});
|
|
6803
|
+
function makeChunk(n) {
|
|
6804
|
+
const c = Buffer.alloc(n);
|
|
6805
|
+
for (let i = 0; i < n; ++i) {
|
|
6806
|
+
c[i] = i % 256;
|
|
6807
|
+
}
|
|
6808
|
+
return c;
|
|
6809
|
+
}
|
|
6810
|
+
|
|
6341
6811
|
// ../../packages/reed-solomon/dist/index.mjs
|
|
6342
6812
|
var __toBinaryNode = (base64) => new Uint8Array(Buffer.from(base64, "base64"));
|
|
6343
6813
|
var reed_solomon_erasure_bg_default = __toBinaryNode("AGFzbQEAAAAB/oCAgAASYAJ/fwF/YAF/AX9gBH9/f38AYAABf2ABfwBgAn9/AGADf39/AX9gAABgBH9/f38Bf2AGf39/f39/AX9gA39/fwBgBX9/f39/AX9gCH9/f39/f39/AGABfwF+YAZ/f39/f38AYAV/f39/fwBgB39/f39/f38Bf2ADfn9/AX8Dj4GAgACNAQkFBgYCBgkKCQwKAAsIDgYGBQsCBQ8PEAgGCgARCgACBQAFCgUFCAIAAgUBAgAABAQFAgIACgoFBAUKBQAEBQUEBAgABQEGCAADAgYGCgAEBQAFBA8EBAULAQEFAAAAAQEKCAoAAAAKAAUFBgAABAcBBwcBAQEAAQABAw0NDQ0HAwMBDQQEBAQEBAQFBASFgICAAAFwAS0tBYOAgIAAAQASBomAgIAAAX8BQYCAwAALB8eAgIAABQZtZW1vcnkCAAZlbmNvZGUADQtyZWNvbnN0cnVjdAAIEV9fd2JpbmRnZW5fbWFsbG9jAEUPX193YmluZGdlbl9mcmVlAFsJvICAgAABAEEBCywoXIQBMnh5hgGFASl2d3pVQ11OaIgBPlJ7hwF8ZEiLAYoBSxs8iQF9TyAqVn5eNAtlHowBgwEKnoWCgACNAaomARd/IwBB8CRrIgYkAEEAIQcCQCAAKAIIIgggAksNAEEBIQcgCCACSQ0AAkACQAJAAkACQAJAAkACQCACRQ0AAkACQCABKAIEIglFDQAgASACQQN0IgpqIQsgASEMA0AgCkUNAiAKQXhqIQpBCCEHIAwoAgQhDSAMQQhqIQwgDSAJRg0ADAsLCyAGQfAkaiQAQQoPC0ELIQcgAiAERw0IQQAhDEEAIQoDQCAMIAMgCmotAABqIQwgCkEBaiIKIAJJDQALQQ0hByAMIAhGDQhBCSEHIAwgACgCACIKSQ0IIAZCADcD4BwCQCAKQSFJDQAgBkHgHGogChAlCyAGIAZB4BxqQYgCEEYhDCAAKAIEIQogDEIANwPgHAJAIApBIUkNACAMQeAcaiAKECQgAEEEaigCACEKCyAMQYgCaiAMQeAcakGIAhBGGiAMQgA3A+AcAkAgCkEhSQ0AIAxB4BxqIAoQJAsgDEGQBGogDEHgHGpBiAIQRhogACgCACEKIAxCADcD4BwCQCAKQSFJDQAgDEHgHGogChAiIAAoAgAhCgsgDEGYBmogDEHgHGpBiAEQRhogDEIANwPgHAJAIApBIUkNACAMQeAcaiAKECILIAxBoAdqIAxB4BxqQYgBEEYaAkAgCyABRg0AIAJBA3QhDSAMQaAHakEMaiEEIAxBoAdqQQhqIQsgDEGIAmpBCGohDiAMQZAEakEIaiEPIAxBmAZqQQxqIRAgDEGYBmpBCGohESAMQQhqIRJBACEKA0AgCiACTw0DAkACQAJAIAMgCmotAABFDQAgDEEMaigCACAMKAIAIgcgB0EgSyIIGyIJIAAoAgBPDQIgAUEEaigCACETIAEoAgAhFAJAIAkgB0EgIAgbRw0AIAxBf0EAQX8gCWd2IAlBAWpBAkkbIgdBAWoiCCAIIAdJGxAlIAwoAgAhBwsgEigCACEIIAxBDEEAIAdBIEsiBxtqIAlBAWo2AgAgCCASIAcbIAlBA3RqIgcgEzYCBCAHIBQ2AgACQCAQKAIAIAwoApgGIgkgCUEgSyIIGyIHIAlBICAIGyIIRw0AAkACQCAIQQFqIgkgCEkNAEEAIQgCQCAJQQJJDQBBfyAJQX9qZ3YhCAsgCEEBaiIJIAhPDQELQX8hCQsgDEGYBmogCRAiIAwoApgGIQkLIBEoAgAgESAJQSBLIggbIQkgECAMQZgGaiAIGyEIDAELIAFBBGooAgAhCSABKAIAIQgCQAJAIAogACgCAE8NAAJAIAxBiAJqQQxqKAIAIAwoAogCIgcgB0EgSyIUGyITIAdBICAUGyIURw0AAkACQCAUQQFqIgcgFEkNAEEAIRQCQCAHQQJJDQBBfyAHQX9qZ3YhFAsgFEEBaiIHIBRPDQELQX8hBwsgDEGIAmogBxAkIAwoAogCIQcLIA4oAgAhFCAMQYgCakEMQQAgB0EgSyIHG2ogE0EBajYCACAUIA4gBxsgE0EDdGoiByAINgIAIAdBBGohBwwBCwJAIAxBkARqQQxqKAIAIAwoApAEIgcgB0EgSyIUGyITIAdBICAUGyIURw0AAkACQCAUQQFqIgcgFEkNAEEAIRQCQCAHQQJJDQBBfyAHQX9qZ3YhFAsgFEEBaiIHIBRPDQELQX8hBwsgDEGQBGogBxAkIAwoApAEIQcLIA8oAgAhFCAMQZAEakEMQQAgB0EgSyIHG2ogE0EBajYCACAUIA8gBxsgE0EDdGoiByAINgIAIAdBBGohBwsgByAJNgIAAkAgBCgCACAMKAKgByIJIAlBIEsiCBsiByAJQSAgCBsiCEcNAAJAAkAgCEEBaiIJIAhJDQBBACEIAkAgCUECSQ0AQX8gCUF/amd2IQgLIAhBAWoiCSAITw0BC0F/IQkLIAxBoAdqIAkQIiAMKAKgByEJCyALKAIAIAsgCUEgSyIIGyEJIAQgDEGgB2ogCBshCAsgCCAHQQFqNgIAIAkgB0ECdGogCjYCAAsgAUEIaiEBIApBAWohCiANQXhqIg0NAAsLIAxBmAZqQQhqIggoAgAhBCAMQZgGakEMaigCACEBIAwoApgGIQkgDCAAQZwIaiIVIAxBoAdqQQhqIgooAgAgCiAMKAKgByIHQSBLIg0bIhYgDEGgB2pBDGooAgAgByANGyIXEBkiCjYCuAogCg0HIAAoAgAiByAHbCIKQX9MDQICQAJAAkAgCkUNAEEBIQsgCkEBEG0iDUUNCSAKIRIgCkGACE0NAQwCC0EBIQ0LIAxB4BxqIA0gChBGGiAMQbAIakECaiAMQeAcakECai0AADoAACAMIAwvAOAcOwGwCCAMKADjHCEQIAwoAOccIRIgDEHQFGogDEHrHGpB+AcQRhpBACELAkAgCkUNACANIApBARBnCyAQIQ0LIAxBzAxqIAs6AAAgDEHNDGoiECAMLwGwCDsAACAMQcAMakEUaiIRIBI2AgAgDEHADGpBEGoiEiANNgIAIAxBzwxqIAxBsAhqQQJqLQAAOgAAIAwgCjYCyAwgDCAHNgLEDCAMIAc2AsAMIAxB2AxqIAxB0BRqQfgHEEYaAkACQAJAIAEgCSAJQSBLIgobIgdFDQAgBCAIIAobIhggB0ECdGohGSAAQRlqIRNBACEIIABBFGohFCAAQSBqIQ4gAEEQaiEPIAxByAxqIRogAEEcaiEbA0ACQCAAKAIAIgRFDQAgGCgCACELQQAhCgNAIA4oAgAgFCgCACIHIAdBgAhLIgcbIgkgCiAPKAIAIAtsaiINTQ0EIBEoAgAgGigCACIJIAlBgAhLIgkbIhwgCiAIIAwoAsQMbGoiAU0NBSASKAIAIBAgCRsgAWogGygCACATIAcbIA1qLQAAOgAAIApBAWoiCiAESQ0ACwsgCEEBaiEIIBhBBGoiGCAZRw0ACwsgDEHgHGogDEHADGoQASAMLQDsHEECRg0FIAxB0BRqIAxB4BxqQZAIEEYaQZgIQQQQbCIKRQ0GIApCgYCAgBA3AgAgCkEIaiAMQdAUakGQCBBGGiAMIAo2AuAcIBUgFiAXIAxB4BxqECZB/wFxIgdBAkcNBwJAIAxBwAxqQQhqKAIAIgdBgQhJDQAgDEHQDGooAgAgB0EBEGcLIAwoArgKIgdFDQkgByAHKAIAIg1Bf2o2AgAgDUEBRw0JIAxBuApqEEEMCQtBlLXEACANIAkQOgALQaS1xAAgASAcEDoAC0HQs8QAQQBBABA6AAtBgLTEACAKIAIQOgALEHIAC0GDgsAAQSsQNwALQZgIQQQQaQALQYOCwABBKyAHQQFxEDYACyAKQQEQaQALIAwgCjYCrAggAEEEaigCACEKIAxCADcD4BwCQCAKQSFJDQAgDEHgHGogChAlCyAMQbAIaiAMQeAcakGIAhBGGgJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAAKAIAIgFFDQAgDEG4CGohCEEAIQoDQCAKIAJPDQMCQAJAIAMgCmotAABFDQAgCkEBaiIKIAFJDQIMAQsgDCgCrAgiB0EMaigCACINIApsIgkgDWoiBCAJSQ0JIAcoAhwgB0EQaigCACILIAtBgAhLIgsbIhAgBEkNCiAHKAIYIAdBFWogCxsgCWohBAJAIAxBsAhqQQxqKAIAIAwoArAIIgcgB0EgSyILGyIJIAdBICALGyILRw0AAkACQCALQQFqIgcgC0kNAEEAIQsCQCAHQQJJDQBBfyAHQX9qZ3YhCwsgC0EBaiIHIAtPDQELQX8hBwsgDEGwCGogBxAlIAwoArAIIQcLIAgoAgAhCyAMQbAIakEMQQAgB0EgSyIHG2ogCUEBajYCACALIAggBxsgCUEDdGoiByANNgIEIAcgBDYCACAKQQFqIgogAUkNAQsLIAAoAgAhCQwBC0EAIQkLIAxBiAJqQQhqIRMgDEEIaiESAkAgCUUNACAMQYgCakEMaigCACAMKAKIAiIKIApBIEsiChshASATKAIAIBMgChshCCAMQQxqKAIAIAwoAgAiCiAKQSBLIgobIQQgEigCACASIAobIQogDEGwCGpBDGooAgAgDCgCsAgiByAHQSBLIgcbIQsgDEGwCGpBCGoiDSgCACANIAcbIRBBACEHA0AgByAETw0DIAAgECALIAcgCigCACAKQQRqKAIAIAggARAJIApBCGohCiAHQQFqIg0hByANIAlJDQALCyAFDQwgAEEEaigCACEKIAxCADcD4BwCQCAKQSFJDQAgDEHgHGogChAlCyAMQbgKaiAMQeAcakGIAhBGGiAMQcAMaiAAEBECQCAAKAIAIgcgAEEIaigCACIBTw0AIAdBA3QhCiAMQbgKakEIaiEIIAxBwAxqQQhqIQQgDEHADGpBDGohFANAIAcgAk8NBgJAIAMgB2otAAANACAUKAIAIAwoAsAMIg0gDUEgSyINGyILIAcgACgCACIJayIQTQ0MIAQoAgAgBCANGyAJQQN0ayAKaiINKAIAIQsgDUEEaigCACEQAkAgDEG4CmpBDGooAgAgDCgCuAoiDSANQSBLIhEbIgkgDUEgIBEbIhFHDQACQAJAIBFBAWoiDSARSQ0AQQAhEQJAIA1BAkkNAEF/IA1Bf2pndiERCyARQQFqIg0gEU8NAQtBfyENCyAMQbgKaiANECUgDCgCuAohDQsgCCgCACERIAxBuApqQQxBACANQSBLIg0baiAJQQFqNgIAIBEgCCANGyAJQQN0aiINIBA2AgQgDSALNgIACyAKQQhqIQogB0EBaiIHIAFJDQALIAAoAgAhBwsgDEIANwPgHAJAIAdBIUkNACAMQeAcaiAHECUgACgCACEHCyAMQdAUaiAMQeAcakGIAhBGGgJAAkACQCAHRQ0AIAxB0BRqQQhqIQggDEGIAmpBDGohFEEAIRFBACEBQQAhCgNAIAogAk8NBgJAAkAgAyAKai0AAEUNACAMQQxqKAIAIAwoAgAiDSANQSBLIg0bIgkgAU0NDSAMQQhqKAIAIBIgDRsgAUEDdGohDSABQQFqIQEMAQsgFCgCACAMKAKIAiINIA1BIEsiDRsiCSARTQ0NIAxBiAJqQQhqKAIAIBMgDRsgEUEDdGohDSARQQFqIRELIApBAWohCiANKAIAIQQgDSgCBCELAkAgDEHQFGpBDGooAgAgDCgC0BQiDSANQSBLIhAbIgkgDUEgIBAbIhBHDQACQAJAIBBBAWoiDSAQSQ0AQQAhEAJAIA1BAkkNAEF/IA1Bf2pndiEQCyAQQQFqIg0gEE8NAQtBfyENCyAMQdAUaiANECUgDCgC0BQhDQsgCCgCACEQIAxB0BRqQQxBACANQSBLIg0baiAJQQFqNgIAIBAgCCANGyAJQQN0aiINIAs2AgQgDSAENgIAIAogB0kNAAsgDCgC0BQhCiAAKAIAIgINAQwCC0EAIQIgDCgC0BQhCkEARQ0BCyAMQZAEakEMaigCACAMKAKQBCIHIAdBIEsiBxshCSAMQZAEakEIaiINKAIAIA0gBxshASAMQdAUakEMaigCACAKIApBIEsiBxshAyAMQdAUakEIaiIKKAIAIAogBxshCiAMQbgKakEMaigCACAMKAK4CiIHIAdBIEsiBxshCCAMQbgKakEIaiINKAIAIA0gBxshBEEAIQcDQCAHIANPDQUgACAEIAggByAKKAIAIApBBGooAgAgASAJEAkgCkEIaiEKIAdBAWoiDSEHIA0gAkkNAAsgDCgC0BQhCgsCQAJAIApBIU8NACAMKALADCIKQSFPDQEMDAsgDEHYFGooAgAgCkEDdEEEEGcgDCgCwAwiCkEhSQ0LCyAMQcgMaigCACAKQQN0QQQQZyAMKAK4CiIKQSFPDQsMDAtBkLTEACAKIAIQOgALQeCzxAAgByAEEDoAC0GwtMQAIAogAhA6AAtB4LPEACAHIAMQOgALQaC0xAAgByACEDoACyAJIAQQOwALIAQgEBA5AAtBwLPEACABIAkQOgALQcCzxAAgESAJEDoAC0HAs8QAIBAgCxA6AAsgDCgCuAoiCkEhSQ0BCyAMQcAKaigCACAKQQN0QQQQZwsCQCAMKAKwCCIKQSFJDQAgDEG4CGooAgAgCkEDdEEEEGcLIAwoAqwIIgogCigCACIKQX9qNgIAAkACQAJAAkACQAJAAkACQAJAAkACQCAKQQFGDQBBISEKIAwoAqAHIgdBIU8NAQwCCyAMQawIahBBQSEhCiAMKAKgByIHQSFJDQELIAxBqAdqKAIAIAdBAnRBBBBnIAwoApgGIgcgCkkNAQwCCyAMKAKYBiIHIApPDQELQSEhCiAMKAKQBCIHQSFPDQEMAgsgDEGgBmooAgAgB0ECdEEEEGdBISEKIAwoApAEIgdBIUkNAQsgDEGYBGooAgAgB0EDdEEEEGcgDCgCiAIiByAKSQ0BDAILIAwoAogCIgcgCk8NAQsgDCgCACIKQSFJDQIMAQsgDEGQAmooAgAgB0EDdEEEEGcgDCgCACIKQSFJDQELIAxBCGooAgAgCkEDdEEEEGcLQQ0hBwsgBkHwJGokACAHC8cWATh/IwBBsCBrIgIkAAJAAkACQAJAAkACQAJAIAEoAgAiAyABKAIERw0AIAJBkAhqIAMQFCABKAIAIgQgAigCkAhHDQEgAigClAggAUEEaigCAGoiBSAEbCIGQX9MDQICQAJAAkAgBkUNAEEBIQcgBkEBEG0iCEUNBiAGIQkgBkGACE0NAQwCC0EBIQgLIAJBoBBqIAggBhBGGiACQawgakECaiACQaAQakECai0AADoAACACIAIvAKAQOwGsICACKACjECEKIAIoAKcQIQkgAkGwGGogAkGrEGpB+AcQRhpBACEHAkAgBkUNACAIIAZBARBnCyAKIQgLIAJBrBBqIAc6AAAgAkGgEGpBDWoiCyACLwGsIDsAACACQaAQakEUaiIMIAk2AgAgAkGgEGpBEGoiDSAINgIAIAJBrxBqIAJBriBqLQAAOgAAIAIgBjYCqBAgAiAFNgKkECACIAQ2AqAQIAJBuBBqIAJBsBhqQfgHEEYaIAEoAgAiDkUNBCABQQ1qIQ8gAkGQCGpBDWohEEEAIRFBASESIAFBBGohE0EIIRQgAkGQCGpBCGohFUGACCEWIAJBkAhqQRRqIRdBACEYDAULQYyIwABBJEH0tcQAEE0ACyACQbwYakEYNgIAIAJBtBBqQQI2AgAgAkEYNgK0GCACIAE2ArAYIAJCAjcCpBAgAkHUtcQANgKgECACIAJBkAhqNgK4GCACIAJBsBhqNgKwECACQaAQakHktcQAED8ACxByAAsgBkEBEGkAC0EAIQYMAQtBASEGCwNAAkACQAJAAkACQAJAAkACQAJAAkAgBg4CAAEBCwJAIAIgAkGgEGpBkAgQRiIGKAKYCCIIQYEISQ0AIAZBoAhqKAIAIAhBARBnCyAGKAIAIhtFDQUgBkENaiEcQQAhHUEBIR5BCCEfIAZBCGohIEGACCEhIAZBFGohIiAGQRBqISNBtpHAACEkQbiLwAAhJUH/ASEmQf4DISdBuI3AACEoQQEhKUEAISpBASEYDAELAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgGA4DAAECAgtBACEGAkAgEygCACIFRQ0AQQAhCCAFIQYDQCABQRRqKAIAIAEgFGooAgAiBCAEIBZLIgQbIgcgCCARIAZsaiIGTQ0FIAwoAgAgAkGgEGogFGooAgAiByAHIBZLIgcbIgogCCARIAIoAqQQbGoiCU0NBiANKAIAIAsgBxsgCWogAUEQaigCACAPIAQbIAZqLQAAOgAAIBMoAgAhBiAIIBJqIgggBUkNAAsLAkAgAigClAgiGUUNACAXKAIAIBUoAgAiCCAIIBZLIgUbIhogGSARbCIKTQ0LQQEhBEEAIQgDQCAMKAIAIAJBoBBqIBRqKAIAIgcgByAWSyIHGyIaIAYgCGogESACKAKkEGwiCWpNDQcgDSgCACALIAcbIAZqIAggCWpqIAJBkAhqQRBqKAIAIBAgBRsgCmotAAA6AAAgCCASaiIHIBlPDQEgAigClAggEWwiCSAEaiEKIAchCCAEIBJqIQQgFygCACAVKAIAIgUgBSAWSyIFGyIaIAkgB2oiB0sNAAwNCwsgESASaiIRIA5JDRFBACEGDBoLICIoAgAiKyAgKAIAIiwgLCAhSyIKGyIJIAIoAgQiBCAqbCItICpqIhhNDQsCQCAjKAIAIBwgChsiGSAYai0AAA0AIAQgKmwhCCAqIAQgKWxqIQZBASEHIAIoAgAhGgNAICogB2ogGk8NASAJIAZNDQcgCCAEaiEIIAcgHmohByAZIAZqIQUgBiAEaiEGIAUtAABFDQALIARFDQAgByAeRg0AIAkgLU0NCSAEICpsIQVBACEGA0AgCSAIIAZqIgdNDQggIygCACAcIAobIgkgBWogBmoiCi0AACEZIAogCSAIaiAGai0AADoAACAiKAIAICAoAgAiCSAJICFLIgkbIgogB00NCSAjKAIAIBwgCRsgCGogBmogGToAAAJAIAYgHmoiByAETw0AIAchBiAiKAIAICAoAgAiCSAJICFLIgobIgkgBSAHaiItSw0BDAsLCyACKAIEIgQgKmwgKmohGCAiKAIAISsgICgCACEsCyArICwgLCAhSyIHGyIKIBhNDQwCQCAjKAIAIgggHCAHGyAYai0AACIGIB5GDQAgBkUNAiAGICVqLQAAIgYgJnMgHSAGayAGGyIGICdPDQ4gBEUNACAKIAQgKmwiCU0NDyAGIChqLQAAIRlBASEIQQAhBgNAICMoAgAgHCAHGyAJaiIHIActAAAgH3QgGXIgJGotAAA6AAAgBiAeaiIGIARPDQEgAigCBCAqbCIFIAhqIQkgCCAeaiEIICIoAgAgICgCACIHIAcgIUsiBxsiCiAFIAZqIgVLDQAMEQsLICogHmoiLSACKAIAIixPDRQgLSEuQQAhBgwSCyAxRQ0SQQAhOUEBIQYMEQsgAEECOgAMICxBgQhJDRQgCCAsQQEQZwwUC0GUtcQAIAYgBxA6AAtBpLXEACAJIAoQOgALQaS1xAAgCSAGaiAIaiAaEDoAC0GUtcQAIAYgCRA6AAtBlLXEACAHIAkQOgALQaS1xAAgByAKEDoAC0GUtcQAIC0gCRA6AAsgCiEHC0GUtcQAIAcgGhA6AAtBlLXEACAYIAkQOgALQZS1xAAgGCAKEDoAC0GUtsQAIAZB/gMQOgALIAkhBQtBlLXEACAFIAoQOgALQQAhGEEBIQYMCAtBASEGDAcLA0ACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgBg4CAAEBCyAiKAIAICAoAgAiBiAGICFLIgQbIgcgAigCBCIZIC5sICpqIgZNDQMCQCAjKAIAIBwgBBsgBmotAAAiGkUNACAZRQ0AIAcgGSAqbCIJTQ0GQQEhCEEAIQYgGSEFA0AgByAGIC4gBWxqIgVNDQMgIygCACAcIAQbIgQgBWoiByAHLQAAIBogH3QgBCAJai0AAHIgJGotAABzOgAAIAYgHmoiBiAZTw0BIAIoAgQiBSAqbCIKIAhqIQkgCCAeaiEIICIoAgAgICgCACIEIAQgIUsiBBsiByAKIAZqIgpLDQAMCAsLIC4gHmoiLiAsSQ0JDA0LIDYoAgAgNCgCACIGIAYgNUsiBBsiByACKAIEIhkgOWwgMWoiBk0NAwJAIDcoAgAgMCAEGyAGai0AACIaRQ0AIBlFDQAgByAZIDFsIglNDQdBASEIQQAhBiAZIQUDQCAHIAYgOSAFbGoiBU0NAyA3KAIAIDAgBBsiBCAFaiIHIActAAAgGiAzdCAEIAlqLQAAciA4ai0AAHM6AAAgBiAyaiIGIBlPDQEgAigCBCIFIDFsIgogCGohCSAIIDJqIQggNigCACA0KAIAIgQgBCA1SyIEGyIHIAogBmoiCksNAAwJCwsgOSAyaiI5IDFJDQkMCwtBpLXEACAFIAcQOgALQaS1xAAgBSAHEDoAC0GUtcQAIAYgBxA6AAtBlLXEACAGIAcQOgALIAkhCgtBlLXEACAKIAcQOgALIAkhCgtBlLXEACAKIAcQOgALQQAhBgwBC0EBIQYMAAsLIDEgMmoiMSAvTw0BQQIhGEEBIQYMBQsgKSAeaiEpIC0hKiAtIBtJDQIgAigCACIvRQ0AIAJBDWohMEEAITFBASEyQQghMyACQQhqITRBgAghNSACQRRqITYgAkEQaiE3QbaRwAAhOEECIRgMAwsgACACQQAgAyADIANBAXQQDiACKAIIIgZBgQhJDQAgAkEQaigCACAGQQEQZyACQbAgaiQADwsgAkGwIGokAA8LQQEhGEEBIQYMAQtBASEGDAALC/oKAg9/AX4jAEEgayIDJABBASEEAkAgAigCGEEiIAJBHGooAgAoAhARAAANAAJAAkAgAUUNACAAIAFqIQUgAkEYaiEGIAJBHGohByAAIQhBACEJQQAhCgJAA0AgCCELIAhBAWohDAJAAkAgCCwAACINQQBIDQAgDUH/AXEhDSAMIQgMAQsCQAJAIAwgBUYNACAMLQAAQT9xIQ4gCEECaiIIIQwMAQtBACEOIAUhCAsgDUEfcSEPAkACQAJAIA1B/wFxIg1B4AFJDQAgCCAFRg0BIAgtAABBP3EhECAIQQFqIgwhEQwCCyAOIA9BBnRyIQ0gDCEIDAILQQAhECAFIRELIBAgDkEGdHIhDgJAAkACQCANQfABSQ0AIBEgBUYNASARQQFqIQggES0AAEE/cSENDAILIA4gD0EMdHIhDSAMIQgMAgtBACENIAwhCAsgDkEGdCAPQRJ0QYCA8ABxciANciINQYCAxABGDQILQQIhDAJAAkACQAJAAkACQAJAAkACQCANQXdqIg9BHksNAEH0ACEOAkAgDw4fCAADAwQDAwMDAwMDAwMDAwMDAwMDAwMDAwIDAwMDAggLQe4AIQ4MBAsgDUHcAEcNAQsgDSEODAULQaC7xAAgDRAhRQ0CDAMLQfIAIQ4LDAILAkAgDUH//wNLDQAgDUGgm8QAQShB8JvEAEGvAkGfnsQAQbwCEBdFDQEMAwsCQCANQf//B0sNACANQdugxABBIUGdocQAQZ4BQbuixABB/QIQF0UNAQwDCyANQe+DOEsNACANQeKLdGpB4o0sSQ0AIA1Bn6h0akGfGEkNACANQd7idGpBDkkNACANQf7//wBxQZ7wCkYNACANQamydWpBKUkNACANQcuRdWpBCksNAgsgDUEBcmdBAnZBB3OtQoCAgIDQAIQhEkEDIQwgDSEOCyADIAE2AgQgAyAANgIAIAMgCTYCCCADIAo2AgwCQCAKIAlJDQACQCAJRQ0AIAkgAUYNACAJIAFPDQEgACAJaiwAAEG/f0wNAQsCQCAKRQ0AIAogAUYNACAKIAFPDQEgACAKaiwAAEG/f0wNAQsCQCAGKAIAIAAgCWogCiAJayAHKAIAKAIMEQYADQADQAJAAkACQAJAAkACQAJAIAxBAUYNAEHcACEJAkAgDEECRg0AIAxBA0cNBiASQiCIp0H/AXFBf2oiDEEESw0GAkAgDA4FAAYEBQMACyASQv////+PYIMhEkEDIQxB/QAhCQwHC0EBIQwMBgtBACEMIA4hCQwFCyASQv////+PYINCgICAgMAAhCESQQMhDAwECyASQv////+PYINCgICAgCCEIRJBAyEMQfsAIQkMAwsgEkL/////j2CDQoCAgIAwhCESQQMhDEH1ACEJDAILIA4gEqciD0ECdEEccXZBD3EiDEEwciAMQdcAaiAMQQpJGyEJAkAgD0UNACASQn98Qv////8PgyASQoCAgIBwg4QhEkEDIQwMAgsgEkL/////j2CDQoCAgIAQhCESQQMhDAwBC0EBIQwCQCANQYABSQ0AQQIhDCANQYAQSQ0AQQNBBCANQYCABEkbIQwLIAwgCmohCQwECyAGKAIAIAkgBygCACgCEBEAAEUNAAsLQQEhBAwGCyADIANBDGo2AhggAyADQQhqNgIUIAMgAzYCECADQRBqEFMACyAKIAtrIAhqIQogBSAIRw0ACwsgCUUNASAJIAFGDQECQCAJIAFPDQAgACAJaiwAAEG/f0oNAgsgACABIAkgARAEAAtBACEJCyACQRhqIgwoAgAgACAJaiABIAlrIAJBHGoiCigCACgCDBEGAA0AIAwoAgBBIiAKKAIAKAIQEQAAIQQLIANBIGokACAEC5wJAQp/IwBBwABrIgMkACADQSRqIAE2AgAgA0E0aiACQRRqKAIAIgQ2AgAgA0EDOgA4IANBLGogAigCECIFIARBA3RqNgIAIANCgICAgIAENwMIIAMgADYCIEEAIQYgA0EANgIYIANBADYCECADIAU2AjAgAyAFNgIoAkACQAJAAkACQCACKAIIIgdFDQAgAigCACEIIAIoAgQiCSACQQxqKAIAIgUgBSAJSxsiCkUNASAAIAgoAgAgCCgCBCABKAIMEQYADQIgCEEMaiEFIANBOGohASADQTRqIQsgA0Ew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QZeVxABBEBBKDAoLIAIgAUGGlcQAQREQSgwJCyACIAFB9JTEAEESEEoMCAsgAiABQeGUxABBExBKDAcLIAIgAUHPlMQAQRIQSgwGCyACIAFBvJTEAEETEEoMBQsgAiABQaqUxABBEhBKDAQLIAIgAUGXlMQAQRMQSgwDCyACIAFBjZTEAEEKEEoMAgsgAiABQfyTxABBERBKDAELIAIgAUHwk8QAQQwQSgsgAhArIQEgAkEQaiQAIAEL+QEBAn8jAEEQayIEJAAgBCABKAIAIgUoAgA2AgwCQAJAAkAgAkECaiICIAJsIgJBgBAgAkGAEEsbIgFBBCAEQQxqQYOCwABBwLLEABAMIgJFDQAgBSAEKAIMNgIADAELIARBg4LAACABQQQQMgJAAkAgBCgCAEUNACAFIAQoAgw2AgAMAQsgBCgCBCICIAQoAgw2AgggBCACNgIMIAFBBCAEQQxqQYOCwABBwLLEABAMIQIgBSAEKAIMNgIAIAINAQtBASEBDAELIAJCADcCBCACIAIgAUECdGpBAnI2AgBBACEBCyAAIAI2AgQgACABNgIAIARBEGokAAvmAQEEfyMAQTBrIgIkACABQQRqIQMCQCABKAIEDQAgASgCACEEIAJBADYCECACQgE3AwggAiACQQhqNgIUIAJBGGpBEGogBEEQaikCADcDACACQRhqQQhqIgUgBEEIaikCADcDACACIAQpAgA3AxggAkEUakG0t8QAIAJBGGoQAxogBSACKAIQNgIAIAIgAikDCDcDGAJAIAMoAgAiBEUNACABQQhqKAIAIgFFDQAgBCABQQEQZwsgAyACKQMYNwIAIANBCGogBSgCADYCAAsgAEHwt8QANgIEIAAgAzYCACACQTBqJAAL0wEBA38gAC0ACCEBAkAgACgCBCICRQ0AIAFB/wFxIQNBASEBAkAgAw0AAkAgACgCACIDLQAAQQRxRQ0AQQEhASADKAIYQd2axABBASADQRxqKAIAKAIMEQYADQEgAEEEaigCACECCwJAIAJBAUcNACAALQAJRQ0AQQEhASAAKAIAIgMoAhhB3JrEAEEBIANBHGooAgAoAgwRBgANAQsgACgCACIBKAIYQd6axABBASABQRxqKAIAKAIMEQYAIQELIABBCGogAToAAAsgAUH/AXFBAEcLuAEBAX8jAEEQayIEJAACQAJAIAFFDQAgBCABNgIEIAJFDQAgA0EESw0BIAJBA2pBAnZBf2oiAUH/AUsNASAAIAFBAnRqQQRqIgFFDQEgBCAANgIIIAQgASgCADYCDCAEQQRqIARBDGogBEEIakHwssQAEB8gASAEKAIMNgIACyAEQRBqJAAPCyAEIAAoAgA2AgwgBEEEaiAEQQxqQYOCwABB2LLEABAfIAAgBCgCDDYCACAEQRBqJAALjwEBA38jAEGAAWsiAiQAIAAoAgAhA0EAIQADQCACIABqQf8AaiADQQ9xIgRBMHIgBEHXAGogBEEKSRs6AAAgAEF/aiEAIANBBHYiAw0ACwJAIABBgAFqIgNBgQFPDQAgAUEBQZKZxABBAiACIABqQYABakEAIABrEAYhACACQYABaiQAIAAPCyADQYABEDsAC44BAQN/IwBBgAFrIgIkACAAKAIAIQNBACEAA0AgAiAAakH/AGogA0EPcSIEQTByIARBN2ogBEEKSRs6AAAgAEF/aiEAIANBBHYiAw0ACwJAIABBgAFqIgNBgQFPDQAgAUEBQZKZxABBAiACIABqQYABakEAIABrEAYhACACQYABaiQAIAAPCyADQYABEDsAC4sBAQV/AkAgACgCCCIBRQ0AIAAoAgAhAiABQQR0IQEDQAJAIAJBBGoiAygCAEUNAAJAIAIoAgAiBEUNACAEIAQoAgAiBUF/ajYCACAFQQFHDQAgAhBACyADEC8LIAJBEGohAiABQXBqIgENAAsLAkAgAEEEaigCACICRQ0AIAAoAgAgAkEEdEEEEGcLC4sBAQV/AkAgACgCCCIBRQ0AIAAoAgAhAiABQQR0IQEDQAJAIAJBBGoiAygCAEUNAAJAIAIoAgAiBEUNACAEIAQoAgAiBUF/ajYCACAFQQFHDQAgAhBBCyADEDALIAJBEGohAiABQXBqIgENAAsLAkAgAEEEaigCACICRQ0AIAAoAgAgAkEEdEEEEGcLC4cBAQJ/AkAgACgCBCICIAAoAggiA2sgAU8NAAJAAkAgAyABaiIBIANJDQAgAkEBdCIDIAEgASADSRsiAUEASA0AAkACQCACRQ0AIAAoAgAgAkEBIAEQYiICRQ0BDAMLIAFBARBsIgINAgsgAUEBEGkACxBvAAsgACACNgIAIABBBGogATYCAAsLcgACQEEAIAJBAnQiAiADQQN0QYCAAWoiAyADIAJJG0GHgARqIgJBEHZAACIDQRB0IANBf0YbIgNFDQAgA0IANwIEIAMgAyACQYCAfHFqQQJyNgIAIAAgAzYCBCAAQQA2AgAPCyAAIAM2AgQgAEEBNgIAC4EBAQF/IwBBwABrIgQkACAEIAE2AgwgBCAANgIIIAQgAzoAFCAEIAI2AhAgBEE8akERNgIAIARBLGpBAjYCACAEQQ82AjQgBEICNwIcIARBwLTEADYCGCAEIARBEGo2AjggBCAEQQhqNgIwIAQgBEEwajYCKCAEQRhqQdC0xAAQRAALewEBfyMAQTBrIgIkACACQRRqQSo2AgAgAkEqNgIMIAIgADYCCCACIABBBGo2AhAgAUEcaigCACEAIAEoAhghASACQSxqQQI2AgAgAkICNwIcIAJBmLjEADYCGCACIAJBCGo2AiggASAAIAJBGGoQAyEBIAJBMGokACABC3oBAX8jAEHAAGsiAyQAIAMgATYCDCADIAA2AgggAyACOgAXIANBPGpBATYCACADQSxqQQI2AgAgA0ECNgI0IANCAjcCHCADQaCyxAA2AhggAyADQRdqNgI4IAMgA0EIajYCMCADIANBMGo2AiggA0EYakGwssQAEEQAC3oBAX8jAEHAAGsiAyQAIAMgATYCDCADIAA2AgggAyACOgAXIANBPGpBDjYCACADQSxqQQI2AgAgA0EPNgI0IANCAjcCHCADQcC0xAA2AhggAyADQRdqNgI4IAMgA0EIajYCMCADIANBMGo2AiggA0EYakHQtMQAEEQAC3MBAX8jAEHAAGsiAiQAIAIgATYCDCACIAA2AgggAkE0akEQNgIAIAJBJGpBAjYCACACQQ82AiwgAkICNwIUIAJBwLTEADYCECACIAJBOGo2AjAgAiACQQhqNgIoIAIgAkEoajYCICACQRBqQdC0xAAQRAALcAIEfwF+IwBBMGsiASQAIAAQcBBZIQIgABBzEFohAyABQQhqIAIQaiABKQMIIQUgAhB0IQQgASACEHU2AhwgASAENgIYIAEgBTcDECABQQA2AiQgASADNgIgIAFBIGpB3LfEACAAEHMgAUEQahAnAAtvAQF/IwBBMGsiAiQAIAIgATYCBCACIAA2AgAgAkEsakEYNgIAIAJBHGpBAjYCACACQRg2AiQgAkICNwIMIAJB4LjEADYCCCACIAJBBGo2AiggAiACNgIgIAIgAkEgajYCGCACQQhqQfC4xAAQRAALbAEBfyMAQTBrIgMkACADIAI2AgQgAyABNgIAIANBLGpBGDYCACADQRxqQQI2AgAgA0EYNgIkIANCAjcCDCADQbi4xAA2AgggAyADNgIoIAMgA0EEajYCICADIANBIGo2AhggA0EIaiAAEEQAC28BAX8jAEEwayICJAAgAiABNgIEIAIgADYCACACQSxqQRg2AgAgAkEcakECNgIAIAJBGDYCJCACQgI3AgwgAkGAucQANgIIIAIgAkEEajYCKCACIAI2AiAgAiACQSBqNgIYIAJBCGpBkLnEABBEAAtjAQF/IwBBIGsiAiQAIAIgACgCADYCBCACQQhqQRBqIAFBEGopAgA3AwAgAkEIakEIaiABQQhqKQIANwMAIAIgASkCADcDCCACQQRqQbS3xAAgAkEIahADIQEgAkEgaiQAIAELaAIBfwN+IwBBMGsiASQAIAApAgghAiAAKQIQIQMgACkCACEEIAFBFGpBADYCACABIAQ3AxggAUGolsQANgIQIAFCATcCBCABIAFBGGo2AgAgASADNwMoIAEgAjcDICABIAFBIGoQRAALaAECfyABKAIAIQIgAUEANgIAAkACQCACRQ0AIAEoAgQhA0EIQQQQbCIBRQ0BIAEgAzYCBCABIAI2AgAgAEH0tMQANgIEIAAgATYCAA8LIABBhLXEADYCBCAAQQE2AgAPC0EIQQQQaQALYgEBfyMAQTBrIgIkACACQSBqIAEoAgAgASgCBCABKAIIIAEoAgwQVCACQRRqIAJBKGopAwA3AgAgAiAANgIIIAJBzLfEADYCBCACQcCVxAA2AgAgAiACKQMgNwIMIAIQOAALVgECfwJAIAAoAgAiAUEQaigCACICQYEISQ0AIAFBGGooAgAgAkEBEGcgACgCACEBCyABIAEoAgQiAkF/ajYCBAJAIAJBAUcNACAAKAIAQZgIQQQQZwsLVgECfwJAIAAoAgAiAUEQaigCACICQYEISQ0AIAFBGGooAgAgAkEBEGcgACgCACEBCyABIAEoAgQiAkF/ajYCBAJAIAJBAUcNACAAKAIAQZgIQQQQZwsLVQEBfwJAAkACQCABQYCAxABGDQBBASEEIAAoAhggASAAQRxqKAIAKAIQEQAADQELIAJFDQEgACgCGCACIAMgAEEcaigCACgCDBEGACEECyAEDwtBAAtIAQF/IwBBEGsiAiQAAkACQCAALQAAQQFHDQAgAiABQd2TxABBCRBKDAELIAIgAUHmk8QAQQoQSgsgAhArIQEgAkEQaiQAIAELSgIBfwF+IwBBIGsiAiQAIAEpAgAhAyACQRRqIAEpAgg3AgAgAiADNwIMIAIgADYCCCACQai4xAA2AgQgAkGolsQANgIAIAIQbgALLgACQCAAQXxLDQACQCAARQ0AIAAgAEF9SUECdBBsIgBFDQEgAA8LQQQPCxBxAAs2AQF/AkAgAkUNACAAIQMDQCADIAEtAAA6AAAgA0EBaiEDIAFBAWohASACQX9qIgINAAsLIAALNwEBfwJAQZjHxAAgAyACEBAiBEUNACAEIAAgAyABIAEgA0sbEEYaQZjHxAAgACABIAIQLAsgBAsxACAAKAIAIQACQCABEF9FDQAgACABEC0PCwJAIAEQYEUNACAAIAEQLg8LIAAgARBkCzwBAX9BACEAAkACQEEAKALIz0RBAUcNAEEAKALMz0QhAAwBC0EAQgE3A8jPRAtBACAANgLMz0QgAEEARws0ACAAIAEoAhggAiADIAFBHGooAgAoAgwRBgA6AAggACABNgIAIAAgA0U6AAkgAEEANgIECy8BAX8gACgCACIAIAIQMSAAIAAoAggiAyACajYCCCADIAAoAgBqIAEgAhBGGkEACywBAX8CQCACRQ0AIAAhAwNAIAMgAToAACADQQFqIQMgAkF/aiICDQALCyAACywBAX8jAEEQayIDJAAgAyABNgIMIAMgADYCCCADQQhqQeC0xABBACACECcACykBAX8jAEEQayICJAAgAiABQbCIwABBDhBKIAIQKyEBIAJBEGokACABCyYBAX8CQCAAKAIEIgFFDQAgAEEIaigCACIARQ0AIAEgAEEBEGcLCyUBAX8jAEEQayICJAAgAiABNgIMIAIgADYCCCACQQhqEIIBGgALIAACQEGYx8QAIAAgARAQIgFFDQAgAUEAIAAQTBoLIAELKgEBfyAAQfS0xABBhLXEACABKAIAIgIbNgIEIAAgAUHDhcAAIAIbNgIACyYBAX8gACgCACIBKAIAIAEoAgQgACgCBCgCACAAKAIIKAIAEAQACx4AIAAgBDYCDCAAIAM2AgggACACNgIEIAAgATYCAAsaACAAQgA3AgQgAEEENgIAIABBDGpCADcCAAscAQF/AkAgACgCBCIBRQ0AIAAoAgAgAUEBEGcLCxoBAX8gACABQQAoArjPRCICQRogAhsRBQAACxQAIAAgASACIAMgBEEBEABB/wFxCxUAAkAgAEUNACAADwtBnLfEABA9AAsVAAJAIABFDQAgAA8LQZy3xAAQPQALEgACQCABRQ0AIAAgAUEEEGcLCxAAIAAoAgAgACgCBCABEGsLEAAgACgCACAAKAIEIAEQawsQACABIAAoAgAgACgCBBAFCw0AIAAtAABBEHFBBHYLDQAgAC0AAEEgcUEFdgsPAEGYx8QAIAAgASACECwLDAAgACABIAIgAxBHCw4AIAAgASACQYCAAhATCw0AIAA1AgBBASABEBwLDQAgADUCAEEBIAEQHAsNAEGYx8QAIAAgARAQCwoAIAAgASACEGELDQBBw4XAAEEZIAEQAgsJACAAIAEQVwALDAAgACABKQIANwIACwoAIAIgACABEAULCAAgACABEGYLCAAgACABEFELBwAgABA4AAsKAEGAuMQAED0ACwcAIABBDGoLBQAQfwALBQAQbwALBwAgACgCCAsHACAAKAIICwcAIAAoAgwLBAAgAQsEAEEACwUAQYAECwQAQQELBwBBnM/EAAsMAELkrsKFl5uliBELDQBChJbbgd3goOPoAAsNAELNp7n04KW6rJV/Cw0AQs2ytoWB2Ij99wALAwAACwQAQQALBABBAAsDAAALDQBCzae59OCluqyVfwsCAAsCAAsCAAsCAAsCAAsCAAsCAAsCAAsCAAsL7c+EgAADAEGAgMAAC8CxBGNhbGxlZCBgUmVzdWx0Ojp1bndyYXAoKWAgb24gYW4gYEVycmAgdmFsdWVhc3NlcnRpb24gZmFpbGVkOiBtaWQgPD0gbGVuc3JjL2xpYmNvcmUvc2xpY2UvbW9kLnJzYXNzZXJ0aW9uIGZhaWxlZDogY2h1bmtfc2l6ZSAhPSAwc3JjL2xpYi5ycwAAAAAAAGF0dGVtcHQgdG8gZGl2aWRlIGJ5IHplcm8AAAAJAAAACgAAAAsAAAAMAAAADQAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAAOiBzcmMvbGliY29yZS9yZXN1bHQucnNjYWxsZWQgYFJlc3VsdDo6dW53cmFwKClgIG9uIGFuIGBFcnJgIHZhbHVlYXNzZXJ0aW9uIGZhaWxlZDogY2h1bmtfc2l6ZSAhPSAwc3JjL2xpYmNvcmUvc2xpY2UvbW9kLnJzYXNzZXJ0aW9uIGZhaWxlZDogbWlkIDw9IGxlbgAAAAAAAAAAAAAAAAAvaG9tZS9uYXphci1wYy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9zbWFsbHZlYy0wLjYuMTAvbGliLnJzAAAAAAAAAAAAAAAvaG9tZS9uYXphci1wYy8uY2FyZ28vZ2l0L2NoZWNrb3V0cy9yZWVkLXNvbG9tb24tZXJhc3VyZS0wNTcwOWMwMGRlZjE0NGQwLzg1ZjhkY2Ivc3JjL21hY3Jvcy5ycwAvaG9tZS9uYXphci1wYy8uY2FyZ28vZ2l0L2NoZWNrb3V0cy9yZWVkLXNvbG9tb24tZXJhc3VyZS0wNTcwOWMwMGRlZjE0NGQwLzg1ZjhkY2Ivc3JjL2xpYi5yczogc3JjL2xpYmNvcmUvcmVzdWx0LnJzUG9pc29uRXJyb3IgeyBpbm5lcjogLi4gfQAAAAAvaG9tZS9uYXphci1wYy8uY2FyZ28vcmVnaXN0cnkvc3JjL2dpdGh1Yi5jb20tMWVjYzYyOTlkYjllYzgyMy9zbWFsbHZlYy0wLjYuMTAvbGliLnJzQ29sb21uIGNvdW50IG9uIGxlZnQgaXMgZGlmZmVyZW50IGZyb20gcm93IGNvdW50IG9uIHJpZ2h0LCBsaHMgOiAsIHJocyA6IC9ob21lL25hemFyLXBjLy5jYXJnby9naXQvY2hlY2tvdXRzL3JlZWQtc29sb21vbi1lcmFzdXJlLTA1NzA5YzAwZGVmMTQ0ZDAvODVmOGRjYi9zcmMvbWF0cml4LnJzTWF0cmljZXMgZG8gbm90IGhhdmUgdGhlIHNhbWUgcm93IGNvdW50LCBsaHMgOiBUcnlpbmcgdG8gaW52ZXJ0IGEgbm9uLXNxdWFyZSBtYXRyaXhTaW5ndWxhck1hdHJpeC9ob21lL25hemFyLXBjLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3NtYWxsdmVjLTAuNi4xMC9saWIucnNh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YnN0ZC9zeXMvd2FzbS9tdXRleC5yc2Nhbm5vdCByZWN1cnNpdmVseSBhY3F1aXJlIG11dGV4Y2FsbGVkIGBSZXN1bHQ6OnVud3JhcCgpYCBvbiBhbiBgRXJyYCB2YWx1ZQAAAC9ydXN0Yy85MTg1NmVkNTJjNThhYTViYTY2YTAxNTM1NGQxY2M2OWU5Nzc5YmRmL3NyYy9saWJjb3JlL3NsaWNlL21vZC5ycy9ob21lL25hemFyLXBjLy5jYXJnby9naXQvY2hlY2tvdXRzL3JlZWQtc29sb21vbi1lcmFzdXJlLTA1NzA5YzAwZGVmMTQ0ZDAvODVmOGRjYi9zcmMvaW52ZXJzaW9uX3RyZWUucnNleHBsaWNpdCBwYW5pY05vdFNxdWFyZUFscmVhZHlTZXRJbnZhbGlkSW5kZXhJbnZhbGlkU2hhcmRGbGFnc0VtcHR5U2hhcmRUb29GZXdTaGFyZHNQcmVzZW50SW5jb3JyZWN0U2hhcmRTaXplVG9vTWFueUJ1ZmZlclNoYXJkc1Rvb0Zld0J1ZmZlclNoYXJkc1Rvb01hbnlQYXJpdHlTaGFyZHNUb29GZXdQYXJpdHlTaGFyZHNUb29NYW55RGF0YVNoYXJkc1Rvb0Zld0RhdGFTaGFyZHNUb29NYW55U2hhcmRzVG9vRmV3U2hhcmRzY2FsbGVkIGBPcHRpb246OnVud3JhcCgpYCBvbiBhIGBOb25lYCB2YWx1ZXNyYy9saWJjb3JlL29wdGlvbi5yc3NyYy9saWJhbGxvYy9yYXdfdmVjLnJzY2FwYWNpdHkgb3ZlcmZsb3dgLi5pbmRleCBvdXQgb2YgYm91bmRzOiB0aGUgbGVuIGlzICBidXQgdGhlIGluZGV4IGlzIGNhbGxlZCBgT3B0aW9uOjp1bndyYXAoKWAgb24gYSBgTm9uZWAgdmFsdWVzcmMvbGliY29yZS9vcHRpb24ucnNzcmMvbGliY29yZS9zbGljZS9tb2QucnNpbmRleCAgb3V0IG9mIHJhbmdlIGZvciBzbGljZSBvZiBsZW5ndGggc2xpY2UgaW5kZXggc3RhcnRzIGF0ICBidXQgZW5kcyBhdCBzcmMvbGliY29yZS9zdHIvbW9kLnJzWy4uLl1ieXRlIGluZGV4ICBpcyBvdXQgb2YgYm91bmRzIG9mIGBiZWdp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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v////+/tgAAAAAAAAAAAP8HAAAAAAD4//8AAAEAAAAAAAAAAAAAAMCfnz0AAAAAAgAAAP///wcAAAAAAAAAAAAAwP8BAAAAAAAA+A8guBIRAEoAAAAIFREAAAIAAAgXEQA3AAAAAAECAwQFBgcICQgKCwwNDg8QERITFAIVFhcYGRobHB0eHyACAgICAgICAgICIQICAgICAgICAgICAgICIiMkJSYCJwIoAgICKSorAiwtLi8wAgIxAgICMgICAgICAgICMwICNAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNQI2AjcCAgICAgICAjgCOQICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICOjs8AgICAj0CAj4/QEFCQ0RFRgICAkcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICSAICAgICAgICAgICSQICAgICOwIAAQICAgIDAgICAgQCBQYCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAEGYx8QAC7gIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPu/gIAABG5hbWUB8L+AgACNAQBKcmVlZF9zb2xvbW9uX2VyYXN1cmU6OlJlZWRTb2xvbW9uOjpyZWNvbnN0cnVjdF9pbnRlcm5hbDo6aGQ0MzhhY2JhNTQ1NzJiMzABP3JlZWRfc29sb21vbl9lcmFzdXJlOjptYXRyaXg6Ok1hdHJpeDo6aW52ZXJ0OjpoMThhNmNmZGNkNTJkYjA2ZgIxPHN0ciBhcyBjb3JlOjpmbXQ6OkRlYnVnPjo6Zm10OjpoZTExOWRiMWJmYWMxOGM2NwMjY29yZTo6Zm10Ojp3cml0ZTo6aDgyMmNkMjY0OGQ4ZWFjZjUELmNvcmU6OnN0cjo6c2xpY2VfZXJyb3JfZmFpbDo6aDZjZjI4OGMxZjcwZDI5YjIFLGNvcmU6OmZtdDo6Rm9ybWF0dGVyOjpwYWQ6Omg5NmM5ZDMyMjA3YjQyNTBhBjVjb3JlOjpmbXQ6OkZvcm1hdHRlcjo6cGFkX2ludGVncmFsOjpoYjkzNmU0N2EzMzRkN2U4MwdBcmVlZF9zb2xvbW9uX2VyYXN1cmU6Om1hdHJpeDo6TWF0cml4OjptdWx0aXBseTo6aGU3Y2Q4ODhmYjYzOGE5OWEIC3JlY29uc3RydWN0CUdyZWVkX3NvbG9tb25fZXJhc3VyZTo6UmVlZFNvbG9tb246OmNvZGVfc2luZ2xlX3NsaWNlOjpoNGQwODU3MDhlODgxMmY3MQpEcmVlZF9zb2xvbW9uX2VyYXN1cmU6Om1hdHJpeDo6TWF0cml4Ojp2YW5kZXJtb25kZTo6aDRlYmZmYjZjMTI5NjE4YzMLMjxjaGFyIGFzIGNvcmU6OmZtdDo6RGVidWc+OjpmbXQ6Omg4OTA4YjRhZmE5YTg4NWUzDC13ZWVfYWxsb2M6OmFsbG9jX2ZpcnN0X2ZpdDo6aDlhNTk4ZGQwMzljYmY2NzANBmVuY29kZQ5DcmVlZF9zb2xvbW9uX2VyYXN1cmU6Om1hdHJpeDo6TWF0cml4OjpzdWJfbWF0cml4OjpoN2RkMDlmODY1NWYwY2IyYg88cmVlZF9zb2xvbW9uX2VyYXN1cmU6OlJlZWRTb2xvbW9uOjplbmNvZGU6OmhlYjU0MGZlYWI2ZDQ2YTBjEFQ8d2VlX2FsbG9jOjpXZWVBbGxvYzwnc3RhdGljPiBhcyBjb3JlOjphbGxvYzo6R2xvYmFsQWxsb2M+OjphbGxvYzo6aDM0ODFhYWI1YjMxZWU4N2MRRXJlZWRfc29sb21vbl9lcmFzdXJlOjpSZWVkU29sb21vbjo6Z2V0X3Bhcml0eV9yb3dzOjpoNjc1ODJiMGYxNWNmMDBiNhJAcmVlZF9zb2xvbW9uX2VyYXN1cmU6OlJlZWRTb2xvbW9uOjplbmNvZGVfc2VwOjpoZDk1N2NiZGM3N2UzMzM2MxNBcmVlZF9zb2xvbW9uX2VyYXN1cmU6OlJlZWRTb2xvbW9uOjp3aXRoX3BwYXJhbTo6aDIyOWJkNzg5MWJjY2E0OWYUQXJlZWRfc29sb21vbl9lcmFzdXJlOjptYXRyaXg6Ok1hdHJpeDo6aWRlbnRpdHk6Omg4OWU0OTQyY2VlMmQyY2U0FT5yZWVkX3NvbG9tb25fZXJhc3VyZTo6Z2Fsb2lzOjptdWxfc2xpY2VfeG9yOjpoMDdlZGRkZmVjNWUyMjkwMBY6cmVlZF9zb2xvbW9uX2VyYXN1cmU6OmdhbG9pczo6bXVsX3NsaWNlOjpoZDQ3ZmUxNWJiOGZkMDM4ZRcyY29yZTo6dW5pY29kZTo6cHJpbnRhYmxlOjpjaGVjazo6aDFhOTVmZjk0ZmNiNzM4ZGIYUXJlZWRfc29sb21vbl9lcmFzdXJlOjppbnZlcnNpb25fdHJlZTo6SW52ZXJzaW9uTm9kZTo6Z2V0X2NoaWxkOjpoZTUzNDg4YmQzZDQwMmUyZBlbcmVlZF9zb2xvbW9uX2VyYXN1cmU6OmludmVyc2lvbl90cmVlOjpJbnZlcnNpb25UcmVlOjpnZXRfaW52ZXJ0ZWRfbWF0cml4OjpoZGMwODIyZTE3NWYxMWY5OBpLcmVlZF9zb2xvbW9uX2VyYXN1cmU6OmludmVyc2lvbl90cmVlOjpJbnZlcnNpb25UcmVlOjpuZXc6OmhkODk5YzdhYjE4MmUyZmFmGzs8Jm11dCBXIGFzIGNvcmU6OmZtdDo6V3JpdGU+Ojp3cml0ZV9jaGFyOjpoMjkzZDQ1NzA5NGFhZjY5YRwvY29yZTo6Zm10OjpudW06OmltcDo6Zm10X3U2NDo6aGMzOTNlMzM3YWI5YmFlOTkdS3JlZWRfc29sb21vbl9lcmFzdXJlOjppbnZlcnNpb25fdHJlZTo6SW52ZXJzaW9uTm9kZTo6bmV3OjpoNjk0ZmQ4Mzg5YTNkOGEwMh5JY29yZTo6Zm10OjpudW06OjxpbXBsIGNvcmU6OmZtdDo6RGVidWcgZm9yIHVzaXplPjo6Zm10OjpoNWQ0MDFjZDE0YTIwYzVhYx9Bd2VlX2FsbG9jOjpXZWVBbGxvYzo6ZGVhbGxvY19pbXBsOjp7e2Nsb3N1cmV9fTo6aGVjODBlODBjMGM1ODliODYgbDxzdGQ6OnBhbmlja2luZzo6Y29udGludWVfcGFuaWNfZm10OjpQYW5pY1BheWxvYWQ8J2E+IGFzIGNvcmU6OnBhbmljOjpCb3hNZVVwPjo6Ym94X21lX3VwOjpoOGQ1N2M2N2IwYzhmMTVmYyE9Y29yZTo6dW5pY29kZTo6Ym9vbF90cmllOjpCb29sVHJpZTo6bG9va3VwOjpoMDI5MmI2MmIxNjQ2MjNmNCIwPHNtYWxsdmVjOjpTbWFsbFZlYzxBPj46Omdyb3c6OmgzODNlYTZlM2IzYzgyN2UwIzxyZWVkX3NvbG9tb25fZXJhc3VyZTo6bWF0cml4OjpNYXRyaXg6Om5ldzo6aDMxNjA2NTFiNzI3Yjg5ZWEkMDxzbWFsbHZlYzo6U21hbGxWZWM8QT4+Ojpncm93OjpoZGExOTQ3ODY5ODI0MzNkMyUwPHNtYWxsdmVjOjpTbWFsbFZlYzxBPj46Omdyb3c6OmhiMWQ4NzE1MzE1N2M5YTk4Jl5yZWVkX3NvbG9tb25fZXJhc3VyZTo6aW52ZXJzaW9uX3RyZWU6OkludmVyc2lvblRyZWU6Omluc2VydF9pbnZlcnRlZF9tYXRyaXg6OmgyMWQ0YjUzZGJjMzNjMWIyJzdzdGQ6OnBhbmlja2luZzo6cnVzdF9wYW5pY193aXRoX2hvb2s6OmhiNzFkNWZlNGRjNmNlYmQzKFE8cmVlZF9zb2xvbW9uX2VyYXN1cmU6OmVycm9yczo6RXJyb3IgYXMgY29yZTo6Zm10OjpEZWJ1Zz46OmZtdDo6aGVlZmU4YTVhYjA1NThiYzkpgAE8d2VlX2FsbG9jOjpzaXplX2NsYXNzZXM6OlNpemVDbGFzc0FsbG9jUG9saWN5PCdhLCAnYj4gYXMgd2VlX2FsbG9jOjpBbGxvY1BvbGljeTwnYT4+OjpuZXdfY2VsbF9mb3JfZnJlZV9saXN0OjpoYjAwMWFhYjFmYmFmZTA3YSpmPHN0ZDo6cGFuaWNraW5nOjpjb250aW51ZV9wYW5pY19mbXQ6OlBhbmljUGF5bG9hZDwnYT4gYXMgY29yZTo6cGFuaWM6OkJveE1lVXA+OjpnZXQ6OmhlMTRjNjZkMzc3MWQ3YjhjKzpjb3JlOjpmbXQ6OmJ1aWxkZXJzOjpEZWJ1Z1R1cGxlOjpmaW5pc2g6OmgzNjg2NDljYzhiM2EwYzFlLFY8d2VlX2FsbG9jOjpXZWVBbGxvYzwnc3RhdGljPiBhcyBjb3JlOjphbGxvYzo6R2xvYmFsQWxsb2M+OjpkZWFsbG9jOjpoYjE0MGMxZWEyNzBmYjJhOS1KY29yZTo6Zm10OjpudW06OjxpbXBsIGNvcmU6OmZtdDo6TG93ZXJIZXggZm9yIGkzMj46OmZtdDo6aDZmNTM3MTU3ZjNiMjM2MjcuSmNvcmU6OmZtdDo6bnVtOjo8aW1wbCBjb3JlOjpmbXQ6OlVwcGVySGV4IGZvciBpMzI+OjpmbXQ6OmgzZDQzYzEzYzUyNzMyNzFjLzBjb3JlOjpwdHI6OnJlYWxfZHJvcF9pbl9wbGFjZTo6aDg1MTgyYWZlNzMxM2M2OWMwMGNvcmU6OnB0cjo6cmVhbF9kcm9wX2luX3BsYWNlOjpoY2Q4ZTRmYjhjMjUxZTJmMTEwPGFsbG9jOjp2ZWM6OlZlYzxUPj46OnJlc2VydmU6OmhhYzhiZWI2NTJmOTRiYjA4MmY8d2VlX2FsbG9jOjpMYXJnZUFsbG9jUG9saWN5IGFzIHdlZV9hbGxvYzo6QWxsb2NQb2xpY3k8J2E+Pjo6bmV3X2NlbGxfZm9yX2ZyZWVfbGlzdDo6aDNmMDA4ODlkMTM4ZWI3NmYzLmNvcmU6OnJlc3VsdDo6dW53cmFwX2ZhaWxlZDo6aGY5MmRkY2RlMGJkYTgwNWM0Sjxjb3JlOjpvcHM6OnJhbmdlOjpSYW5nZTxJZHg+IGFzIGNvcmU6OmZtdDo6RGVidWc+OjpmbXQ6OmhlMTkwOWJmY2Q5OWZkZjI2NS5jb3JlOjpyZXN1bHQ6OnVud3JhcF9mYWlsZWQ6OmhkNmJhMjEzNjFhN2M5YjRlNi5jb3JlOjpyZXN1bHQ6OnVud3JhcF9mYWlsZWQ6OmgwOWM3M2FkY2FmMzAzYTQ3Ny5jb3JlOjpyZXN1bHQ6OnVud3JhcF9mYWlsZWQ6OmhhNTE0ZmNkNzUxZGIzMTdlODVzdGQ6OnBhbmlja2luZzo6Y29udGludWVfcGFuaWNfZm10OjpoMWRhOWJlM2MwN2ZlZDk3OTk0Y29yZTo6c2xpY2U6OnNsaWNlX2luZGV4X2xlbl9mYWlsOjpoZjYyNjUyMDI2MWYwNDhmZTo2Y29yZTo6cGFuaWNraW5nOjpwYW5pY19ib3VuZHNfY2hlY2s6OmgyNzNlNDlhMzgwZDAxZmI3OzZjb3JlOjpzbGljZTo6c2xpY2VfaW5kZXhfb3JkZXJfZmFpbDo6aGRlYmNhY2YzNDk4MmJiNTI8OjwmbXV0IFcgYXMgY29yZTo6Zm10OjpXcml0ZT46OndyaXRlX2ZtdDo6aGI3ZmQ2NTIyZjg0MjE5M2Q9KWNvcmU6OnBhbmlja2luZzo6cGFuaWM6OmgzYzUxMmM3YzJiYjZkYTI1PmQ8c3RkOjpwYW5pY2tpbmc6OmJlZ2luX3BhbmljOjpQYW5pY1BheWxvYWQ8QT4gYXMgY29yZTo6cGFuaWM6OkJveE1lVXA+Ojpib3hfbWVfdXA6Omg1YmRjYmM1MDMwNzE1NjU1PzJzdGQ6OnBhbmlja2luZzo6YmVnaW5fcGFuaWNfZm10OjpoZjhmODM2MjQ5NWQyYWU4MEAzPGFsbG9jOjpzeW5jOjpBcmM8VD4+Ojpkcm9wX3Nsb3c6OmhkZmU1ZmRkMDYzNjMwZTcxQTM8YWxsb2M6OnN5bmM6OkFyYzxUPj46OmRyb3Bfc2xvdzo6aGQ4NTRhMTljMmU3MTRiMDhCQ2NvcmU6OmZtdDo6Rm9ybWF0dGVyOjpwYWRfaW50ZWdyYWw6OndyaXRlX3ByZWZpeDo6aGZkY2ZkMDc0YmUzNWM1ZTBDWTxyZWVkX3NvbG9tb25fZXJhc3VyZTo6aW52ZXJzaW9uX3RyZWU6OkVycm9yIGFzIGNvcmU6OmZtdDo6RGVidWc+OjpmbXQ6Omg4ODVlZTVkMGE4Mzg2NDNlRC1jb3JlOjpwYW5pY2tpbmc6OnBhbmljX2ZtdDo6aDQ3MmQ3NjZlNGRmZjcxYTJFEV9fd2JpbmRnZW5fbWFsbG9jRgZtZW1jcHlHDF9fcmdfcmVhbGxvY0gwPCZUIGFzIGNvcmU6OmZtdDo6RGVidWc+OjpmbXQ6OmgxM2JmNWJkYjM2Njg4ZTU1SSxzdGQ6OnBhbmlja2luZzo6cGFuaWNraW5nOjpoZDI1NjQ1YTczYTYwZjE0Yko0Y29yZTo6Zm10OjpGb3JtYXR0ZXI6OmRlYnVnX3R1cGxlOjpoOTczZTJhZTEzODkyNzZiYks6PCZtdXQgVyBhcyBjb3JlOjpmbXQ6OldyaXRlPjo6d3JpdGVfc3RyOjpoNjZiZDVkNDkzYTllNjhjNUwGbWVtc2V0TS5zdGQ6OnBhbmlja2luZzo6YmVnaW5fcGFuaWM6OmgyNDE4ZmE2ZmJiMTZlM2E4TlE8cmVlZF9zb2xvbW9uX2VyYXN1cmU6Om1hdHJpeDo6RXJyb3IgYXMgY29yZTo6Zm10OjpEZWJ1Zz46OmZtdDo6aDAwMGExZmQ5OTA0ZjYwNjlPMGNvcmU6OnB0cjo6cmVhbF9kcm9wX2luX3BsYWNlOjpoMWFkYmNiZmQ4YTQ5YzYzM1AKcnVzdF9wYW5pY1ERX19yZ19hbGxvY196ZXJvZWRSXjxzdGQ6OnBhbmlja2luZzo6YmVnaW5fcGFuaWM6OlBhbmljUGF5bG9hZDxBPiBhcyBjb3JlOjpwYW5pYzo6Qm94TWVVcD46OmdldDo6aDU4MDBjODBhYjY0MjA0ZTlTgAFjb3JlOjpzdHI6OnRyYWl0czo6PGltcGwgY29yZTo6c2xpY2U6OlNsaWNlSW5kZXg8c3RyPiBmb3IgY29yZTo6b3BzOjpyYW5nZTo6UmFuZ2U8dXNpemU+Pjo6aW5kZXg6Ont7Y2xvc3VyZX19OjpoNWE0YjljMjk5NTVhY2U0YlQ+Y29yZTo6cGFuaWM6OkxvY2F0aW9uOjppbnRlcm5hbF9jb25zdHJ1Y3Rvcjo6aGU2ZTU1MWIwOTBjZTM2NTJVOndhc21fYmluZGdlbjo6YW55cmVmOjpIRUFQX1NMQUI6Ol9faW5pdDo6aGRhYTQxNDMzYjlmOTNiZWRWMGNvcmU6OnB0cjo6cmVhbF9kcm9wX2luX3BsYWNlOjpoNGQ5ZmE0NjY4ZTMwMGM2YVcIcnVzdF9vb21YRnJlZWRfc29sb21vbl9lcmFzdXJlOjpSZWVkU29sb21vbjo6cmVjb25zdHJ1Y3RfZGF0YTo6aDc1YjE5Mjk5M2JhZDFlMGVZNDxjb3JlOjpvcHRpb246Ok9wdGlvbjxUPj46OnVud3JhcDo6aDBiN2QyYWM0ZjA3MzJkMDhaNDxjb3JlOjpvcHRpb246Ok9wdGlvbjxUPj46OnVud3JhcDo6aGY5Y2ViOGY2MmIwOTU1MDFbD19fd2JpbmRnZW5fZnJlZVwyPCZUIGFzIGNvcmU6OmZtdDo6RGlzcGxheT46OmZtdDo6aGFjMTkzZjNhNDI5MjQxZmJdMjwmVCBhcyBjb3JlOjpmbXQ6OkRpc3BsYXk+OjpmbXQ6OmhkZDFlMTI0NmNiMjQ4M2IzXjI8JlQgYXMgY29yZTo6Zm10OjpEaXNwbGF5Pjo6Zm10OjpoYWE4OTNlZjUwOTIyOWUwOF84Y29yZTo6Zm10OjpGb3JtYXR0ZXI6OmRlYnVnX2xvd2VyX2hleDo6aDA1ZTI5NmFiM2Y4YjFiYjdgOGNvcmU6OmZtdDo6Rm9ybWF0dGVyOjpkZWJ1Z191cHBlcl9oZXg6OmgwODUwNWQ1M2JiMDQxMDRmYQxfX3JnX2RlYWxsb2NiDl9fcnVzdF9yZWFsbG9jYzlyZWVkX3NvbG9tb25fZXJhc3VyZTo6UmVlZFNvbG9tb246Om5ldzo6aGRkYzdlMDAzYjIyODRlOWRkTmNvcmU6OmZtdDo6bnVtOjppbXA6OjxpbXBsIGNvcmU6OmZtdDo6RGlzcGxheSBmb3IgdTMyPjo6Zm10OjpoNjJmYzg5OTRmNGY1ZWRiM2U0Y29yZTo6Zm10OjpBcmd1bWVudFYxOjpzaG93X3VzaXplOjpoZWQ5MzI0ZGJlNjlkZmM0MWYKX19yZ19hbGxvY2cOX19ydXN0X2RlYWxsb2NoVTxzdGQ6OnN5c19jb21tb246OnBvaXNvbjo6UG9pc29uRXJyb3I8VD4gYXMgY29yZTo6Zm10OjpEZWJ1Zz46OmZtdDo6aGRlZDZkZjI5Y2FiMjIxNGRpM2FsbG9jOjphbGxvYzo6aGFuZGxlX2FsbG9jX2Vycm9yOjpoMmJmNDQ0ZjA0NzA0OWIwZWouY29yZTo6cGFuaWM6OkxvY2F0aW9uOjpmaWxlOjpoYTk5OTc1ZTA0YWJlYTI4N2szPHN0ciBhcyBjb3JlOjpmbXQ6OkRpc3BsYXk+OjpmbXQ6OmhiMTZhNjk5MTMwMDM0MDM0bAxfX3J1c3RfYWxsb2NtE19fcnVzdF9hbGxvY196ZXJvZWRuEXJ1c3RfYmVnaW5fdW53aW5kbzRhbGxvYzo6cmF3X3ZlYzo6Y2FwYWNpdHlfb3ZlcmZsb3c6OmhhM2ZmMjQ3Y2YxZDA3MmZhcDNjb3JlOjpwYW5pYzo6UGFuaWNJbmZvOjpsb2NhdGlvbjo6aGM4MmI2ZDgwMjQ3NmRmNTRxNXdhc21fYmluZGdlbjo6X19ydDo6bWFsbG9jX2ZhaWx1cmU6OmhjMTkwYjVkOWE2YTU3ODZmcks8YWxsb2M6OnJhd192ZWM6OlJhd1ZlYzxULCBBPj46OmFsbG9jYXRlX2luOjp7e2Nsb3N1cmV9fTo6aDIwMjQzMDAwMGY2ZjQwOThzMmNvcmU6OnBhbmljOjpQYW5pY0luZm86Om1lc3NhZ2U6OmhiZDE3NDJhZjNlYjE5MDI3dC5jb3JlOjpwYW5pYzo6TG9jYXRpb246OmxpbmU6OmgxOGZiY2VhYjJjNmQwMGNjdTBjb3JlOjpwYW5pYzo6TG9jYXRpb246OmNvbHVtbjo6aDk5N2FlM2RmYWVkYTc4MDh2dzx3ZWVfYWxsb2M6OnNpemVfY2xhc3Nlczo6U2l6ZUNsYXNzQWxsb2NQb2xpY3k8J2EsICdiPiBhcyB3ZWVfYWxsb2M6OkFsbG9jUG9saWN5PCdhPj46Om1pbl9jZWxsX3NpemU6Omg5MDFjMTQ1ZWY5ZDYxZmQ2d4oBPHdlZV9hbGxvYzo6c2l6ZV9jbGFzc2VzOjpTaXplQ2xhc3NBbGxvY1BvbGljeTwnYSwgJ2I+IGFzIHdlZV9hbGxvYzo6QWxsb2NQb2xpY3k8J2E+Pjo6c2hvdWxkX21lcmdlX2FkamFjZW50X2ZyZWVfY2VsbHM6Omg0MzgyZGZkYmJkMzFmM2E1eF08d2VlX2FsbG9jOjpMYXJnZUFsbG9jUG9saWN5IGFzIHdlZV9hbGxvYzo6QWxsb2NQb2xpY3k8J2E+Pjo6bWluX2NlbGxfc2l6ZTo6aDlmMWQ3MmEwODYzMGE2YjR5cDx3ZWVfYWxsb2M6OkxhcmdlQWxsb2NQb2xpY3kgYXMgd2VlX2FsbG9jOjpBbGxvY1BvbGljeTwnYT4+OjpzaG91bGRfbWVyZ2VfYWRqYWNlbnRfZnJlZV9jZWxsczo6aDQ2Njc2N2Q4ZjA4NmFjNjN6O3dhc21fYmluZGdlbjo6YW55cmVmOjpIRUFQX1NMQUI6Ol9fZ2V0aXQ6OmhkZGU3YmIwMjNkZWVkYTlmezE8VCBhcyBjb3JlOjphbnk6OkFueT46OnR5cGVfaWQ6Omg2YmQ3N2Y5NzE3ZGJjZjg5fDE8VCBhcyBjb3JlOjphbnk6OkFueT46OnR5cGVfaWQ6Omg4NDFmZDAyNTc5OWZkYjAwfTE8VCBhcyBjb3JlOjphbnk6OkFueT46OnR5cGVfaWQ6Omg3YzQ4MTk0MGYxMDFiYWVhfjE8VCBhcyBjb3JlOjphbnk6OkFueT46OnR5cGVfaWQ6OmhjZDFhMTkzYmU2ZjFkNTQxfyZzdGQ6OnByb2Nlc3M6OmFib3J0OjpoZjYyMWVlNzUyNzY5MjhhYoABNXN0ZDo6c3lzX2NvbW1vbjo6bXV0ZXg6Ok11dGV4OjpuZXc6OmgwNzIyODJjNzE4YTQ0OWZhgQE1c3RkOjpzeXNfY29tbW9uOjpwb2lzb246OkZsYWc6Om5ldzo6aDIzY2JhMzU4ZjkyMzdjNTCCARJfX3J1c3Rfc3RhcnRfcGFuaWODATE8VCBhcyBjb3JlOjphbnk6OkFueT46OnR5cGVfaWQ6Omg3MDUwNjI4NzZkNzc5NWY4hAEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6OmhiZmUxMDUwYzNiMmU2OTI0hQEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6OmgwMTQ2MGFlOTQyOGNiNTkwhgEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6OmhiZmUxMDUwYzNiMmU2OTI0hwEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6OmhjNjVmMTJiYTZiNDUxM2FmiAEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6OmhlY2FkZTFjOWU1Nzk3YmE1iQEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6OmgyZWFkYzhmYzEzNzU4ZTA0igFWPHN0ZDo6c3lzX2NvbW1vbjo6dGhyZWFkX2xvY2FsOjpLZXkgYXMgY29yZTo6b3BzOjpkcm9wOjpEcm9wPjo6ZHJvcDo6aDg2ZDkzMjk5Mjg4NWIzODiLATdzdGQ6OmFsbG9jOjpkZWZhdWx0X2FsbG9jX2Vycm9yX2hvb2s6OmgxOTJmYjQ4YWM5NWUwNjE0jAEwY29yZTo6cHRyOjpyZWFsX2Ryb3BfaW5fcGxhY2U6Omg5ZDIwYTQzNmU4OTMxNjg1AP+AgIAACXByb2R1Y2VycwIIbGFuZ3VhZ2UBBFJ1c3QEMjAxNQxwcm9jZXNzZWQtYnkDBXJ1c3RjHTEuMzQuMCAoOTE4NTZlZDUyIDIwMTktMDQtMTApBndhbHJ1cwYwLjExLjAMd2FzbS1iaW5kZ2VuEjAuMi40OSAoOTA2YWMxNTAwKQ==");
|
|
6344
6814
|
|
|
6345
|
-
// ../../packages/sdk/dist/chunk-
|
|
6815
|
+
// ../../packages/sdk/dist/chunk-NHWWORCH.mjs
|
|
6346
6816
|
var DEFAULT_CHUNK_SIZE_BYTES2 = 2 * 1024 * 1024;
|
|
6347
6817
|
|
|
6348
|
-
// ../../packages/sdk/dist/chunk-
|
|
6818
|
+
// ../../packages/sdk/dist/chunk-E5QCRTBU.mjs
|
|
6349
6819
|
import {
|
|
6350
|
-
AccountAddress as
|
|
6351
|
-
Aptos as Aptos4
|
|
6352
|
-
AptosConfig as AptosConfig3
|
|
6820
|
+
AccountAddress as AccountAddress6,
|
|
6821
|
+
Aptos as Aptos4
|
|
6353
6822
|
} from "@aptos-labs/ts-sdk";
|
|
6354
6823
|
var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
6355
6824
|
aptos;
|
|
@@ -6375,17 +6844,8 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
|
6375
6844
|
* ```
|
|
6376
6845
|
*/
|
|
6377
6846
|
constructor(config) {
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
...baseAptosConfig,
|
|
6381
|
-
clientConfig: {
|
|
6382
|
-
...baseAptosConfig.clientConfig,
|
|
6383
|
-
// Only use top-level apiKey if no API_KEY is already provided in Aptos settings
|
|
6384
|
-
API_KEY: baseAptosConfig.clientConfig?.API_KEY ?? config.apiKey
|
|
6385
|
-
}
|
|
6386
|
-
});
|
|
6387
|
-
this.aptos = new Aptos4(aptosConfig);
|
|
6388
|
-
this.deployer = config.deployer ?? AccountAddress7.fromString(MICROPAYMENTS_DEPLOYER);
|
|
6847
|
+
this.aptos = new Aptos4(getAptosConfig(config));
|
|
6848
|
+
this.deployer = config.deployer ?? AccountAddress6.fromString(MICROPAYMENTS_DEPLOYER);
|
|
6389
6849
|
this.indexer = getShelbyIndexerClient(config);
|
|
6390
6850
|
}
|
|
6391
6851
|
/**
|
|
@@ -6813,7 +7273,7 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
|
6813
7273
|
return {
|
|
6814
7274
|
sender: params.sender,
|
|
6815
7275
|
receiver: params.receiver,
|
|
6816
|
-
fungibleAssetAddress:
|
|
7276
|
+
fungibleAssetAddress: AccountAddress6.fromString(
|
|
6817
7277
|
channelInfo.asset_metadata.inner
|
|
6818
7278
|
),
|
|
6819
7279
|
balance: Number(channelInfo.balance),
|
|
@@ -6832,9 +7292,13 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
|
|
|
6832
7292
|
}
|
|
6833
7293
|
};
|
|
6834
7294
|
|
|
6835
|
-
// ../../packages/sdk/dist/chunk-
|
|
7295
|
+
// ../../packages/sdk/dist/chunk-D6GQHO6G.mjs
|
|
6836
7296
|
import { Network as Network4 } from "@aptos-labs/ts-sdk";
|
|
6837
|
-
var shelbyNetworks = [
|
|
7297
|
+
var shelbyNetworks = [
|
|
7298
|
+
Network4.LOCAL,
|
|
7299
|
+
Network4.TESTNET,
|
|
7300
|
+
Network4.SHELBYNET
|
|
7301
|
+
];
|
|
6838
7302
|
|
|
6839
7303
|
// ../../packages/sdk/dist/chunk-BDSW5PHM.mjs
|
|
6840
7304
|
import { Network as Network5 } from "@aptos-labs/ts-sdk";
|
|
@@ -6860,26 +7324,6 @@ function getShelbyAccountExplorerUrl(network, accountAddress) {
|
|
|
6860
7324
|
return `${baseUrl}/account/${accountAddress}`;
|
|
6861
7325
|
}
|
|
6862
7326
|
|
|
6863
|
-
// ../../packages/sdk/dist/chunk-7P6ASYW6.mjs
|
|
6864
|
-
var __defProp2 = Object.defineProperty;
|
|
6865
|
-
var __export = (target, all) => {
|
|
6866
|
-
for (var name2 in all)
|
|
6867
|
-
__defProp2(target, name2, { get: all[name2], enumerable: true });
|
|
6868
|
-
};
|
|
6869
|
-
|
|
6870
|
-
// ../../packages/sdk/dist/chunk-A4IG6GSE.mjs
|
|
6871
|
-
var testUtil_exports = {};
|
|
6872
|
-
__export(testUtil_exports, {
|
|
6873
|
-
makeChunk: () => makeChunk
|
|
6874
|
-
});
|
|
6875
|
-
function makeChunk(n) {
|
|
6876
|
-
const c = Buffer.alloc(n);
|
|
6877
|
-
for (let i = 0; i < n; ++i) {
|
|
6878
|
-
c[i] = i % 256;
|
|
6879
|
-
}
|
|
6880
|
-
return c;
|
|
6881
|
-
}
|
|
6882
|
-
|
|
6883
7327
|
// ../../packages/sdk/dist/chunk-C6RQ3AEU.mjs
|
|
6884
7328
|
import { Network as Network6 } from "@aptos-labs/ts-sdk";
|
|
6885
7329
|
function getAptosExplorerBaseUrl(network) {
|
|
@@ -6943,7 +7387,7 @@ import os2 from "os";
|
|
|
6943
7387
|
import path2 from "path";
|
|
6944
7388
|
import {
|
|
6945
7389
|
Aptos as Aptos5,
|
|
6946
|
-
AptosConfig as
|
|
7390
|
+
AptosConfig as AptosConfig2,
|
|
6947
7391
|
Ed25519Account,
|
|
6948
7392
|
Ed25519PrivateKey,
|
|
6949
7393
|
NetworkToNetworkName
|
|
@@ -6989,6 +7433,14 @@ import path from "path";
|
|
|
6989
7433
|
import fs from "fs-extra";
|
|
6990
7434
|
import YAML from "yaml";
|
|
6991
7435
|
import { z as z7 } from "zod";
|
|
7436
|
+
|
|
7437
|
+
// src/utils/permissions.ts
|
|
7438
|
+
var DIR_PERMISSIONS = 448;
|
|
7439
|
+
var FILE_PERMISSIONS = 384;
|
|
7440
|
+
var PERMISSION_MASK = 511;
|
|
7441
|
+
var GROUP_WORLD_BITS = 63;
|
|
7442
|
+
|
|
7443
|
+
// src/utils/global-config.ts
|
|
6992
7444
|
var GlobalConfigSchema = z7.object({
|
|
6993
7445
|
config_location_behavior: z7.enum(["global", "walk"])
|
|
6994
7446
|
});
|
|
@@ -7022,7 +7474,15 @@ function loadGlobalConfig() {
|
|
|
7022
7474
|
function saveGlobalConfig(config) {
|
|
7023
7475
|
fs.mkdirpSync(path.dirname(GLOBAL_CONFIG_PATH));
|
|
7024
7476
|
GlobalConfigSchema.parse(config);
|
|
7025
|
-
fs.writeFileSync(GLOBAL_CONFIG_PATH, YAML.stringify(config),
|
|
7477
|
+
fs.writeFileSync(GLOBAL_CONFIG_PATH, YAML.stringify(config), {
|
|
7478
|
+
encoding: "utf8",
|
|
7479
|
+
mode: FILE_PERMISSIONS
|
|
7480
|
+
});
|
|
7481
|
+
fs.chmodSync(GLOBAL_CONFIG_PATH, FILE_PERMISSIONS);
|
|
7482
|
+
const dir = path.dirname(GLOBAL_CONFIG_PATH);
|
|
7483
|
+
if (path.basename(dir) === ".shelby") {
|
|
7484
|
+
fs.chmodSync(dir, DIR_PERMISSIONS);
|
|
7485
|
+
}
|
|
7026
7486
|
}
|
|
7027
7487
|
|
|
7028
7488
|
// src/utils/config.ts
|
|
@@ -7066,6 +7526,19 @@ function loadConfigOrExit(configFile) {
|
|
|
7066
7526
|
);
|
|
7067
7527
|
process.exit(1);
|
|
7068
7528
|
}
|
|
7529
|
+
if (process.platform !== "win32") {
|
|
7530
|
+
const mode = fs2.statSync(configPath).mode & PERMISSION_MASK;
|
|
7531
|
+
if (mode & GROUP_WORLD_BITS) {
|
|
7532
|
+
console.error(
|
|
7533
|
+
`\u274C Permissions 0${mode.toString(8)} for '${configPath}' are too open.`
|
|
7534
|
+
);
|
|
7535
|
+
console.error(
|
|
7536
|
+
" Your config file contains private keys and must not be accessible by others."
|
|
7537
|
+
);
|
|
7538
|
+
console.error(` Run: chmod 600 ${configPath}`);
|
|
7539
|
+
process.exit(1);
|
|
7540
|
+
}
|
|
7541
|
+
}
|
|
7069
7542
|
return { configPath, config: loadConfig(configPath) };
|
|
7070
7543
|
} catch (err) {
|
|
7071
7544
|
console.error("\u274C Failed to load configuration file");
|
|
@@ -7144,7 +7617,15 @@ function saveConfig(config, configPath) {
|
|
|
7144
7617
|
const resolvedPath = resolveConfigPath(configPath);
|
|
7145
7618
|
fs2.mkdirpSync(path2.dirname(resolvedPath));
|
|
7146
7619
|
ConfigSchema.parse(config);
|
|
7147
|
-
fs2.writeFileSync(resolvedPath, YAML2.stringify(config),
|
|
7620
|
+
fs2.writeFileSync(resolvedPath, YAML2.stringify(config), {
|
|
7621
|
+
encoding: "utf8",
|
|
7622
|
+
mode: FILE_PERMISSIONS
|
|
7623
|
+
});
|
|
7624
|
+
fs2.chmodSync(resolvedPath, FILE_PERMISSIONS);
|
|
7625
|
+
const dir = path2.dirname(resolvedPath);
|
|
7626
|
+
if (path2.basename(dir) === ".shelby") {
|
|
7627
|
+
fs2.chmodSync(dir, DIR_PERMISSIONS);
|
|
7628
|
+
}
|
|
7148
7629
|
}
|
|
7149
7630
|
function getCurrentContext(config, contextName) {
|
|
7150
7631
|
const name2 = contextName || config.default_context;
|
|
@@ -7196,7 +7677,7 @@ function getAptosSettingsFromContext(context) {
|
|
|
7196
7677
|
}
|
|
7197
7678
|
function getAptosFromContext(context) {
|
|
7198
7679
|
const config = getAptosSettingsFromContext(context);
|
|
7199
|
-
return new Aptos5(new
|
|
7680
|
+
return new Aptos5(new AptosConfig2(config));
|
|
7200
7681
|
}
|
|
7201
7682
|
function getShelbyConfigFromContext(context) {
|
|
7202
7683
|
const aptosSettings = getAptosSettingsFromContext(context);
|
|
@@ -7241,7 +7722,7 @@ function validateAccountName(name2, config) {
|
|
|
7241
7722
|
// src/utils/keys.ts
|
|
7242
7723
|
import {
|
|
7243
7724
|
Account,
|
|
7244
|
-
AccountAddress as
|
|
7725
|
+
AccountAddress as AccountAddress7,
|
|
7245
7726
|
Ed25519PrivateKey as Ed25519PrivateKey2,
|
|
7246
7727
|
Secp256k1PrivateKey,
|
|
7247
7728
|
SigningSchemeInput
|
|
@@ -7263,7 +7744,7 @@ function isValidEd25519PrivateKey(value) {
|
|
|
7263
7744
|
}
|
|
7264
7745
|
}
|
|
7265
7746
|
function isValidAddress(address) {
|
|
7266
|
-
return
|
|
7747
|
+
return AccountAddress7.isValid({ input: address }).valid;
|
|
7267
7748
|
}
|
|
7268
7749
|
var ED25519_NAME = "ed25519";
|
|
7269
7750
|
var SignatureSchemeSchema = z9.enum([ED25519_NAME]);
|
|
@@ -7922,7 +8403,7 @@ import { useEffect as useEffect4, useState as useState6 } from "react";
|
|
|
7922
8403
|
|
|
7923
8404
|
// src/utils/balance.ts
|
|
7924
8405
|
import {
|
|
7925
|
-
AccountAddress as
|
|
8406
|
+
AccountAddress as AccountAddress8,
|
|
7926
8407
|
AptosApiError
|
|
7927
8408
|
} from "@aptos-labs/ts-sdk";
|
|
7928
8409
|
|
|
@@ -7961,7 +8442,8 @@ var DEFAULT_CONFIG = {
|
|
|
7961
8442
|
// Override shelby_network for local
|
|
7962
8443
|
shelby_network: { rpc_endpoint: "http://localhost:9090/" }
|
|
7963
8444
|
},
|
|
7964
|
-
[Network7.SHELBYNET]: createContextForNetwork(Network7.SHELBYNET)
|
|
8445
|
+
[Network7.SHELBYNET]: createContextForNetwork(Network7.SHELBYNET),
|
|
8446
|
+
[Network7.TESTNET]: createContextForNetwork(Network7.TESTNET)
|
|
7965
8447
|
},
|
|
7966
8448
|
accounts: {},
|
|
7967
8449
|
default_context: Network7.SHELBYNET,
|
|
@@ -8009,10 +8491,10 @@ function resolveAccountAddress({
|
|
|
8009
8491
|
if (!isValidAddress(explicitAddress)) {
|
|
8010
8492
|
throw new InvalidAccountAddressError(explicitAddress);
|
|
8011
8493
|
}
|
|
8012
|
-
return
|
|
8494
|
+
return AccountAddress8.from(explicitAddress).toString();
|
|
8013
8495
|
}
|
|
8014
8496
|
if (derivedAddress) {
|
|
8015
|
-
return
|
|
8497
|
+
return AccountAddress8.from(derivedAddress).toString();
|
|
8016
8498
|
}
|
|
8017
8499
|
return void 0;
|
|
8018
8500
|
}
|
|
@@ -8021,7 +8503,7 @@ async function getBalanceWithFallback({
|
|
|
8021
8503
|
accountAddress,
|
|
8022
8504
|
target
|
|
8023
8505
|
}) {
|
|
8024
|
-
const addrString =
|
|
8506
|
+
const addrString = AccountAddress8.from(accountAddress).toString();
|
|
8025
8507
|
const assetType = assetTypeToString(target.asset);
|
|
8026
8508
|
try {
|
|
8027
8509
|
const balance = await aptos.getBalance({
|
|
@@ -8057,7 +8539,7 @@ async function resolveDecimals({
|
|
|
8057
8539
|
}
|
|
8058
8540
|
try {
|
|
8059
8541
|
const metadata = await aptos.getFungibleAssetMetadataByAssetType({
|
|
8060
|
-
assetType: typeof target.asset === "string" ? target.asset :
|
|
8542
|
+
assetType: typeof target.asset === "string" ? target.asset : AccountAddress8.from(target.asset).toString()
|
|
8061
8543
|
});
|
|
8062
8544
|
if (typeof metadata?.decimals === "number") {
|
|
8063
8545
|
return metadata.decimals;
|
|
@@ -8138,7 +8620,7 @@ function assetTypeToString(asset) {
|
|
|
8138
8620
|
if (typeof asset === "string") {
|
|
8139
8621
|
return asset;
|
|
8140
8622
|
}
|
|
8141
|
-
return
|
|
8623
|
+
return AccountAddress8.from(asset).toString();
|
|
8142
8624
|
}
|
|
8143
8625
|
|
|
8144
8626
|
// src/utils/cache.ts
|
|
@@ -8297,7 +8779,9 @@ async function checkForUpdatesAsync() {
|
|
|
8297
8779
|
var providerPromise;
|
|
8298
8780
|
function getErasureCodingProvider() {
|
|
8299
8781
|
if (!providerPromise) {
|
|
8300
|
-
providerPromise = ClayErasureCodingProvider.create(
|
|
8782
|
+
providerPromise = ClayErasureCodingProvider.create(
|
|
8783
|
+
defaultErasureCodingConfig()
|
|
8784
|
+
);
|
|
8301
8785
|
}
|
|
8302
8786
|
return providerPromise;
|
|
8303
8787
|
}
|
|
@@ -8994,7 +9478,8 @@ var ERROR_CODES = {
|
|
|
8994
9478
|
EBLOB_WRITE_INSUFFICIENT_FUNDS: "EBLOB_WRITE_INSUFFICIENT_FUNDS",
|
|
8995
9479
|
EBLOB_WRITE_CHUNKSET_ALREADY_EXISTS: "EBLOB_WRITE_CHUNKSET_ALREADY_EXISTS",
|
|
8996
9480
|
ECONNREFUSED: "ECONNREFUSED",
|
|
8997
|
-
ENOTFOUND: "ENOTFOUND"
|
|
9481
|
+
ENOTFOUND: "ENOTFOUND",
|
|
9482
|
+
EPIPE: "EPIPE"
|
|
8998
9483
|
};
|
|
8999
9484
|
var DEFAULT_ERROR_RESPONSE = {
|
|
9000
9485
|
displayMessage: "An unknown error occurred",
|
|
@@ -9038,6 +9523,18 @@ var handleError = (error) => {
|
|
|
9038
9523
|
code: ERROR_CODES.ENOTFOUND
|
|
9039
9524
|
};
|
|
9040
9525
|
}
|
|
9526
|
+
if (error.code === ERROR_CODES.EPIPE) {
|
|
9527
|
+
return {
|
|
9528
|
+
displayMessage: "Upload failed because the connection to the Shelby RPC endpoint was closed while sending data (EPIPE).",
|
|
9529
|
+
code: ERROR_CODES.EPIPE
|
|
9530
|
+
};
|
|
9531
|
+
}
|
|
9532
|
+
}
|
|
9533
|
+
if (error.message.includes(ERROR_CODES.EPIPE)) {
|
|
9534
|
+
return {
|
|
9535
|
+
displayMessage: "Upload failed because the connection to the Shelby RPC endpoint was closed while sending data (EPIPE).",
|
|
9536
|
+
code: ERROR_CODES.EPIPE
|
|
9537
|
+
};
|
|
9041
9538
|
}
|
|
9042
9539
|
if (error.cause instanceof AggregateError) {
|
|
9043
9540
|
const firstKnownError = error.cause.errors.find((error2) => {
|
|
@@ -9295,7 +9792,8 @@ function accountCommand(program) {
|
|
|
9295
9792
|
columns: [
|
|
9296
9793
|
{ header: "Name", width: 30, flex: true },
|
|
9297
9794
|
{ header: "Size", width: 12 },
|
|
9298
|
-
{ header: "Expires", width: 25 }
|
|
9795
|
+
{ header: "Expires", width: 25 },
|
|
9796
|
+
{ header: "Status", width: 10 }
|
|
9299
9797
|
],
|
|
9300
9798
|
padding: 12
|
|
9301
9799
|
});
|
|
@@ -9312,7 +9810,8 @@ function accountCommand(program) {
|
|
|
9312
9810
|
minute: "2-digit",
|
|
9313
9811
|
hour12: true
|
|
9314
9812
|
});
|
|
9315
|
-
const
|
|
9813
|
+
const status = blob.isWritten ? "Written" : "Pending";
|
|
9814
|
+
const row = [displayName, formattedSize, formattedDate, status];
|
|
9316
9815
|
table.push(row.map((cell, i) => wrapCell(cell, i)));
|
|
9317
9816
|
}
|
|
9318
9817
|
console.log(table.toString());
|
|
@@ -9890,7 +10389,7 @@ function contextCommand(program) {
|
|
|
9890
10389
|
}
|
|
9891
10390
|
|
|
9892
10391
|
// src/commands/delete.tsx
|
|
9893
|
-
import { Aptos as Aptos6, AptosConfig as
|
|
10392
|
+
import { Aptos as Aptos6, AptosConfig as AptosConfig3 } from "@aptos-labs/ts-sdk";
|
|
9894
10393
|
import { Box as Box7, render as render3, Text as Text7 } from "ink";
|
|
9895
10394
|
import SelectInput4 from "ink-select-input";
|
|
9896
10395
|
import ora from "ora";
|
|
@@ -10075,7 +10574,7 @@ function deleteCommand(program) {
|
|
|
10075
10574
|
config,
|
|
10076
10575
|
program.opts().account
|
|
10077
10576
|
).account;
|
|
10078
|
-
const aptos = new Aptos6(new
|
|
10577
|
+
const aptos = new Aptos6(new AptosConfig3(shelbyConfig.aptos));
|
|
10079
10578
|
const shelbyClient = new ShelbyNodeClient(shelbyConfig);
|
|
10080
10579
|
const start = performance.now();
|
|
10081
10580
|
let deleteList;
|
|
@@ -10229,13 +10728,13 @@ import { z as z17 } from "zod";
|
|
|
10229
10728
|
|
|
10230
10729
|
// src/utils/micropayment-manager.ts
|
|
10231
10730
|
import crypto2 from "crypto";
|
|
10232
|
-
import { AccountAddress as
|
|
10731
|
+
import { AccountAddress as AccountAddress10 } from "@aptos-labs/ts-sdk";
|
|
10233
10732
|
|
|
10234
10733
|
// src/utils/micropayment-storage.ts
|
|
10235
10734
|
import os3 from "os";
|
|
10236
10735
|
import path5 from "path";
|
|
10237
10736
|
import {
|
|
10238
|
-
AccountAddress as
|
|
10737
|
+
AccountAddress as AccountAddress9,
|
|
10239
10738
|
Ed25519PublicKey
|
|
10240
10739
|
} from "@aptos-labs/ts-sdk";
|
|
10241
10740
|
import fs6 from "fs-extra";
|
|
@@ -10297,7 +10796,7 @@ function extractMicropaymentParams(micropayment) {
|
|
|
10297
10796
|
8
|
|
10298
10797
|
).getBigUint64(0, true)
|
|
10299
10798
|
);
|
|
10300
|
-
const fungibleAssetAddress =
|
|
10799
|
+
const fungibleAssetAddress = AccountAddress9.from(
|
|
10301
10800
|
args[3].bcsToHex().toString()
|
|
10302
10801
|
);
|
|
10303
10802
|
return {
|
|
@@ -10347,8 +10846,8 @@ function validateReceivedMicropayment(micropayment, expectedSender, expectedRece
|
|
|
10347
10846
|
);
|
|
10348
10847
|
}
|
|
10349
10848
|
const entryFunction = rawTxn.payload.entryFunction;
|
|
10350
|
-
if (!
|
|
10351
|
-
|
|
10849
|
+
if (!AccountAddress9.from(entryFunction.module_name.address).equals(
|
|
10850
|
+
AccountAddress9.from(MICROPAYMENTS_DEPLOYER)
|
|
10352
10851
|
)) {
|
|
10353
10852
|
throw new Error("Invalid micropayment: incorrect deployer address");
|
|
10354
10853
|
}
|
|
@@ -10379,7 +10878,7 @@ var MicropaymentManager = class {
|
|
|
10379
10878
|
this.micropaymentClient = micropaymentClient;
|
|
10380
10879
|
this.sender = sender;
|
|
10381
10880
|
this.receiver = receiver;
|
|
10382
|
-
this.fungibleAssetAddress =
|
|
10881
|
+
this.fungibleAssetAddress = AccountAddress10.from(
|
|
10383
10882
|
SHELBYUSD_FA_METADATA_ADDRESS
|
|
10384
10883
|
);
|
|
10385
10884
|
}
|
|
@@ -10543,7 +11042,7 @@ async function createMicropaymentManager(context, sender) {
|
|
|
10543
11042
|
apiKey: context.api_key,
|
|
10544
11043
|
aptos: getAptosSettingsFromContext(context)
|
|
10545
11044
|
});
|
|
10546
|
-
const receiver =
|
|
11045
|
+
const receiver = AccountAddress10.from(receiverAddress);
|
|
10547
11046
|
const manager = new MicropaymentManager(micropaymentClient, sender, receiver);
|
|
10548
11047
|
await manager.initialize();
|
|
10549
11048
|
return manager;
|
|
@@ -11065,7 +11564,7 @@ import { Option as Option2 } from "@commander-js/extra-typings";
|
|
|
11065
11564
|
import { execaSync } from "execa";
|
|
11066
11565
|
import { z as z18 } from "zod";
|
|
11067
11566
|
var FaucetOptionsSchema = z18.object({
|
|
11068
|
-
network: z18.enum([Network9.SHELBYNET]).optional(),
|
|
11567
|
+
network: z18.enum([Network9.SHELBYNET, Network9.TESTNET]).optional(),
|
|
11069
11568
|
open: z18.boolean().optional().default(true)
|
|
11070
11569
|
});
|
|
11071
11570
|
function faucetCommand(program) {
|
|
@@ -11281,9 +11780,11 @@ function ensureConfigDir(resolvedPath) {
|
|
|
11281
11780
|
}
|
|
11282
11781
|
|
|
11283
11782
|
// src/commands/upload.tsx
|
|
11783
|
+
import { createReadStream as createReadStream2 } from "fs";
|
|
11284
11784
|
import * as fs9 from "fs/promises";
|
|
11285
11785
|
import * as path8 from "path";
|
|
11286
|
-
import {
|
|
11786
|
+
import { Readable as Readable3 } from "stream";
|
|
11787
|
+
import { Aptos as Aptos7, AptosConfig as AptosConfig4 } from "@aptos-labs/ts-sdk";
|
|
11287
11788
|
import * as chrono from "chrono-node";
|
|
11288
11789
|
import { glob } from "glob";
|
|
11289
11790
|
import ignore from "ignore";
|
|
@@ -11293,6 +11794,11 @@ import ora3 from "ora";
|
|
|
11293
11794
|
import { z as z19 } from "zod";
|
|
11294
11795
|
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
11295
11796
|
var normBlobName2 = (i, f, b) => normBlobName(path8, i, f, b);
|
|
11797
|
+
function createFileStream(filePath) {
|
|
11798
|
+
return Readable3.toWeb(
|
|
11799
|
+
createReadStream2(filePath)
|
|
11800
|
+
);
|
|
11801
|
+
}
|
|
11296
11802
|
var flexibleDateSchema = z19.string().transform((val, ctx) => {
|
|
11297
11803
|
const now = /* @__PURE__ */ new Date();
|
|
11298
11804
|
let parsedDate = null;
|
|
@@ -11632,7 +12138,7 @@ function uploadCommand(program) {
|
|
|
11632
12138
|
config,
|
|
11633
12139
|
program.opts().account
|
|
11634
12140
|
).account;
|
|
11635
|
-
const aptos = new Aptos7(new
|
|
12141
|
+
const aptos = new Aptos7(new AptosConfig4(shelbyConfig.aptos));
|
|
11636
12142
|
const shelbyClient = new ShelbyNodeClient(shelbyConfig);
|
|
11637
12143
|
const handleSigint = () => {
|
|
11638
12144
|
spinner.fail("Quitting due to ctrl-C / SIGINT...");
|
|
@@ -11671,19 +12177,21 @@ function uploadCommand(program) {
|
|
|
11671
12177
|
for (const entry of filelist) {
|
|
11672
12178
|
const fileName = path8.basename(entry.filename);
|
|
11673
12179
|
let currentFileUploadedBytes = 0;
|
|
12180
|
+
let finalizeTimer;
|
|
12181
|
+
const assertUnchangedSize = async (stage) => {
|
|
12182
|
+
const latestStats = await fs9.stat(entry.filename);
|
|
12183
|
+
if (latestStats.size !== entry.sizeBytes) {
|
|
12184
|
+
throw new Error(
|
|
12185
|
+
`Size of file ${entry.filename} changed before ${stage}. Original size was ${entry.sizeBytes} but it is now ${latestStats.size}`
|
|
12186
|
+
);
|
|
12187
|
+
}
|
|
12188
|
+
};
|
|
11674
12189
|
const formatOverallProgress = () => isSingleFile ? `(${formatOverallProgressPercent(currentFileUploadedBytes)}%)` : `(${filesProcessed}/${filelist.length} files, ${formatOverallProgressPercent(
|
|
11675
12190
|
currentFileUploadedBytes
|
|
11676
12191
|
)}%)`;
|
|
11677
12192
|
const overallProgress = formatOverallProgress();
|
|
11678
|
-
spinner.text = `\u{
|
|
12193
|
+
spinner.text = `\u{1F517} Checking if blob exists... ${overallProgress}`;
|
|
11679
12194
|
try {
|
|
11680
|
-
const blobData = await fs9.readFile(entry.filename);
|
|
11681
|
-
if (blobData.length !== entry.sizeBytes) {
|
|
11682
|
-
throw new Error(
|
|
11683
|
-
`Size of file ${entry.filename} changed after initial scan. Original size was ${entry.sizeBytes} but it is now ${blobData.length}`
|
|
11684
|
-
);
|
|
11685
|
-
}
|
|
11686
|
-
spinner.text = `\u{1F517} Checking if blob exists... ${overallProgress}`;
|
|
11687
12195
|
const existingBlobMetadata = await shelbyClient.coordination.getBlobMetadata({
|
|
11688
12196
|
account: activeAccount.accountAddress,
|
|
11689
12197
|
name: entry.blobname
|
|
@@ -11695,8 +12203,12 @@ function uploadCommand(program) {
|
|
|
11695
12203
|
process.exit(1);
|
|
11696
12204
|
}
|
|
11697
12205
|
spinner.text = `\u{1F517} Generating commitments for ${fileName}... ${overallProgress}`;
|
|
12206
|
+
await assertUnchangedSize("commitment generation");
|
|
11698
12207
|
const provider = await getErasureCodingProvider();
|
|
11699
|
-
const blobCommitments = await generateCommitments(
|
|
12208
|
+
const blobCommitments = await generateCommitments(
|
|
12209
|
+
provider,
|
|
12210
|
+
createFileStream(entry.filename)
|
|
12211
|
+
);
|
|
11700
12212
|
if (options.outputCommitments) {
|
|
11701
12213
|
outputCommitments[entry.filename] = blobCommitments;
|
|
11702
12214
|
}
|
|
@@ -11705,7 +12217,7 @@ function uploadCommand(program) {
|
|
|
11705
12217
|
account: activeAccount,
|
|
11706
12218
|
blobName: entry.blobname,
|
|
11707
12219
|
blobMerkleRoot: blobCommitments.blob_merkle_root,
|
|
11708
|
-
size:
|
|
12220
|
+
size: entry.sizeBytes,
|
|
11709
12221
|
expirationMicros: options.expiration.getTime() * 1e3
|
|
11710
12222
|
});
|
|
11711
12223
|
const registerTransactionHash = pendingRegisterBlobTransaction.hash;
|
|
@@ -11716,17 +12228,29 @@ function uploadCommand(program) {
|
|
|
11716
12228
|
transactionHash: pendingRegisterBlobTransaction.hash
|
|
11717
12229
|
});
|
|
11718
12230
|
spinner.text = `\u{1F4E4} Uploading ${fileName} to Shelby RPC... ${overallProgress}`;
|
|
12231
|
+
await assertUnchangedSize("upload");
|
|
11719
12232
|
await shelbyClient.rpc.putBlob({
|
|
11720
12233
|
account: activeAccount.accountAddress,
|
|
11721
12234
|
blobName: entry.blobname,
|
|
11722
|
-
blobData,
|
|
11723
|
-
|
|
12235
|
+
blobData: createFileStream(entry.filename),
|
|
12236
|
+
totalBytes: entry.sizeBytes,
|
|
12237
|
+
onProgress: ({ phase, uploadedBytes, totalBytes }) => {
|
|
12238
|
+
if (phase === "finalizing") {
|
|
12239
|
+
const finalizeStart = performance.now();
|
|
12240
|
+
finalizeTimer = setInterval(() => {
|
|
12241
|
+
const elapsed = ((performance.now() - finalizeStart) / 1e3).toFixed(0);
|
|
12242
|
+
spinner.text = `\u{1F4E4} Finalizing ${fileName} (${elapsed}s) \u2014 server is reassembling chunks and encoding erasure data (do not quit)`;
|
|
12243
|
+
}, 1e3);
|
|
12244
|
+
spinner.text = `\u{1F4E4} Finalizing ${fileName} (0s) \u2014 server is reassembling chunks and encoding erasure data (do not quit)`;
|
|
12245
|
+
return;
|
|
12246
|
+
}
|
|
11724
12247
|
currentFileUploadedBytes = uploadedBytes;
|
|
11725
12248
|
const pct = totalBytes > 0 ? (100 * uploadedBytes / totalBytes).toFixed(2) : "0.00";
|
|
11726
12249
|
spinner.text = isSingleFile ? `\u{1F4E4} Uploading ${fileName} to Shelby RPC... ${pct}%` : `\u{1F4E4} Uploading ${fileName} to Shelby RPC... ${pct}% ${formatOverallProgress()}`;
|
|
11727
12250
|
}
|
|
11728
12251
|
});
|
|
11729
|
-
|
|
12252
|
+
clearInterval(finalizeTimer);
|
|
12253
|
+
amountUploaded += entry.sizeBytes;
|
|
11730
12254
|
filesProcessed++;
|
|
11731
12255
|
} catch (error) {
|
|
11732
12256
|
const { displayMessage } = handleError(error);
|
|
@@ -12545,14 +13069,39 @@ function createProgram() {
|
|
|
12545
13069
|
localnetCommand(program);
|
|
12546
13070
|
uploadCommand(program);
|
|
12547
13071
|
commitmentCommand(program);
|
|
13072
|
+
program.action(() => {
|
|
13073
|
+
program.outputHelp();
|
|
13074
|
+
});
|
|
12548
13075
|
return program;
|
|
12549
13076
|
}
|
|
12550
13077
|
|
|
13078
|
+
// src/utils/cli-args.ts
|
|
13079
|
+
function findUnknownCommandArg(args, knownCommands) {
|
|
13080
|
+
const firstPositionalArg = args.find((arg) => !arg.startsWith("-"));
|
|
13081
|
+
if (firstPositionalArg !== void 0 && firstPositionalArg !== "help" && !knownCommands.has(firstPositionalArg)) {
|
|
13082
|
+
return firstPositionalArg;
|
|
13083
|
+
}
|
|
13084
|
+
return void 0;
|
|
13085
|
+
}
|
|
13086
|
+
|
|
12551
13087
|
// src/entry.ts
|
|
12552
13088
|
function main() {
|
|
12553
13089
|
checkForUpdatesAsync();
|
|
12554
13090
|
const rawArgs = process.argv.slice(2);
|
|
12555
13091
|
const normalizedArgs = rawArgs[0] === "--" ? rawArgs.slice(1) : rawArgs;
|
|
12556
|
-
createProgram()
|
|
13092
|
+
const program = createProgram();
|
|
13093
|
+
const knownCommands = new Set(
|
|
13094
|
+
program.commands.map((command) => command.name())
|
|
13095
|
+
);
|
|
13096
|
+
const unknownCommandArg = findUnknownCommandArg(
|
|
13097
|
+
normalizedArgs,
|
|
13098
|
+
knownCommands
|
|
13099
|
+
);
|
|
13100
|
+
if (unknownCommandArg !== void 0) {
|
|
13101
|
+
console.error(`error: unknown command '${unknownCommandArg}'`);
|
|
13102
|
+
program.outputHelp();
|
|
13103
|
+
process.exit(1);
|
|
13104
|
+
}
|
|
13105
|
+
program.parse([process.argv[0], process.argv[1], ...normalizedArgs]);
|
|
12557
13106
|
}
|
|
12558
13107
|
main();
|