@shelby-protocol/cli 0.0.21 → 0.0.23

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.
Files changed (2) hide show
  1. package/bin/entry.js +2076 -1681
  2. package/package.json +2 -2
package/bin/entry.js CHANGED
@@ -459,13 +459,13 @@ custom_config:
459
459
  event_index: []
460
460
  event_type: []
461
461
  sequence_number: []
462
- 0xc63d6a5efb0080a6029403131715bd4971e1149f7cc099aac69bb0069b3ddbf5::placement_group::StorageProviderLeftEvent:
462
+ 0xc63d6a5efb0080a6029403131715bd4971e1149f7cc099aac69bb0069b3ddbf5::placement_group::StorageProviderVacatedEvent:
463
463
  constant_values:
464
464
  - column: "status"
465
465
  table: "placement_group_slots"
466
- value: "left"
466
+ value: "vacated"
467
467
  event_fields:
468
- $.left_at:
468
+ $.vacated_at:
469
469
  - column: "updated_at"
470
470
  table: "placement_group_slots"
471
471
  $.placement_group_address:
@@ -505,13 +505,246 @@ 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.21";
508
+ var version = "0.0.23";
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-4ZOFT75Q.mjs
516
+ import { Network } from "@aptos-labs/ts-sdk";
517
+ var NetworkToShelbyRPCBaseUrl = {
518
+ [Network.SHELBYNET]: "https://api.shelbynet.shelby.xyz/shelby",
519
+ [Network.NETNA]: void 0,
520
+ [Network.DEVNET]: void 0,
521
+ [Network.TESTNET]: "https://api.testnet.shelby.xyz/shelby",
522
+ [Network.MAINNET]: void 0,
523
+ [Network.LOCAL]: void 0,
524
+ [Network.CUSTOM]: void 0
525
+ };
526
+ var NetworkToShelbyBlobIndexerBaseUrl = {
527
+ [Network.SHELBYNET]: "https://api.shelbynet.aptoslabs.com/nocode/v1/public/cmforrguw0042s601fn71f9l2/v1/graphql",
528
+ [Network.NETNA]: void 0,
529
+ [Network.DEVNET]: void 0,
530
+ [Network.TESTNET]: "https://api.testnet.aptoslabs.com/nocode/v1/public/cmlfqs5wt00qrs601zt5s4kfj/v1/graphql",
531
+ [Network.MAINNET]: void 0,
532
+ [Network.LOCAL]: void 0,
533
+ [Network.CUSTOM]: void 0
534
+ };
535
+ var NetworkToGasStationBaseUrl = {
536
+ [Network.SHELBYNET]: "https://api.shelbynet.shelby.xyz/gs/v1",
537
+ [Network.NETNA]: void 0,
538
+ [Network.DEVNET]: void 0,
539
+ [Network.TESTNET]: "https://api.testnet.shelby.xyz/gs/v1",
540
+ [Network.MAINNET]: void 0,
541
+ [Network.LOCAL]: void 0,
542
+ [Network.CUSTOM]: void 0
543
+ };
544
+ var SHELBY_DEPLOYER = "0xc63d6a5efb0080a6029403131715bd4971e1149f7cc099aac69bb0069b3ddbf5";
545
+ var MICROPAYMENTS_DEPLOYER = "0xb42ac038b6dae86f6171e28e297aab9555ce09909445ec579e4ffe6b8d4d63bf";
546
+ var SHELBYUSD_TOKEN_NAME = "ShelbyUSD";
547
+ var SHELBYUSD_FA_METADATA_ADDRESS = "0x1b18363a9f1fe5e6ebf247daba5cc1c18052bb232efdc4c50f556053922d98e1";
548
+
549
+ // ../../packages/sdk/dist/chunk-KTVNKLBT.mjs
550
+ import {
551
+ AccountAddress,
552
+ Deserializer,
553
+ Hex,
554
+ Serializer
555
+ } from "@aptos-labs/ts-sdk";
556
+ var MICROPAYMENTS_MODULE_NAME = "micropayments";
557
+ var WITHDRAW_APPROVAL_STRUCT_NAME = "WithdrawApproval";
558
+ function serializeTypeInfo(serializer, moduleAddress, moduleName, structName) {
559
+ moduleAddress.serialize(serializer);
560
+ const moduleNameBytes = new TextEncoder().encode(moduleName);
561
+ serializer.serializeBytes(moduleNameBytes);
562
+ const structNameBytes = new TextEncoder().encode(structName);
563
+ serializer.serializeBytes(structNameBytes);
564
+ }
565
+ var StaleChannelStateError = class _StaleChannelStateError extends Error {
566
+ /**
567
+ * The last valid micropayment stored by the server.
568
+ * Clients can use this to reset their local channel state.
569
+ */
570
+ storedMicropayment;
571
+ constructor(storedMicropayment, message) {
572
+ super(
573
+ message ?? "Client has stale channel state. Use the returned micropayment to reset local state."
574
+ );
575
+ this.name = "StaleChannelStateError";
576
+ this.storedMicropayment = storedMicropayment;
577
+ }
578
+ /**
579
+ * Returns the stored micropayment as a base64-encoded string.
580
+ */
581
+ toBase64() {
582
+ const bytes = this.storedMicropayment.bcsToBytes();
583
+ const binaryString = Array.from(
584
+ bytes,
585
+ (byte) => String.fromCharCode(byte)
586
+ ).join("");
587
+ return btoa(binaryString);
588
+ }
589
+ /**
590
+ * Creates a StaleChannelStateError from a base64-encoded micropayment string.
591
+ */
592
+ static fromBase64(base64, message) {
593
+ const binaryString = atob(base64);
594
+ const bytes = Uint8Array.from(binaryString, (char) => char.charCodeAt(0));
595
+ const micropayment = SenderBuiltMicropayment.deserialize(bytes);
596
+ return new _StaleChannelStateError(micropayment, message);
597
+ }
598
+ };
599
+ var SenderBuiltMicropayment = class _SenderBuiltMicropayment {
600
+ /**
601
+ * The sender's address (owner of the payment channel).
602
+ */
603
+ sender;
604
+ /**
605
+ * The receiver's address (beneficiary of the withdrawal).
606
+ */
607
+ receiver;
608
+ /**
609
+ * The unique ID of the payment channel.
610
+ */
611
+ paymentChannelId;
612
+ /**
613
+ * The cumulative amount the receiver is authorized to withdraw.
614
+ */
615
+ amount;
616
+ /**
617
+ * The fungible asset metadata address.
618
+ */
619
+ fungibleAssetAddress;
620
+ /**
621
+ * Monotonically increasing sequence number for replay protection.
622
+ */
623
+ sequenceNumber;
624
+ /**
625
+ * The sender's Ed25519 public key (32 bytes).
626
+ * Used by the receiver to verify the signature before submitting.
627
+ */
628
+ publicKey;
629
+ /**
630
+ * The Ed25519 signature of the SignedMessage<WithdrawApproval> struct.
631
+ * The SignedMessage includes TypeInfo for domain separation.
632
+ */
633
+ signature;
634
+ /**
635
+ * The deployer address of the micropayments module.
636
+ * This is needed to reconstruct the TypeInfo for signature verification.
637
+ */
638
+ deployer;
639
+ constructor(sender, receiver, paymentChannelId, amount, fungibleAssetAddress, sequenceNumber, publicKey, signature, deployer) {
640
+ this.sender = sender;
641
+ this.receiver = receiver;
642
+ this.paymentChannelId = paymentChannelId;
643
+ this.amount = amount;
644
+ this.fungibleAssetAddress = fungibleAssetAddress;
645
+ this.sequenceNumber = sequenceNumber;
646
+ this.publicKey = publicKey;
647
+ this.signature = signature;
648
+ this.deployer = deployer ?? AccountAddress.fromString(MICROPAYMENTS_DEPLOYER);
649
+ }
650
+ /**
651
+ * Creates the BCS-serialized message that was signed.
652
+ * This is a SignedMessage<WithdrawApproval> which includes:
653
+ * 1. TypeInfo (module_address, module_name, struct_name)
654
+ * 2. WithdrawApproval struct fields
655
+ *
656
+ * This format is used with signature_verify_strict_t for domain separation.
657
+ */
658
+ getSignedMessage() {
659
+ return _SenderBuiltMicropayment.buildSignedMessage({
660
+ deployer: this.deployer,
661
+ sender: this.sender,
662
+ receiver: this.receiver,
663
+ fungibleAssetAddress: this.fungibleAssetAddress,
664
+ amount: this.amount,
665
+ paymentChannelId: this.paymentChannelId,
666
+ sequenceNumber: this.sequenceNumber
667
+ });
668
+ }
669
+ /**
670
+ * Static helper to build the SignedMessage<WithdrawApproval> bytes from raw parameters.
671
+ * This can be used to create the message for signing without constructing the full object.
672
+ *
673
+ * @param params - The withdrawal approval parameters.
674
+ * @returns The BCS-serialized SignedMessage<WithdrawApproval> bytes.
675
+ */
676
+ static buildSignedMessage(params) {
677
+ const serializer = new Serializer();
678
+ serializeTypeInfo(
679
+ serializer,
680
+ params.deployer,
681
+ MICROPAYMENTS_MODULE_NAME,
682
+ WITHDRAW_APPROVAL_STRUCT_NAME
683
+ );
684
+ params.sender.serialize(serializer);
685
+ params.receiver.serialize(serializer);
686
+ params.fungibleAssetAddress.serialize(serializer);
687
+ serializer.serializeU64(params.amount);
688
+ serializer.serializeU64(params.paymentChannelId);
689
+ serializer.serializeU64(params.sequenceNumber);
690
+ return serializer.toUint8Array();
691
+ }
692
+ serialize(serializer) {
693
+ this.sender.serialize(serializer);
694
+ this.receiver.serialize(serializer);
695
+ this.fungibleAssetAddress.serialize(serializer);
696
+ serializer.serializeU64(this.amount);
697
+ serializer.serializeU64(this.paymentChannelId);
698
+ serializer.serializeU64(this.sequenceNumber);
699
+ serializer.serializeBytes(this.publicKey);
700
+ serializer.serializeBytes(this.signature);
701
+ this.deployer.serialize(serializer);
702
+ }
703
+ bcsToBytes() {
704
+ const serializer = new Serializer();
705
+ this.serialize(serializer);
706
+ return serializer.toUint8Array();
707
+ }
708
+ bcsToHex() {
709
+ return Hex.fromHexInput(this.bcsToBytes());
710
+ }
711
+ toStringWithoutPrefix() {
712
+ return this.bcsToHex().toStringWithoutPrefix();
713
+ }
714
+ toString() {
715
+ return this.bcsToHex().toString();
716
+ }
717
+ /**
718
+ * Deserializes a SenderBuiltMicropayment from BCS bytes.
719
+ * @param bytes - The bytes to deserialize from (Uint8Array or hex string).
720
+ * @returns A new SenderBuiltMicropayment instance.
721
+ */
722
+ static deserialize(bytes) {
723
+ const bytesArray = typeof bytes === "string" ? Hex.fromHexInput(bytes).toUint8Array() : bytes;
724
+ const deserializer = new Deserializer(bytesArray);
725
+ const sender = AccountAddress.deserialize(deserializer);
726
+ const receiver = AccountAddress.deserialize(deserializer);
727
+ const fungibleAssetAddress = AccountAddress.deserialize(deserializer);
728
+ const amount = deserializer.deserializeU64();
729
+ const paymentChannelId = deserializer.deserializeU64();
730
+ const sequenceNumber = deserializer.deserializeU64();
731
+ const publicKey = deserializer.deserializeBytes();
732
+ const signature = deserializer.deserializeBytes();
733
+ const deployer = AccountAddress.deserialize(deserializer);
734
+ return new _SenderBuiltMicropayment(
735
+ sender,
736
+ receiver,
737
+ paymentChannelId,
738
+ amount,
739
+ fungibleAssetAddress,
740
+ sequenceNumber,
741
+ publicKey,
742
+ signature,
743
+ deployer
744
+ );
745
+ }
746
+ };
747
+
515
748
  // ../../node_modules/.pnpm/tslib@2.8.1/node_modules/tslib/tslib.es6.mjs
516
749
  var __assign = function() {
517
750
  __assign = Object.assign || function __assign2(t) {
@@ -3857,32 +4090,7 @@ var getAptosConfig = (config) => {
3857
4090
  });
3858
4091
  };
3859
4092
 
3860
- // ../../packages/sdk/dist/chunk-FLLOQZVD.mjs
3861
- import { Network } from "@aptos-labs/ts-sdk";
3862
- var NetworkToShelbyRPCBaseUrl = {
3863
- [Network.SHELBYNET]: "https://api.shelbynet.shelby.xyz/shelby",
3864
- [Network.NETNA]: void 0,
3865
- [Network.DEVNET]: void 0,
3866
- [Network.TESTNET]: void 0,
3867
- [Network.MAINNET]: void 0,
3868
- [Network.LOCAL]: void 0,
3869
- [Network.CUSTOM]: void 0
3870
- };
3871
- var NetworkToShelbyBlobIndexerBaseUrl = {
3872
- [Network.SHELBYNET]: "https://api.shelbynet.aptoslabs.com/nocode/v1/public/cmforrguw0042s601fn71f9l2/v1/graphql",
3873
- [Network.NETNA]: void 0,
3874
- [Network.DEVNET]: void 0,
3875
- [Network.TESTNET]: void 0,
3876
- [Network.MAINNET]: void 0,
3877
- [Network.LOCAL]: void 0,
3878
- [Network.CUSTOM]: void 0
3879
- };
3880
- var SHELBY_DEPLOYER = "0xc63d6a5efb0080a6029403131715bd4971e1149f7cc099aac69bb0069b3ddbf5";
3881
- var MICROPAYMENTS_DEPLOYER = "0xb42ac038b6dae86f6171e28e297aab9555ce09909445ec579e4ffe6b8d4d63bf";
3882
- var SHELBYUSD_TOKEN_NAME = "ShelbyUSD";
3883
- var SHELBYUSD_FA_METADATA_ADDRESS = "0x1b18363a9f1fe5e6ebf247daba5cc1c18052bb232efdc4c50f556053922d98e1";
3884
-
3885
- // ../../packages/sdk/dist/chunk-3ZL3FSNA.mjs
4093
+ // ../../packages/sdk/dist/chunk-CGYJLKBU.mjs
3886
4094
  import { Network as Network2 } from "@aptos-labs/ts-sdk";
3887
4095
 
3888
4096
  // ../../node_modules/.pnpm/graphql-request@7.2.0_graphql@16.11.0/node_modules/graphql-request/build/legacy/classes/ClientError.js
@@ -4397,7 +4605,7 @@ var parseRequestArgs = (documentOrOptions, variables, requestHeaders) => {
4397
4605
  };
4398
4606
  };
4399
4607
 
4400
- // ../../packages/sdk/dist/chunk-3ZL3FSNA.mjs
4608
+ // ../../packages/sdk/dist/chunk-CGYJLKBU.mjs
4401
4609
  function createShelbyIndexerClient(baseUrl, options) {
4402
4610
  const graphqlClient = new GraphQLClient(baseUrl, options);
4403
4611
  return getSdk(graphqlClient);
@@ -4430,14 +4638,41 @@ function getShelbyIndexerClient(config) {
4430
4638
  });
4431
4639
  }
4432
4640
 
4433
- // ../../packages/sdk/dist/chunk-OTBLZL2S.mjs
4434
- import { AccountAddress } from "@aptos-labs/ts-sdk";
4435
- var createBlobKey = (params) => {
4436
- return `@${AccountAddress.from(params.account).toStringLongWithoutPrefix()}/${params.blobName}`;
4437
- };
4641
+ // ../../packages/sdk/dist/chunk-Z4FZ7W6L.mjs
4642
+ import { z } from "zod";
4643
+ 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("/"), {
4644
+ message: "Blob name cannot end with a slash"
4645
+ });
4646
+
4647
+ // ../../packages/sdk/dist/chunk-I6NG5GNL.mjs
4648
+ function sleep(ms) {
4649
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
4650
+ }
4651
+
4652
+ // ../../packages/sdk/dist/chunk-IE6LYVIA.mjs
4653
+ import { z as z2 } from "zod";
4654
+ var StartMultipartUploadResponseSchema = z2.object({
4655
+ uploadId: z2.string()
4656
+ });
4657
+ var UploadPartResponseSchema = z2.object({
4658
+ success: z2.literal(true)
4659
+ });
4660
+ var CompleteMultipartUploadResponseSchema = z2.object({
4661
+ success: z2.literal(true)
4662
+ });
4663
+ var RPCErrorResponseSchema = z2.object({
4664
+ error: z2.string()
4665
+ });
4666
+ var StaleMicropaymentErrorResponseSchema = z2.object({
4667
+ error: z2.string().optional(),
4668
+ storedMicropayment: z2.string().optional()
4669
+ });
4438
4670
 
4439
- // ../../packages/sdk/dist/chunk-4JZO2D7T.mjs
4440
- import { Hex } from "@aptos-labs/ts-sdk";
4671
+ // ../../packages/sdk/dist/chunk-UEZNZBJO.mjs
4672
+ import {
4673
+ AccountAddress as AccountAddress2,
4674
+ Hex as Hex2
4675
+ } from "@aptos-labs/ts-sdk";
4441
4676
  async function* readInChunks(input, chunkSize) {
4442
4677
  let idx = 0;
4443
4678
  if (isReadableStream(input)) {
@@ -4497,7 +4732,7 @@ function zeroPadBytes(buffer, desiredLength) {
4497
4732
  return paddedBuffer;
4498
4733
  }
4499
4734
  async function concatHashes(parts) {
4500
- const chunks = parts.map((part) => Hex.fromHexInput(part).toUint8Array());
4735
+ const chunks = parts.map((part) => Hex2.fromHexInput(part).toUint8Array());
4501
4736
  const totalLength = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
4502
4737
  const combined = new Uint8Array(totalLength);
4503
4738
  let offset = 0;
@@ -4505,7 +4740,7 @@ async function concatHashes(parts) {
4505
4740
  combined.set(chunk, offset);
4506
4741
  offset += chunk.byteLength;
4507
4742
  }
4508
- return Hex.fromHexInput(
4743
+ return Hex2.fromHexInput(
4509
4744
  new Uint8Array(await crypto.subtle.digest("SHA-256", combined))
4510
4745
  );
4511
4746
  }
@@ -4525,1546 +4760,1743 @@ function getBlobNameSuffix(blobName) {
4525
4760
  const parts = blobName.split("/");
4526
4761
  return parts.slice(1).join("/") || "";
4527
4762
  }
4763
+ function normalizeAddress(address) {
4764
+ return AccountAddress2.from(address, { maxMissingChars: 63 });
4765
+ }
4528
4766
 
4529
- // ../../packages/sdk/dist/chunk-67F5YZ25.mjs
4530
- var CHUNK_SIZE_PARAMS = {
4531
- [
4532
- "ChunkSet10MiB_Chunk1MiB"
4533
- /* ChunkSet10MiB_Chunk1MiB */
4534
- ]: {
4535
- // 1MiB
4536
- chunkSizeBytes: 1 * 1024 * 1024,
4537
- // 10MiB
4538
- chunksetSizeBytes: 10 * 1024 * 1024
4539
- }
4540
- };
4541
- var DEFAULT_CHUNK_SIZE_BYTES = CHUNK_SIZE_PARAMS[
4542
- "ChunkSet10MiB_Chunk1MiB"
4543
- /* ChunkSet10MiB_Chunk1MiB */
4544
- ].chunkSizeBytes;
4545
- var DEFAULT_CHUNKSET_SIZE_BYTES = CHUNK_SIZE_PARAMS[
4546
- "ChunkSet10MiB_Chunk1MiB"
4547
- /* ChunkSet10MiB_Chunk1MiB */
4548
- ].chunksetSizeBytes;
4549
- var ERASURE_CODE_AND_CHUNK_MAPPING = {
4550
- [
4551
- "ClayCode_16Total_10Data_13Helper"
4552
- /* ClayCode_16Total_10Data_13Helper */
4553
- ]: {
4554
- ...CHUNK_SIZE_PARAMS.ChunkSet10MiB_Chunk1MiB
4767
+ // ../../packages/sdk/dist/chunk-EFR6H3RT.mjs
4768
+ var MICROPAYMENT_HEADER = "X-Shelby-Micropayment";
4769
+ function encodeURIComponentKeepSlashes(str) {
4770
+ return encodeURIComponent(str).replace(/%2F/g, "/");
4771
+ }
4772
+ function validateTotalBytes(totalBytes) {
4773
+ if (!Number.isInteger(totalBytes) || totalBytes < 0) {
4774
+ throw new Error("totalBytes must be a non-negative integer");
4555
4775
  }
4556
- };
4557
-
4558
- // ../../packages/sdk/dist/chunk-LZSIZJYR.mjs
4559
- var ERASURE_CODE_PARAMS = {
4560
- [
4561
- "ClayCode_16Total_10Data_13Helper"
4562
- /* ClayCode_16Total_10Data_13Helper */
4563
- ]: {
4564
- // total chunks (data + parity)
4565
- erasure_n: 16,
4566
- // data chunks
4567
- erasure_k: 10,
4568
- // helper nodes
4569
- erasure_d: 13
4776
+ }
4777
+ function getErrorCode(error) {
4778
+ if (typeof error === "object" && error !== null && "code" in error && typeof error.code === "string") {
4779
+ return error.code;
4570
4780
  }
4571
- };
4572
- var DEFAULT_ERASURE_N = ERASURE_CODE_PARAMS[
4573
- "ClayCode_16Total_10Data_13Helper"
4574
- /* ClayCode_16Total_10Data_13Helper */
4575
- ].erasure_n;
4576
- var DEFAULT_ERASURE_K = ERASURE_CODE_PARAMS[
4577
- "ClayCode_16Total_10Data_13Helper"
4578
- /* ClayCode_16Total_10Data_13Helper */
4579
- ].erasure_k;
4580
- var DEFAULT_ERASURE_D = ERASURE_CODE_PARAMS[
4581
- "ClayCode_16Total_10Data_13Helper"
4582
- /* ClayCode_16Total_10Data_13Helper */
4583
- ].erasure_d;
4584
- var DEFAULT_ERASURE_M = DEFAULT_ERASURE_N - DEFAULT_ERASURE_K;
4585
-
4586
- // ../../packages/sdk/dist/chunk-RLRI2533.mjs
4587
- import { Hex as Hex2 } from "@aptos-labs/ts-sdk";
4588
- import { z } from "zod";
4589
- var COMMITMENT_SCHEMA_VERSION = "1.3";
4590
- var ChunksetCommitmentSchema = z.object({
4591
- // Chunkset root (vector commitment of child chunks)
4592
- chunkset_root: z.string(),
4593
- // the size is known statically from the current configuration
4594
- chunk_commitments: z.array(z.string())
4595
- }).refine(
4596
- (data) => {
4597
- return data.chunk_commitments.length === DEFAULT_ERASURE_K + DEFAULT_ERASURE_M;
4598
- },
4599
- {
4600
- message: `Chunkset must have exactly ${DEFAULT_ERASURE_K + DEFAULT_ERASURE_M} chunks (ERASURE_K + ERASURE_M = ${DEFAULT_ERASURE_K} + ${DEFAULT_ERASURE_M})`,
4601
- path: ["chunk_commitments"]
4781
+ if (error instanceof Error) {
4782
+ const match = error.message.match(/\bE[A-Z0-9_]+\b/);
4783
+ return match?.[0];
4602
4784
  }
4603
- );
4604
- function expectedTotalChunksets(rawSize, chunksetSize = DEFAULT_CHUNKSET_SIZE_BYTES) {
4605
- if (chunksetSize <= 0) {
4606
- throw new Error("chunksetSize must be positive");
4607
- }
4608
- if (rawSize === 0) return 1;
4609
- return Math.ceil(rawSize / chunksetSize);
4610
- }
4611
- var BlobCommitmentsSchema = z.object({
4612
- schema_version: z.string(),
4613
- raw_data_size: z.number(),
4614
- // FIXME I am not sure about this being here, or if it should be somewhere else
4615
- blob_merkle_root: z.string(),
4616
- chunkset_commitments: z.array(ChunksetCommitmentSchema)
4617
- }).refine(
4618
- (data) => {
4619
- return expectedTotalChunksets(data.raw_data_size) === data.chunkset_commitments.length;
4620
- },
4621
- {
4622
- message: "Total chunkset count mismatches with raw data size",
4623
- // FIXME put more details in here
4624
- path: ["chunkset_commitments"]
4625
- }
4626
- );
4627
- async function generateMerkleRoot(leafHashes) {
4628
- if (!leafHashes.length) {
4629
- throw new Error(
4630
- "An empty array cannot be used to construct a Merkle tree."
4631
- );
4632
- }
4633
- const zeroArray = new Uint8Array(leafHashes[0].toUint8Array().length);
4634
- const zeroBytes = Hex2.fromHexInput(zeroArray);
4635
- let currentLeaves = leafHashes;
4636
- while (currentLeaves.length > 1) {
4637
- if (currentLeaves.length % 2 !== 0) {
4638
- currentLeaves.push(zeroBytes);
4639
- }
4640
- const nextLeaves = [];
4641
- for (let i = 0; i < currentLeaves.length; i += 2) {
4642
- nextLeaves.push(
4643
- await concatHashes([
4644
- currentLeaves[i].toUint8Array(),
4645
- currentLeaves[i + 1].toUint8Array()
4646
- ])
4647
- );
4648
- }
4649
- currentLeaves = nextLeaves;
4650
- }
4651
- return currentLeaves[0];
4652
- }
4653
- async function generateChunksetCommitments(shouldPad, chunksetIdx, chunksetData, expectedChunksetSize, provider, onChunk) {
4654
- const { erasure_n } = provider.config;
4655
- const chunksetPayload = shouldPad ? zeroPadBytes(chunksetData, expectedChunksetSize) : validatePrePaddedChunkset(
4656
- chunksetData,
4657
- expectedChunksetSize,
4658
- chunksetIdx
4659
- );
4660
- const { chunks } = provider.encode(chunksetPayload);
4661
- if (chunks.length !== erasure_n) {
4662
- throw new Error(
4663
- `Erasure provider produced ${chunks.length} chunks, expected ${erasure_n}.`
4664
- );
4665
- }
4666
- const chunkRoots = provider.getChunkMerkleRoots();
4667
- let chunkIdx = 0;
4668
- for (const chunkData of chunks) {
4669
- if (onChunk !== void 0) {
4670
- await onChunk(chunksetIdx, chunkIdx, chunkData);
4671
- }
4672
- chunkIdx += 1;
4673
- }
4674
- const a = await generateMerkleRoot(
4675
- chunkRoots.map((a2) => Hex2.fromHexInput(a2))
4676
- );
4677
- const entry = {
4678
- chunkset_root: a.toString(),
4679
- chunk_commitments: chunkRoots.map(
4680
- (chunk) => Hex2.fromHexInput(chunk).toString()
4681
- )
4682
- };
4683
- return { h: a, entry };
4684
- }
4685
- async function generateCommitments(provider, fullData, onChunk, options) {
4686
- const expectedChunksetSize = DEFAULT_CHUNKSET_SIZE_BYTES;
4687
- const shouldPad = options?.pad ?? true;
4688
- const chunksetCommitments = [];
4689
- const chunksetCommitmentHashes = [];
4690
- let rawDataSize = 0;
4691
- const chunksetGen = readInChunks(fullData, expectedChunksetSize);
4692
- for await (const [chunksetIdx, chunksetData] of chunksetGen) {
4693
- rawDataSize += chunksetData.length;
4694
- const { h, entry } = await generateChunksetCommitments(
4695
- shouldPad,
4696
- chunksetIdx,
4697
- chunksetData,
4698
- expectedChunksetSize,
4699
- provider,
4700
- onChunk
4701
- );
4702
- chunksetCommitments.push(entry);
4703
- chunksetCommitmentHashes.push(h);
4704
- }
4705
- if (rawDataSize === 0) {
4706
- const zeroChunkset = new Uint8Array(expectedChunksetSize);
4707
- const { h, entry } = await generateChunksetCommitments(
4708
- shouldPad,
4709
- 0,
4710
- zeroChunkset,
4711
- expectedChunksetSize,
4712
- provider,
4713
- onChunk
4714
- );
4715
- chunksetCommitments.push(entry);
4716
- chunksetCommitmentHashes.push(h);
4717
- }
4718
- return {
4719
- schema_version: COMMITMENT_SCHEMA_VERSION,
4720
- raw_data_size: rawDataSize,
4721
- blob_merkle_root: (await generateMerkleRoot(chunksetCommitmentHashes)).toString(),
4722
- chunkset_commitments: chunksetCommitments
4723
- };
4724
- }
4725
- function validatePrePaddedChunkset(chunkset, expectedSize, chunksetIdx) {
4726
- if (chunkset.byteLength !== expectedSize) {
4727
- throw new Error(
4728
- `Chunkset ${chunksetIdx} has size ${chunkset.byteLength} bytes but expected ${expectedSize} bytes. Enable padding or supply pre-padded data before calling generateCommitments.`
4729
- );
4730
- }
4731
- return chunkset;
4785
+ return void 0;
4732
4786
  }
4733
-
4734
- // ../../packages/sdk/dist/chunk-AGRRYZWV.mjs
4735
- import {
4736
- AccountAddress as AccountAddress2,
4737
- Aptos,
4738
- Hex as Hex3,
4739
- U32
4740
- } from "@aptos-labs/ts-sdk";
4741
- var MissingTransactionSubmitterError = class extends Error {
4742
- constructor() {
4743
- super(
4744
- "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."
4745
- );
4746
- this.name = "MissingTransactionSubmitterError";
4747
- }
4748
- };
4749
- var ShelbyBlobClient = class _ShelbyBlobClient {
4750
- aptos;
4751
- deployer;
4787
+ var ShelbyRPCClient = class {
4788
+ baseUrl;
4789
+ apiKey;
4790
+ rpcConfig;
4752
4791
  indexer;
4753
- defaultOptions;
4754
4792
  /**
4755
- * The ShelbyBlobClient is used to interact with the Shelby contract on the Aptos blockchain. This
4756
- * includes functions for registering blob commitments and retrieving blob metadata.
4793
+ * Creates a new ShelbyRPCClient for interacting with Shelby RPC nodes.
4794
+ * This client handles blob storage operations including upload and download.
4757
4795
  *
4758
4796
  * @param config - The client configuration object.
4759
4797
  * @param config.network - The Shelby network to use.
4760
- * @param defaultOptions - Optional default options for blob operations.
4761
4798
  *
4762
4799
  * @example
4763
4800
  * ```typescript
4764
- * const blobClient = new ShelbyBlobClient({
4765
- * aptos: {
4766
- * network: Network.SHELBYNET,
4767
- * clientConfig: {
4768
- * API_KEY: "AG-***",
4769
- * },
4770
- * },
4801
+ * const client = new ShelbyRPCClient({
4802
+ * network: Network.SHELBYNET,
4803
+ * apiKey: "AG-***",
4771
4804
  * });
4772
4805
  * ```
4773
- *
4774
- * @example
4775
- * ```typescript
4776
- * // With default options for USD sponsorship
4777
- * const blobClient = new ShelbyBlobClient(
4778
- * {
4779
- * network: Network.SHELBYNET,
4780
- * aptos: {
4781
- * pluginSettings: {
4782
- * TRANSACTION_SUBMITTER: myGasStationSubmitter,
4783
- * },
4784
- * },
4785
- * },
4786
- * {
4787
- * usdSponsor: { feePayerAddress: sponsorAddress },
4788
- * }
4789
- * );
4790
- * ```
4791
4806
  */
4792
- constructor(config, defaultOptions) {
4793
- this.aptos = new Aptos(getAptosConfig(config));
4794
- this.deployer = config.deployer ?? AccountAddress2.fromString(SHELBY_DEPLOYER);
4807
+ constructor(config) {
4808
+ this.baseUrl = config.rpc?.baseUrl ?? NetworkToShelbyRPCBaseUrl.shelbynet;
4809
+ this.apiKey = config.apiKey ?? config.rpc?.apiKey;
4810
+ this.rpcConfig = config.rpc ?? {};
4795
4811
  this.indexer = getShelbyIndexerClient(config);
4796
- this.defaultOptions = defaultOptions ?? {};
4797
- }
4798
- /**
4799
- * Merges method-level options with default options, giving precedence to method-level values.
4800
- */
4801
- mergeOptions(options) {
4802
- return {
4803
- build: options?.build ?? this.defaultOptions.build,
4804
- submit: options?.submit ?? this.defaultOptions.submit,
4805
- usdSponsor: options?.usdSponsor ?? this.defaultOptions.usdSponsor,
4806
- chunksetSizeBytes: options?.chunksetSizeBytes ?? this.defaultOptions.chunksetSizeBytes
4807
- };
4808
4812
  }
4809
- /**
4810
- * Validates that if USD sponsorship is requested, a transaction submitter is
4811
- * configured as well. Checks both the client-level and method-level transaction
4812
- * submitter configurations. Throws MissingTransactionSubmitterError if usdSponsor is
4813
- * provided without a transaction submitter.
4814
- */
4815
- validateUsdSponsorConfig(usdSponsor, submit) {
4816
- if (!usdSponsor) {
4817
- return;
4813
+ async #uploadPart(uploadId, partIdx, partData) {
4814
+ const nRetries = 5;
4815
+ let lastResponse;
4816
+ let lastError;
4817
+ const partUrl = buildRequestUrl(
4818
+ `/v1/multipart-uploads/${uploadId}/parts/${partIdx}`,
4819
+ this.baseUrl
4820
+ );
4821
+ for (let i = 0; i < nRetries; ++i) {
4822
+ try {
4823
+ lastResponse = await fetch(partUrl, {
4824
+ method: "PUT",
4825
+ headers: {
4826
+ "Content-Type": "application/octet-stream",
4827
+ ...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
4828
+ },
4829
+ body: partData
4830
+ });
4831
+ lastError = void 0;
4832
+ } catch (error) {
4833
+ lastError = error;
4834
+ if (i < nRetries - 1) {
4835
+ const delay = 2 ** i * 100;
4836
+ await sleep(delay);
4837
+ continue;
4838
+ }
4839
+ break;
4840
+ }
4841
+ if (lastResponse.ok) return;
4842
+ if (i < nRetries - 1) {
4843
+ const delay = 2 ** i * 100;
4844
+ await sleep(delay);
4845
+ }
4818
4846
  }
4819
- const hasClientSubmitter = this.aptos.config.getTransactionSubmitter();
4820
- const hasMethodSubmitter = submit?.transactionSubmitter !== void 0 && submit?.transactionSubmitter !== null;
4821
- if (!hasClientSubmitter && !hasMethodSubmitter) {
4822
- throw new MissingTransactionSubmitterError();
4847
+ if (lastError !== void 0) {
4848
+ const errorCode = getErrorCode(lastError);
4849
+ const errorMessage = lastError instanceof Error ? lastError.message : String(lastError);
4850
+ throw new Error(
4851
+ `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}`,
4852
+ { cause: lastError }
4853
+ );
4823
4854
  }
4855
+ const errorBody = await lastResponse?.text().catch(() => "");
4856
+ throw new Error(
4857
+ `Failed to upload part ${partIdx} for multipart upload ${uploadId} after ${nRetries} attempts. status: ${lastResponse?.status}, body: ${errorBody}`
4858
+ );
4824
4859
  }
4825
- /**
4826
- * Retrieves the blob metadata from the blockchain. If it does not exist,
4827
- * returns `undefined`.
4828
- *
4829
- * @param params.account - The account namespace the blob is stored in (e.g. "0x1")
4830
- * @param params.name - The name of the blob (e.g. "foo/bar")
4831
- * @returns The blob metadata.
4860
+ async #putBlobMultipart(account, blobName, blobData, totalBytes, partSize = 5 * 1024 * 1024, onProgress) {
4861
+ validateTotalBytes(totalBytes);
4862
+ const startResponse = await fetch(
4863
+ buildRequestUrl("/v1/multipart-uploads", this.baseUrl),
4864
+ {
4865
+ method: "POST",
4866
+ headers: {
4867
+ "Content-Type": "application/json",
4868
+ ...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
4869
+ },
4870
+ body: JSON.stringify({
4871
+ rawAccount: account.toString(),
4872
+ rawBlobName: blobName,
4873
+ rawPartSize: partSize
4874
+ })
4875
+ }
4876
+ );
4877
+ if (!startResponse.ok) {
4878
+ let errorBodyText = "Could not read error body";
4879
+ try {
4880
+ errorBodyText = await startResponse.text();
4881
+ } catch (_e) {
4882
+ }
4883
+ throw new Error(
4884
+ `Failed to start multipart upload! status: ${startResponse.status}, body: ${errorBodyText}`
4885
+ );
4886
+ }
4887
+ const { uploadId } = StartMultipartUploadResponseSchema.parse(
4888
+ await startResponse.json()
4889
+ );
4890
+ const totalParts = Math.ceil(totalBytes / partSize);
4891
+ let uploadedBytes = 0;
4892
+ for await (const [partIdx, partData] of readInChunks(blobData, partSize)) {
4893
+ await this.#uploadPart(uploadId, partIdx, partData);
4894
+ uploadedBytes += partData.length;
4895
+ onProgress?.({
4896
+ phase: "uploading",
4897
+ partIdx,
4898
+ totalParts,
4899
+ partBytes: partData.length,
4900
+ uploadedBytes,
4901
+ totalBytes
4902
+ });
4903
+ }
4904
+ if (uploadedBytes !== totalBytes) {
4905
+ throw new Error(
4906
+ `Uploaded bytes (${uploadedBytes}) did not match declared totalBytes (${totalBytes})`
4907
+ );
4908
+ }
4909
+ const finalPartIdx = totalParts > 0 ? totalParts - 1 : 0;
4910
+ onProgress?.({
4911
+ phase: "finalizing",
4912
+ partIdx: finalPartIdx,
4913
+ totalParts,
4914
+ // no part uploaded in this phase
4915
+ partBytes: 0,
4916
+ uploadedBytes: totalBytes,
4917
+ totalBytes
4918
+ });
4919
+ const completeResponse = await fetch(
4920
+ buildRequestUrl(
4921
+ `/v1/multipart-uploads/${uploadId}/complete`,
4922
+ this.baseUrl
4923
+ ),
4924
+ {
4925
+ method: "POST",
4926
+ headers: {
4927
+ "Content-Type": "application/json",
4928
+ ...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
4929
+ }
4930
+ }
4931
+ );
4932
+ if (!completeResponse.ok) {
4933
+ let errorBodyText = "Could not read error body";
4934
+ try {
4935
+ errorBodyText = await completeResponse.text();
4936
+ } catch (_e) {
4937
+ }
4938
+ throw new Error(
4939
+ `Failed to complete multipart upload! status: ${completeResponse.status}, body: ${errorBodyText}`
4940
+ );
4941
+ }
4942
+ }
4943
+ /**
4944
+ * Uploads blob data to the Shelby RPC node for storage by storage providers.
4945
+ * This method should be called after blob commitments have been registered on the blockchain.
4946
+ * Uses multipart upload for efficient handling of large files.
4947
+ *
4948
+ * @param params.account - The account that owns the blob.
4949
+ * @param params.blobName - The name/path of the blob (e.g. "folder/file.txt").
4950
+ * @param params.blobData - The raw blob data as a Uint8Array or ReadableStream.
4951
+ * @param params.totalBytes - Total byte length. Required for streams; optional for Uint8Array.
4832
4952
  *
4833
4953
  * @example
4834
4954
  * ```typescript
4835
- * const metadata = await client.getBlobMetadata({
4836
- * account: AccountAddress.fromString("0x1"),
4837
- * name: "foo/bar.txt",
4955
+ * const blobData = new TextEncoder().encode("Hello, world!");
4956
+ *
4957
+ * await client.putBlob({
4958
+ * account: AccountAddress.from("0x1"),
4959
+ * blobName: "greetings/hello.txt",
4960
+ * blobData,
4838
4961
  * });
4839
4962
  * ```
4840
4963
  */
4841
- async getBlobMetadata(params) {
4842
- try {
4843
- const rawMetadata = await this.aptos.view({
4844
- payload: {
4845
- function: `${this.deployer.toString()}::blob_metadata::get_blob_metadata`,
4846
- functionArguments: [
4847
- createBlobKey({
4848
- account: params.account,
4849
- blobName: params.name
4850
- })
4851
- ]
4852
- }
4853
- });
4854
- if (!rawMetadata?.[0]?.vec?.[0]) {
4855
- return void 0;
4856
- }
4857
- const metadata = rawMetadata[0].vec[0];
4858
- let encoding;
4859
- if (metadata.encoding.__variant__ === "ClayCode_16Total_10Data_13Helper") {
4860
- encoding = {
4861
- variant: "clay",
4862
- ...ERASURE_CODE_PARAMS[metadata.encoding.__variant__],
4863
- ...ERASURE_CODE_AND_CHUNK_MAPPING[metadata.encoding.__variant__]
4864
- };
4865
- } else {
4964
+ async putBlob(params) {
4965
+ BlobNameSchema.parse(params.blobName);
4966
+ let totalBytes;
4967
+ if (params.blobData instanceof Uint8Array) {
4968
+ totalBytes = params.totalBytes ?? params.blobData.length;
4969
+ if (totalBytes !== params.blobData.length) {
4866
4970
  throw new Error(
4867
- "Could not parse encoding from Shelby Smart Contract, this SDK is out of date."
4971
+ "totalBytes must match blobData.length when blobData is a Uint8Array"
4868
4972
  );
4869
4973
  }
4870
- return {
4871
- blobMerkleRoot: Hex3.fromHexInput(
4872
- metadata.blob_commitment
4873
- ).toUint8Array(),
4874
- owner: AccountAddress2.fromString(metadata.owner),
4875
- name: params.name,
4876
- blobNameSuffix: getBlobNameSuffix(params.name),
4877
- size: Number(metadata.blob_size),
4878
- encoding,
4879
- expirationMicros: Number(metadata.expiration_micros),
4880
- creationMicros: Number(metadata.creation_micros),
4881
- sliceAddress: AccountAddress2.fromString(metadata.slice.inner),
4882
- isWritten: metadata.is_written
4883
- };
4884
- } catch (error) {
4885
- if (error instanceof Error && // Depending on the network, the error message may show up differently.
4886
- (error.message?.includes("sub_status: Some(404)") || error.message?.includes("EBLOB_NOT_FOUND"))) {
4887
- return void 0;
4974
+ } else {
4975
+ if (params.totalBytes === void 0) {
4976
+ throw new Error(
4977
+ "totalBytes is required when blobData is a ReadableStream"
4978
+ );
4888
4979
  }
4889
- throw error;
4980
+ totalBytes = params.totalBytes;
4890
4981
  }
4982
+ validateTotalBytes(totalBytes);
4983
+ await this.#putBlobMultipart(
4984
+ params.account,
4985
+ params.blobName,
4986
+ params.blobData,
4987
+ totalBytes,
4988
+ void 0,
4989
+ params.onProgress
4990
+ );
4891
4991
  }
4892
4992
  /**
4893
- * Retrieves all the blobs and their metadata for an account from the
4894
- * blockchain.
4993
+ * Downloads a blob from the Shelby RPC node.
4994
+ * Returns a streaming response with validation to ensure data integrity.
4895
4995
  *
4896
- * @param params.account - The account namespace the blobs are stored in (e.g. "0x1")
4897
- * @param params.pagination (optional) - The pagination options.
4898
- * @param params.orderBy (optional) - The order by clause to sort the blobs by.
4899
- * @returns The blob metadata for all the blobs for the account.
4996
+ * @param params.account - The account that owns the blob.
4997
+ * @param params.blobName - The name/path of the blob (e.g. "folder/file.txt").
4998
+ * @param params.range - Optional byte range for partial downloads.
4999
+ * @param params.range.start - Starting byte position (inclusive).
5000
+ * @param params.range.end - Ending byte position (inclusive, optional).
5001
+ * @param params.micropayment - Optional micropayment to attach to the request.
5002
+ *
5003
+ * @returns A ShelbyBlob object containing the account, name, readable stream, and content length.
5004
+ *
5005
+ * @throws Error if the download fails or content length doesn't match.
5006
+ * @throws StaleChannelStateError if the micropayment is stale (server has newer state).
4900
5007
  *
4901
5008
  * @example
4902
5009
  * ```typescript
4903
- * // BlobMetadata[]
4904
- * const blobs = await client.getAccountBlobs({
4905
- * account: AccountAddress.fromString("0x1"),
5010
+ * // Download entire blob
5011
+ * const blob = await client.getBlob({
5012
+ * account: AccountAddress.from("0x1"),
5013
+ * blobName: "documents/report.pdf"
4906
5014
  * });
4907
- * ```
4908
- */
4909
- getAccountBlobs(params) {
4910
- const { where, ...rest } = params;
4911
- return this.getBlobs({
4912
- where: {
4913
- ...where,
4914
- owner: { _eq: AccountAddress2.from(params.account).toString() }
4915
- },
4916
- pagination: rest.pagination,
4917
- orderBy: rest.orderBy
4918
- });
4919
- }
4920
- /**
4921
- * Retrieves blobs and their metadata from the blockchain.
4922
5015
  *
4923
- * @param params.where (optional) - The where clause to filter the blobs by.
4924
- * @param params.pagination (optional) - The pagination options.
4925
- * @param params.orderBy (optional) - The order by clause to sort the blobs by.
4926
- * @returns The blob metadata for all the blobs that match the where clause.
5016
+ * // Download partial content (bytes 100-199)
5017
+ * const partial = await client.getBlob({
5018
+ * account: AccountAddress.from("0x1"),
5019
+ * blobName: "large-file.bin",
5020
+ * range: { start: 100, end: 199 }
5021
+ * });
4927
5022
  *
4928
- * @example
4929
- * ```typescript
4930
- * // BlobMetadata[]
4931
- * const blobs = await client.getBlobs({
4932
- * where: { owner: { _eq: AccountAddress.fromString("0x1").toString() } },
5023
+ * // Download with micropayment
5024
+ * const blob = await client.getBlob({
5025
+ * account: AccountAddress.from("0x1"),
5026
+ * blobName: "documents/report.pdf",
5027
+ * micropayment: senderBuiltMicropayment
4933
5028
  * });
4934
5029
  * ```
4935
5030
  */
4936
- async getBlobs(params = {}) {
4937
- const { limit, offset } = params.pagination ?? {};
4938
- const { orderBy, where } = params;
4939
- const currentMicros = String(Date.now() * 1e3);
4940
- const defaultActiveFilter = {
4941
- expires_at: { _gte: currentMicros },
4942
- is_deleted: { _eq: "0" }
4943
- };
4944
- const finalWhere = where !== void 0 ? { ...defaultActiveFilter, ...where } : defaultActiveFilter;
4945
- const { blobs } = await this.indexer.getBlobs({
4946
- where: finalWhere,
4947
- limit,
4948
- offset,
4949
- orderBy
4950
- });
4951
- return blobs.map(
4952
- (blob) => ({
4953
- owner: AccountAddress2.from(blob.owner),
4954
- name: blob.blob_name,
4955
- blobNameSuffix: getBlobNameSuffix(blob.blob_name),
4956
- blobMerkleRoot: Hex3.fromHexInput(blob.blob_commitment).toUint8Array(),
4957
- size: Number(blob.size),
4958
- // TODO: Add encoding when supported in NCI
4959
- encoding: {
4960
- variant: "clay",
4961
- ...ERASURE_CODE_PARAMS.ClayCode_16Total_10Data_13Helper,
4962
- ...ERASURE_CODE_AND_CHUNK_MAPPING.ClayCode_16Total_10Data_13Helper
4963
- },
4964
- expirationMicros: Number(blob.expires_at),
4965
- creationMicros: Number(blob.created_at),
4966
- sliceAddress: AccountAddress2.from(blob.slice_address),
4967
- isWritten: Boolean(Number(blob.is_written)),
4968
- isDeleted: Boolean(Number(blob.is_deleted))
4969
- })
5031
+ async getBlob(params) {
5032
+ BlobNameSchema.parse(params.blobName);
5033
+ const url = buildRequestUrl(
5034
+ `/v1/blobs/${params.account.toString()}/${encodeURIComponentKeepSlashes(
5035
+ params.blobName
5036
+ )}`,
5037
+ this.baseUrl
4970
5038
  );
4971
- }
4972
- async getBlobActivities(params) {
4973
- const { limit, offset } = params.pagination ?? {};
4974
- const { orderBy, where } = params;
4975
- const { blob_activities } = await this.indexer.getBlobActivities({
4976
- where,
4977
- limit,
4978
- offset,
4979
- orderBy
5039
+ const headers = new Headers();
5040
+ if (params.range !== void 0) {
5041
+ const { start, end } = params.range;
5042
+ if (end === void 0) {
5043
+ headers.set("Range", `bytes=${start}-`);
5044
+ } else {
5045
+ if (end < start) {
5046
+ throw new Error("Range end cannot be less than start.");
5047
+ }
5048
+ headers.set("Range", `bytes=${start}-${end}`);
5049
+ }
5050
+ }
5051
+ if (this.apiKey) {
5052
+ headers.set("Authorization", `Bearer ${this.apiKey}`);
5053
+ }
5054
+ if (params.micropayment) {
5055
+ const bytes = params.micropayment.bcsToBytes();
5056
+ const binaryString = Array.from(
5057
+ bytes,
5058
+ (byte) => String.fromCharCode(byte)
5059
+ ).join("");
5060
+ headers.set(MICROPAYMENT_HEADER, btoa(binaryString));
5061
+ }
5062
+ const response = await fetch(url, { headers });
5063
+ if (response.status === 409) {
5064
+ let json;
5065
+ try {
5066
+ json = await response.json();
5067
+ } catch {
5068
+ throw new Error(
5069
+ `Failed to download blob: ${response.status} ${response.statusText}`
5070
+ );
5071
+ }
5072
+ const parseResult = StaleMicropaymentErrorResponseSchema.safeParse(json);
5073
+ if (!parseResult.success) {
5074
+ throw new Error(
5075
+ `Failed to download blob: ${response.status} ${response.statusText}`
5076
+ );
5077
+ }
5078
+ const errorBody = parseResult.data;
5079
+ if (errorBody.storedMicropayment) {
5080
+ throw StaleChannelStateError.fromBase64(
5081
+ errorBody.storedMicropayment,
5082
+ errorBody.error
5083
+ );
5084
+ }
5085
+ throw new Error(
5086
+ errorBody.error ?? `Failed to download blob: ${response.status} ${response.statusText}`
5087
+ );
5088
+ }
5089
+ if (!response.ok) {
5090
+ throw new Error(
5091
+ `Failed to download blob: ${response.status} ${response.statusText}`
5092
+ );
5093
+ }
5094
+ if (!response.body) {
5095
+ throw new Error("Response body is null");
5096
+ }
5097
+ const contentLengthHeader = response.headers.get("content-length");
5098
+ if (contentLengthHeader === null) {
5099
+ throw new Error(
5100
+ "Response did not have content-length header, which is required"
5101
+ );
5102
+ }
5103
+ const expectedContentLength = Number.parseInt(contentLengthHeader, 10);
5104
+ if (Number.isNaN(expectedContentLength)) {
5105
+ throw new Error(
5106
+ `Invalid content-length header received: ${contentLengthHeader}`
5107
+ );
5108
+ }
5109
+ const validatingStream = new ReadableStream({
5110
+ start(controller) {
5111
+ const maybeReader = response.body?.getReader();
5112
+ if (!maybeReader) {
5113
+ controller.error(new Error("Response body reader is unavailable"));
5114
+ return;
5115
+ }
5116
+ const reader = maybeReader;
5117
+ let bytesReceived = 0;
5118
+ function pump() {
5119
+ return reader.read().then(({ done, value }) => {
5120
+ if (done) {
5121
+ if (bytesReceived !== expectedContentLength) {
5122
+ controller.error(
5123
+ new Error(
5124
+ `Downloaded data size (${bytesReceived} bytes) does not match content-length header (${expectedContentLength} bytes). This might indicate a partial or corrupted download.`
5125
+ )
5126
+ );
5127
+ return;
5128
+ }
5129
+ controller.close();
5130
+ return;
5131
+ }
5132
+ bytesReceived += value.byteLength;
5133
+ controller.enqueue(value);
5134
+ return pump();
5135
+ }).catch((error) => {
5136
+ controller.error(error);
5137
+ });
5138
+ }
5139
+ return pump();
5140
+ }
4980
5141
  });
4981
- const activityTypeMapping = {
4982
- [`${this.deployer.toStringLong()}::blob_metadata::BlobRegisteredEvent`]: "register_blob",
4983
- [`${this.deployer.toStringLong()}::blob_metadata::BlobDeletedEvent`]: "delete_blob",
4984
- [`${this.deployer.toStringLong()}::blob_metadata::BlobExpirationExtendedEvent`]: "extend_blob_expiration",
4985
- [`${this.deployer.toStringLong()}::blob_metadata::BlobWrittenEvent`]: "write_blob"
5142
+ return {
5143
+ account: normalizeAddress(params.account),
5144
+ name: params.blobName,
5145
+ readable: validatingStream,
5146
+ contentLength: expectedContentLength
4986
5147
  };
4987
- return blob_activities.map(
4988
- (activity) => ({
4989
- blobName: activity.blob_name,
4990
- accountAddress: AccountAddress2.from(
4991
- activity.blob_name.substring(1, 65)
4992
- ),
4993
- type: activityTypeMapping[activity.event_type] ?? "unknown",
4994
- eventType: activity.event_type,
4995
- eventIndex: Number(activity.event_index),
4996
- transactionHash: activity.transaction_hash,
4997
- // Using Number here in JS is technically not okay because txn version can be
4998
- // as large as u64::MAX, but it should be fine for a long while.
4999
- transactionVersion: Number(activity.transaction_version),
5000
- timestamp: `${activity.timestamp}Z`
5001
- })
5002
- );
5148
+ }
5149
+ };
5150
+
5151
+ // ../../packages/sdk/dist/chunk-OGKZ575S.mjs
5152
+ import {
5153
+ createDecoder,
5154
+ createEncoder
5155
+ } from "@shelby-protocol/clay-codes";
5156
+ function getTotalChunks(config) {
5157
+ return config.erasure_n;
5158
+ }
5159
+ var ClayErasureCodingProvider = class _ClayErasureCodingProvider {
5160
+ config;
5161
+ encoderCache;
5162
+ decoderCache;
5163
+ lastFunction;
5164
+ constructor(config) {
5165
+ this.config = config;
5166
+ this.lastFunction = "none";
5003
5167
  }
5004
5168
  /**
5005
- * Retrieves the total number of blobs from the blockchain.
5006
- *
5007
- * @param params.where (optional) - The where clause to filter the blobs by.
5008
- * @returns The total number of blobs.
5009
- *
5010
- * @example
5011
- * ```typescript
5012
- * const count = await client.getBlobsCount();
5013
- * ```
5169
+ * Static factory method to create an initialized ClayErasureCodingProvider
5014
5170
  */
5015
- async getBlobsCount(params) {
5016
- const { where } = params;
5017
- const { blobs_aggregate } = await this.indexer.getBlobsCount({ where });
5018
- return blobs_aggregate?.aggregate?.count ?? 0;
5171
+ static async create(config) {
5172
+ const provider = new _ClayErasureCodingProvider(config);
5173
+ [provider.encoderCache, provider.decoderCache] = await Promise.all([
5174
+ createEncoder({
5175
+ n: getTotalChunks(config),
5176
+ k: config.erasure_k,
5177
+ d: config.erasure_d,
5178
+ chunkSizeBytes: config.chunkSizeBytes
5179
+ }),
5180
+ createDecoder({
5181
+ n: getTotalChunks(config),
5182
+ k: config.erasure_k,
5183
+ d: config.erasure_d,
5184
+ chunkSizeBytes: config.chunkSizeBytes,
5185
+ erasedChunksMask: 0
5186
+ // No chunks erased initially; will be reconfigured on decode
5187
+ })
5188
+ ]);
5189
+ return provider;
5190
+ }
5191
+ encode(data) {
5192
+ const { erasure_k, chunkSizeBytes } = this.config;
5193
+ if (!this.encoderCache) {
5194
+ throw new Error("Encoder cache is missing");
5195
+ }
5196
+ const systematicCapacity = erasure_k * chunkSizeBytes;
5197
+ if (data.byteLength > systematicCapacity) {
5198
+ throw new Error(
5199
+ `Data size ${data.byteLength} bytes exceeds systematic capacity ${systematicCapacity} bytes (erasure_k=${erasure_k} * chunkSizeBytes=${chunkSizeBytes}).`
5200
+ );
5201
+ }
5202
+ if (this.requiresPadding(data.length)) {
5203
+ throw new Error(
5204
+ `Data size ${data.length} bytes does not match systematic capacity ${systematicCapacity} bytes (erasure_k=${erasure_k} * chunkSizeBytes=${chunkSizeBytes}). Provide pre-padded data before encoding.`
5205
+ );
5206
+ }
5207
+ this.lastFunction = "encoded";
5208
+ return this.encoderCache.erasureCode(data);
5209
+ }
5210
+ decode(available, config) {
5211
+ if (!this.decoderCache) {
5212
+ throw new Error("Decoder cache is missing");
5213
+ }
5214
+ const { erasure_k, chunkSizeBytes } = this.config;
5215
+ if (available.length < erasure_k) {
5216
+ throw new Error(
5217
+ `Insufficient available chunks: need at least ${erasure_k}, received ${available.length}.`
5218
+ );
5219
+ }
5220
+ for (let i = 0; i < available.length; i++) {
5221
+ const chunk = available[i];
5222
+ if (chunk.length !== chunkSizeBytes) {
5223
+ throw new Error(
5224
+ `Chunk ${i} size ${chunk.length} bytes does not match expected chunkSizeBytes ${chunkSizeBytes}.`
5225
+ );
5226
+ }
5227
+ }
5228
+ this.lastFunction = "decoded";
5229
+ return this.decoderCache.decode(available, config);
5230
+ }
5231
+ getChunkMerkleRoots() {
5232
+ if (this.decoderCache && this.lastFunction === "decoded")
5233
+ return this.decoderCache.getChunkMerkleRoots();
5234
+ if (this.encoderCache && this.lastFunction === "encoded")
5235
+ return this.encoderCache.getChunkMerkleRoots();
5236
+ throw new Error(
5237
+ "You must call encode or decode before calling getChunkMerkleRoots"
5238
+ );
5019
5239
  }
5020
5240
  /**
5021
- * Retrieves the total number of blob activities from the blockchain.
5241
+ * Determines if data can be erasure coded as-is or requires padding.
5022
5242
  *
5023
- * @param params.where (optional) - The where clause to filter the blob activities by.
5024
- * @returns The total number of blob activities.
5243
+ * Data can be erasure coded without padding if its size exactly matches
5244
+ * the total systematic data capacity (k * chunkSizeBytes).
5025
5245
  *
5026
- * @example
5027
- * ```typescript
5028
- * const count = await client.getBlobActivitiesCount();
5029
- * ```
5246
+ * @param dataSize - Size of the data in bytes
5247
+ * @returns true if data needs padding, false if it can be coded as-is
5030
5248
  */
5031
- async getBlobActivitiesCount(params) {
5032
- const { where } = params;
5033
- const { blob_activities_aggregate } = await this.indexer.getBlobActivitiesCount({ where });
5034
- return blob_activities_aggregate?.aggregate?.count ?? 0;
5249
+ requiresPadding(dataSize) {
5250
+ const { erasure_k, chunkSizeBytes } = this.config;
5251
+ const systematicCapacity = erasure_k * chunkSizeBytes;
5252
+ return dataSize !== systematicCapacity;
5035
5253
  }
5036
- /**
5037
- * Registers a blob on the blockchain by writing its merkle root and metadata.
5038
- *
5039
- * @param params.account - The account that is signing and paying for the transaction.
5040
- * @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
5041
- * @param params.blobMerkleRoot - The merkle root of the blob commitments.
5042
- * @param params.size - The size of the blob in bytes.
5043
- * @param params.expirationMicros - The expiration time of the blob in microseconds.
5044
- * @param params.options - Optional transaction building options.
5045
- * @param params.options.chunksetSizeBytes - Custom chunkset size (defaults to DEFAULT_CHUNKSET_SIZE_BYTES).
5046
- * @param params.options.build - Additional Aptos transaction building options.
5047
- *
5048
- * @returns An object containing the pending transaction.
5049
- *
5050
- * @example
5051
- * ```typescript
5052
- * const provider = await ClayErasureCodingProvider.create();
5053
- * const blobCommitments = await generateCommitments(provider, data);
5054
- *
5055
- * const { transaction } = await client.registerBlob({
5056
- * account: signer,
5057
- * blobName: "foo/bar.txt",
5058
- * blobMerkleRoot: blobCommitments.blob_merkle_root,
5059
- * size: data.length,
5060
- * expirationMicros: Date.now() * 1000 + 3600_000_000, // 1 hour from now in microseconds
5061
- * });
5062
- * ```
5063
- */
5064
- async registerBlob(params) {
5065
- const options = this.mergeOptions(params.options);
5066
- this.validateUsdSponsorConfig(options.usdSponsor, options.submit);
5067
- const chunksetSize = options.chunksetSizeBytes ?? DEFAULT_CHUNKSET_SIZE_BYTES;
5068
- const buildArgs = {
5069
- ...options.build,
5070
- data: _ShelbyBlobClient.createRegisterBlobPayload({
5071
- deployer: this.deployer,
5072
- account: params.account.accountAddress,
5073
- blobName: params.blobName,
5074
- blobSize: params.size,
5075
- blobMerkleRoot: params.blobMerkleRoot,
5076
- numChunksets: expectedTotalChunksets(params.size, chunksetSize),
5077
- expirationMicros: params.expirationMicros,
5078
- useSponsoredUsdVariant: options.usdSponsor !== void 0
5079
- }),
5080
- sender: params.account.accountAddress
5081
- };
5082
- const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
5083
- ...buildArgs,
5084
- secondarySignerAddresses: [options.usdSponsor.feePayerAddress]
5085
- }) : await this.aptos.transaction.build.simple(buildArgs);
5086
- return {
5087
- transaction: await this.aptos.signAndSubmitTransaction({
5088
- signer: params.account,
5089
- transaction,
5090
- ...options.submit
5091
- })
5092
- };
5254
+ };
5255
+
5256
+ // ../../packages/sdk/dist/chunk-JTXYKO3U.mjs
5257
+ var CHUNK_SIZE_PARAMS = {
5258
+ [
5259
+ "ChunkSet10MiB_Chunk1MiB"
5260
+ /* ChunkSet10MiB_Chunk1MiB */
5261
+ ]: {
5262
+ // 1MiB
5263
+ chunkSizeBytes: 1 * 1024 * 1024,
5264
+ // 10MiB
5265
+ chunksetSizeBytes: 10 * 1024 * 1024
5266
+ },
5267
+ [
5268
+ "ChunkSet2MiB_Chunk1MiB"
5269
+ /* ChunkSet2MiB_Chunk1MiB */
5270
+ ]: {
5271
+ // 1MiB
5272
+ chunkSizeBytes: 1 * 1024 * 1024,
5273
+ // 2MiB
5274
+ chunksetSizeBytes: 2 * 1024 * 1024
5093
5275
  }
5094
- /**
5095
- * Deletes a blob on the blockchain.
5096
- *
5097
- * @param params.account - The account that is signing and paying for the transaction.
5098
- * @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
5099
- * @param params.options - Optional transaction building options.
5100
- *
5101
- * @returns An object containing the pending transaction.
5102
- *
5103
- * @example
5104
- * ```typescript
5105
- *
5106
- * const { transaction } = await client.deleteBlob({
5107
- * account: signer,
5108
- * blobName: "foo/bar.txt",
5109
- * });
5110
- * ```
5111
- */
5112
- async deleteBlob(params) {
5113
- const transaction = await this.aptos.transaction.build.simple({
5114
- ...params.options,
5115
- data: _ShelbyBlobClient.createDeleteBlobPayload({
5116
- deployer: this.deployer,
5117
- blobName: params.blobName
5118
- }),
5119
- sender: params.account.accountAddress
5120
- });
5121
- return {
5122
- transaction: await this.aptos.signAndSubmitTransaction({
5123
- signer: params.account,
5124
- transaction
5125
- })
5126
- };
5276
+ };
5277
+ var DEFAULT_CHUNK_SIZE_BYTES = CHUNK_SIZE_PARAMS[
5278
+ "ChunkSet10MiB_Chunk1MiB"
5279
+ /* ChunkSet10MiB_Chunk1MiB */
5280
+ ].chunkSizeBytes;
5281
+ var DEFAULT_CHUNKSET_SIZE_BYTES = CHUNK_SIZE_PARAMS[
5282
+ "ChunkSet10MiB_Chunk1MiB"
5283
+ /* ChunkSet10MiB_Chunk1MiB */
5284
+ ].chunksetSizeBytes;
5285
+ var ERASURE_CODE_AND_CHUNK_MAPPING = {
5286
+ [
5287
+ "ClayCode_16Total_10Data_13Helper"
5288
+ /* ClayCode_16Total_10Data_13Helper */
5289
+ ]: {
5290
+ ...CHUNK_SIZE_PARAMS.ChunkSet10MiB_Chunk1MiB
5291
+ },
5292
+ [
5293
+ "ClayCode_4Total_2Data_3Helper"
5294
+ /* ClayCode_4Total_2Data_3Helper */
5295
+ ]: {
5296
+ ...CHUNK_SIZE_PARAMS.ChunkSet2MiB_Chunk1MiB
5127
5297
  }
5128
- /**
5129
- * Deletes multiple blobs on the blockchain in a single atomic transaction.
5130
- *
5131
- * **Note:** This function requires the `delete_multiple_blobs` entry function
5132
- * which will be deployed to the smart contract on 2026-02-04. Using this
5133
- * function before that date will result in a transaction failure.
5134
- *
5135
- * This operation is atomic: if any blob deletion fails (e.g., blob not found),
5136
- * the entire transaction fails and no blobs are deleted.
5137
- *
5138
- * @param params.account - The account that is signing and paying for the transaction.
5139
- * @param params.blobNames - Array of blob name suffixes without the account address prefix
5140
- * (e.g. ["foo/bar.txt", "baz.txt"], NOT ["0x1/foo/bar.txt"]). The account address
5141
- * prefix is automatically derived from the signer.
5142
- * @param params.options - Optional transaction building options.
5143
- *
5144
- * @returns An object containing the pending transaction.
5145
- *
5146
- * @example
5147
- * ```typescript
5148
- *
5149
- * const { transaction } = await client.deleteMultipleBlobs({
5150
- * account: signer,
5151
- * blobNames: ["foo/bar.txt", "baz.txt"],
5152
- * });
5153
- * ```
5154
- */
5155
- async deleteMultipleBlobs(params) {
5156
- const transaction = await this.aptos.transaction.build.simple({
5157
- ...params.options,
5158
- data: _ShelbyBlobClient.createDeleteMultipleBlobsPayload({
5159
- deployer: this.deployer,
5160
- blobNames: params.blobNames
5161
- }),
5162
- sender: params.account.accountAddress
5163
- });
5164
- return {
5165
- transaction: await this.aptos.signAndSubmitTransaction({
5166
- signer: params.account,
5167
- transaction
5168
- })
5169
- };
5298
+ };
5299
+
5300
+ // ../../packages/sdk/dist/chunk-AUQDI5BS.mjs
5301
+ var ERASURE_CODE_PARAMS = {
5302
+ [
5303
+ "ClayCode_16Total_10Data_13Helper"
5304
+ /* ClayCode_16Total_10Data_13Helper */
5305
+ ]: {
5306
+ // total chunks (data + parity)
5307
+ erasure_n: 16,
5308
+ // data chunks
5309
+ erasure_k: 10,
5310
+ // helper nodes
5311
+ erasure_d: 13,
5312
+ // enum index
5313
+ enumIndex: 0
5314
+ },
5315
+ [
5316
+ "ClayCode_4Total_2Data_3Helper"
5317
+ /* ClayCode_4Total_2Data_3Helper */
5318
+ ]: {
5319
+ // total chunks (data + parity)
5320
+ erasure_n: 4,
5321
+ // data chunks
5322
+ erasure_k: 2,
5323
+ // helper nodes
5324
+ erasure_d: 3,
5325
+ // enum index
5326
+ enumIndex: 1
5170
5327
  }
5171
- /**
5172
- * Acks the blob chunksets on-chain. If each chunkset meets the necessary threshold, the entire blob will be marked as written.
5173
- *
5174
- * @param params.account - The account that is signing the transaction.
5175
- * @param params.blobOwner - The account that owns the blob.
5176
- * @param params.blobName - The name of the blob (e.g. "foo/bar")
5177
- * @param params.creationMicros - The creation time of the blob in microseconds.
5178
- * @param params.chunksetIdx - The index of the chunkset being acknowledged.
5179
- * @param params.storageProviderChunksetAcks - The signatures
5180
- * @param params.options - Additional options for transaction building and encoding.
5181
- *
5182
- * @returns The blob commitments and the pending transaction.
5183
- *
5184
- * @example
5185
- * ```typescript
5186
- * const { transaction } = await client.addChunksetAcknowledgements({
5187
- * account: signer,
5188
- * blobOwner: owner,
5189
- * blobName: "foo/bar.txt",
5190
- * creationMicros, // Taken from the blob metadata at registration time.
5191
- * chunksetIdx,
5192
- * storageProviderAcks: An array of StorageProviderAck types, each having the slot index and signature from the SP.
5193
- * });
5194
- * ```
5195
- */
5196
- async addChunksetAcknowledgements(params) {
5197
- const transaction = await this.aptos.transaction.build.simple({
5198
- ...params.options?.build,
5199
- data: _ShelbyBlobClient.createChunksetAcknowledgementsPayload({
5200
- blobOwner: params.blobOwner,
5201
- blobName: params.blobName,
5202
- creationMicros: params.creationMicros,
5203
- chunksetIdx: params.chunksetIdx,
5204
- storageProviderAcks: params.storageProviderAcks
5205
- }),
5206
- sender: params.account.accountAddress
5207
- });
5208
- return {
5209
- transaction: await this.aptos.signAndSubmitTransaction({
5210
- signer: params.account,
5211
- transaction
5212
- })
5213
- };
5328
+ };
5329
+ var DEFAULT_ERASURE_N = ERASURE_CODE_PARAMS[
5330
+ "ClayCode_16Total_10Data_13Helper"
5331
+ /* ClayCode_16Total_10Data_13Helper */
5332
+ ].erasure_n;
5333
+ var DEFAULT_ERASURE_K = ERASURE_CODE_PARAMS[
5334
+ "ClayCode_16Total_10Data_13Helper"
5335
+ /* ClayCode_16Total_10Data_13Helper */
5336
+ ].erasure_k;
5337
+ var DEFAULT_ERASURE_D = ERASURE_CODE_PARAMS[
5338
+ "ClayCode_16Total_10Data_13Helper"
5339
+ /* ClayCode_16Total_10Data_13Helper */
5340
+ ].erasure_d;
5341
+ var DEFAULT_ERASURE_M = DEFAULT_ERASURE_N - DEFAULT_ERASURE_K;
5342
+
5343
+ // ../../packages/sdk/dist/chunk-HPPMI7DC.mjs
5344
+ function defaultErasureCodingConfig() {
5345
+ console.log(
5346
+ `default erasure coding, with env: ${process.env.SHELBY_ENCODING}`
5347
+ );
5348
+ const encoding = Number(process.env.SHELBY_ENCODING) || 0;
5349
+ if (encoding === 0) {
5350
+ console.log("getting default erasure coding (16,10,13)");
5351
+ return erasureCodingConfig16Total10Data13Helper();
5214
5352
  }
5215
- /**
5216
- * Registers multiple blobs on the blockchain by writing their merkle roots and metadata.
5217
- *
5218
- * @param params.account - The account that is signing and paying for the transaction.
5219
- * @param params.expirationMicros - The expiration time of the blobs in microseconds.
5220
- * @param params.blobs - The blobs to register.
5221
- * @param params.blobs.blobName - The name/path of the blob (e.g. "foo/bar.txt").
5222
- * @param params.blobs.blobSize - The size of the blob in bytes.
5223
- * @param params.blobs.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
5224
- * @param params.options - Optional transaction building options.
5225
- * @param params.options.chunksetSizeBytes - Custom chunkset size (defaults to DEFAULT_CHUNKSET_SIZE_BYTES).
5226
- * @param params.options.build - Additional Aptos transaction building options.
5227
- *
5228
- * @returns An object containing the pending transaction.
5229
- *
5230
- * @example
5231
- * ```typescript
5232
- * const provider = await ClayErasureCodingProvider.create();
5233
- * const blobCommitments = await generateCommitments(provider, data);
5234
- *
5235
- * const { transaction } = await client.batchRegisterBlobs({
5236
- * account: signer,
5237
- * expirationMicros: Date.now() * 1000 + 3600_000_000, // 1 hour from now in microseconds
5238
- * blobs: [
5239
- * {
5240
- * blobName: "foo/bar.txt",
5241
- * blobSize: data.length,
5242
- * blobMerkleRoot: blobCommitments.blob_merkle_root,
5243
- * },
5244
- * ],
5245
- * });
5246
- * ```
5247
- */
5248
- async batchRegisterBlobs(params) {
5249
- const options = this.mergeOptions(params.options);
5250
- this.validateUsdSponsorConfig(options.usdSponsor, options.submit);
5251
- const chunksetSize = options.chunksetSizeBytes ?? DEFAULT_CHUNKSET_SIZE_BYTES;
5252
- const buildArgs = {
5253
- ...options.build,
5254
- sender: params.account.accountAddress,
5255
- data: _ShelbyBlobClient.createBatchRegisterBlobsPayload({
5256
- deployer: this.deployer,
5257
- account: params.account.accountAddress,
5258
- expirationMicros: params.expirationMicros,
5259
- blobs: params.blobs.map((blob) => ({
5260
- blobName: blob.blobName,
5261
- blobSize: blob.blobSize,
5262
- blobMerkleRoot: blob.blobMerkleRoot,
5263
- numChunksets: expectedTotalChunksets(blob.blobSize, chunksetSize)
5264
- })),
5265
- useSponsoredUsdVariant: options.usdSponsor !== void 0
5266
- })
5267
- };
5268
- const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
5269
- ...buildArgs,
5270
- secondarySignerAddresses: [options.usdSponsor.feePayerAddress]
5271
- }) : await this.aptos.transaction.build.simple(buildArgs);
5272
- return {
5273
- transaction: await this.aptos.signAndSubmitTransaction({
5274
- signer: params.account,
5275
- transaction,
5276
- ...options.submit
5277
- })
5278
- };
5353
+ console.log("getting default erasure coding (4,2,3)");
5354
+ return erasureCodingConfig4Total2Data3Helper();
5355
+ }
5356
+ function erasureCodingConfig16Total10Data13Helper() {
5357
+ return erasureCodingConfig(
5358
+ "ClayCode_16Total_10Data_13Helper"
5359
+ /* ClayCode_16Total_10Data_13Helper */
5360
+ );
5361
+ }
5362
+ function erasureCodingConfig4Total2Data3Helper() {
5363
+ return erasureCodingConfig(
5364
+ "ClayCode_4Total_2Data_3Helper"
5365
+ /* ClayCode_4Total_2Data_3Helper */
5366
+ );
5367
+ }
5368
+ function erasureCodingConfig(encodingScheme) {
5369
+ return {
5370
+ erasure_n: ERASURE_CODE_PARAMS[encodingScheme].erasure_n,
5371
+ erasure_k: ERASURE_CODE_PARAMS[encodingScheme].erasure_k,
5372
+ erasure_d: ERASURE_CODE_PARAMS[encodingScheme].erasure_d,
5373
+ chunkSizeBytes: DEFAULT_CHUNK_SIZE_BYTES,
5374
+ enumIndex: ERASURE_CODE_PARAMS[encodingScheme].enumIndex
5375
+ };
5376
+ }
5377
+
5378
+ // ../../packages/sdk/dist/chunk-3NRBHSMQ.mjs
5379
+ var createBlobKey = (params) => {
5380
+ return `@${normalizeAddress(params.account).toStringLongWithoutPrefix()}/${params.blobName}`;
5381
+ };
5382
+
5383
+ // ../../packages/sdk/dist/chunk-BXEVML7N.mjs
5384
+ import { Hex as Hex3 } from "@aptos-labs/ts-sdk";
5385
+ import { z as z3 } from "zod";
5386
+ var COMMITMENT_SCHEMA_VERSION = "1.3";
5387
+ var ChunksetCommitmentSchema = z3.object({
5388
+ // Chunkset root (vector commitment of child chunks)
5389
+ chunkset_root: z3.string(),
5390
+ // the size is known statically from the current configuration
5391
+ chunk_commitments: z3.array(z3.string())
5392
+ }).refine(
5393
+ (data) => {
5394
+ return data.chunk_commitments.length === DEFAULT_ERASURE_K + DEFAULT_ERASURE_M;
5395
+ },
5396
+ {
5397
+ message: `Chunkset must have exactly ${DEFAULT_ERASURE_K + DEFAULT_ERASURE_M} chunks (ERASURE_K + ERASURE_M = ${DEFAULT_ERASURE_K} + ${DEFAULT_ERASURE_M})`,
5398
+ path: ["chunk_commitments"]
5279
5399
  }
5280
- /**
5281
- * Creates a transaction payload to register a blob on the blockchain.
5282
- * This is a static helper method for constructing the Move function call payload.
5283
- *
5284
- * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
5285
- * @param params.account - The account that will own the blob.
5286
- * @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
5287
- * @param params.blobSize - The size of the blob in bytes.
5288
- * @param params.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
5289
- * @param params.expirationMicros - The expiration time of the blob in microseconds.
5290
- * @param params.numChunksets - The total number of chunksets in the blob.
5291
- *
5292
- * @returns An Aptos transaction payload data object for the register_blob Move function.
5293
- *
5294
- * @see https://github.com/shelby/shelby/blob/e08e84742cf2b80ad8bb7227deb3013398076d53/move/shelby_contract/sources/global_metadata.move#L357
5295
- */
5296
- static createRegisterBlobPayload(params) {
5297
- const functionName = params.useSponsoredUsdVariant ? "register_blob_with_sponsor" : "register_blob";
5298
- return {
5299
- function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
5300
- functionArguments: [
5301
- params.blobName,
5302
- params.expirationMicros,
5303
- Hex3.fromHexString(params.blobMerkleRoot).toUint8Array(),
5304
- params.numChunksets,
5305
- params.blobSize,
5306
- // TODO
5307
- 0,
5308
- // payment tier
5309
- 0
5310
- // encoding
5311
- ]
5312
- };
5400
+ );
5401
+ function expectedTotalChunksets(rawSize, chunksetSize = DEFAULT_CHUNKSET_SIZE_BYTES) {
5402
+ if (chunksetSize <= 0) {
5403
+ throw new Error("chunksetSize must be positive");
5313
5404
  }
5314
- /**
5315
- * Creates a transaction payload to register multiple blobs on the blockchain.
5316
- * This is a static helper method for constructing the Move function call payload.
5317
- *
5318
- * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
5319
- * @param params.account - The account that will own the blobs.
5320
- * @param params.expirationMicros - The expiration time of the blobs in microseconds.
5321
- * @param params.blobs - The blobs to register.
5322
- * @param params.blobs.blobName - The name/path of the blob (e.g. "foo/bar.txt").
5323
- * @param params.blobs.blobSize - The size of the blob in bytes.
5324
- * @param params.blobs.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
5325
- * @param params.blobs.numChunksets - The total number of chunksets in the blob.
5326
- *
5327
- * @returns An Aptos transaction payload data object for the register_multiple_blobs Move function.
5328
- *
5329
- * @see https://github.com/shelby/shelby/blob/e08e84742cf2b80ad8bb7227deb3013398076d53/move/shelby_contract/sources/global_metadata.move#L357
5330
- */
5331
- static createBatchRegisterBlobsPayload(params) {
5332
- const functionName = params.useSponsoredUsdVariant ? "register_multiple_blobs_with_sponsor" : "register_multiple_blobs";
5333
- const blobNames = [];
5334
- const blobMerkleRoots = [];
5335
- const blobNumChunksets = [];
5336
- const blobSizes = [];
5337
- params.blobs.forEach((blob) => {
5338
- blobNames.push(blob.blobName);
5339
- blobMerkleRoots.push(
5340
- Hex3.fromHexString(blob.blobMerkleRoot).toUint8Array()
5405
+ if (rawSize === 0) return 1;
5406
+ return Math.ceil(rawSize / chunksetSize);
5407
+ }
5408
+ var BlobCommitmentsSchema = z3.object({
5409
+ schema_version: z3.string(),
5410
+ raw_data_size: z3.number(),
5411
+ // FIXME I am not sure about this being here, or if it should be somewhere else
5412
+ blob_merkle_root: z3.string(),
5413
+ chunkset_commitments: z3.array(ChunksetCommitmentSchema)
5414
+ }).refine(
5415
+ (data) => {
5416
+ return expectedTotalChunksets(data.raw_data_size) === data.chunkset_commitments.length;
5417
+ },
5418
+ {
5419
+ message: "Total chunkset count mismatches with raw data size",
5420
+ // FIXME put more details in here
5421
+ path: ["chunkset_commitments"]
5422
+ }
5423
+ );
5424
+ async function generateMerkleRoot(leafHashes) {
5425
+ if (!leafHashes.length) {
5426
+ throw new Error(
5427
+ "An empty array cannot be used to construct a Merkle tree."
5428
+ );
5429
+ }
5430
+ const zeroArray = new Uint8Array(leafHashes[0].toUint8Array().length);
5431
+ const zeroBytes = Hex3.fromHexInput(zeroArray);
5432
+ let currentLeaves = leafHashes;
5433
+ while (currentLeaves.length > 1) {
5434
+ if (currentLeaves.length % 2 !== 0) {
5435
+ currentLeaves.push(zeroBytes);
5436
+ }
5437
+ const nextLeaves = [];
5438
+ for (let i = 0; i < currentLeaves.length; i += 2) {
5439
+ nextLeaves.push(
5440
+ await concatHashes([
5441
+ currentLeaves[i].toUint8Array(),
5442
+ currentLeaves[i + 1].toUint8Array()
5443
+ ])
5341
5444
  );
5342
- blobNumChunksets.push(blob.numChunksets);
5343
- blobSizes.push(blob.blobSize);
5344
- });
5345
- return {
5346
- function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
5347
- functionArguments: [
5348
- blobNames,
5349
- params.expirationMicros,
5350
- blobMerkleRoots,
5351
- blobNumChunksets,
5352
- blobSizes,
5353
- // TODO
5354
- 0,
5355
- 0
5356
- ]
5357
- };
5445
+ }
5446
+ currentLeaves = nextLeaves;
5358
5447
  }
5359
- /**
5360
- * Creates a transaction payload to delete a blob on the blockchain.
5361
- * This is a static helper method for constructing the Move function call payload.
5362
- *
5363
- * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
5364
- * @param params.blobName - The blob name (e.g. "bar.txt", without the account address prefix).
5365
- *
5366
- * @returns An Aptos transaction payload data object for the delete_blob Move function.
5367
- *
5368
- * @see https://github.com/shelby/shelby/blob/64e9d7b4f0005e586faeb1e4085c79159234b6b6/move/shelby_contract/sources/global_metadata.move#L616
5369
- */
5370
- static createDeleteBlobPayload(params) {
5371
- return {
5372
- function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_blob`,
5373
- functionArguments: [params.blobName]
5374
- };
5448
+ return currentLeaves[0];
5449
+ }
5450
+ async function generateChunksetCommitments(shouldPad, chunksetIdx, chunksetData, expectedChunksetSize, provider, onChunk) {
5451
+ const { erasure_n } = provider.config;
5452
+ const chunksetPayload = shouldPad ? zeroPadBytes(chunksetData, expectedChunksetSize) : validatePrePaddedChunkset(
5453
+ chunksetData,
5454
+ expectedChunksetSize,
5455
+ chunksetIdx
5456
+ );
5457
+ const { chunks } = provider.encode(chunksetPayload);
5458
+ if (chunks.length !== erasure_n) {
5459
+ throw new Error(
5460
+ `Erasure provider produced ${chunks.length} chunks, expected ${erasure_n}.`
5461
+ );
5375
5462
  }
5376
- /**
5377
- * Creates a transaction payload to delete multiple blobs on the blockchain.
5378
- * This is a static helper method for constructing the Move function call payload.
5379
- *
5380
- * **Note:** This function requires the `delete_multiple_blobs` entry function
5381
- * which will be deployed to the smart contract on 2026-02-04. Using this
5382
- * function before that date will result in a transaction failure.
5383
- *
5384
- * This operation is atomic: if any blob deletion fails (e.g., blob not found),
5385
- * the entire transaction fails and no blobs are deleted.
5386
- *
5387
- * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
5388
- * @param params.blobNames - Array of blob name suffixes without the account address prefix
5389
- * (e.g. ["foo/bar.txt", "baz.txt"], NOT ["0x1/foo/bar.txt"]). The account address
5390
- * prefix is automatically derived from the transaction sender.
5391
- *
5392
- * @returns An Aptos transaction payload data object for the delete_multiple_blobs Move function.
5393
- *
5394
- * @see https://github.com/shelby/shelby/blob/main/move/shelby_contract/sources/blob_metadata.move
5395
- */
5396
- static createDeleteMultipleBlobsPayload(params) {
5397
- return {
5398
- function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_multiple_blobs`,
5399
- functionArguments: [params.blobNames]
5400
- };
5463
+ const chunkRoots = provider.getChunkMerkleRoots();
5464
+ let chunkIdx = 0;
5465
+ for (const chunkData of chunks) {
5466
+ if (onChunk !== void 0) {
5467
+ await onChunk(chunksetIdx, chunkIdx, chunkData);
5468
+ }
5469
+ chunkIdx += 1;
5401
5470
  }
5402
- static createChunksetAcknowledgementsPayload(params) {
5403
- const ackBitMask = params.storageProviderAcks.reduce(
5404
- (acc, ack) => acc | 1 << ack.slot,
5405
- 0
5471
+ const a = await generateMerkleRoot(
5472
+ chunkRoots.map((a2) => Hex3.fromHexInput(a2))
5473
+ );
5474
+ const entry = {
5475
+ chunkset_root: a.toString(),
5476
+ chunk_commitments: chunkRoots.map(
5477
+ (chunk) => Hex3.fromHexInput(chunk).toString()
5478
+ )
5479
+ };
5480
+ return { h: a, entry };
5481
+ }
5482
+ async function generateCommitments(provider, fullData, onChunk, options) {
5483
+ const expectedChunksetSize = provider.config.chunkSizeBytes * provider.config.erasure_k;
5484
+ const shouldPad = options?.pad ?? true;
5485
+ const chunksetCommitments = [];
5486
+ const chunksetCommitmentHashes = [];
5487
+ let rawDataSize = 0;
5488
+ const chunksetGen = readInChunks(fullData, expectedChunksetSize);
5489
+ for await (const [chunksetIdx, chunksetData] of chunksetGen) {
5490
+ rawDataSize += chunksetData.length;
5491
+ const { h, entry } = await generateChunksetCommitments(
5492
+ shouldPad,
5493
+ chunksetIdx,
5494
+ chunksetData,
5495
+ expectedChunksetSize,
5496
+ provider,
5497
+ onChunk
5406
5498
  );
5407
- return {
5408
- function: `${SHELBY_DEPLOYER}::blob_metadata::add_chunkset_acknowledgements`,
5409
- functionArguments: [
5410
- createBlobKey({
5411
- account: params.blobOwner,
5412
- blobName: params.blobName
5413
- }),
5414
- params.chunksetIdx,
5415
- params.creationMicros,
5416
- new U32(Number(ackBitMask)),
5417
- params.storageProviderAcks.map((ack) => ack.signature)
5418
- ]
5419
- };
5499
+ chunksetCommitments.push(entry);
5500
+ chunksetCommitmentHashes.push(h);
5420
5501
  }
5421
- };
5502
+ if (rawDataSize === 0) {
5503
+ const zeroChunkset = new Uint8Array(expectedChunksetSize);
5504
+ const { h, entry } = await generateChunksetCommitments(
5505
+ shouldPad,
5506
+ 0,
5507
+ zeroChunkset,
5508
+ expectedChunksetSize,
5509
+ provider,
5510
+ onChunk
5511
+ );
5512
+ chunksetCommitments.push(entry);
5513
+ chunksetCommitmentHashes.push(h);
5514
+ }
5515
+ return {
5516
+ schema_version: COMMITMENT_SCHEMA_VERSION,
5517
+ raw_data_size: rawDataSize,
5518
+ blob_merkle_root: (await generateMerkleRoot(chunksetCommitmentHashes)).toString(),
5519
+ chunkset_commitments: chunksetCommitments
5520
+ };
5521
+ }
5522
+ function validatePrePaddedChunkset(chunkset, expectedSize, chunksetIdx) {
5523
+ if (chunkset.byteLength !== expectedSize) {
5524
+ throw new Error(
5525
+ `Chunkset ${chunksetIdx} has size ${chunkset.byteLength} bytes but expected ${expectedSize} bytes. Enable padding or supply pre-padded data before calling generateCommitments.`
5526
+ );
5527
+ }
5528
+ return chunkset;
5529
+ }
5422
5530
 
5423
- // ../../packages/sdk/dist/chunk-UCDAABAS.mjs
5531
+ // ../../packages/sdk/dist/chunk-IBAUPQOF.mjs
5424
5532
  import {
5425
- createDecoder,
5426
- createEncoder
5427
- } from "@shelby-protocol/clay-codes";
5428
- function getTotalChunks(config) {
5429
- return config.erasure_n;
5430
- }
5431
- var ClayErasureCodingProvider = class _ClayErasureCodingProvider {
5432
- config;
5433
- encoderCache;
5434
- decoderCache;
5435
- lastFunction;
5436
- constructor(config) {
5437
- this.config = config;
5438
- this.lastFunction = "none";
5533
+ AccountAddress as AccountAddress3,
5534
+ Aptos,
5535
+ Hex as Hex4,
5536
+ U32
5537
+ } from "@aptos-labs/ts-sdk";
5538
+ var MissingTransactionSubmitterError = class extends Error {
5539
+ constructor() {
5540
+ super(
5541
+ "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."
5542
+ );
5543
+ this.name = "MissingTransactionSubmitterError";
5439
5544
  }
5545
+ };
5546
+ var ShelbyBlobClient = class _ShelbyBlobClient {
5547
+ aptos;
5548
+ deployer;
5549
+ indexer;
5550
+ defaultOptions;
5440
5551
  /**
5441
- * Static factory method to create an initialized ClayErasureCodingProvider
5552
+ * The ShelbyBlobClient is used to interact with the Shelby contract on the Aptos blockchain. This
5553
+ * includes functions for registering blob commitments and retrieving blob metadata.
5554
+ *
5555
+ * @param config - The client configuration object.
5556
+ * @param config.network - The Shelby network to use.
5557
+ * @param defaultOptions - Optional default options for blob operations.
5558
+ *
5559
+ * @example
5560
+ * ```typescript
5561
+ * const blobClient = new ShelbyBlobClient({
5562
+ * aptos: {
5563
+ * network: Network.SHELBYNET,
5564
+ * clientConfig: {
5565
+ * API_KEY: "AG-***",
5566
+ * },
5567
+ * },
5568
+ * });
5569
+ * ```
5570
+ *
5571
+ * @example
5572
+ * ```typescript
5573
+ * // With default options for USD sponsorship
5574
+ * const blobClient = new ShelbyBlobClient(
5575
+ * {
5576
+ * network: Network.SHELBYNET,
5577
+ * aptos: {
5578
+ * pluginSettings: {
5579
+ * TRANSACTION_SUBMITTER: myGasStationSubmitter,
5580
+ * },
5581
+ * },
5582
+ * },
5583
+ * {
5584
+ * usdSponsor: { feePayerAddress: sponsorAddress },
5585
+ * }
5586
+ * );
5587
+ * ```
5442
5588
  */
5443
- static async create(options) {
5444
- const config = buildClayConfig({
5445
- erasure_n: options?.erasure_n ?? DEFAULT_ERASURE_N,
5446
- erasure_k: options?.erasure_k ?? DEFAULT_ERASURE_K,
5447
- erasure_d: options?.erasure_d ?? DEFAULT_ERASURE_D,
5448
- chunkSizeBytes: options?.chunkSizeBytes ?? DEFAULT_CHUNK_SIZE_BYTES
5449
- });
5450
- const provider = new _ClayErasureCodingProvider(config);
5451
- [provider.encoderCache, provider.decoderCache] = await Promise.all([
5452
- createEncoder({
5453
- n: getTotalChunks(config),
5454
- k: config.erasure_k,
5455
- d: config.erasure_d,
5456
- chunkSizeBytes: config.chunkSizeBytes
5457
- }),
5458
- createDecoder({
5459
- n: getTotalChunks(config),
5460
- k: config.erasure_k,
5461
- d: config.erasure_d,
5462
- chunkSizeBytes: config.chunkSizeBytes,
5463
- erasedChunksMask: 0
5464
- // No chunks erased initially; will be reconfigured on decode
5465
- })
5466
- ]);
5467
- return provider;
5468
- }
5469
- encode(data) {
5470
- const { erasure_k, chunkSizeBytes } = this.config;
5471
- if (!this.encoderCache) {
5472
- throw new Error("Encoder cache is missing");
5473
- }
5474
- const systematicCapacity = erasure_k * chunkSizeBytes;
5475
- if (data.byteLength > systematicCapacity) {
5476
- throw new Error(
5477
- `Data size ${data.byteLength} bytes exceeds systematic capacity ${systematicCapacity} bytes (erasure_k=${erasure_k} * chunkSizeBytes=${chunkSizeBytes}).`
5478
- );
5479
- }
5480
- if (this.requiresPadding(data.length)) {
5481
- throw new Error(
5482
- `Data size ${data.length} bytes does not match systematic capacity ${systematicCapacity} bytes (erasure_k=${erasure_k} * chunkSizeBytes=${chunkSizeBytes}). Provide pre-padded data before encoding.`
5483
- );
5484
- }
5485
- this.lastFunction = "encoded";
5486
- return this.encoderCache.erasureCode(data);
5589
+ constructor(config, defaultOptions) {
5590
+ this.aptos = new Aptos(getAptosConfig(config));
5591
+ this.deployer = config.deployer ?? AccountAddress3.fromString(SHELBY_DEPLOYER);
5592
+ this.indexer = getShelbyIndexerClient(config);
5593
+ this.defaultOptions = defaultOptions ?? {};
5487
5594
  }
5488
- decode(available, config) {
5489
- if (!this.decoderCache) {
5490
- throw new Error("Decoder cache is missing");
5595
+ /**
5596
+ * Merges method-level options with default options, giving precedence to method-level values.
5597
+ */
5598
+ mergeOptions(options) {
5599
+ return {
5600
+ build: options?.build ?? this.defaultOptions.build,
5601
+ submit: options?.submit ?? this.defaultOptions.submit,
5602
+ usdSponsor: options?.usdSponsor ?? this.defaultOptions.usdSponsor,
5603
+ chunksetSizeBytes: options?.chunksetSizeBytes ?? this.defaultOptions.chunksetSizeBytes
5604
+ };
5605
+ }
5606
+ /**
5607
+ * Validates that if USD sponsorship is requested, a transaction submitter is
5608
+ * configured as well. Checks both the client-level and method-level transaction
5609
+ * submitter configurations. Throws MissingTransactionSubmitterError if usdSponsor is
5610
+ * provided without a transaction submitter.
5611
+ */
5612
+ validateUsdSponsorConfig(usdSponsor, submit) {
5613
+ if (!usdSponsor) {
5614
+ return;
5491
5615
  }
5492
- const { erasure_k, chunkSizeBytes } = this.config;
5493
- if (available.length < erasure_k) {
5494
- throw new Error(
5495
- `Insufficient available chunks: need at least ${erasure_k}, received ${available.length}.`
5496
- );
5616
+ const hasClientSubmitter = this.aptos.config.getTransactionSubmitter();
5617
+ const hasMethodSubmitter = submit?.transactionSubmitter !== void 0 && submit?.transactionSubmitter !== null;
5618
+ if (!hasClientSubmitter && !hasMethodSubmitter) {
5619
+ throw new MissingTransactionSubmitterError();
5497
5620
  }
5498
- for (let i = 0; i < available.length; i++) {
5499
- const chunk = available[i];
5500
- if (chunk.length !== chunkSizeBytes) {
5621
+ }
5622
+ /**
5623
+ * Retrieves the blob metadata from the blockchain. If it does not exist,
5624
+ * returns `undefined`.
5625
+ *
5626
+ * @param params.account - The account namespace the blob is stored in (e.g. "0x1")
5627
+ * @param params.name - The name of the blob (e.g. "foo/bar")
5628
+ * @returns The blob metadata.
5629
+ *
5630
+ * @example
5631
+ * ```typescript
5632
+ * const metadata = await client.getBlobMetadata({
5633
+ * account: AccountAddress.fromString("0x1"),
5634
+ * name: "foo/bar.txt",
5635
+ * });
5636
+ * ```
5637
+ */
5638
+ async getBlobMetadata(params) {
5639
+ try {
5640
+ const rawMetadata = await this.aptos.view({
5641
+ payload: {
5642
+ function: `${this.deployer.toString()}::blob_metadata::get_blob_metadata`,
5643
+ functionArguments: [
5644
+ createBlobKey({
5645
+ account: params.account,
5646
+ blobName: params.name
5647
+ })
5648
+ ]
5649
+ }
5650
+ });
5651
+ if (!rawMetadata?.[0]?.vec?.[0]) {
5652
+ return void 0;
5653
+ }
5654
+ const metadata = rawMetadata[0].vec[0];
5655
+ let encoding;
5656
+ if (metadata.encoding.__variant__ === "ClayCode_16Total_10Data_13Helper") {
5657
+ console.log("read blob metadata with ClayCode_16Total_10Data_13Helper");
5658
+ encoding = {
5659
+ variant: "clay",
5660
+ ...ERASURE_CODE_PARAMS[metadata.encoding.__variant__],
5661
+ ...ERASURE_CODE_AND_CHUNK_MAPPING[metadata.encoding.__variant__]
5662
+ };
5663
+ } else if (metadata.encoding.__variant__ === "ClayCode_4Total_2Data_3Helper") {
5664
+ console.log("read blob metadata with ClayCode_4Total_2Data_3Helper");
5665
+ encoding = {
5666
+ variant: "clay",
5667
+ ...ERASURE_CODE_PARAMS[metadata.encoding.__variant__],
5668
+ ...ERASURE_CODE_AND_CHUNK_MAPPING[metadata.encoding.__variant__]
5669
+ };
5670
+ } else {
5501
5671
  throw new Error(
5502
- `Chunk ${i} size ${chunk.length} bytes does not match expected chunkSizeBytes ${chunkSizeBytes}.`
5672
+ "Could not parse encoding from Shelby Smart Contract, this SDK is out of date."
5503
5673
  );
5504
5674
  }
5675
+ return {
5676
+ blobMerkleRoot: Hex4.fromHexInput(
5677
+ metadata.blob_commitment
5678
+ ).toUint8Array(),
5679
+ owner: normalizeAddress(metadata.owner),
5680
+ name: params.name,
5681
+ blobNameSuffix: getBlobNameSuffix(params.name),
5682
+ size: Number(metadata.blob_size),
5683
+ encoding,
5684
+ expirationMicros: Number(metadata.expiration_micros),
5685
+ creationMicros: Number(metadata.creation_micros),
5686
+ sliceAddress: normalizeAddress(metadata.slice.inner),
5687
+ isWritten: metadata.is_written
5688
+ };
5689
+ } catch (error) {
5690
+ if (error instanceof Error && // Depending on the network, the error message may show up differently.
5691
+ (error.message?.includes("sub_status: Some(404)") || error.message?.includes("EBLOB_NOT_FOUND"))) {
5692
+ return void 0;
5693
+ }
5694
+ throw error;
5505
5695
  }
5506
- this.lastFunction = "decoded";
5507
- return this.decoderCache.decode(available, config);
5508
- }
5509
- getChunkMerkleRoots() {
5510
- if (this.decoderCache && this.lastFunction === "decoded")
5511
- return this.decoderCache.getChunkMerkleRoots();
5512
- if (this.encoderCache && this.lastFunction === "encoded")
5513
- return this.encoderCache.getChunkMerkleRoots();
5514
- throw new Error(
5515
- "You must call encode or decode before calling getChunkMerkleRoots"
5516
- );
5517
5696
  }
5518
5697
  /**
5519
- * Determines if data can be erasure coded as-is or requires padding.
5698
+ * Retrieves all the blobs and their metadata for an account from the
5699
+ * blockchain.
5520
5700
  *
5521
- * Data can be erasure coded without padding if its size exactly matches
5522
- * the total systematic data capacity (k * chunkSizeBytes).
5701
+ * @param params.account - The account namespace the blobs are stored in (e.g. "0x1")
5702
+ * @param params.pagination (optional) - The pagination options.
5703
+ * @param params.orderBy (optional) - The order by clause to sort the blobs by.
5704
+ * @returns The blob metadata for all the blobs for the account.
5523
5705
  *
5524
- * @param dataSize - Size of the data in bytes
5525
- * @returns true if data needs padding, false if it can be coded as-is
5706
+ * @example
5707
+ * ```typescript
5708
+ * // BlobMetadata[]
5709
+ * const blobs = await client.getAccountBlobs({
5710
+ * account: AccountAddress.fromString("0x1"),
5711
+ * });
5712
+ * ```
5526
5713
  */
5527
- requiresPadding(dataSize) {
5528
- const { erasure_k, chunkSizeBytes } = this.config;
5529
- const systematicCapacity = erasure_k * chunkSizeBytes;
5530
- return dataSize !== systematicCapacity;
5714
+ getAccountBlobs(params) {
5715
+ const { where, ...rest } = params;
5716
+ return this.getBlobs({
5717
+ where: {
5718
+ ...where,
5719
+ owner: { _eq: normalizeAddress(params.account).toString() }
5720
+ },
5721
+ pagination: rest.pagination,
5722
+ orderBy: rest.orderBy
5723
+ });
5531
5724
  }
5532
- };
5533
- function buildClayConfig(input) {
5534
- const { erasure_n, erasure_k, erasure_d, chunkSizeBytes } = input;
5535
- if (erasure_n <= 0)
5536
- throw new Error("erasure_n (total number of chunks) must be > 0");
5537
- if (erasure_k <= 0)
5538
- throw new Error("erasure_k (number of data chunks) must be > 0");
5539
- if (erasure_k >= erasure_n)
5540
- throw new Error(
5541
- `erasure_k (${erasure_k}) must be < erasure_n (${erasure_n})`
5542
- );
5543
- if (erasure_d <= erasure_k)
5544
- throw new Error(
5545
- `erasure_d (${erasure_d}) must be > erasure_k (${erasure_k})`
5546
- );
5547
- if (erasure_d >= erasure_n)
5548
- throw new Error(
5549
- `erasure_d (${erasure_d}) must be < erasure_n (${erasure_n})`
5550
- );
5551
- if (chunkSizeBytes <= 0) throw new Error("chunkSizeBytes must be > 0");
5552
- return {
5553
- erasure_n,
5554
- erasure_k,
5555
- erasure_d,
5556
- chunkSizeBytes
5557
- };
5558
- }
5559
-
5560
- // ../../packages/sdk/dist/chunk-4MG4XGY4.mjs
5561
- import {
5562
- AccountAuthenticator,
5563
- Deserializer,
5564
- Hex as Hex4,
5565
- MultiAgentTransaction,
5566
- Serializer
5567
- } from "@aptos-labs/ts-sdk";
5568
- var StaleChannelStateError = class _StaleChannelStateError extends Error {
5569
5725
  /**
5570
- * The last valid micropayment stored by the server.
5571
- * Clients can use this to reset their local channel state.
5726
+ * Retrieves blobs and their metadata from the blockchain.
5727
+ *
5728
+ * @param params.where (optional) - The where clause to filter the blobs by.
5729
+ * @param params.pagination (optional) - The pagination options.
5730
+ * @param params.orderBy (optional) - The order by clause to sort the blobs by.
5731
+ * @returns The blob metadata for all the blobs that match the where clause.
5732
+ *
5733
+ * @example
5734
+ * ```typescript
5735
+ * // BlobMetadata[]
5736
+ * const blobs = await client.getBlobs({
5737
+ * where: { owner: { _eq: AccountAddress.fromString("0x1").toString() } },
5738
+ * });
5739
+ * ```
5572
5740
  */
5573
- storedMicropayment;
5574
- constructor(storedMicropayment, message) {
5575
- super(
5576
- message ?? "Client has stale channel state. Use the returned micropayment to reset local state."
5741
+ async getBlobs(params = {}) {
5742
+ const { limit, offset } = params.pagination ?? {};
5743
+ const { orderBy, where } = params;
5744
+ const currentMicros = String(Date.now() * 1e3);
5745
+ const defaultActiveFilter = {
5746
+ expires_at: { _gte: currentMicros },
5747
+ is_deleted: { _eq: "0" }
5748
+ };
5749
+ const finalWhere = where !== void 0 ? { ...defaultActiveFilter, ...where } : defaultActiveFilter;
5750
+ const { blobs } = await this.indexer.getBlobs({
5751
+ where: finalWhere,
5752
+ limit,
5753
+ offset,
5754
+ orderBy
5755
+ });
5756
+ return blobs.map(
5757
+ (blob) => ({
5758
+ owner: normalizeAddress(blob.owner),
5759
+ name: blob.blob_name,
5760
+ blobNameSuffix: getBlobNameSuffix(blob.blob_name),
5761
+ blobMerkleRoot: Hex4.fromHexInput(blob.blob_commitment).toUint8Array(),
5762
+ size: Number(blob.size),
5763
+ // TODO: Add encoding when supported in NCI
5764
+ encoding: {
5765
+ variant: "clay",
5766
+ ...ERASURE_CODE_PARAMS.ClayCode_16Total_10Data_13Helper,
5767
+ ...ERASURE_CODE_AND_CHUNK_MAPPING.ClayCode_16Total_10Data_13Helper
5768
+ },
5769
+ expirationMicros: Number(blob.expires_at),
5770
+ creationMicros: Number(blob.created_at),
5771
+ sliceAddress: normalizeAddress(blob.slice_address),
5772
+ isWritten: Boolean(Number(blob.is_written)),
5773
+ isDeleted: Boolean(Number(blob.is_deleted))
5774
+ })
5577
5775
  );
5578
- this.name = "StaleChannelStateError";
5579
- this.storedMicropayment = storedMicropayment;
5776
+ }
5777
+ async getBlobActivities(params) {
5778
+ const { limit, offset } = params.pagination ?? {};
5779
+ const { orderBy, where } = params;
5780
+ const { blob_activities } = await this.indexer.getBlobActivities({
5781
+ where,
5782
+ limit,
5783
+ offset,
5784
+ orderBy
5785
+ });
5786
+ const activityTypeMapping = {
5787
+ [`${this.deployer.toStringLong()}::blob_metadata::BlobRegisteredEvent`]: "register_blob",
5788
+ [`${this.deployer.toStringLong()}::blob_metadata::BlobDeletedEvent`]: "delete_blob",
5789
+ [`${this.deployer.toStringLong()}::blob_metadata::BlobExpirationExtendedEvent`]: "extend_blob_expiration",
5790
+ [`${this.deployer.toStringLong()}::blob_metadata::BlobWrittenEvent`]: "write_blob"
5791
+ };
5792
+ return blob_activities.map(
5793
+ (activity) => ({
5794
+ blobName: activity.blob_name,
5795
+ accountAddress: normalizeAddress(activity.blob_name.substring(1, 65)),
5796
+ type: activityTypeMapping[activity.event_type] ?? "unknown",
5797
+ eventType: activity.event_type,
5798
+ eventIndex: Number(activity.event_index),
5799
+ transactionHash: activity.transaction_hash,
5800
+ // Using Number here in JS is technically not okay because txn version can be
5801
+ // as large as u64::MAX, but it should be fine for a long while.
5802
+ transactionVersion: Number(activity.transaction_version),
5803
+ timestamp: `${activity.timestamp}Z`
5804
+ })
5805
+ );
5806
+ }
5807
+ /**
5808
+ * Retrieves the total number of blobs from the blockchain.
5809
+ *
5810
+ * @param params.where (optional) - The where clause to filter the blobs by.
5811
+ * @returns The total number of blobs.
5812
+ *
5813
+ * @example
5814
+ * ```typescript
5815
+ * const count = await client.getBlobsCount();
5816
+ * ```
5817
+ */
5818
+ async getBlobsCount(params) {
5819
+ const { where } = params;
5820
+ const { blobs_aggregate } = await this.indexer.getBlobsCount({ where });
5821
+ return blobs_aggregate?.aggregate?.count ?? 0;
5580
5822
  }
5581
5823
  /**
5582
- * Returns the stored micropayment as a base64-encoded string.
5824
+ * Retrieves the total number of blob activities from the blockchain.
5825
+ *
5826
+ * @param params.where (optional) - The where clause to filter the blob activities by.
5827
+ * @returns The total number of blob activities.
5828
+ *
5829
+ * @example
5830
+ * ```typescript
5831
+ * const count = await client.getBlobActivitiesCount();
5832
+ * ```
5583
5833
  */
5584
- toBase64() {
5585
- const bytes = this.storedMicropayment.bcsToBytes();
5586
- const binaryString = Array.from(
5587
- bytes,
5588
- (byte) => String.fromCharCode(byte)
5589
- ).join("");
5590
- return btoa(binaryString);
5834
+ async getBlobActivitiesCount(params) {
5835
+ const { where } = params;
5836
+ const { blob_activities_aggregate } = await this.indexer.getBlobActivitiesCount({ where });
5837
+ return blob_activities_aggregate?.aggregate?.count ?? 0;
5591
5838
  }
5592
5839
  /**
5593
- * Creates a StaleChannelStateError from a base64-encoded micropayment string.
5840
+ * Registers a blob on the blockchain by writing its merkle root and metadata.
5841
+ *
5842
+ * @param params.account - The account that is signing and paying for the transaction.
5843
+ * @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
5844
+ * @param params.blobMerkleRoot - The merkle root of the blob commitments.
5845
+ * @param params.size - The size of the blob in bytes.
5846
+ * @param params.expirationMicros - The expiration time of the blob in microseconds.
5847
+ * @param params.options - Optional transaction building options.
5848
+ * @param params.options.chunksetSizeBytes - Custom chunkset size (defaults to DEFAULT_CHUNKSET_SIZE_BYTES).
5849
+ * @param params.options.build - Additional Aptos transaction building options.
5850
+ *
5851
+ * @returns An object containing the pending transaction.
5852
+ *
5853
+ * @example
5854
+ * ```typescript
5855
+ * const provider = await ClayErasureCodingProvider.create();
5856
+ * const blobCommitments = await generateCommitments(provider, data);
5857
+ *
5858
+ * const { transaction } = await client.registerBlob({
5859
+ * account: signer,
5860
+ * blobName: "foo/bar.txt",
5861
+ * blobMerkleRoot: blobCommitments.blob_merkle_root,
5862
+ * size: data.length,
5863
+ * expirationMicros: Date.now() * 1000 + 3600_000_000, // 1 hour from now in microseconds
5864
+ * });
5865
+ * ```
5594
5866
  */
5595
- static fromBase64(base64, message) {
5596
- const binaryString = atob(base64);
5597
- const bytes = Uint8Array.from(binaryString, (char) => char.charCodeAt(0));
5598
- const micropayment = SenderBuiltMicropayment.deserialize(bytes);
5599
- return new _StaleChannelStateError(micropayment, message);
5867
+ async registerBlob(params) {
5868
+ const options = this.mergeOptions(params.options);
5869
+ this.validateUsdSponsorConfig(options.usdSponsor, options.submit);
5870
+ const config = params.config ?? defaultErasureCodingConfig();
5871
+ const chunksetSize = config.chunkSizeBytes * config.erasure_k;
5872
+ const buildArgs = {
5873
+ ...options.build,
5874
+ data: _ShelbyBlobClient.createRegisterBlobPayload({
5875
+ deployer: this.deployer,
5876
+ account: params.account.accountAddress,
5877
+ blobName: params.blobName,
5878
+ blobSize: params.size,
5879
+ blobMerkleRoot: params.blobMerkleRoot,
5880
+ numChunksets: expectedTotalChunksets(params.size, chunksetSize),
5881
+ expirationMicros: params.expirationMicros,
5882
+ useSponsoredUsdVariant: options.usdSponsor !== void 0,
5883
+ encoding: config.enumIndex
5884
+ }),
5885
+ sender: params.account.accountAddress
5886
+ };
5887
+ const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
5888
+ ...buildArgs,
5889
+ secondarySignerAddresses: [options.usdSponsor.feePayerAddress]
5890
+ }) : await this.aptos.transaction.build.simple(buildArgs);
5891
+ return {
5892
+ transaction: await this.aptos.signAndSubmitTransaction({
5893
+ signer: params.account,
5894
+ transaction,
5895
+ ...options.submit
5896
+ })
5897
+ };
5600
5898
  }
5601
- };
5602
- var SenderBuiltMicropayment = class _SenderBuiltMicropayment {
5603
5899
  /**
5604
- * The actual micropayment transaction. It is built with the receiver address as fee payer and also requires a signature from the receiver to submit.
5900
+ * Deletes a blob on the blockchain.
5901
+ *
5902
+ * @param params.account - The account that is signing and paying for the transaction.
5903
+ * @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
5904
+ * @param params.options - Optional transaction building options.
5905
+ *
5906
+ * @returns An object containing the pending transaction.
5907
+ *
5908
+ * @example
5909
+ * ```typescript
5910
+ *
5911
+ * const { transaction } = await client.deleteBlob({
5912
+ * account: signer,
5913
+ * blobName: "foo/bar.txt",
5914
+ * });
5915
+ * ```
5605
5916
  */
5606
- micropayment;
5917
+ async deleteBlob(params) {
5918
+ const transaction = await this.aptos.transaction.build.simple({
5919
+ ...params.options,
5920
+ data: _ShelbyBlobClient.createDeleteBlobPayload({
5921
+ deployer: this.deployer,
5922
+ blobName: params.blobName
5923
+ }),
5924
+ sender: params.account.accountAddress
5925
+ });
5926
+ return {
5927
+ transaction: await this.aptos.signAndSubmitTransaction({
5928
+ signer: params.account,
5929
+ transaction
5930
+ })
5931
+ };
5932
+ }
5607
5933
  /**
5608
- * The sender's signature.
5934
+ * Deletes multiple blobs on the blockchain in a single atomic transaction.
5935
+ *
5936
+ * **Note:** This function requires the `delete_multiple_blobs` entry function
5937
+ * which will be deployed to the smart contract on 2026-02-04. Using this
5938
+ * function before that date will result in a transaction failure.
5939
+ *
5940
+ * This operation is atomic: if any blob deletion fails (e.g., blob not found),
5941
+ * the entire transaction fails and no blobs are deleted.
5942
+ *
5943
+ * @param params.account - The account that is signing and paying for the transaction.
5944
+ * @param params.blobNames - Array of blob name suffixes without the account address prefix
5945
+ * (e.g. ["foo/bar.txt", "baz.txt"], NOT ["0x1/foo/bar.txt"]). The account address
5946
+ * prefix is automatically derived from the signer.
5947
+ * @param params.options - Optional transaction building options.
5948
+ *
5949
+ * @returns An object containing the pending transaction.
5950
+ *
5951
+ * @example
5952
+ * ```typescript
5953
+ *
5954
+ * const { transaction } = await client.deleteMultipleBlobs({
5955
+ * account: signer,
5956
+ * blobNames: ["foo/bar.txt", "baz.txt"],
5957
+ * });
5958
+ * ```
5609
5959
  */
5610
- senderSignature;
5611
- constructor(micropayment, senderSignature) {
5612
- this.micropayment = micropayment;
5613
- this.senderSignature = senderSignature;
5614
- }
5615
- serialize(serializer) {
5616
- this.micropayment.serialize(serializer);
5617
- this.senderSignature.serialize(serializer);
5618
- }
5619
- bcsToBytes() {
5620
- const serializer = new Serializer();
5621
- this.serialize(serializer);
5622
- return serializer.toUint8Array();
5623
- }
5624
- bcsToHex() {
5625
- return Hex4.fromHexInput(this.bcsToBytes());
5626
- }
5627
- toStringWithoutPrefix() {
5628
- return this.bcsToHex().toStringWithoutPrefix();
5629
- }
5630
- toString() {
5631
- return this.bcsToHex().toString();
5960
+ async deleteMultipleBlobs(params) {
5961
+ const transaction = await this.aptos.transaction.build.simple({
5962
+ ...params.options,
5963
+ data: _ShelbyBlobClient.createDeleteMultipleBlobsPayload({
5964
+ deployer: this.deployer,
5965
+ blobNames: params.blobNames
5966
+ }),
5967
+ sender: params.account.accountAddress
5968
+ });
5969
+ return {
5970
+ transaction: await this.aptos.signAndSubmitTransaction({
5971
+ signer: params.account,
5972
+ transaction
5973
+ })
5974
+ };
5632
5975
  }
5633
5976
  /**
5634
- * Deserializes a SenderBuiltMicropayment from BCS bytes.
5635
- * @param bytes - The bytes to deserialize from (Uint8Array or hex string).
5636
- * @returns A new SenderBuiltMicropayment instance.
5977
+ * Acks the blob chunksets on-chain. If each chunkset meets the necessary threshold, the entire blob will be marked as written.
5978
+ *
5979
+ * @param params.account - The account that is signing the transaction.
5980
+ * @param params.blobOwner - The account that owns the blob.
5981
+ * @param params.blobName - The name of the blob (e.g. "foo/bar")
5982
+ * @param params.creationMicros - The creation time of the blob in microseconds.
5983
+ * @param params.chunksetIdx - The index of the chunkset being acknowledged.
5984
+ * @param params.storageProviderChunksetAcks - The signatures
5985
+ * @param params.options - Additional options for transaction building and encoding.
5986
+ *
5987
+ * @returns The blob commitments and the pending transaction.
5988
+ *
5989
+ * @example
5990
+ * ```typescript
5991
+ * const { transaction } = await client.addChunksetAcknowledgements({
5992
+ * account: signer,
5993
+ * blobOwner: owner,
5994
+ * blobName: "foo/bar.txt",
5995
+ * creationMicros, // Taken from the blob metadata at registration time.
5996
+ * chunksetIdx,
5997
+ * storageProviderAcks: An array of StorageProviderAck types, each having the slot index and signature from the SP.
5998
+ * });
5999
+ * ```
5637
6000
  */
5638
- static deserialize(bytes) {
5639
- const bytesArray = typeof bytes === "string" ? Hex4.fromHexInput(bytes).toUint8Array() : bytes;
5640
- const deserializer = new Deserializer(bytesArray);
5641
- const micropayment = MultiAgentTransaction.deserialize(deserializer);
5642
- const senderSignature = AccountAuthenticator.deserialize(deserializer);
5643
- return new _SenderBuiltMicropayment(micropayment, senderSignature);
5644
- }
5645
- };
5646
-
5647
- // ../../packages/sdk/dist/chunk-W5NRGZEP.mjs
5648
- import { AccountAddress as AccountAddress3 } from "@aptos-labs/ts-sdk";
5649
- import { z as z2 } from "zod";
5650
- var BlobNameSchema = z2.string().min(1, "Blob name path parameter cannot be empty.").max(1024, "Blob name cannot exceed 1024 characters.").refine((name2) => !name2.endsWith("/"), {
5651
- message: "Blob name cannot end with a slash"
5652
- });
5653
-
5654
- // ../../packages/sdk/dist/chunk-I6NG5GNL.mjs
5655
- function sleep(ms) {
5656
- return new Promise((resolve3) => setTimeout(resolve3, ms));
5657
- }
5658
-
5659
- // ../../packages/sdk/dist/chunk-IE6LYVIA.mjs
5660
- import { z as z3 } from "zod";
5661
- var StartMultipartUploadResponseSchema = z3.object({
5662
- uploadId: z3.string()
5663
- });
5664
- var UploadPartResponseSchema = z3.object({
5665
- success: z3.literal(true)
5666
- });
5667
- var CompleteMultipartUploadResponseSchema = z3.object({
5668
- success: z3.literal(true)
5669
- });
5670
- var RPCErrorResponseSchema = z3.object({
5671
- error: z3.string()
5672
- });
5673
- var StaleMicropaymentErrorResponseSchema = z3.object({
5674
- error: z3.string().optional(),
5675
- storedMicropayment: z3.string().optional()
5676
- });
5677
-
5678
- // ../../packages/sdk/dist/chunk-ZAM2EUVN.mjs
5679
- import { AccountAddress as AccountAddress4 } from "@aptos-labs/ts-sdk";
5680
- var MICROPAYMENT_HEADER = "X-Shelby-Micropayment";
5681
- function encodeURIComponentKeepSlashes(str) {
5682
- return encodeURIComponent(str).replace(/%2F/g, "/");
5683
- }
5684
- function validateTotalBytes(totalBytes) {
5685
- if (!Number.isInteger(totalBytes) || totalBytes < 0) {
5686
- throw new Error("totalBytes must be a non-negative integer");
5687
- }
5688
- }
5689
- function getErrorCode(error) {
5690
- if (typeof error === "object" && error !== null && "code" in error && typeof error.code === "string") {
5691
- return error.code;
5692
- }
5693
- if (error instanceof Error) {
5694
- const match = error.message.match(/\bE[A-Z0-9_]+\b/);
5695
- return match?.[0];
6001
+ async addChunksetAcknowledgements(params) {
6002
+ const transaction = await this.aptos.transaction.build.simple({
6003
+ ...params.options?.build,
6004
+ data: _ShelbyBlobClient.createChunksetAcknowledgementsPayload({
6005
+ blobOwner: params.blobOwner,
6006
+ blobName: params.blobName,
6007
+ creationMicros: params.creationMicros,
6008
+ chunksetIdx: params.chunksetIdx,
6009
+ storageProviderAcks: params.storageProviderAcks
6010
+ }),
6011
+ sender: params.account.accountAddress
6012
+ });
6013
+ return {
6014
+ transaction: await this.aptos.signAndSubmitTransaction({
6015
+ signer: params.account,
6016
+ transaction
6017
+ })
6018
+ };
5696
6019
  }
5697
- return void 0;
5698
- }
5699
- var ShelbyRPCClient = class {
5700
- baseUrl;
5701
- apiKey;
5702
- rpcConfig;
5703
- indexer;
5704
6020
  /**
5705
- * Creates a new ShelbyRPCClient for interacting with Shelby RPC nodes.
5706
- * This client handles blob storage operations including upload and download.
6021
+ * Registers multiple blobs on the blockchain by writing their merkle roots and metadata.
5707
6022
  *
5708
- * @param config - The client configuration object.
5709
- * @param config.network - The Shelby network to use.
6023
+ * @param params.account - The account that is signing and paying for the transaction.
6024
+ * @param params.expirationMicros - The expiration time of the blobs in microseconds.
6025
+ * @param params.blobs - The blobs to register.
6026
+ * @param params.blobs.blobName - The name/path of the blob (e.g. "foo/bar.txt").
6027
+ * @param params.blobs.blobSize - The size of the blob in bytes.
6028
+ * @param params.blobs.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
6029
+ * @param params.options - Optional transaction building options.
6030
+ * @param params.options.chunksetSizeBytes - Custom chunkset size (defaults to DEFAULT_CHUNKSET_SIZE_BYTES).
6031
+ * @param params.options.build - Additional Aptos transaction building options.
6032
+ *
6033
+ * @returns An object containing the pending transaction.
5710
6034
  *
5711
6035
  * @example
5712
6036
  * ```typescript
5713
- * const client = new ShelbyRPCClient({
5714
- * network: Network.SHELBYNET,
5715
- * apiKey: "AG-***",
6037
+ * const provider = await ClayErasureCodingProvider.create();
6038
+ * const blobCommitments = await generateCommitments(provider, data);
6039
+ *
6040
+ * const { transaction } = await client.batchRegisterBlobs({
6041
+ * account: signer,
6042
+ * expirationMicros: Date.now() * 1000 + 3600_000_000, // 1 hour from now in microseconds
6043
+ * blobs: [
6044
+ * {
6045
+ * blobName: "foo/bar.txt",
6046
+ * blobSize: data.length,
6047
+ * blobMerkleRoot: blobCommitments.blob_merkle_root,
6048
+ * },
6049
+ * ],
5716
6050
  * });
5717
6051
  * ```
5718
6052
  */
5719
- constructor(config) {
5720
- this.baseUrl = config.rpc?.baseUrl ?? NetworkToShelbyRPCBaseUrl.shelbynet;
5721
- this.apiKey = config.apiKey ?? config.rpc?.apiKey;
5722
- this.rpcConfig = config.rpc ?? {};
5723
- this.indexer = getShelbyIndexerClient(config);
6053
+ async batchRegisterBlobs(params) {
6054
+ const options = this.mergeOptions(params.options);
6055
+ this.validateUsdSponsorConfig(options.usdSponsor, options.submit);
6056
+ const config = params.config ?? defaultErasureCodingConfig();
6057
+ const chunksetSize = config.chunkSizeBytes * config.erasure_k;
6058
+ const buildArgs = {
6059
+ ...options.build,
6060
+ sender: params.account.accountAddress,
6061
+ data: _ShelbyBlobClient.createBatchRegisterBlobsPayload({
6062
+ deployer: this.deployer,
6063
+ account: params.account.accountAddress,
6064
+ expirationMicros: params.expirationMicros,
6065
+ blobs: params.blobs.map((blob) => ({
6066
+ blobName: blob.blobName,
6067
+ blobSize: blob.blobSize,
6068
+ blobMerkleRoot: blob.blobMerkleRoot,
6069
+ numChunksets: expectedTotalChunksets(blob.blobSize, chunksetSize)
6070
+ })),
6071
+ useSponsoredUsdVariant: options.usdSponsor !== void 0,
6072
+ encoding: config.enumIndex
6073
+ })
6074
+ };
6075
+ const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
6076
+ ...buildArgs,
6077
+ secondarySignerAddresses: [options.usdSponsor.feePayerAddress]
6078
+ }) : await this.aptos.transaction.build.simple(buildArgs);
6079
+ return {
6080
+ transaction: await this.aptos.signAndSubmitTransaction({
6081
+ signer: params.account,
6082
+ transaction,
6083
+ ...options.submit
6084
+ })
6085
+ };
5724
6086
  }
5725
- async #uploadPart(uploadId, partIdx, partData) {
5726
- const nRetries = 5;
5727
- let lastResponse;
5728
- let lastError;
5729
- const partUrl = buildRequestUrl(
5730
- `/v1/multipart-uploads/${uploadId}/parts/${partIdx}`,
5731
- this.baseUrl
5732
- );
5733
- for (let i = 0; i < nRetries; ++i) {
5734
- try {
5735
- lastResponse = await fetch(partUrl, {
5736
- method: "PUT",
5737
- headers: {
5738
- "Content-Type": "application/octet-stream",
5739
- ...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
5740
- },
5741
- body: partData
5742
- });
5743
- lastError = void 0;
5744
- } catch (error) {
5745
- lastError = error;
5746
- if (i < nRetries - 1) {
5747
- const delay = 2 ** i * 100;
5748
- await sleep(delay);
5749
- continue;
5750
- }
5751
- break;
5752
- }
5753
- if (lastResponse.ok) return;
5754
- if (i < nRetries - 1) {
5755
- const delay = 2 ** i * 100;
5756
- await sleep(delay);
5757
- }
5758
- }
5759
- if (lastError !== void 0) {
5760
- const errorCode = getErrorCode(lastError);
5761
- const errorMessage = lastError instanceof Error ? lastError.message : String(lastError);
5762
- throw new Error(
5763
- `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}`,
5764
- { cause: lastError }
5765
- );
5766
- }
5767
- const errorBody = await lastResponse?.text().catch(() => "");
5768
- throw new Error(
5769
- `Failed to upload part ${partIdx} for multipart upload ${uploadId} after ${nRetries} attempts. status: ${lastResponse?.status}, body: ${errorBody}`
5770
- );
6087
+ /**
6088
+ * Creates a transaction payload to register a blob on the blockchain.
6089
+ * This is a static helper method for constructing the Move function call payload.
6090
+ *
6091
+ * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
6092
+ * @param params.account - The account that will own the blob.
6093
+ * @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
6094
+ * @param params.blobSize - The size of the blob in bytes.
6095
+ * @param params.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
6096
+ * @param params.expirationMicros - The expiration time of the blob in microseconds.
6097
+ * @param params.numChunksets - The total number of chunksets in the blob.
6098
+ *
6099
+ * @returns An Aptos transaction payload data object for the register_blob Move function.
6100
+ *
6101
+ * @see https://github.com/shelby/shelby/blob/e08e84742cf2b80ad8bb7227deb3013398076d53/move/shelby_contract/sources/global_metadata.move#L357
6102
+ */
6103
+ static createRegisterBlobPayload(params) {
6104
+ const functionName = params.useSponsoredUsdVariant ? "register_blob_with_sponsor" : "register_blob";
6105
+ return {
6106
+ function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
6107
+ functionArguments: [
6108
+ params.blobName,
6109
+ params.expirationMicros,
6110
+ Hex4.fromHexString(params.blobMerkleRoot).toUint8Array(),
6111
+ params.numChunksets,
6112
+ params.blobSize,
6113
+ // TODO
6114
+ 0,
6115
+ // payment tier
6116
+ params.encoding
6117
+ ]
6118
+ };
5771
6119
  }
5772
- async #putBlobMultipart(account, blobName, blobData, totalBytes, partSize = 5 * 1024 * 1024, onProgress) {
5773
- validateTotalBytes(totalBytes);
5774
- const startResponse = await fetch(
5775
- buildRequestUrl("/v1/multipart-uploads", this.baseUrl),
5776
- {
5777
- method: "POST",
5778
- headers: {
5779
- "Content-Type": "application/json",
5780
- ...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
5781
- },
5782
- body: JSON.stringify({
5783
- rawAccount: account.toString(),
5784
- rawBlobName: blobName,
5785
- rawPartSize: partSize
5786
- })
5787
- }
5788
- );
5789
- if (!startResponse.ok) {
5790
- let errorBodyText = "Could not read error body";
5791
- try {
5792
- errorBodyText = await startResponse.text();
5793
- } catch (_e) {
5794
- }
5795
- throw new Error(
5796
- `Failed to start multipart upload! status: ${startResponse.status}, body: ${errorBodyText}`
5797
- );
5798
- }
5799
- const { uploadId } = StartMultipartUploadResponseSchema.parse(
5800
- await startResponse.json()
5801
- );
5802
- const totalParts = Math.ceil(totalBytes / partSize);
5803
- let uploadedBytes = 0;
5804
- for await (const [partIdx, partData] of readInChunks(blobData, partSize)) {
5805
- await this.#uploadPart(uploadId, partIdx, partData);
5806
- uploadedBytes += partData.length;
5807
- onProgress?.({
5808
- phase: "uploading",
5809
- partIdx,
5810
- totalParts,
5811
- partBytes: partData.length,
5812
- uploadedBytes,
5813
- totalBytes
5814
- });
5815
- }
5816
- if (uploadedBytes !== totalBytes) {
5817
- throw new Error(
5818
- `Uploaded bytes (${uploadedBytes}) did not match declared totalBytes (${totalBytes})`
5819
- );
5820
- }
5821
- const finalPartIdx = totalParts > 0 ? totalParts - 1 : 0;
5822
- onProgress?.({
5823
- phase: "finalizing",
5824
- partIdx: finalPartIdx,
5825
- totalParts,
5826
- // no part uploaded in this phase
5827
- partBytes: 0,
5828
- uploadedBytes: totalBytes,
5829
- totalBytes
5830
- });
5831
- const completeResponse = await fetch(
5832
- buildRequestUrl(
5833
- `/v1/multipart-uploads/${uploadId}/complete`,
5834
- this.baseUrl
5835
- ),
5836
- {
5837
- method: "POST",
5838
- headers: {
5839
- "Content-Type": "application/json",
5840
- ...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
5841
- }
5842
- }
5843
- );
5844
- if (!completeResponse.ok) {
5845
- let errorBodyText = "Could not read error body";
5846
- try {
5847
- errorBodyText = await completeResponse.text();
5848
- } catch (_e) {
5849
- }
5850
- throw new Error(
5851
- `Failed to complete multipart upload! status: ${completeResponse.status}, body: ${errorBodyText}`
6120
+ /**
6121
+ * Creates a transaction payload to register multiple blobs on the blockchain.
6122
+ * This is a static helper method for constructing the Move function call payload.
6123
+ *
6124
+ * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
6125
+ * @param params.account - The account that will own the blobs.
6126
+ * @param params.expirationMicros - The expiration time of the blobs in microseconds.
6127
+ * @param params.blobs - The blobs to register.
6128
+ * @param params.blobs.blobName - The name/path of the blob (e.g. "foo/bar.txt").
6129
+ * @param params.blobs.blobSize - The size of the blob in bytes.
6130
+ * @param params.blobs.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
6131
+ * @param params.blobs.numChunksets - The total number of chunksets in the blob.
6132
+ *
6133
+ * @returns An Aptos transaction payload data object for the register_multiple_blobs Move function.
6134
+ *
6135
+ * @see https://github.com/shelby/shelby/blob/e08e84742cf2b80ad8bb7227deb3013398076d53/move/shelby_contract/sources/global_metadata.move#L357
6136
+ */
6137
+ static createBatchRegisterBlobsPayload(params) {
6138
+ const functionName = params.useSponsoredUsdVariant ? "register_multiple_blobs_with_sponsor" : "register_multiple_blobs";
6139
+ const blobNames = [];
6140
+ const blobMerkleRoots = [];
6141
+ const blobNumChunksets = [];
6142
+ const blobSizes = [];
6143
+ params.blobs.forEach((blob) => {
6144
+ blobNames.push(blob.blobName);
6145
+ blobMerkleRoots.push(
6146
+ Hex4.fromHexString(blob.blobMerkleRoot).toUint8Array()
5852
6147
  );
5853
- }
6148
+ blobNumChunksets.push(blob.numChunksets);
6149
+ blobSizes.push(blob.blobSize);
6150
+ });
6151
+ return {
6152
+ function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
6153
+ functionArguments: [
6154
+ blobNames,
6155
+ params.expirationMicros,
6156
+ blobMerkleRoots,
6157
+ blobNumChunksets,
6158
+ blobSizes,
6159
+ // TODO
6160
+ 0,
6161
+ // payment tier
6162
+ params.encoding
6163
+ ]
6164
+ };
5854
6165
  }
5855
6166
  /**
5856
- * Uploads blob data to the Shelby RPC node for storage by storage providers.
5857
- * This method should be called after blob commitments have been registered on the blockchain.
5858
- * Uses multipart upload for efficient handling of large files.
6167
+ * Creates a transaction payload to delete a blob on the blockchain.
6168
+ * This is a static helper method for constructing the Move function call payload.
5859
6169
  *
5860
- * @param params.account - The account that owns the blob.
5861
- * @param params.blobName - The name/path of the blob (e.g. "folder/file.txt").
5862
- * @param params.blobData - The raw blob data as a Uint8Array or ReadableStream.
5863
- * @param params.totalBytes - Total byte length. Required for streams; optional for Uint8Array.
6170
+ * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
6171
+ * @param params.blobName - The blob name (e.g. "bar.txt", without the account address prefix).
5864
6172
  *
5865
- * @example
5866
- * ```typescript
5867
- * const blobData = new TextEncoder().encode("Hello, world!");
6173
+ * @returns An Aptos transaction payload data object for the delete_blob Move function.
5868
6174
  *
5869
- * await client.putBlob({
5870
- * account: AccountAddress.from("0x1"),
5871
- * blobName: "greetings/hello.txt",
5872
- * blobData,
5873
- * });
5874
- * ```
6175
+ * @see https://github.com/shelby/shelby/blob/64e9d7b4f0005e586faeb1e4085c79159234b6b6/move/shelby_contract/sources/global_metadata.move#L616
5875
6176
  */
5876
- async putBlob(params) {
5877
- BlobNameSchema.parse(params.blobName);
5878
- let totalBytes;
5879
- if (params.blobData instanceof Uint8Array) {
5880
- totalBytes = params.totalBytes ?? params.blobData.length;
5881
- if (totalBytes !== params.blobData.length) {
5882
- throw new Error(
5883
- "totalBytes must match blobData.length when blobData is a Uint8Array"
5884
- );
5885
- }
5886
- } else {
5887
- if (params.totalBytes === void 0) {
5888
- throw new Error(
5889
- "totalBytes is required when blobData is a ReadableStream"
5890
- );
5891
- }
5892
- totalBytes = params.totalBytes;
5893
- }
5894
- validateTotalBytes(totalBytes);
5895
- await this.#putBlobMultipart(
5896
- params.account,
5897
- params.blobName,
5898
- params.blobData,
5899
- totalBytes,
5900
- void 0,
5901
- params.onProgress
5902
- );
6177
+ static createDeleteBlobPayload(params) {
6178
+ return {
6179
+ function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_blob`,
6180
+ functionArguments: [params.blobName]
6181
+ };
5903
6182
  }
5904
6183
  /**
5905
- * Downloads a blob from the Shelby RPC node.
5906
- * Returns a streaming response with validation to ensure data integrity.
6184
+ * Creates a transaction payload to delete multiple blobs on the blockchain.
6185
+ * This is a static helper method for constructing the Move function call payload.
5907
6186
  *
5908
- * @param params.account - The account that owns the blob.
5909
- * @param params.blobName - The name/path of the blob (e.g. "folder/file.txt").
5910
- * @param params.range - Optional byte range for partial downloads.
5911
- * @param params.range.start - Starting byte position (inclusive).
5912
- * @param params.range.end - Ending byte position (inclusive, optional).
5913
- * @param params.micropayment - Optional micropayment to attach to the request.
6187
+ * **Note:** This function requires the `delete_multiple_blobs` entry function
6188
+ * which will be deployed to the smart contract on 2026-02-04. Using this
6189
+ * function before that date will result in a transaction failure.
5914
6190
  *
5915
- * @returns A ShelbyBlob object containing the account, name, readable stream, and content length.
6191
+ * This operation is atomic: if any blob deletion fails (e.g., blob not found),
6192
+ * the entire transaction fails and no blobs are deleted.
5916
6193
  *
5917
- * @throws Error if the download fails or content length doesn't match.
5918
- * @throws StaleChannelStateError if the micropayment is stale (server has newer state).
6194
+ * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
6195
+ * @param params.blobNames - Array of blob name suffixes without the account address prefix
6196
+ * (e.g. ["foo/bar.txt", "baz.txt"], NOT ["0x1/foo/bar.txt"]). The account address
6197
+ * prefix is automatically derived from the transaction sender.
6198
+ *
6199
+ * @returns An Aptos transaction payload data object for the delete_multiple_blobs Move function.
6200
+ *
6201
+ * @see https://github.com/shelby/shelby/blob/main/move/shelby_contract/sources/blob_metadata.move
6202
+ */
6203
+ static createDeleteMultipleBlobsPayload(params) {
6204
+ return {
6205
+ function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_multiple_blobs`,
6206
+ functionArguments: [params.blobNames]
6207
+ };
6208
+ }
6209
+ static createChunksetAcknowledgementsPayload(params) {
6210
+ const ackBitMask = params.storageProviderAcks.reduce(
6211
+ (acc, ack) => acc | 1 << ack.slot,
6212
+ 0
6213
+ );
6214
+ return {
6215
+ function: `${SHELBY_DEPLOYER}::blob_metadata::add_chunkset_acknowledgements`,
6216
+ functionArguments: [
6217
+ createBlobKey({
6218
+ account: params.blobOwner,
6219
+ blobName: params.blobName
6220
+ }),
6221
+ params.chunksetIdx,
6222
+ params.creationMicros,
6223
+ new U32(Number(ackBitMask)),
6224
+ params.storageProviderAcks.map((ack) => ack.signature)
6225
+ ]
6226
+ };
6227
+ }
6228
+ };
6229
+
6230
+ // ../../packages/sdk/dist/chunk-7O77OM4T.mjs
6231
+ import {
6232
+ AccountAddress as AccountAddress4,
6233
+ Aptos as Aptos2,
6234
+ Hex as Hex5
6235
+ } from "@aptos-labs/ts-sdk";
6236
+ function parseStorageProviderState(raw) {
6237
+ switch (raw.__variant__) {
6238
+ case "Active":
6239
+ return {
6240
+ variant: "Active",
6241
+ quota: raw.quota.value,
6242
+ stakeAtStartOfStakingEpoch: raw.stake_at_start_of_staking_epoch,
6243
+ faulty: raw.faulty,
6244
+ leaving: raw.leaving
6245
+ };
6246
+ case "Waitlisted":
6247
+ return {
6248
+ variant: "Waitlisted"
6249
+ };
6250
+ case "Frozen":
6251
+ return {
6252
+ variant: "Frozen",
6253
+ frozenReason: raw.frozen_reason,
6254
+ frozenFrom: raw.frozen_from,
6255
+ frozenTill: raw.frozen_till
6256
+ };
6257
+ }
6258
+ }
6259
+ var ShelbyMetadataClient = class {
6260
+ aptos;
6261
+ deployer;
6262
+ /**
6263
+ * The ShelbyMetadataClient is used to interact with the Shelby contract on the Aptos blockchain. This
6264
+ * includes functions like gathering basic details about the Shelby system, including storage provider information.
6265
+ *
6266
+ * @param config.aptos.config - The Aptos config.
6267
+ * @param config.shelbyDeployer - The deployer account address of the Shelby contract. If not provided, the default deployer address will be used.
5919
6268
  *
5920
6269
  * @example
5921
6270
  * ```typescript
5922
- * // Download entire blob
5923
- * const blob = await client.getBlob({
5924
- * account: AccountAddress.from("0x1"),
5925
- * blobName: "documents/report.pdf"
5926
- * });
6271
+ * const aptos = new Aptos(new AptosConfig({ network: Network.TESTNET }));
6272
+ * const metadataClient = new ShelbyMetadataClient({ aptos });
6273
+ * ```
6274
+ */
6275
+ constructor(config) {
6276
+ this.aptos = new Aptos2(getAptosConfig(config));
6277
+ this.deployer = config.deployer ?? AccountAddress4.fromString(SHELBY_DEPLOYER);
6278
+ }
6279
+ /**
6280
+ * Retrieves storage provider list from the blockchain.
5927
6281
  *
5928
- * // Download partial content (bytes 100-199)
5929
- * const partial = await client.getBlob({
5930
- * account: AccountAddress.from("0x1"),
5931
- * blobName: "large-file.bin",
5932
- * range: { start: 100, end: 199 }
5933
- * });
6282
+ * @returns A list of storage providers, or empty array if none exist.
5934
6283
  *
5935
- * // Download with micropayment
5936
- * const blob = await client.getBlob({
5937
- * account: AccountAddress.from("0x1"),
5938
- * blobName: "documents/report.pdf",
5939
- * micropayment: senderBuiltMicropayment
5940
- * });
6284
+ * @example
6285
+ * ```typescript
6286
+ * const spList = await client.getStorageProviders();
5941
6287
  * ```
5942
6288
  */
5943
- async getBlob(params) {
5944
- BlobNameSchema.parse(params.blobName);
5945
- const url = buildRequestUrl(
5946
- `/v1/blobs/${params.account.toString()}/${encodeURIComponentKeepSlashes(
5947
- params.blobName
5948
- )}`,
5949
- this.baseUrl
5950
- );
5951
- const headers = new Headers();
5952
- if (params.range !== void 0) {
5953
- const { start, end } = params.range;
5954
- if (end === void 0) {
5955
- headers.set("Range", `bytes=${start}-`);
5956
- } else {
5957
- if (end < start) {
5958
- throw new Error("Range end cannot be less than start.");
6289
+ async getStorageProviders() {
6290
+ try {
6291
+ const rawMetadata = await this.aptos.view({
6292
+ payload: {
6293
+ function: `${this.deployer.toString()}::storage_provider_registry::get_all_storage_providers`,
6294
+ functionArguments: []
5959
6295
  }
5960
- headers.set("Range", `bytes=${start}-${end}`);
5961
- }
5962
- }
5963
- if (this.apiKey) {
5964
- headers.set("Authorization", `Bearer ${this.apiKey}`);
5965
- }
5966
- if (params.micropayment) {
5967
- const bytes = params.micropayment.bcsToBytes();
5968
- const binaryString = Array.from(
5969
- bytes,
5970
- (byte) => String.fromCharCode(byte)
5971
- ).join("");
5972
- headers.set(MICROPAYMENT_HEADER, btoa(binaryString));
5973
- }
5974
- const response = await fetch(url, { headers });
5975
- if (response.status === 409) {
5976
- let json;
5977
- try {
5978
- json = await response.json();
5979
- } catch {
5980
- throw new Error(
5981
- `Failed to download blob: ${response.status} ${response.statusText}`
5982
- );
5983
- }
5984
- const parseResult = StaleMicropaymentErrorResponseSchema.safeParse(json);
5985
- if (!parseResult.success) {
5986
- throw new Error(
5987
- `Failed to download blob: ${response.status} ${response.statusText}`
5988
- );
5989
- }
5990
- const errorBody = parseResult.data;
5991
- if (errorBody.storedMicropayment) {
5992
- throw StaleChannelStateError.fromBase64(
5993
- errorBody.storedMicropayment,
5994
- errorBody.error
5995
- );
6296
+ });
6297
+ const metadata = rawMetadata[0];
6298
+ return metadata.map((provider) => ({
6299
+ address: normalizeAddress(provider.address),
6300
+ ipAddress: provider.ip_address,
6301
+ port: provider.port,
6302
+ blsPublicKey: Hex5.fromHexInput(provider.bls_public_key).toUint8Array(),
6303
+ availabilityZone: provider.availability_zone,
6304
+ state: parseStorageProviderState(provider.state)
6305
+ }));
6306
+ } catch (error) {
6307
+ if (error instanceof Error && // Depending on the network, the error message may show up differently.
6308
+ error.message?.includes("sub_status: Some(404)")) {
6309
+ return [];
5996
6310
  }
5997
- throw new Error(
5998
- errorBody.error ?? `Failed to download blob: ${response.status} ${response.statusText}`
5999
- );
6000
- }
6001
- if (!response.ok) {
6002
- throw new Error(
6003
- `Failed to download blob: ${response.status} ${response.statusText}`
6004
- );
6005
- }
6006
- if (!response.body) {
6007
- throw new Error("Response body is null");
6008
- }
6009
- const contentLengthHeader = response.headers.get("content-length");
6010
- if (contentLengthHeader === null) {
6011
- throw new Error(
6012
- "Response did not have content-length header, which is required"
6013
- );
6311
+ throw error;
6014
6312
  }
6015
- const expectedContentLength = Number.parseInt(contentLengthHeader, 10);
6016
- if (Number.isNaN(expectedContentLength)) {
6017
- throw new Error(
6018
- `Invalid content-length header received: ${contentLengthHeader}`
6019
- );
6313
+ }
6314
+ /**
6315
+ * Retrieves the list of placement group addresses.
6316
+ *
6317
+ * @returns The placement group address list, or an empty array if none exist.
6318
+ *
6319
+ * @example
6320
+ * ```typescript
6321
+ * const pgList = await client.getPlacementGroupAddresses();
6322
+ * ```
6323
+ */
6324
+ async getPlacementGroupAddresses() {
6325
+ try {
6326
+ const pgSizeMetadata = await this.aptos.view({
6327
+ payload: {
6328
+ function: `${this.deployer.toString()}::placement_group_registry::get_number_of_placement_groups`,
6329
+ functionArguments: []
6330
+ }
6331
+ });
6332
+ const finalPlacementGroupIndex = pgSizeMetadata[0] - 1;
6333
+ const addressMetadataArray = await this.aptos.view({
6334
+ payload: {
6335
+ function: `${this.deployer.toString()}::placement_group_registry::get_placement_group_addresses`,
6336
+ functionArguments: [0, finalPlacementGroupIndex]
6337
+ }
6338
+ });
6339
+ const metadata = addressMetadataArray[0];
6340
+ return metadata.map((pg) => normalizeAddress(pg));
6341
+ } catch (error) {
6342
+ if (error instanceof Error && // Depending on the network, the error message may show up differently.
6343
+ (error.message?.includes("sub_status: Some(404)") || error.message?.includes("E_PLACEMENT_GROUP_NOT_FOUND"))) {
6344
+ return [];
6345
+ }
6346
+ throw error;
6020
6347
  }
6021
- const validatingStream = new ReadableStream({
6022
- start(controller) {
6023
- const maybeReader = response.body?.getReader();
6024
- if (!maybeReader) {
6025
- controller.error(new Error("Response body reader is unavailable"));
6026
- return;
6348
+ }
6349
+ /**
6350
+ * Retrieves the list of slice addresses.
6351
+ *
6352
+ * @returns The slice group list, or an empty array if none exist.
6353
+ *
6354
+ * @example
6355
+ * ```typescript
6356
+ * const pgList = await client.getSliceAddresses();
6357
+ * ```
6358
+ */
6359
+ async getSliceAddresses() {
6360
+ try {
6361
+ const sliceSizeMetadata = await this.aptos.view({
6362
+ payload: {
6363
+ function: `${this.deployer.toString()}::slice_registry::get_number_of_slices`,
6364
+ functionArguments: []
6027
6365
  }
6028
- const reader = maybeReader;
6029
- let bytesReceived = 0;
6030
- function pump() {
6031
- return reader.read().then(({ done, value }) => {
6032
- if (done) {
6033
- if (bytesReceived !== expectedContentLength) {
6034
- controller.error(
6035
- new Error(
6036
- `Downloaded data size (${bytesReceived} bytes) does not match content-length header (${expectedContentLength} bytes). This might indicate a partial or corrupted download.`
6037
- )
6038
- );
6039
- return;
6040
- }
6041
- controller.close();
6042
- return;
6043
- }
6044
- bytesReceived += value.byteLength;
6045
- controller.enqueue(value);
6046
- return pump();
6047
- }).catch((error) => {
6048
- controller.error(error);
6049
- });
6366
+ });
6367
+ const finalSliceIndex = sliceSizeMetadata[0] - 1;
6368
+ const addressMetadataArray = await this.aptos.view({
6369
+ payload: {
6370
+ function: `${this.deployer.toString()}::slice_registry::get_slice_addresses`,
6371
+ functionArguments: [0, finalSliceIndex]
6050
6372
  }
6051
- return pump();
6373
+ });
6374
+ const metadata = addressMetadataArray[0];
6375
+ return metadata.map((slice) => normalizeAddress(slice));
6376
+ } catch (error) {
6377
+ if (error instanceof Error && // Depending on the network, the error message may show up differently.
6378
+ (error.message?.includes("sub_status: Some(404)") || error.message?.includes("E_SLICE_NOT_FOUND"))) {
6379
+ return [];
6380
+ }
6381
+ throw error;
6382
+ }
6383
+ }
6384
+ /**
6385
+ * Gets the placement group address for a slice.
6386
+ *
6387
+ * @param sliceAddress - The address of the slice account.
6388
+ * @returns The placement group address as a string.
6389
+ */
6390
+ async getPlacementGroupAddressForSlice(sliceAddress) {
6391
+ const sliceMetadata = await this.aptos.view({
6392
+ payload: {
6393
+ function: `${this.deployer.toString()}::slice::get_slice_info`,
6394
+ functionArguments: [sliceAddress.toString()]
6052
6395
  }
6053
6396
  });
6054
- return {
6055
- account: AccountAddress4.from(params.account),
6056
- name: params.blobName,
6057
- readable: validatingStream,
6058
- contentLength: expectedContentLength
6059
- };
6397
+ return sliceMetadata[0].placement_group_assignments[0].placement_group_address;
6398
+ }
6399
+ /**
6400
+ * Retrieves the designated storage providers for a slice.
6401
+ *
6402
+ * Designated SPs are those appointed to store data for their slots:
6403
+ * - Active: Currently serving data
6404
+ * - Receiving: Receiving data during slot transfer
6405
+ * - Repairing: Repairing data after crash or failed transfer
6406
+ * - Reconstructing: Reconstructing data if the repair fails
6407
+ *
6408
+ * @param params.account - The address of the slice account.
6409
+ * @returns An array where result[i] is the designated SP for slot i, or null if no SP is designated.
6410
+ *
6411
+ * @example
6412
+ * ```typescript
6413
+ * const providers = await client.getDesignatedStorageProvidersForSlice({ account: sliceAddress });
6414
+ * ```
6415
+ */
6416
+ async getDesignatedStorageProvidersForSlice(params) {
6417
+ const placementGroupAddress = await this.getPlacementGroupAddressForSlice(
6418
+ params.account
6419
+ );
6420
+ const rawMetadata = await this.aptos.view({
6421
+ payload: {
6422
+ function: `${this.deployer.toString()}::placement_group::get_designated_storage_providers`,
6423
+ functionArguments: [placementGroupAddress]
6424
+ }
6425
+ });
6426
+ const providers = rawMetadata[0];
6427
+ return providers.map(
6428
+ (opt) => opt.vec.length > 0 ? normalizeAddress(opt.vec[0]) : null
6429
+ );
6430
+ }
6431
+ /**
6432
+ * Retrieves the active storage providers for a slice.
6433
+ *
6434
+ * Active SPs have a complete copy of the data for the slot, and are not in any data transfer/repair/reconstruction phase.
6435
+ * Active SP can be audited for the data it contains.
6436
+ * Each slot has at most one active SP.
6437
+ *
6438
+ * @param params.account - The address of the slice account.
6439
+ * @returns An array where result[i] is the active SP for slot i, or null if no SP is active.
6440
+ *
6441
+ * @example
6442
+ * ```typescript
6443
+ * const providers = await client.getActiveStorageProvidersForSlice({ account: sliceAddress });
6444
+ * ```
6445
+ */
6446
+ async getActiveStorageProvidersForSlice(params) {
6447
+ const placementGroupAddress = await this.getPlacementGroupAddressForSlice(
6448
+ params.account
6449
+ );
6450
+ const rawMetadata = await this.aptos.view({
6451
+ payload: {
6452
+ function: `${this.deployer.toString()}::placement_group::get_active_storage_providers`,
6453
+ functionArguments: [placementGroupAddress]
6454
+ }
6455
+ });
6456
+ const providers = rawMetadata[0];
6457
+ return providers.map(
6458
+ (opt) => opt.vec.length > 0 ? normalizeAddress(opt.vec[0]) : null
6459
+ );
6460
+ }
6461
+ /**
6462
+ * Retrieves the serving storage providers for a slice.
6463
+ *
6464
+ * Serving SPs are those that can respond to read requests. The serving logic is:
6465
+ * - If an Active SP exists for a slot: Only the Active SP is serving
6466
+ * - If no Active SP (transition in progress): Both Designated and Vacating SPs serve
6467
+ *
6468
+ * Each slot may have multiple serving SPs during transitions.
6469
+ *
6470
+ * @param params.account - The address of the slice account.
6471
+ * @returns An array where result[i] contains the serving SPs for slot i.
6472
+ *
6473
+ * @example
6474
+ * ```typescript
6475
+ * const providers = await client.getServingStorageProvidersForSlice({ account: sliceAddress });
6476
+ * ```
6477
+ */
6478
+ async getServingStorageProvidersForSlice(params) {
6479
+ const placementGroupAddress = await this.getPlacementGroupAddressForSlice(
6480
+ params.account
6481
+ );
6482
+ const rawMetadata = await this.aptos.view({
6483
+ payload: {
6484
+ function: `${this.deployer.toString()}::placement_group::get_serving_storage_providers`,
6485
+ functionArguments: [placementGroupAddress]
6486
+ }
6487
+ });
6488
+ const providers = rawMetadata[0];
6489
+ return providers.map(
6490
+ (slotProviders) => slotProviders.map((addr) => normalizeAddress(addr))
6491
+ );
6060
6492
  }
6061
6493
  };
6062
6494
 
6063
- // ../../packages/sdk/dist/chunk-W6YL46DT.mjs
6495
+ // ../../packages/sdk/dist/chunk-5CES6RPZ.mjs
6064
6496
  import {
6065
- AccountAddress as AccountAddress5,
6066
- Aptos as Aptos2,
6497
+ Aptos as Aptos3,
6067
6498
  DEFAULT_TXN_TIMEOUT_SEC,
6499
+ Network as Network3,
6068
6500
  TransactionResponseType
6069
6501
  } from "@aptos-labs/ts-sdk";
6070
6502
 
@@ -6205,13 +6637,17 @@ function validateConcurrency(concurrency) {
6205
6637
  }
6206
6638
  }
6207
6639
 
6208
- // ../../packages/sdk/dist/chunk-W6YL46DT.mjs
6640
+ // ../../packages/sdk/dist/chunk-5CES6RPZ.mjs
6209
6641
  var ShelbyClient = class {
6210
6642
  /**
6211
6643
  * The coordination client is used to interact with the Aptos blockchain which handles the commitments
6212
6644
  * and metadata for blobs.
6213
6645
  */
6214
6646
  coordination;
6647
+ /**
6648
+ * The metadata client is used for protocol-level metadata queries.
6649
+ */
6650
+ metadata;
6215
6651
  /**
6216
6652
  * The RPC client is used to interact with the Shelby RPC node which can be responsible for storing,
6217
6653
  * confirming, and retrieving blobs from the storage layer.
@@ -6261,8 +6697,9 @@ var ShelbyClient = class {
6261
6697
  */
6262
6698
  constructor(config, provider) {
6263
6699
  this.config = config;
6264
- this.aptos = new Aptos2(getAptosConfig(config));
6700
+ this.aptos = new Aptos3(getAptosConfig(config));
6265
6701
  this.coordination = new ShelbyBlobClient(config);
6702
+ this.metadata = new ShelbyMetadataClient(config);
6266
6703
  this.rpc = new ShelbyRPCClient(config);
6267
6704
  this._provider = provider;
6268
6705
  }
@@ -6272,7 +6709,9 @@ var ShelbyClient = class {
6272
6709
  */
6273
6710
  async getProvider() {
6274
6711
  if (!this._provider) {
6275
- this._provider = await ClayErasureCodingProvider.create();
6712
+ this._provider = await ClayErasureCodingProvider.create(
6713
+ defaultErasureCodingConfig()
6714
+ );
6276
6715
  }
6277
6716
  return this._provider;
6278
6717
  }
@@ -6329,6 +6768,7 @@ var ShelbyClient = class {
6329
6768
  blobMerkleRoot: blobCommitments.blob_merkle_root,
6330
6769
  size: params.blobData.length,
6331
6770
  expirationMicros: params.expirationMicros,
6771
+ config: provider.config,
6332
6772
  options: params.options
6333
6773
  });
6334
6774
  await this.coordination.aptos.waitForTransaction({
@@ -6409,6 +6849,7 @@ var ShelbyClient = class {
6409
6849
  blobSize: blob.blobData.length,
6410
6850
  blobMerkleRoot: blobCommitments[index].blob_merkle_root
6411
6851
  })),
6852
+ config: provider.config,
6412
6853
  options: params.options
6413
6854
  });
6414
6855
  await this.coordination.aptos.waitForTransaction({
@@ -6466,6 +6907,11 @@ var ShelbyClient = class {
6466
6907
  * ```
6467
6908
  */
6468
6909
  async fundAccountWithShelbyUSD(params) {
6910
+ if (this.config.network === Network3.TESTNET) {
6911
+ throw new Error(
6912
+ `ShelbyUSD cannot be minted programmatically on ${Network3.TESTNET}. Please use the faucet at https://docs.shelby.xyz/apis/faucet/shelbyusd instead.`
6913
+ );
6914
+ }
6469
6915
  const { address, amount } = params;
6470
6916
  try {
6471
6917
  const faucet = this.config.faucet?.baseUrl ?? "https://faucet.shelbynet.shelby.xyz/fund?asset=shelbyusd";
@@ -6473,7 +6919,7 @@ var ShelbyClient = class {
6473
6919
  const response = await fetch(`${faucet}`, {
6474
6920
  method: "POST",
6475
6921
  body: JSON.stringify({
6476
- address: AccountAddress5.from(address).toString(),
6922
+ address: normalizeAddress(address).toString(),
6477
6923
  amount
6478
6924
  }),
6479
6925
  headers: {
@@ -6527,48 +6973,22 @@ var ShelbyClient = class {
6527
6973
  }
6528
6974
  };
6529
6975
 
6530
- // ../../packages/sdk/dist/chunk-DI2K6OUG.mjs
6976
+ // ../../packages/sdk/dist/chunk-33BZ7KYA.mjs
6531
6977
  var ShelbyNodeClient = class extends ShelbyClient {
6532
6978
  };
6533
6979
 
6534
- // ../../packages/sdk/dist/chunk-YZXIPUVQ.mjs
6535
- import {
6536
- AccountAddress as AccountAddress6,
6537
- Aptos as Aptos3,
6538
- Hex as Hex5
6539
- } from "@aptos-labs/ts-sdk";
6540
-
6541
- // ../../packages/sdk/dist/chunk-7P6ASYW6.mjs
6542
- var __defProp2 = Object.defineProperty;
6543
- var __export = (target, all) => {
6544
- for (var name2 in all)
6545
- __defProp2(target, name2, { get: all[name2], enumerable: true });
6546
- };
6547
-
6548
- // ../../packages/sdk/dist/chunk-A4IG6GSE.mjs
6549
- var testUtil_exports = {};
6550
- __export(testUtil_exports, {
6551
- makeChunk: () => makeChunk
6552
- });
6553
- function makeChunk(n) {
6554
- const c = Buffer.alloc(n);
6555
- for (let i = 0; i < n; ++i) {
6556
- c[i] = i % 256;
6557
- }
6558
- return c;
6559
- }
6560
-
6561
6980
  // ../../packages/reed-solomon/dist/index.mjs
6562
6981
  var __toBinaryNode = (base64) => new Uint8Array(Buffer.from(base64, "base64"));
6563
6982
  var reed_solomon_erasure_bg_default = __toBinaryNode("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QCAKIAlJDQACQCAJRQ0AIAkgAUYNACAJIAFPDQEgACAJaiwAAEG/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==");
6564
6983
 
6565
- // ../../packages/sdk/dist/chunk-PZF2VTGP.mjs
6984
+ // ../../packages/sdk/dist/chunk-NHWWORCH.mjs
6566
6985
  var DEFAULT_CHUNK_SIZE_BYTES2 = 2 * 1024 * 1024;
6567
6986
 
6568
- // ../../packages/sdk/dist/chunk-66GI734H.mjs
6987
+ // ../../packages/sdk/dist/chunk-OQNP5QXH.mjs
6569
6988
  import {
6570
- AccountAddress as AccountAddress7,
6571
- Aptos as Aptos4
6989
+ AccountAddress as AccountAddress5,
6990
+ Aptos as Aptos4,
6991
+ MoveVector
6572
6992
  } from "@aptos-labs/ts-sdk";
6573
6993
  var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
6574
6994
  aptos;
@@ -6595,7 +7015,7 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
6595
7015
  */
6596
7016
  constructor(config) {
6597
7017
  this.aptos = new Aptos4(getAptosConfig(config));
6598
- this.deployer = config.deployer ?? AccountAddress7.fromString(MICROPAYMENTS_DEPLOYER);
7018
+ this.deployer = config.deployer ?? AccountAddress5.fromString(MICROPAYMENTS_DEPLOYER);
6599
7019
  this.indexer = getShelbyIndexerClient(config);
6600
7020
  }
6601
7021
  /**
@@ -6664,7 +7084,8 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
6664
7084
  receiver: params.receiver,
6665
7085
  expirationMicros: params.expirationMicros,
6666
7086
  depositAmount: params.depositAmount,
6667
- fungibleAssetAddress: params.fungibleAssetAddress
7087
+ fungibleAssetAddress: params.fungibleAssetAddress,
7088
+ publicKey: params.publicKey ?? params.sender.publicKey.toUint8Array()
6668
7089
  }
6669
7090
  ),
6670
7091
  sender: params.sender.accountAddress
@@ -6686,6 +7107,7 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
6686
7107
  * @param params.expirationMicros - The expiration of the micropayment channel.
6687
7108
  * @param params.depositAmount - The amount of the asset locked to the channel.
6688
7109
  * @param params.fungibleAssetAddress - The account address of the fungible asset.
7110
+ * @param params.publicKey - The Ed25519 public key bytes for the channel.
6689
7111
  *
6690
7112
  * @returns An Aptos transaction payload data object for the create_channel Move function.
6691
7113
  */
@@ -6696,7 +7118,8 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
6696
7118
  params.receiver,
6697
7119
  params.expirationMicros,
6698
7120
  params.depositAmount,
6699
- params.fungibleAssetAddress
7121
+ params.fungibleAssetAddress,
7122
+ MoveVector.U8(params.publicKey)
6700
7123
  ]
6701
7124
  };
6702
7125
  }
@@ -6754,94 +7177,86 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
6754
7177
  }
6755
7178
  /**
6756
7179
  * Creates a micropayment that can be sent to a receiver.
7180
+ * The sender signs a WithdrawApproval message that authorizes the receiver
7181
+ * to withdraw funds from the micropayment channel.
6757
7182
  *
6758
- * @param params.sender - The account address of the sender.
6759
- * @param params.receiver - The account that is withdrawing funds.
6760
- * @param params.amount - The amount to withdraw into the receiver's account.
6761
- * @param params.paymentChannelId - The id of the payment channel.
6762
- * @param params.sequenceNumber - The sequence number of the micropayment. These must be increasing to be able to store on chain.
7183
+ * @param params.sender - The account that owns the payment channel and signs the approval.
7184
+ * @param params.receiver - The account address that will receive funds.
6763
7185
  * @param params.fungibleAssetAddress - The account address of the fungible asset.
6764
- * @param params.options - Optional transaction generation options.
7186
+ * @param params.amount - The cumulative amount to authorize (not incremental).
7187
+ * @param params.paymentChannelId - The id of the payment channel.
7188
+ * @param params.sequenceNumber - The sequence number of the micropayment. Must be >= channel's next_withdrawn_sequence_number.
6765
7189
  *
6766
- * @returns An object containing the pending transaction and signature.
7190
+ * @returns A SenderBuiltMicropayment containing the signed approval.
6767
7191
  *
6768
7192
  * @example
6769
7193
  * ```typescript
6770
- * const senderBuiltMicropayment = await client.createMicropayment({
6771
- * sender: senderAddress,
6772
- * receiver: receiver,
6773
- * amount: 1,
6774
- * paymentChannelId: channelIdFromLookup,
6775
- * sequenceNumber: localSequenceNumber,
7194
+ * const senderBuiltMicropayment = client.createMicropayment({
7195
+ * sender: senderAccount,
7196
+ * receiver: receiverAddress,
6776
7197
  * fungibleAssetAddress: fungibleAssetAddress,
7198
+ * amount: 100,
7199
+ * paymentChannelId: channelId,
7200
+ * sequenceNumber: 1,
6777
7201
  * });
6778
7202
  * ```
6779
7203
  */
6780
- async createMicropayment(params) {
6781
- const replayProtectionNonce = params.options?.replayProtectionNonce ?? Math.floor(Math.random() * 2 ** 24);
6782
- const {
6783
- accountSequenceNumber: _unusedSequenceNumber,
6784
- expireTimestamp: _unusedTimestamp,
6785
- ...restOptions
6786
- } = params.options ?? {};
6787
- const micropayment = await this.aptos.transaction.build.multiAgent({
6788
- options: {
6789
- ...restOptions,
6790
- replayProtectionNonce,
6791
- expireTimestamp: Math.floor(Date.now() / 1e3 + 60)
6792
- // 60 seconds from now
6793
- },
6794
- withFeePayer: true,
6795
- data: _ShelbyMicropaymentChannelClient.createMicropaymentTransactionPayload(
6796
- {
6797
- deployer: this.deployer,
6798
- amount: params.amount,
6799
- paymentChannelId: params.paymentChannelId,
6800
- sequenceNumber: params.sequenceNumber,
6801
- fungibleAssetAddress: params.fungibleAssetAddress
6802
- }
6803
- ),
7204
+ createMicropayment(params) {
7205
+ const message = SenderBuiltMicropayment.buildSignedMessage({
7206
+ deployer: this.deployer,
6804
7207
  sender: params.sender.accountAddress,
6805
- secondarySignerAddresses: [params.receiver]
7208
+ receiver: params.receiver,
7209
+ fungibleAssetAddress: params.fungibleAssetAddress,
7210
+ amount: params.amount,
7211
+ paymentChannelId: params.paymentChannelId,
7212
+ sequenceNumber: params.sequenceNumber
6806
7213
  });
7214
+ const signature = params.sender.sign(message);
6807
7215
  return new SenderBuiltMicropayment(
6808
- micropayment,
6809
- this.aptos.sign({
6810
- signer: params.sender,
6811
- transaction: micropayment
6812
- })
7216
+ params.sender.accountAddress,
7217
+ params.receiver,
7218
+ BigInt(params.paymentChannelId),
7219
+ BigInt(params.amount),
7220
+ params.fungibleAssetAddress,
7221
+ BigInt(params.sequenceNumber),
7222
+ params.sender.publicKey.toUint8Array(),
7223
+ signature.toUint8Array(),
7224
+ this.deployer
6813
7225
  );
6814
7226
  }
6815
7227
  /**
6816
- * Creates a static payload for the receiver_withdraw Move function. This is what
6817
- * constitutes a miropaymet.
6818
- * This is a helper method for constructing the transaction payload without signing.
7228
+ * Creates a static payload for the receiver_withdraw Move function.
7229
+ * This is a helper method for constructing the transaction payload.
6819
7230
  *
6820
7231
  * @param params.deployer - Optional deployer account address. Defaults to MICROPAYMENTS_DEPLOYER.
6821
- * @param params.amount - The amount of the fungible asset's smallest increment to send.
6822
- * @param params.paymentChannelId - The payment channel id.
7232
+ * @param params.sender - The sender's account address.
6823
7233
  * @param params.fungibleAssetAddress - The account address of the fungible asset.
7234
+ * @param params.amount - The cumulative amount authorized to withdraw.
7235
+ * @param params.paymentChannelId - The payment channel id.
7236
+ * @param params.sequenceNumber - The sequence number for this withdrawal.
7237
+ * @param params.signature - The Ed25519 signature bytes.
6824
7238
  *
6825
- * @returns An Aptos transaction payload data object for the sender_withdraw Move function.
7239
+ * @returns An Aptos transaction payload data object for the receiver_withdraw Move function.
6826
7240
  */
6827
7241
  static createMicropaymentTransactionPayload(params) {
6828
7242
  return {
6829
7243
  function: `${(params.deployer ?? MICROPAYMENTS_DEPLOYER).toString()}::micropayments::receiver_withdraw`,
6830
7244
  functionArguments: [
7245
+ params.sender,
7246
+ params.fungibleAssetAddress,
6831
7247
  params.amount,
6832
7248
  params.paymentChannelId,
6833
7249
  params.sequenceNumber,
6834
- params.fungibleAssetAddress
7250
+ MoveVector.U8(params.signature)
6835
7251
  ]
6836
7252
  };
6837
7253
  }
6838
7254
  /**
6839
- * Withdraws funds from a micropayment channel as the receiver. The receiver
6840
- * does this by signing and submitting a signed transaction the sender sent it.
7255
+ * Withdraws funds from a micropayment channel as the receiver.
7256
+ * The receiver submits the sender's signed approval to claim funds.
6841
7257
  *
6842
- * @param params.receiver - The receiver withdrawing funds.
6843
- * @param params.receiverSignature - The fee-paying transaction signature.
6844
- * @param params.micropayment - The fee-paying transaction signature.
7258
+ * @param params.receiver - The receiver account that will sign and submit the transaction.
7259
+ * @param params.micropayment - The sender's signed micropayment approval.
6845
7260
  * @param params.options - Optional transaction generation options.
6846
7261
  *
6847
7262
  * @returns An object containing the pending transaction.
@@ -6849,23 +7264,31 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
6849
7264
  * @example
6850
7265
  * ```typescript
6851
7266
  * const { transaction } = await client.receiverWithdraw({
6852
- * receiver: receiver,
6853
- * micropayment,
6854
- * senderSignature,
7267
+ * receiver: receiverAccount,
7268
+ * micropayment: senderBuiltMicropayment,
6855
7269
  * });
6856
7270
  * ```
6857
7271
  */
6858
7272
  async receiverWithdraw(params) {
6859
- const mySignature = this.aptos.signAsFeePayer({
6860
- signer: params.receiver,
6861
- transaction: params.micropayment.micropayment
7273
+ const transaction = await this.aptos.transaction.build.simple({
7274
+ options: params.options,
7275
+ data: _ShelbyMicropaymentChannelClient.createMicropaymentTransactionPayload(
7276
+ {
7277
+ deployer: this.deployer,
7278
+ sender: params.micropayment.sender,
7279
+ fungibleAssetAddress: params.micropayment.fungibleAssetAddress,
7280
+ amount: params.micropayment.amount,
7281
+ paymentChannelId: params.micropayment.paymentChannelId,
7282
+ sequenceNumber: params.micropayment.sequenceNumber,
7283
+ signature: params.micropayment.signature
7284
+ }
7285
+ ),
7286
+ sender: params.receiver.accountAddress
6862
7287
  });
6863
7288
  return {
6864
- transaction: await this.aptos.transaction.submit.multiAgent({
6865
- transaction: params.micropayment.micropayment,
6866
- senderAuthenticator: params.micropayment.senderSignature,
6867
- additionalSignersAuthenticators: [mySignature],
6868
- feePayerAuthenticator: mySignature
7289
+ transaction: await this.aptos.signAndSubmitTransaction({
7290
+ signer: params.receiver,
7291
+ transaction
6869
7292
  })
6870
7293
  };
6871
7294
  }
@@ -7001,7 +7424,7 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
7001
7424
  * ```typescript
7002
7425
  * const channelInfoVec = await client.getChannelInfo({
7003
7426
  * sender: AccountAddress.fromString("0x1"),
7004
- * receiver: AccountAddress.fromSTring("0x2"),
7427
+ * receiver: AccountAddress.fromString("0x2"),
7005
7428
  * });
7006
7429
  * ```
7007
7430
  */
@@ -7020,10 +7443,14 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
7020
7443
  const channelInfoArray = rawArray[0];
7021
7444
  return channelInfoArray.map(
7022
7445
  (channelInfo) => {
7446
+ const publicKeyHex = channelInfo.public_key.startsWith("0x") ? channelInfo.public_key.slice(2) : channelInfo.public_key;
7447
+ const publicKey = new Uint8Array(
7448
+ publicKeyHex.match(/.{1,2}/g)?.map((byte) => Number.parseInt(byte, 16)) ?? []
7449
+ );
7023
7450
  return {
7024
7451
  sender: params.sender,
7025
7452
  receiver: params.receiver,
7026
- fungibleAssetAddress: AccountAddress7.fromString(
7453
+ fungibleAssetAddress: normalizeAddress(
7027
7454
  channelInfo.asset_metadata.inner
7028
7455
  ),
7029
7456
  balance: Number(channelInfo.balance),
@@ -7035,31 +7462,36 @@ var ShelbyMicropaymentChannelClient = class _ShelbyMicropaymentChannelClient {
7035
7462
  paymentChannelId: Number(channelInfo.payment_channel_id),
7036
7463
  receiverWithdrawnAmount: Number(
7037
7464
  channelInfo.receiver_withdrawn_amount
7038
- )
7465
+ ),
7466
+ publicKey
7039
7467
  };
7040
7468
  }
7041
7469
  );
7042
7470
  }
7043
7471
  };
7044
7472
 
7045
- // ../../packages/sdk/dist/chunk-VRLIOKWG.mjs
7046
- import { Network as Network3 } from "@aptos-labs/ts-sdk";
7047
- var shelbyNetworks = [Network3.LOCAL, Network3.SHELBYNET];
7473
+ // ../../packages/sdk/dist/chunk-D6GQHO6G.mjs
7474
+ import { Network as Network4 } from "@aptos-labs/ts-sdk";
7475
+ var shelbyNetworks = [
7476
+ Network4.LOCAL,
7477
+ Network4.TESTNET,
7478
+ Network4.SHELBYNET
7479
+ ];
7048
7480
 
7049
7481
  // ../../packages/sdk/dist/chunk-BDSW5PHM.mjs
7050
- import { Network as Network4 } from "@aptos-labs/ts-sdk";
7482
+ import { Network as Network5 } from "@aptos-labs/ts-sdk";
7051
7483
  function getShelbyExplorerBaseUrl(network) {
7052
7484
  const normalizedNetwork = network.toLowerCase();
7053
7485
  switch (normalizedNetwork) {
7054
- case Network4.MAINNET.toLowerCase():
7486
+ case Network5.MAINNET.toLowerCase():
7055
7487
  return "https://explorer.shelby.xyz/mainnet";
7056
- case Network4.TESTNET.toLowerCase():
7488
+ case Network5.TESTNET.toLowerCase():
7057
7489
  return "https://explorer.shelby.xyz/testnet";
7058
- case Network4.DEVNET.toLowerCase():
7490
+ case Network5.DEVNET.toLowerCase():
7059
7491
  return "https://explorer.shelby.xyz/devnet";
7060
- case Network4.LOCAL.toLowerCase():
7492
+ case Network5.LOCAL.toLowerCase():
7061
7493
  return "https://explorer.shelby.xyz/local";
7062
- case Network4.SHELBYNET.toLowerCase():
7494
+ case Network5.SHELBYNET.toLowerCase():
7063
7495
  return "https://explorer.shelby.xyz/shelbynet";
7064
7496
  default:
7065
7497
  return `https://explorer.shelby.xyz/${normalizedNetwork}`;
@@ -7070,20 +7502,40 @@ function getShelbyAccountExplorerUrl(network, accountAddress) {
7070
7502
  return `${baseUrl}/account/${accountAddress}`;
7071
7503
  }
7072
7504
 
7505
+ // ../../packages/sdk/dist/chunk-7P6ASYW6.mjs
7506
+ var __defProp2 = Object.defineProperty;
7507
+ var __export = (target, all) => {
7508
+ for (var name2 in all)
7509
+ __defProp2(target, name2, { get: all[name2], enumerable: true });
7510
+ };
7511
+
7512
+ // ../../packages/sdk/dist/chunk-A4IG6GSE.mjs
7513
+ var testUtil_exports = {};
7514
+ __export(testUtil_exports, {
7515
+ makeChunk: () => makeChunk
7516
+ });
7517
+ function makeChunk(n) {
7518
+ const c = Buffer.alloc(n);
7519
+ for (let i = 0; i < n; ++i) {
7520
+ c[i] = i % 256;
7521
+ }
7522
+ return c;
7523
+ }
7524
+
7073
7525
  // ../../packages/sdk/dist/chunk-C6RQ3AEU.mjs
7074
- import { Network as Network5 } from "@aptos-labs/ts-sdk";
7526
+ import { Network as Network6 } from "@aptos-labs/ts-sdk";
7075
7527
  function getAptosExplorerBaseUrl(network) {
7076
7528
  const normalizedNetwork = network.toLowerCase();
7077
7529
  switch (normalizedNetwork) {
7078
- case Network5.MAINNET.toLowerCase():
7530
+ case Network6.MAINNET.toLowerCase():
7079
7531
  return "https://explorer.aptoslabs.com";
7080
- case Network5.TESTNET.toLowerCase():
7532
+ case Network6.TESTNET.toLowerCase():
7081
7533
  return "https://explorer.aptoslabs.com";
7082
- case Network5.DEVNET.toLowerCase():
7534
+ case Network6.DEVNET.toLowerCase():
7083
7535
  return "https://explorer.aptoslabs.com";
7084
- case Network5.LOCAL.toLowerCase():
7536
+ case Network6.LOCAL.toLowerCase():
7085
7537
  return "https://explorer.aptoslabs.com";
7086
- case Network5.SHELBYNET.toLowerCase():
7538
+ case Network6.SHELBYNET.toLowerCase():
7087
7539
  return "https://explorer.aptoslabs.com";
7088
7540
  default:
7089
7541
  return "https://explorer.aptoslabs.com";
@@ -7092,15 +7544,15 @@ function getAptosExplorerBaseUrl(network) {
7092
7544
  function getAptosExplorerNetworkParam(network) {
7093
7545
  const normalizedNetwork = network.toLowerCase();
7094
7546
  switch (normalizedNetwork) {
7095
- case Network5.MAINNET.toLowerCase():
7547
+ case Network6.MAINNET.toLowerCase():
7096
7548
  return "mainnet";
7097
- case Network5.TESTNET.toLowerCase():
7549
+ case Network6.TESTNET.toLowerCase():
7098
7550
  return "testnet";
7099
- case Network5.DEVNET.toLowerCase():
7551
+ case Network6.DEVNET.toLowerCase():
7100
7552
  return "devnet";
7101
- case Network5.LOCAL.toLowerCase():
7553
+ case Network6.LOCAL.toLowerCase():
7102
7554
  return "local";
7103
- case Network5.SHELBYNET.toLowerCase():
7555
+ case Network6.SHELBYNET.toLowerCase():
7104
7556
  return "shelbynet";
7105
7557
  default:
7106
7558
  return normalizedNetwork;
@@ -7468,7 +7920,7 @@ function validateAccountName(name2, config) {
7468
7920
  // src/utils/keys.ts
7469
7921
  import {
7470
7922
  Account,
7471
- AccountAddress as AccountAddress8,
7923
+ AccountAddress as AccountAddress6,
7472
7924
  Ed25519PrivateKey as Ed25519PrivateKey2,
7473
7925
  Secp256k1PrivateKey,
7474
7926
  SigningSchemeInput
@@ -7490,7 +7942,7 @@ function isValidEd25519PrivateKey(value) {
7490
7942
  }
7491
7943
  }
7492
7944
  function isValidAddress(address) {
7493
- return AccountAddress8.isValid({ input: address }).valid;
7945
+ return AccountAddress6.isValid({ input: address }).valid;
7494
7946
  }
7495
7947
  var ED25519_NAME = "ed25519";
7496
7948
  var SignatureSchemeSchema = z9.enum([ED25519_NAME]);
@@ -8140,7 +8592,7 @@ import { useState as useState5 } from "react";
8140
8592
  import { jsx as jsx7 } from "react/jsx-runtime";
8141
8593
 
8142
8594
  // src/components/InitWizard.tsx
8143
- import { Account as Account2, Ed25519PrivateKey as Ed25519PrivateKey3, Network as Network7 } from "@aptos-labs/ts-sdk";
8595
+ import { Account as Account2, Ed25519PrivateKey as Ed25519PrivateKey3, Network as Network8 } from "@aptos-labs/ts-sdk";
8144
8596
  import { Box as Box6, Text as Text6 } from "ink";
8145
8597
  import SelectInput3 from "ink-select-input";
8146
8598
  import Spinner from "ink-spinner";
@@ -8149,12 +8601,12 @@ import { useEffect as useEffect4, useState as useState6 } from "react";
8149
8601
 
8150
8602
  // src/utils/balance.ts
8151
8603
  import {
8152
- AccountAddress as AccountAddress9,
8604
+ AccountAddress as AccountAddress7,
8153
8605
  AptosApiError
8154
8606
  } from "@aptos-labs/ts-sdk";
8155
8607
 
8156
8608
  // src/utils/constants.ts
8157
- import { APTOS_COIN, Network as Network6 } from "@aptos-labs/ts-sdk";
8609
+ import { APTOS_COIN, Network as Network7 } from "@aptos-labs/ts-sdk";
8158
8610
 
8159
8611
  // src/utils/context-helpers.ts
8160
8612
  import {
@@ -8183,15 +8635,16 @@ function createContextForNetwork(network) {
8183
8635
  // src/utils/constants.ts
8184
8636
  var DEFAULT_CONFIG = {
8185
8637
  contexts: {
8186
- [Network6.LOCAL]: {
8187
- ...createContextForNetwork(Network6.LOCAL),
8638
+ [Network7.LOCAL]: {
8639
+ ...createContextForNetwork(Network7.LOCAL),
8188
8640
  // Override shelby_network for local
8189
8641
  shelby_network: { rpc_endpoint: "http://localhost:9090/" }
8190
8642
  },
8191
- [Network6.SHELBYNET]: createContextForNetwork(Network6.SHELBYNET)
8643
+ [Network7.SHELBYNET]: createContextForNetwork(Network7.SHELBYNET),
8644
+ [Network7.TESTNET]: createContextForNetwork(Network7.TESTNET)
8192
8645
  },
8193
8646
  accounts: {},
8194
- default_context: Network6.SHELBYNET,
8647
+ default_context: Network7.SHELBYNET,
8195
8648
  default_account: ""
8196
8649
  };
8197
8650
  var STANDARD_CONTEXT_NAMES = Object.keys(DEFAULT_CONFIG.contexts).join(
@@ -8236,10 +8689,10 @@ function resolveAccountAddress({
8236
8689
  if (!isValidAddress(explicitAddress)) {
8237
8690
  throw new InvalidAccountAddressError(explicitAddress);
8238
8691
  }
8239
- return AccountAddress9.from(explicitAddress).toString();
8692
+ return AccountAddress7.from(explicitAddress).toString();
8240
8693
  }
8241
8694
  if (derivedAddress) {
8242
- return AccountAddress9.from(derivedAddress).toString();
8695
+ return AccountAddress7.from(derivedAddress).toString();
8243
8696
  }
8244
8697
  return void 0;
8245
8698
  }
@@ -8248,7 +8701,7 @@ async function getBalanceWithFallback({
8248
8701
  accountAddress,
8249
8702
  target
8250
8703
  }) {
8251
- const addrString = AccountAddress9.from(accountAddress).toString();
8704
+ const addrString = AccountAddress7.from(accountAddress).toString();
8252
8705
  const assetType = assetTypeToString(target.asset);
8253
8706
  try {
8254
8707
  const balance = await aptos.getBalance({
@@ -8284,7 +8737,7 @@ async function resolveDecimals({
8284
8737
  }
8285
8738
  try {
8286
8739
  const metadata = await aptos.getFungibleAssetMetadataByAssetType({
8287
- assetType: typeof target.asset === "string" ? target.asset : AccountAddress9.from(target.asset).toString()
8740
+ assetType: typeof target.asset === "string" ? target.asset : AccountAddress7.from(target.asset).toString()
8288
8741
  });
8289
8742
  if (typeof metadata?.decimals === "number") {
8290
8743
  return metadata.decimals;
@@ -8365,7 +8818,7 @@ function assetTypeToString(asset) {
8365
8818
  if (typeof asset === "string") {
8366
8819
  return asset;
8367
8820
  }
8368
- return AccountAddress9.from(asset).toString();
8821
+ return AccountAddress7.from(asset).toString();
8369
8822
  }
8370
8823
 
8371
8824
  // src/utils/cache.ts
@@ -8524,7 +8977,9 @@ async function checkForUpdatesAsync() {
8524
8977
  var providerPromise;
8525
8978
  function getErasureCodingProvider() {
8526
8979
  if (!providerPromise) {
8527
- providerPromise = ClayErasureCodingProvider.create();
8980
+ providerPromise = ClayErasureCodingProvider.create(
8981
+ defaultErasureCodingConfig()
8982
+ );
8528
8983
  }
8529
8984
  return providerPromise;
8530
8985
  }
@@ -8869,9 +9324,9 @@ var InitWizard = ({
8869
9324
  if (setupStandardContexts) {
8870
9325
  const modifiedStandardContexts = { ...DEFAULT_CONFIG.contexts };
8871
9326
  if (standardContextsApiKey) {
8872
- if (modifiedStandardContexts[Network7.SHELBYNET]) {
8873
- modifiedStandardContexts[Network7.SHELBYNET] = {
8874
- ...modifiedStandardContexts[Network7.SHELBYNET],
9327
+ if (modifiedStandardContexts[Network8.SHELBYNET]) {
9328
+ modifiedStandardContexts[Network8.SHELBYNET] = {
9329
+ ...modifiedStandardContexts[Network8.SHELBYNET],
8875
9330
  api_key: standardContextsApiKey
8876
9331
  };
8877
9332
  }
@@ -9058,7 +9513,7 @@ var InitWizard = ({
9058
9513
  ] }),
9059
9514
  /* @__PURE__ */ jsxs6(Text6, { children: [
9060
9515
  "Enter API Key for ",
9061
- Network7.SHELBYNET,
9516
+ Network8.SHELBYNET,
9062
9517
  " (optional: press Enter to skip)"
9063
9518
  ] }),
9064
9519
  /* @__PURE__ */ jsx8(
@@ -9535,7 +9990,8 @@ function accountCommand(program) {
9535
9990
  columns: [
9536
9991
  { header: "Name", width: 30, flex: true },
9537
9992
  { header: "Size", width: 12 },
9538
- { header: "Expires", width: 25 }
9993
+ { header: "Expires", width: 25 },
9994
+ { header: "Status", width: 10 }
9539
9995
  ],
9540
9996
  padding: 12
9541
9997
  });
@@ -9552,7 +10008,8 @@ function accountCommand(program) {
9552
10008
  minute: "2-digit",
9553
10009
  hour12: true
9554
10010
  });
9555
- const row = [displayName, formattedSize, formattedDate];
10011
+ const status = blob.isWritten ? "Written" : "Pending";
10012
+ const row = [displayName, formattedSize, formattedDate, status];
9556
10013
  table.push(row.map((cell, i) => wrapCell(cell, i)));
9557
10014
  }
9558
10015
  console.log(table.toString());
@@ -10469,14 +10926,15 @@ import { z as z17 } from "zod";
10469
10926
 
10470
10927
  // src/utils/micropayment-manager.ts
10471
10928
  import crypto2 from "crypto";
10472
- import { AccountAddress as AccountAddress11 } from "@aptos-labs/ts-sdk";
10929
+ import { AccountAddress as AccountAddress9 } from "@aptos-labs/ts-sdk";
10473
10930
 
10474
10931
  // src/utils/micropayment-storage.ts
10475
10932
  import os3 from "os";
10476
10933
  import path5 from "path";
10477
10934
  import {
10478
- AccountAddress as AccountAddress10,
10479
- Ed25519PublicKey
10935
+ AccountAddress as AccountAddress8,
10936
+ Ed25519PublicKey,
10937
+ Ed25519Signature
10480
10938
  } from "@aptos-labs/ts-sdk";
10481
10939
  import fs6 from "fs-extra";
10482
10940
  var MICROPAYMENTS_DIR = path5.join(os3.homedir(), ".shelby", "micropayments");
@@ -10511,95 +10969,38 @@ function saveLastMicropayment(sender, receiver, asset, micropayment) {
10511
10969
  fs6.writeFileSync(filePath, base64, "utf-8");
10512
10970
  }
10513
10971
  function extractMicropaymentParams(micropayment) {
10514
- const rawTxn = micropayment.micropayment.rawTransaction;
10515
- const payload = rawTxn.payload;
10516
- const args = payload.entryFunction.args;
10517
- const amountBytes = args[0].bcsToBytes();
10518
- const paymentChannelIdBytes = args[1].bcsToBytes();
10519
- const sequenceNumberBytes = args[2].bcsToBytes();
10520
- const amount = Number(
10521
- new DataView(amountBytes.buffer, amountBytes.byteOffset, 8).getBigUint64(
10522
- 0,
10523
- true
10524
- )
10525
- );
10526
- const paymentChannelId = Number(
10527
- new DataView(
10528
- paymentChannelIdBytes.buffer,
10529
- paymentChannelIdBytes.byteOffset,
10530
- 8
10531
- ).getBigUint64(0, true)
10532
- );
10533
- const sequenceNumber = Number(
10534
- new DataView(
10535
- sequenceNumberBytes.buffer,
10536
- sequenceNumberBytes.byteOffset,
10537
- 8
10538
- ).getBigUint64(0, true)
10539
- );
10540
- const fungibleAssetAddress = AccountAddress10.from(
10541
- args[3].bcsToHex().toString()
10542
- );
10543
10972
  return {
10544
- amount,
10545
- paymentChannelId,
10546
- sequenceNumber,
10547
- fungibleAssetAddress
10973
+ amount: Number(micropayment.amount),
10974
+ paymentChannelId: Number(micropayment.paymentChannelId),
10975
+ sequenceNumber: Number(micropayment.sequenceNumber),
10976
+ fungibleAssetAddress: micropayment.fungibleAssetAddress
10548
10977
  };
10549
10978
  }
10550
- function validateReceivedMicropayment(micropayment, expectedSender, expectedReceiver, signingMessage) {
10551
- const rawTxn = micropayment.micropayment.rawTransaction;
10552
- const senderSignature = micropayment.senderSignature;
10553
- if (!senderSignature.isEd25519()) {
10554
- throw new Error("Invalid micropayment: signature is not Ed25519");
10555
- }
10556
- const senderPubKey = new Ed25519PublicKey(
10557
- senderSignature.public_key.toString()
10558
- );
10559
- if (!senderPubKey.verifySignature({
10560
- message: signingMessage,
10561
- signature: senderSignature.signature
10562
- })) {
10563
- throw new Error("Invalid micropayment: signature verification failed");
10564
- }
10565
- const derivedAddress = senderPubKey.authKey().derivedAddress();
10566
- if (!derivedAddress.equals(expectedSender)) {
10979
+ function validateReceivedMicropayment(micropayment, expectedSender, expectedReceiver) {
10980
+ if (!micropayment.sender.equals(expectedSender)) {
10567
10981
  throw new Error(
10568
10982
  "Invalid micropayment: sender address does not match expected sender"
10569
10983
  );
10570
10984
  }
10571
- if (!rawTxn.sender.equals(expectedSender)) {
10572
- throw new Error(
10573
- "Invalid micropayment: transaction sender does not match expected sender"
10574
- );
10575
- }
10576
- const isReceiverInSecondarySigners = micropayment.micropayment.secondarySignerAddresses.some(
10577
- (addr) => addr.equals(expectedReceiver)
10578
- );
10579
- if (!isReceiverInSecondarySigners) {
10580
- throw new Error(
10581
- "Invalid micropayment: expected receiver not found in secondary signers"
10582
- );
10583
- }
10584
- if (!("entryFunction" in rawTxn.payload)) {
10985
+ if (!micropayment.receiver.equals(expectedReceiver)) {
10585
10986
  throw new Error(
10586
- "Invalid micropayment: transaction payload is not an entry function"
10987
+ "Invalid micropayment: receiver address does not match expected receiver"
10587
10988
  );
10588
10989
  }
10589
- const entryFunction = rawTxn.payload.entryFunction;
10590
- if (!AccountAddress10.from(entryFunction.module_name.address).equals(
10591
- AccountAddress10.from(MICROPAYMENTS_DEPLOYER)
10592
- )) {
10990
+ if (!micropayment.deployer.equals(AccountAddress8.from(MICROPAYMENTS_DEPLOYER))) {
10593
10991
  throw new Error("Invalid micropayment: incorrect deployer address");
10594
10992
  }
10595
- if (entryFunction.module_name.name.identifier !== "micropayments") {
10596
- throw new Error("Invalid micropayment: incorrect module name");
10597
- }
10598
- if (entryFunction.function_name.identifier !== "receiver_withdraw") {
10599
- throw new Error("Invalid micropayment: incorrect function name");
10993
+ const pubKey = new Ed25519PublicKey(micropayment.publicKey);
10994
+ const signature = new Ed25519Signature(micropayment.signature);
10995
+ const message = micropayment.getSignedMessage();
10996
+ if (!pubKey.verifySignature({ message, signature })) {
10997
+ throw new Error("Invalid micropayment: signature verification failed");
10600
10998
  }
10601
- if (entryFunction.args.length !== 4) {
10602
- throw new Error("Invalid micropayment: incorrect number of arguments");
10999
+ const derivedAddress = pubKey.authKey().derivedAddress();
11000
+ if (!derivedAddress.equals(expectedSender)) {
11001
+ throw new Error(
11002
+ "Invalid micropayment: public key does not derive to expected sender address"
11003
+ );
10603
11004
  }
10604
11005
  }
10605
11006
 
@@ -10619,7 +11020,7 @@ var MicropaymentManager = class {
10619
11020
  this.micropaymentClient = micropaymentClient;
10620
11021
  this.sender = sender;
10621
11022
  this.receiver = receiver;
10622
- this.fungibleAssetAddress = AccountAddress11.from(
11023
+ this.fungibleAssetAddress = AccountAddress9.from(
10623
11024
  SHELBYUSD_FA_METADATA_ADDRESS
10624
11025
  );
10625
11026
  }
@@ -10718,22 +11119,20 @@ var MicropaymentManager = class {
10718
11119
  /**
10719
11120
  * Creates a micropayment for the next request.
10720
11121
  */
10721
- async createMicropayment() {
11122
+ createMicropayment() {
10722
11123
  if (!this.channelInfo) {
10723
11124
  throw new Error("Channel not initialized");
10724
11125
  }
10725
11126
  const newAmount = this.currentAmount + MICROPAYMENT_INCREMENT_PER_REQUEST;
10726
11127
  const newSequenceNumber = this.nextSequenceNumber;
10727
- const micropayment = await this.micropaymentClient.createMicropayment({
11128
+ return this.micropaymentClient.createMicropayment({
10728
11129
  sender: this.sender,
10729
11130
  receiver: this.receiver,
10730
11131
  amount: newAmount,
10731
11132
  paymentChannelId: this.channelInfo.paymentChannelId,
10732
11133
  sequenceNumber: newSequenceNumber,
10733
- fungibleAssetAddress: this.fungibleAssetAddress,
10734
- options: { replayProtectionNonce: crypto2.randomInt(2 ** 24) }
11134
+ fungibleAssetAddress: this.fungibleAssetAddress
10735
11135
  });
10736
- return micropayment;
10737
11136
  }
10738
11137
  /**
10739
11138
  * Called after a successful request to update local state.
@@ -10753,14 +11152,10 @@ var MicropaymentManager = class {
10753
11152
  * Called when a stale error is received to update local state from the server's stored payment.
10754
11153
  */
10755
11154
  onStaleError(storedMicropayment) {
10756
- const signingMessage = this.micropaymentClient.aptos.getSigningMessage({
10757
- transaction: storedMicropayment.micropayment
10758
- });
10759
11155
  validateReceivedMicropayment(
10760
11156
  storedMicropayment,
10761
11157
  this.sender.accountAddress,
10762
- this.receiver,
10763
- signingMessage
11158
+ this.receiver
10764
11159
  );
10765
11160
  const params = extractMicropaymentParams(storedMicropayment);
10766
11161
  this.currentAmount = params.amount;
@@ -10783,7 +11178,7 @@ async function createMicropaymentManager(context, sender) {
10783
11178
  apiKey: context.api_key,
10784
11179
  aptos: getAptosSettingsFromContext(context)
10785
11180
  });
10786
- const receiver = AccountAddress11.from(receiverAddress);
11181
+ const receiver = AccountAddress9.from(receiverAddress);
10787
11182
  const manager = new MicropaymentManager(micropaymentClient, sender, receiver);
10788
11183
  await manager.initialize();
10789
11184
  return manager;
@@ -11300,12 +11695,12 @@ function downloadCommand(program) {
11300
11695
  }
11301
11696
 
11302
11697
  // src/commands/faucet.tsx
11303
- import { Network as Network8 } from "@aptos-labs/ts-sdk";
11698
+ import { Network as Network9 } from "@aptos-labs/ts-sdk";
11304
11699
  import { Option as Option2 } from "@commander-js/extra-typings";
11305
11700
  import { execaSync } from "execa";
11306
11701
  import { z as z18 } from "zod";
11307
11702
  var FaucetOptionsSchema = z18.object({
11308
- network: z18.enum([Network8.SHELBYNET]).optional(),
11703
+ network: z18.enum([Network9.SHELBYNET, Network9.TESTNET]).optional(),
11309
11704
  open: z18.boolean().optional().default(true)
11310
11705
  });
11311
11706
  function faucetCommand(program) {
@@ -11313,7 +11708,7 @@ function faucetCommand(program) {
11313
11708
  new Option2(
11314
11709
  "--network <network>",
11315
11710
  "Network to request tokens for (shelbynet)"
11316
- ).choices(Object.values(Network8))
11711
+ ).choices(Object.values(Network9))
11317
11712
  ).addOption(
11318
11713
  new Option2(
11319
11714
  "--no-open",
@@ -11325,7 +11720,7 @@ function faucetCommand(program) {
11325
11720
  const { config } = loadConfigOrExit(program.opts().configFile);
11326
11721
  const accountName = program.opts().account || config.default_account;
11327
11722
  const { account } = getCurrentAccount(config, accountName);
11328
- const network = validatedOptions.network || Network8.SHELBYNET;
11723
+ const network = validatedOptions.network || Network9.SHELBYNET;
11329
11724
  if (network === "mainnet") {
11330
11725
  throw new Error(
11331
11726
  "\u274C No faucet available for mainnet. Mainnet tokens must be obtained through other means."
@@ -11387,7 +11782,7 @@ function openBrowser(url) {
11387
11782
 
11388
11783
  // src/commands/init.tsx
11389
11784
  import path7 from "path";
11390
- import { Network as Network9 } from "@aptos-labs/ts-sdk";
11785
+ import { Network as Network10 } from "@aptos-labs/ts-sdk";
11391
11786
  import fs8 from "fs-extra";
11392
11787
  import { render as render4 } from "ink";
11393
11788
  import { jsx as jsx13 } from "react/jsx-runtime";
@@ -11459,7 +11854,7 @@ function initCommand(program) {
11459
11854
  console.log(` Private key: ${generated.privateKey.toAIP80String()}`);
11460
11855
  console.log("");
11461
11856
  console.log(
11462
- `\u2139\uFE0F To fund your new account on-chain (${Network9.SHELBYNET} only), run:`
11857
+ `\u2139\uFE0F To fund your new account on-chain (${Network10.SHELBYNET} only), run:`
11463
11858
  );
11464
11859
  console.log(" \u{1F449} shelby faucet");
11465
11860
  console.log("");
@@ -11490,7 +11885,7 @@ function initCommand(program) {
11490
11885
  )) {
11491
11886
  console.log("");
11492
11887
  console.log(
11493
- `\u2139\uFE0F To fund your new account on-chain (${Network9.SHELBYNET} only), run:`
11888
+ `\u2139\uFE0F To fund your new account on-chain (${Network10.SHELBYNET} only), run:`
11494
11889
  );
11495
11890
  console.log(" \u{1F449} shelby faucet");
11496
11891
  }