@shelby-protocol/sdk 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/browser/index.d.ts +9 -9
  2. package/dist/browser/index.mjs +1068 -589
  3. package/dist/core/clients/ShelbyBlobClient.d.ts +155 -40
  4. package/dist/core/clients/ShelbyBlobClient.mjs +314 -112
  5. package/dist/core/clients/ShelbyClient.d.ts +27 -4
  6. package/dist/core/clients/ShelbyClient.mjs +869 -551
  7. package/dist/core/clients/ShelbyClientConfig.d.ts +9 -1
  8. package/dist/core/clients/ShelbyMetadataClient.d.ts +38 -6
  9. package/dist/core/clients/ShelbyMetadataClient.mjs +95 -13
  10. package/dist/core/clients/ShelbyMicropaymentChannelClient.d.ts +42 -0
  11. package/dist/core/clients/ShelbyMicropaymentChannelClient.mjs +62 -7
  12. package/dist/core/clients/ShelbyPlacementGroupClient.mjs +10 -7
  13. package/dist/core/clients/ShelbyRPCClient.d.ts +55 -66
  14. package/dist/core/clients/ShelbyRPCClient.mjs +344 -360
  15. package/dist/core/clients/index.d.ts +3 -2
  16. package/dist/core/clients/index.mjs +933 -551
  17. package/dist/core/clients/utils.mjs +1 -1
  18. package/dist/core/commitments.d.ts +12 -1
  19. package/dist/core/commitments.mjs +7 -0
  20. package/dist/core/constants.d.ts +1 -1
  21. package/dist/core/constants.mjs +1 -1
  22. package/dist/core/erasure/constants.d.ts +16 -1
  23. package/dist/core/erasure/constants.mjs +15 -1
  24. package/dist/core/erasure/index.d.ts +1 -1
  25. package/dist/core/erasure/index.mjs +15 -1
  26. package/dist/core/errors.d.ts +20 -1
  27. package/dist/core/errors.mjs +29 -0
  28. package/dist/core/index.d.ts +9 -9
  29. package/dist/core/index.mjs +1068 -589
  30. package/dist/core/operations/generated/sdk.d.ts +798 -42
  31. package/dist/core/operations/generated/sdk.mjs +93 -9
  32. package/dist/core/operations/index.d.ts +1 -1
  33. package/dist/core/operations/index.mjs +94 -10
  34. package/dist/core/rpc-responses.d.ts +1 -57
  35. package/dist/core/rpc-responses.mjs +1 -21
  36. package/dist/core/sp/chunk_proof.d.ts +23 -0
  37. package/dist/core/sp/chunk_proof.mjs +113 -0
  38. package/dist/core/sp/index.d.ts +3 -0
  39. package/dist/core/sp/index.mjs +402 -0
  40. package/dist/core/sp/sp_write_client.d.ts +53 -0
  41. package/dist/core/sp/sp_write_client.mjs +302 -0
  42. package/dist/core/types/blobs.d.ts +24 -5
  43. package/dist/core/types/blobs.mjs +24 -0
  44. package/dist/core/types/index.d.ts +2 -2
  45. package/dist/core/types/index.mjs +46 -2
  46. package/dist/core/types/payments.mjs +1 -1
  47. package/dist/core/types/storage_providers.d.ts +32 -6
  48. package/dist/core/types/storage_providers.mjs +22 -0
  49. package/dist/gen/rpc_server_pb.d.ts +295 -0
  50. package/dist/gen/rpc_server_pb.mjs +28 -0
  51. package/dist/node/clients/ShelbyNodeClient.d.ts +1 -0
  52. package/dist/node/clients/ShelbyNodeClient.mjs +869 -551
  53. package/dist/node/clients/index.d.ts +1 -0
  54. package/dist/node/clients/index.mjs +867 -551
  55. package/dist/node/index.d.ts +9 -9
  56. package/dist/node/index.mjs +1068 -589
  57. package/dist/node/parallel/commitment_worker.mjs +36 -249
  58. package/dist/node/parallel/commitment_worker_pool.mjs +56 -3
  59. package/dist/node/parallel/coverage_flush.d.ts +16 -0
  60. package/dist/node/parallel/coverage_flush.mjs +43 -0
  61. package/dist/node/parallel/default_commitment_worker_pool.mjs +56 -3
  62. package/dist/node/parallel/index.d.ts +1 -0
  63. package/dist/node/parallel/index.mjs +72 -4
  64. package/dist/node/parallel/parallel_commitments.mjs +56 -3
  65. package/dist/node/parallel/worker_pool.mjs +56 -3
  66. package/package.json +11 -4
@@ -122,7 +122,7 @@ var BlobCommitmentsSchema = z.object({
122
122
  // src/core/constants.ts
123
123
  import { Network } from "@aptos-labs/ts-sdk";
124
124
  var NetworkToShelbyRPCBaseUrl = {
125
- [Network.SHELBYNET]: "https://api.shelbynet.shelby.xyz/shelby",
125
+ [Network.SHELBYNET]: "https://shelby.shelbynet.shelby.xyz/shelby",
126
126
  [Network.NETNA]: void 0,
127
127
  [Network.DEVNET]: void 0,
128
128
  [Network.TESTNET]: "https://api.testnet.shelby.xyz/shelby",
@@ -150,6 +150,27 @@ var NetworkToGasStationBaseUrl = {
150
150
  };
151
151
  var SHELBY_DEPLOYER = "0x85fdb9a176ab8ef1d9d9c1b60d60b3924f0800ac1de1cc2085fb0b8bb4988e6a";
152
152
 
153
+ // src/core/types/blobs.ts
154
+ var BLOB_ENCRYPTION_TO_MOVE_ENUM_INDEX = {
155
+ Unencrypted: 0,
156
+ AES_GCM_V1: 1
157
+ };
158
+ function blobEncryptionToMoveEnumIndex(encryption) {
159
+ return BLOB_ENCRYPTION_TO_MOVE_ENUM_INDEX[encryption];
160
+ }
161
+ function blobEncryptionFromMoveVariant(variant) {
162
+ switch (variant) {
163
+ case "Unencrypted":
164
+ return "Unencrypted";
165
+ case "AES_GCM_V1":
166
+ return "AES_GCM_V1";
167
+ default:
168
+ throw new Error(
169
+ "Could not parse encryption from Shelby Smart Contract, this SDK is out of date."
170
+ );
171
+ }
172
+ }
173
+
153
174
  // src/core/erasure/clay-codes.ts
154
175
  import {
155
176
  createDecoder,
@@ -226,18 +247,20 @@ import gql from "graphql-tag";
226
247
  var GetBlobsDocument = gql`
227
248
  query getBlobs($where: blobs_bool_exp, $orderBy: [blobs_order_by!], $limit: Int, $offset: Int) {
228
249
  blobs(where: $where, order_by: $orderBy, limit: $limit, offset: $offset) {
250
+ uid
251
+ object_name
229
252
  owner
230
253
  blob_commitment
231
- blob_name
232
254
  created_at
233
255
  expires_at
256
+ updated_at
234
257
  num_chunksets
235
- is_deleted
236
- is_written
237
- placement_group
238
258
  size
239
- updated_at
240
259
  slice_address
260
+ placement_group
261
+ is_persisted
262
+ is_committed
263
+ is_deleted
241
264
  }
242
265
  }
243
266
  `;
@@ -249,7 +272,8 @@ var GetBlobActivitiesDocument = gql`
249
272
  limit: $limit
250
273
  offset: $offset
251
274
  ) {
252
- blob_name
275
+ uid
276
+ object_name
253
277
  event_index
254
278
  event_type
255
279
  transaction_hash
@@ -395,6 +419,33 @@ var MissingTransactionSubmitterError = class extends Error {
395
419
  this.name = "MissingTransactionSubmitterError";
396
420
  }
397
421
  };
422
+ var COMMIT_REJECTION_REASONS = /* @__PURE__ */ new Set([
423
+ "AlreadyExists",
424
+ "NoPriorVersion",
425
+ "EtagMismatch"
426
+ ]);
427
+ var ObjectCommitRejectedError = class extends Error {
428
+ constructor(blobName, uid, reason) {
429
+ super(
430
+ `commit_object rejected the write for '${blobName}' (uid ${uid}): ${reason}`
431
+ );
432
+ this.blobName = blobName;
433
+ this.uid = uid;
434
+ this.reason = reason;
435
+ this.name = "ObjectCommitRejectedError";
436
+ }
437
+ };
438
+ function encryptionFunctionArgs(params) {
439
+ if (params.omitEncryptionArg) {
440
+ if (params.encryption && params.encryption !== "Unencrypted") {
441
+ throw new Error(
442
+ `Blob encryption (${params.encryption}) is not supported on this network: the deployed contract predates the encryption upgrade (#1739).`
443
+ );
444
+ }
445
+ return [];
446
+ }
447
+ return [blobEncryptionToMoveEnumIndex(params.encryption ?? "Unencrypted")];
448
+ }
398
449
  var ShelbyBlobClient = class _ShelbyBlobClient {
399
450
  aptos;
400
451
  deployer;
@@ -443,7 +494,10 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
443
494
  this.aptos = new Aptos(getAptosConfig(config));
444
495
  this.deployer = config.deployer ?? AccountAddress2.fromString(SHELBY_DEPLOYER);
445
496
  this.indexer = getShelbyIndexerClient(config);
446
- this.defaultOptions = defaultOptions ?? {};
497
+ this.defaultOptions = {
498
+ locationHint: config.locationHint,
499
+ ...defaultOptions
500
+ };
447
501
  this.orderless = config.orderless ?? false;
448
502
  }
449
503
  /**
@@ -454,7 +508,9 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
454
508
  build: options?.build ?? this.defaultOptions.build,
455
509
  submit: options?.submit ?? this.defaultOptions.submit,
456
510
  usdSponsor: options?.usdSponsor ?? this.defaultOptions.usdSponsor,
457
- chunksetSizeBytes: options?.chunksetSizeBytes ?? this.defaultOptions.chunksetSizeBytes
511
+ chunksetSizeBytes: options?.chunksetSizeBytes ?? this.defaultOptions.chunksetSizeBytes,
512
+ selectedLocation: options?.selectedLocation ?? this.defaultOptions.selectedLocation,
513
+ locationHint: options?.locationHint ?? this.defaultOptions.locationHint
458
514
  };
459
515
  }
460
516
  /**
@@ -496,17 +552,17 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
496
552
  *
497
553
  * @example
498
554
  * ```typescript
499
- * const metadata = await client.getBlobMetadata({
555
+ * const metadata = await client.getFullObjectMetadata({
500
556
  * account: AccountAddress.fromString("0x1"),
501
557
  * name: "foo/bar.txt",
502
558
  * });
503
559
  * ```
504
560
  */
505
- async getBlobMetadata(params) {
561
+ async getFullObjectMetadata(params) {
506
562
  try {
507
563
  const rawMetadata = await this.aptos.view({
508
564
  payload: {
509
- function: `${this.deployer.toString()}::blob_metadata::get_blob_metadata`,
565
+ function: `${this.deployer.toString()}::blob_metadata::get_full_object_metadata`,
510
566
  functionArguments: [
511
567
  createBlobKey({
512
568
  account: params.account,
@@ -518,47 +574,94 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
518
574
  if (!rawMetadata?.[0]?.vec?.[0]) {
519
575
  return void 0;
520
576
  }
521
- const metadata = rawMetadata[0].vec[0];
522
- let encoding;
523
- if (metadata.encoding.__variant__ === "ClayCode_16Total_10Data_13Helper") {
524
- encoding = {
525
- variant: "clay",
526
- ...ERASURE_CODE_PARAMS[metadata.encoding.__variant__],
527
- ...ERASURE_CODE_AND_CHUNK_MAPPING[metadata.encoding.__variant__]
528
- };
529
- } else if (metadata.encoding.__variant__ === "ClayCode_4Total_2Data_3Helper") {
530
- encoding = {
531
- variant: "clay",
532
- ...ERASURE_CODE_PARAMS[metadata.encoding.__variant__],
533
- ...ERASURE_CODE_AND_CHUNK_MAPPING[metadata.encoding.__variant__]
534
- };
535
- } else {
536
- throw new Error(
537
- "Could not parse encoding from Shelby Smart Contract, this SDK is out of date."
538
- );
539
- }
540
- return {
541
- blobMerkleRoot: Hex3.fromHexInput(
542
- metadata.blob_commitment
543
- ).toUint8Array(),
544
- owner: normalizeAddress(metadata.owner),
577
+ const view = rawMetadata[0].vec[0];
578
+ return this.parseBlobMetadata(view.blob_metadata, {
579
+ uid: BigInt(view.object_metadata.current_blob_uid),
545
580
  name: params.name,
546
- blobNameSuffix: getBlobNameSuffix(params.name),
547
- size: Number(metadata.blob_size),
548
- encoding,
549
- expirationMicros: Number(metadata.expiration_micros),
550
- creationMicros: Number(metadata.creation_micros),
551
- sliceAddress: normalizeAddress(metadata.slice.inner),
552
- isWritten: metadata.is_written
553
- };
581
+ // Any blob bound under an object name has cleared the commit-time
582
+ // `is_written()` check, so a resolved object is always written.
583
+ isWritten: true
584
+ });
554
585
  } catch (error) {
555
586
  if (error instanceof Error && // Depending on the network, the error message may show up differently.
556
- (error.message?.includes("sub_status: Some(404)") || error.message?.includes("EBLOB_NOT_FOUND"))) {
587
+ (error.message?.includes("sub_status: Some(404)") || error.message?.includes("EBLOB_NOT_FOUND") || error.message?.includes("EOBJECT_NOT_FOUND"))) {
557
588
  return void 0;
558
589
  }
559
590
  throw error;
560
591
  }
561
592
  }
593
+ /**
594
+ * Retrieves blob metadata directly by its on-chain UID, including blobs in
595
+ * the pending (registered-but-not-yet-committed) state that
596
+ * {@link getFullObjectMetadata} cannot resolve by object name. Returns `undefined`
597
+ * if no blob has that UID.
598
+ *
599
+ * The returned `name`/`blobNameSuffix` are empty: the blob layer is keyed by
600
+ * UID and carries no object name (a name binding is established only at
601
+ * commit). `isWritten` reflects whether the blob has been committed.
602
+ */
603
+ async getFullObjectMetadataByUid(uid) {
604
+ try {
605
+ const rawMetadata = await this.aptos.view(
606
+ {
607
+ payload: {
608
+ function: `${this.deployer.toString()}::blob_metadata::get_blob_metadata`,
609
+ functionArguments: [uid]
610
+ }
611
+ }
612
+ );
613
+ if (!rawMetadata?.[0]?.vec?.[0]) {
614
+ return void 0;
615
+ }
616
+ const raw = rawMetadata[0].vec[0];
617
+ return this.parseBlobMetadata(raw, {
618
+ uid,
619
+ name: "",
620
+ isWritten: raw.state.__variant__ === "CommittedObject"
621
+ });
622
+ } catch (error) {
623
+ if (error instanceof Error && (error.message?.includes("sub_status: Some(404)") || error.message?.includes("EBLOB_NOT_FOUND"))) {
624
+ return void 0;
625
+ }
626
+ throw error;
627
+ }
628
+ }
629
+ /**
630
+ * Parse the on-chain `BlobMetadata::V1` view shape into the SDK
631
+ * {@link FullObjectMetadata}. `uid` / `name` / `isWritten` are supplied by the
632
+ * caller since they depend on the lookup path (by object name vs by UID).
633
+ */
634
+ parseBlobMetadata(raw, extra) {
635
+ const { content } = raw;
636
+ const variant = content.encoding.__variant__;
637
+ if (variant !== "ClayCode_16Total_10Data_13Helper" && variant !== "ClayCode_4Total_2Data_3Helper") {
638
+ throw new Error(
639
+ "Could not parse encoding from Shelby Smart Contract, this SDK is out of date."
640
+ );
641
+ }
642
+ const encoding = {
643
+ variant: "clay",
644
+ ...ERASURE_CODE_PARAMS[variant],
645
+ ...ERASURE_CODE_AND_CHUNK_MAPPING[variant]
646
+ };
647
+ const encryption = blobEncryptionFromMoveVariant(
648
+ content.encryption?.__variant__ ?? "Unencrypted"
649
+ );
650
+ return {
651
+ uid: extra.uid,
652
+ blobMerkleRoot: Hex3.fromHexInput(content.blob_commitment).toUint8Array(),
653
+ owner: normalizeAddress(raw.owner),
654
+ name: extra.name,
655
+ blobNameSuffix: extra.name ? getBlobNameSuffix(extra.name) : "",
656
+ size: Number(content.blob_size),
657
+ encoding,
658
+ encryption,
659
+ expirationMicros: Number(raw.expiration_micros),
660
+ creationMicros: Number(raw.creation_micros),
661
+ sliceAddress: normalizeAddress(raw.slice.inner),
662
+ isWritten: extra.isWritten
663
+ };
664
+ }
562
665
  /**
563
666
  * Retrieves all the blobs and their metadata for an account from the
564
667
  * blockchain.
@@ -570,7 +673,7 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
570
673
  *
571
674
  * @example
572
675
  * ```typescript
573
- * // BlobMetadata[]
676
+ * // FullObjectMetadata[]
574
677
  * const blobs = await client.getAccountBlobs({
575
678
  * account: AccountAddress.fromString("0x1"),
576
679
  * });
@@ -587,6 +690,25 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
587
690
  orderBy: rest.orderBy
588
691
  });
589
692
  }
693
+ /**
694
+ * Object-facing default filter: only committed, non-deleted, unexpired rows.
695
+ * The blobs table is UID-keyed, so during an atomic overwrite a single
696
+ * object_name transiently has two non-deleted rows — the currently committed
697
+ * blob and the new pending (is_committed = "0") blob. Filtering on
698
+ * is_committed keeps name lookups/listings pinned to the committed object and
699
+ * avoids returning or duplicating the in-flight pending row. Applied to
700
+ * getBlobs *and* the getBlobsCount / getTotalBlobsSize aggregates so counts
701
+ * and sizes agree with the listing mid-overwrite. Callers can override any
702
+ * key (e.g. is_committed) via their own `where`.
703
+ */
704
+ activeBlobsWhere(where) {
705
+ const defaultActiveFilter = {
706
+ expires_at: { _gte: String(Date.now() * 1e3) },
707
+ is_deleted: { _eq: "0" },
708
+ is_committed: { _eq: "1" }
709
+ };
710
+ return { ...defaultActiveFilter, ...where };
711
+ }
590
712
  /**
591
713
  * Retrieves blobs and their metadata from the blockchain.
592
714
  *
@@ -597,7 +719,7 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
597
719
  *
598
720
  * @example
599
721
  * ```typescript
600
- * // BlobMetadata[]
722
+ * // FullObjectMetadata[]
601
723
  * const blobs = await client.getBlobs({
602
724
  * where: { owner: { _eq: AccountAddress.fromString("0x1").toString() } },
603
725
  * });
@@ -606,12 +728,7 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
606
728
  async getBlobs(params = {}) {
607
729
  const { limit, offset } = params.pagination ?? {};
608
730
  const { orderBy, where } = params;
609
- const currentMicros = String(Date.now() * 1e3);
610
- const defaultActiveFilter = {
611
- expires_at: { _gte: currentMicros },
612
- is_deleted: { _eq: "0" }
613
- };
614
- const finalWhere = where !== void 0 ? { ...defaultActiveFilter, ...where } : defaultActiveFilter;
731
+ const finalWhere = this.activeBlobsWhere(where);
615
732
  const { blobs } = await this.indexer.getBlobs({
616
733
  where: finalWhere,
617
734
  limit,
@@ -620,9 +737,10 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
620
737
  });
621
738
  return blobs.map(
622
739
  (blob) => ({
740
+ uid: BigInt(blob.uid),
623
741
  owner: normalizeAddress(blob.owner),
624
- name: blob.blob_name,
625
- blobNameSuffix: getBlobNameSuffix(blob.blob_name),
742
+ name: blob.object_name,
743
+ blobNameSuffix: getBlobNameSuffix(blob.object_name),
626
744
  blobMerkleRoot: Hex3.fromHexInput(blob.blob_commitment).toUint8Array(),
627
745
  size: Number(blob.size),
628
746
  // TODO: Add encoding when supported in NCI
@@ -634,7 +752,7 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
634
752
  expirationMicros: Number(blob.expires_at),
635
753
  creationMicros: Number(blob.created_at),
636
754
  sliceAddress: normalizeAddress(blob.slice_address),
637
- isWritten: Boolean(Number(blob.is_written)),
755
+ isWritten: Boolean(Number(blob.is_persisted)),
638
756
  isDeleted: Boolean(Number(blob.is_deleted))
639
757
  })
640
758
  );
@@ -652,12 +770,15 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
652
770
  [`${this.deployer.toStringLong()}::blob_metadata::BlobRegisteredEvent`]: "register_blob",
653
771
  [`${this.deployer.toStringLong()}::blob_metadata::BlobDeletedEvent`]: "delete_blob",
654
772
  [`${this.deployer.toStringLong()}::blob_metadata::BlobExpirationExtendedEvent`]: "extend_blob_expiration",
655
- [`${this.deployer.toStringLong()}::blob_metadata::BlobWrittenEvent`]: "write_blob"
773
+ [`${this.deployer.toStringLong()}::blob_metadata::BlobPersistedEvent`]: "write_blob",
774
+ [`${this.deployer.toStringLong()}::blob_metadata::ObjectCommittedEvent`]: "commit_object",
775
+ [`${this.deployer.toStringLong()}::blob_metadata::ObjectDeletedEvent`]: "delete_object",
776
+ [`${this.deployer.toStringLong()}::blob_metadata::ObjectCommitRejectedEvent`]: "reject_object_commit"
656
777
  };
657
778
  return blob_activities.map(
658
779
  (activity) => ({
659
- blobName: activity.blob_name,
660
- accountAddress: normalizeAddress(activity.blob_name.substring(1, 65)),
780
+ blobName: activity.object_name,
781
+ accountAddress: normalizeAddress(activity.object_name.substring(1, 65)),
661
782
  type: activityTypeMapping[activity.event_type] ?? "unknown",
662
783
  eventType: activity.event_type,
663
784
  eventIndex: Number(activity.event_index),
@@ -680,9 +801,10 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
680
801
  * const count = await client.getBlobsCount();
681
802
  * ```
682
803
  */
683
- async getBlobsCount(params) {
684
- const { where } = params;
685
- const { blobs_aggregate } = await this.indexer.getBlobsCount({ where });
804
+ async getBlobsCount(params = {}) {
805
+ const { blobs_aggregate } = await this.indexer.getBlobsCount({
806
+ where: this.activeBlobsWhere(params.where)
807
+ });
686
808
  return blobs_aggregate?.aggregate?.count ?? 0;
687
809
  }
688
810
  /**
@@ -697,8 +819,9 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
697
819
  * ```
698
820
  */
699
821
  async getTotalBlobsSize(params = {}) {
700
- const { where } = params;
701
- const { blobs_aggregate } = await this.indexer.getTotalBlobsSize({ where });
822
+ const { blobs_aggregate } = await this.indexer.getTotalBlobsSize({
823
+ where: this.activeBlobsWhere(params.where)
824
+ });
702
825
  return Number(blobs_aggregate?.aggregate?.sum?.size ?? 0);
703
826
  }
704
827
  /**
@@ -757,12 +880,15 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
757
880
  deployer: this.deployer,
758
881
  account: params.account.accountAddress,
759
882
  blobName: params.blobName,
883
+ selectedLocation: options.selectedLocation,
884
+ locationHint: options.locationHint,
760
885
  blobSize: params.size,
761
886
  blobMerkleRoot: params.blobMerkleRoot,
762
887
  numChunksets: expectedTotalChunksets(params.size, chunksetSize),
763
888
  expirationMicros: params.expirationMicros,
764
889
  useSponsoredUsdVariant: options.usdSponsor !== void 0,
765
- encoding: config.enumIndex
890
+ encoding: config.enumIndex,
891
+ encryption: params.encryption
766
892
  }),
767
893
  sender: params.account.accountAddress
768
894
  };
@@ -790,16 +916,16 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
790
916
  * @example
791
917
  * ```typescript
792
918
  *
793
- * const { transaction } = await client.deleteBlob({
919
+ * const { transaction } = await client.deleteObject({
794
920
  * account: signer,
795
921
  * blobName: "foo/bar.txt",
796
922
  * });
797
923
  * ```
798
924
  */
799
- async deleteBlob(params) {
925
+ async deleteObject(params) {
800
926
  const transaction = await this.aptos.transaction.build.simple({
801
927
  options: this.orderlessTxOptions(params.options),
802
- data: _ShelbyBlobClient.createDeleteBlobPayload({
928
+ data: _ShelbyBlobClient.createDeleteObjectPayload({
803
929
  deployer: this.deployer,
804
930
  blobName: params.blobName
805
931
  }),
@@ -815,10 +941,6 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
815
941
  /**
816
942
  * Deletes multiple blobs on the blockchain in a single atomic transaction.
817
943
  *
818
- * **Note:** This function requires the `delete_multiple_blobs` entry function
819
- * which will be deployed to the smart contract on 2026-02-04. Using this
820
- * function before that date will result in a transaction failure.
821
- *
822
944
  * This operation is atomic: if any blob deletion fails (e.g., blob not found),
823
945
  * the entire transaction fails and no blobs are deleted.
824
946
  *
@@ -833,16 +955,16 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
833
955
  * @example
834
956
  * ```typescript
835
957
  *
836
- * const { transaction } = await client.deleteMultipleBlobs({
958
+ * const { transaction } = await client.deleteMultipleObjects({
837
959
  * account: signer,
838
960
  * blobNames: ["foo/bar.txt", "baz.txt"],
839
961
  * });
840
962
  * ```
841
963
  */
842
- async deleteMultipleBlobs(params) {
964
+ async deleteMultipleObjects(params) {
843
965
  const transaction = await this.aptos.transaction.build.simple({
844
966
  options: this.orderlessTxOptions(params.options),
845
- data: _ShelbyBlobClient.createDeleteMultipleBlobsPayload({
967
+ data: _ShelbyBlobClient.createDeleteMultipleObjectsPayload({
846
968
  deployer: this.deployer,
847
969
  blobNames: params.blobNames
848
970
  }),
@@ -900,6 +1022,8 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
900
1022
  data: _ShelbyBlobClient.createBatchRegisterBlobsPayload({
901
1023
  deployer: this.deployer,
902
1024
  account: params.account.accountAddress,
1025
+ selectedLocation: options.selectedLocation,
1026
+ locationHint: options.locationHint,
903
1027
  expirationMicros: params.expirationMicros,
904
1028
  blobs: params.blobs.map((blob) => ({
905
1029
  blobName: blob.blobName,
@@ -908,7 +1032,8 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
908
1032
  numChunksets: expectedTotalChunksets(blob.blobSize, chunksetSize)
909
1033
  })),
910
1034
  useSponsoredUsdVariant: options.usdSponsor !== void 0,
911
- encoding: config.enumIndex
1035
+ encoding: config.enumIndex,
1036
+ encryption: params.encryption
912
1037
  })
913
1038
  };
914
1039
  const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
@@ -923,6 +1048,55 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
923
1048
  })
924
1049
  };
925
1050
  }
1051
+ /**
1052
+ * Extracts the on-chain UIDs assigned at registration from a committed
1053
+ * register transaction's events.
1054
+ *
1055
+ * `register_blob` / `register_multiple_blobs` create *pending* blobs and emit
1056
+ * one `BlobRegisteredEvent` per blob. The UID is published only on this event
1057
+ * (the blob is not yet in the `objects` map, so it cannot be read back by
1058
+ * name), so callers must parse it here before uploading bytes or committing.
1059
+ *
1060
+ * @param events - The committed transaction's events (from `waitForTransaction`).
1061
+ * @param deployer - The contract deployer address.
1062
+ * @returns One entry per registered blob, keyed by its full object name
1063
+ * (`@<owner>/<suffix>`, matching {@link createBlobKey}).
1064
+ */
1065
+ static registeredBlobUids(events, deployer) {
1066
+ const eventType = `${deployer.toStringLong()}::blob_metadata::BlobRegisteredEvent`;
1067
+ return events.filter((event) => event.type === eventType).map((event) => {
1068
+ const data = event.data;
1069
+ return { objectName: data.object_name, uid: BigInt(data.uid) };
1070
+ });
1071
+ }
1072
+ /**
1073
+ * Detects whether `commit_object` rejected the write for `uid` rather than
1074
+ * applying it. A rejected commit is still a *successful* transaction — the
1075
+ * contract tears down the pending blob and emits `ObjectCommitRejectedEvent`
1076
+ * instead of aborting — so callers must inspect the finalized transaction's
1077
+ * events to tell a durable write apart from a silent no-op.
1078
+ *
1079
+ * @param events - The committed transaction's events (from `waitForTransaction`).
1080
+ * @param deployer - The contract deployer address.
1081
+ * @param uid - The UID passed to `commit_object`.
1082
+ * @returns The rejection reason, or `undefined` if the commit was applied.
1083
+ */
1084
+ static findObjectCommitRejection(events, deployer, uid) {
1085
+ const eventType = `${deployer.toStringLong()}::blob_metadata::ObjectCommitRejectedEvent`;
1086
+ const rejection = events.find(
1087
+ (event) => event.type === eventType && BigInt(event.data.uid) === uid
1088
+ );
1089
+ if (!rejection) {
1090
+ return void 0;
1091
+ }
1092
+ const reason = rejection.data.rejection_reason.__variant__;
1093
+ if (!COMMIT_REJECTION_REASONS.has(reason)) {
1094
+ throw new Error(
1095
+ `Unrecognized ObjectCommitRejectedEvent rejection_reason '${reason}' for uid ${uid}`
1096
+ );
1097
+ }
1098
+ return reason;
1099
+ }
926
1100
  /**
927
1101
  * Creates a transaction payload to register a blob on the blockchain.
928
1102
  * This is a static helper method for constructing the Move function call payload.
@@ -936,8 +1110,6 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
936
1110
  * @param params.numChunksets - The total number of chunksets in the blob.
937
1111
  *
938
1112
  * @returns An Aptos transaction payload data object for the register_blob Move function.
939
- *
940
- * @see https://github.com/shelby/shelby/blob/e08e84742cf2b80ad8bb7227deb3013398076d53/move/shelby_contract/sources/global_metadata.move#L357
941
1113
  */
942
1114
  static createRegisterBlobPayload(params) {
943
1115
  const functionName = params.useSponsoredUsdVariant ? "register_blob_with_sponsor" : "register_blob";
@@ -945,6 +1117,8 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
945
1117
  function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
946
1118
  functionArguments: [
947
1119
  params.blobName,
1120
+ params.selectedLocation ?? null,
1121
+ params.locationHint ?? null,
948
1122
  params.expirationMicros,
949
1123
  Hex3.fromHexString(params.blobMerkleRoot).toUint8Array(),
950
1124
  params.numChunksets,
@@ -952,7 +1126,8 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
952
1126
  // TODO
953
1127
  0,
954
1128
  // payment tier
955
- params.encoding
1129
+ params.encoding,
1130
+ ...encryptionFunctionArgs(params)
956
1131
  ]
957
1132
  };
958
1133
  }
@@ -970,8 +1145,6 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
970
1145
  * @param params.blobs.numChunksets - The total number of chunksets in the blob.
971
1146
  *
972
1147
  * @returns An Aptos transaction payload data object for the register_multiple_blobs Move function.
973
- *
974
- * @see https://github.com/shelby/shelby/blob/e08e84742cf2b80ad8bb7227deb3013398076d53/move/shelby_contract/sources/global_metadata.move#L357
975
1148
  */
976
1149
  static createBatchRegisterBlobsPayload(params) {
977
1150
  const functionName = params.useSponsoredUsdVariant ? "register_multiple_blobs_with_sponsor" : "register_multiple_blobs";
@@ -991,6 +1164,8 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
991
1164
  function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
992
1165
  functionArguments: [
993
1166
  blobNames,
1167
+ params.selectedLocation ?? null,
1168
+ params.locationHint ?? null,
994
1169
  params.expirationMicros,
995
1170
  blobMerkleRoots,
996
1171
  blobNumChunksets,
@@ -998,7 +1173,8 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
998
1173
  // TODO
999
1174
  0,
1000
1175
  // payment tier
1001
- params.encoding
1176
+ params.encoding,
1177
+ ...encryptionFunctionArgs(params)
1002
1178
  ]
1003
1179
  };
1004
1180
  }
@@ -1009,24 +1185,20 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
1009
1185
  * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
1010
1186
  * @param params.blobName - The blob name (e.g. "bar.txt", without the account address prefix).
1011
1187
  *
1012
- * @returns An Aptos transaction payload data object for the delete_blob Move function.
1013
- *
1014
- * @see https://github.com/shelby/shelby/blob/64e9d7b4f0005e586faeb1e4085c79159234b6b6/move/shelby_contract/sources/global_metadata.move#L616
1188
+ * @returns An Aptos transaction payload data object for the delete_object Move function.
1015
1189
  */
1016
- static createDeleteBlobPayload(params) {
1190
+ static createDeleteObjectPayload(params) {
1017
1191
  return {
1018
- function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_blob`,
1019
- functionArguments: [params.blobName]
1192
+ function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_object`,
1193
+ // Second arg is `if_match_etag: Option<vector<u8>>`; `null` => None
1194
+ // (unconditional delete).
1195
+ functionArguments: [params.blobName, null]
1020
1196
  };
1021
1197
  }
1022
1198
  /**
1023
1199
  * Creates a transaction payload to delete multiple blobs on the blockchain.
1024
1200
  * This is a static helper method for constructing the Move function call payload.
1025
1201
  *
1026
- * **Note:** This function requires the `delete_multiple_blobs` entry function
1027
- * which will be deployed to the smart contract on 2026-02-04. Using this
1028
- * function before that date will result in a transaction failure.
1029
- *
1030
1202
  * This operation is atomic: if any blob deletion fails (e.g., blob not found),
1031
1203
  * the entire transaction fails and no blobs are deleted.
1032
1204
  *
@@ -1035,42 +1207,71 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
1035
1207
  * (e.g. ["foo/bar.txt", "baz.txt"], NOT ["0x1/foo/bar.txt"]). The account address
1036
1208
  * prefix is automatically derived from the transaction sender.
1037
1209
  *
1038
- * @returns An Aptos transaction payload data object for the delete_multiple_blobs Move function.
1039
- *
1040
- * @see https://github.com/shelby/shelby/blob/main/move/shelby_contract/sources/blob_metadata.move
1210
+ * @returns An Aptos transaction payload data object for the delete_multiple_objects Move function.
1041
1211
  */
1042
- static createDeleteMultipleBlobsPayload(params) {
1212
+ static createDeleteMultipleObjectsPayload(params) {
1043
1213
  return {
1044
- function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_multiple_blobs`,
1045
- functionArguments: [params.blobNames]
1214
+ function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::delete_multiple_objects`,
1215
+ // Second arg is `if_match_etags: vector<Option<vector<u8>>>`; an empty
1216
+ // vector means "no etag check on any object" (unconditional delete).
1217
+ functionArguments: [params.blobNames, []]
1046
1218
  };
1047
1219
  }
1048
- static createBlobAcknowledgementsPayload(params) {
1049
- const ackBitMask = params.storageProviderAcks.reduce(
1220
+ /**
1221
+ * Sort acks by slot and reduce to the `(ack_bits, signatures)` pair the
1222
+ * contract expects: it walks the set bits low-to-high and consumes the
1223
+ * signatures in that same order.
1224
+ */
1225
+ static encodeAcks(storageProviderAcks) {
1226
+ const sortedAcks = [...storageProviderAcks].sort((a, b) => a.slot - b.slot);
1227
+ const ackBitMask = sortedAcks.reduce(
1050
1228
  (acc, ack) => acc | 1 << ack.slot,
1051
1229
  0
1052
1230
  );
1053
1231
  return {
1054
- function: `${SHELBY_DEPLOYER}::blob_metadata::add_blob_acknowledgements`,
1232
+ ackBits: new U32(Number(ackBitMask)),
1233
+ signatures: sortedAcks.map((ack) => ack.signature)
1234
+ };
1235
+ }
1236
+ /**
1237
+ * Payload for `commit_object(uid, object_name_suffix, overwrite, if_match_etag,
1238
+ * ack_bits, signatures)` — binds a written pending blob under its object name,
1239
+ * finalizing the upload. SP acks may be batched in here (the contract applies
1240
+ * them before the `is_written` check), so register → upload → commit needs
1241
+ * only a single finalize transaction.
1242
+ *
1243
+ * @param params.uid - The blob UID returned at registration.
1244
+ * @param params.blobName - The object name suffix the blob was registered under.
1245
+ * @param params.overwrite - Allow replacing an existing binding under this name.
1246
+ * @param params.storageProviderAcks - Acks applied atomically with the commit.
1247
+ */
1248
+ static createCommitObjectPayload(params) {
1249
+ const { ackBits, signatures } = _ShelbyBlobClient.encodeAcks(
1250
+ params.storageProviderAcks
1251
+ );
1252
+ return {
1253
+ function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::commit_object`,
1055
1254
  functionArguments: [
1056
- createBlobKey({
1057
- account: params.blobOwner,
1058
- blobName: params.blobName
1059
- }),
1060
- params.creationMicros,
1061
- new U32(Number(ackBitMask)),
1062
- params.storageProviderAcks.map((ack) => ack.signature)
1255
+ params.uid,
1256
+ params.blobName,
1257
+ params.overwrite,
1258
+ // `if_match_etag: Option<vector<u8>>` is `null` => None; conditional
1259
+ // (CAS) writes are not yet exposed by the SDK.
1260
+ null,
1261
+ ackBits,
1262
+ signatures
1063
1263
  ]
1064
1264
  };
1065
1265
  }
1066
- async addBlobAcknowledgements(params) {
1266
+ async commitObject(params) {
1067
1267
  const transaction = await this.aptos.transaction.build.simple({
1068
1268
  ...params.options?.build,
1069
1269
  options: this.orderlessTxOptions(params.options?.build?.options),
1070
- data: _ShelbyBlobClient.createBlobAcknowledgementsPayload({
1071
- blobOwner: params.blobOwner,
1270
+ data: _ShelbyBlobClient.createCommitObjectPayload({
1271
+ deployer: this.deployer,
1272
+ uid: params.uid,
1072
1273
  blobName: params.blobName,
1073
- creationMicros: params.creationMicros,
1274
+ overwrite: params.overwrite,
1074
1275
  storageProviderAcks: params.storageProviderAcks
1075
1276
  }),
1076
1277
  sender: params.account.accountAddress
@@ -1085,5 +1286,6 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
1085
1286
  };
1086
1287
  export {
1087
1288
  MissingTransactionSubmitterError,
1289
+ ObjectCommitRejectedError,
1088
1290
  ShelbyBlobClient
1089
1291
  };