@shelby-protocol/sdk 0.3.0 → 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 (126) hide show
  1. package/dist/browser/index.d.ts +19 -10
  2. package/dist/browser/index.mjs +4200 -146
  3. package/dist/core/aptos-explorer.mjs +46 -5
  4. package/dist/core/blobs.mjs +12 -4
  5. package/dist/core/chunk.mjs +58 -9
  6. package/dist/core/clients/ShelbyBlobClient.d.ts +155 -83
  7. package/dist/core/clients/ShelbyBlobClient.mjs +1286 -17
  8. package/dist/core/clients/ShelbyClient.d.ts +39 -6
  9. package/dist/core/clients/ShelbyClient.mjs +3233 -23
  10. package/dist/core/clients/ShelbyClientConfig.d.ts +9 -1
  11. package/dist/core/clients/ShelbyClientConfig.mjs +0 -1
  12. package/dist/core/clients/ShelbyMetadataClient.d.ts +20 -6
  13. package/dist/core/clients/ShelbyMetadataClient.mjs +388 -6
  14. package/dist/core/clients/ShelbyMicropaymentChannelClient.d.ts +7 -7
  15. package/dist/core/clients/ShelbyMicropaymentChannelClient.mjs +894 -13
  16. package/dist/core/clients/ShelbyPlacementGroupClient.mjs +310 -8
  17. package/dist/core/clients/ShelbyRPCClient.d.ts +117 -25
  18. package/dist/core/clients/ShelbyRPCClient.mjs +1245 -12
  19. package/dist/core/clients/index.d.ts +4 -2
  20. package/dist/core/clients/index.mjs +3802 -39
  21. package/dist/core/clients/utils.mjs +65 -6
  22. package/dist/core/commitments.d.ts +12 -1
  23. package/dist/core/commitments.mjs +277 -11
  24. package/dist/core/constants.d.ts +3 -3
  25. package/dist/core/constants.mjs +39 -16
  26. package/dist/core/erasure/clay-codes.mjs +129 -4
  27. package/dist/core/erasure/constants.d.ts +16 -1
  28. package/dist/core/erasure/constants.mjs +48 -11
  29. package/dist/core/erasure/default.mjs +191 -9
  30. package/dist/core/erasure/index.d.ts +1 -1
  31. package/dist/core/erasure/index.mjs +281 -24
  32. package/dist/core/erasure/reed-solomon.mjs +68 -4
  33. package/dist/core/erasure/utils.mjs +0 -2
  34. package/dist/core/errors.d.ts +20 -1
  35. package/dist/core/errors.mjs +58 -8
  36. package/dist/core/index.d.ts +9 -9
  37. package/dist/core/index.mjs +4194 -146
  38. package/dist/core/layout.mjs +37 -5
  39. package/dist/core/networks.mjs +10 -5
  40. package/dist/core/operations/generated/sdk.d.ts +807 -42
  41. package/dist/core/operations/generated/sdk.mjs +267 -18
  42. package/dist/core/operations/index.d.ts +1 -1
  43. package/dist/core/operations/index.mjs +368 -24
  44. package/dist/core/promises.mjs +4 -4
  45. package/dist/core/rpc-responses.d.ts +1 -57
  46. package/dist/core/rpc-responses.mjs +14 -15
  47. package/dist/core/shelby-explorer.mjs +31 -6
  48. package/dist/core/sp/chunk_proof.d.ts +23 -0
  49. package/dist/core/sp/chunk_proof.mjs +113 -0
  50. package/dist/core/sp/index.d.ts +3 -0
  51. package/dist/core/sp/index.mjs +402 -0
  52. package/dist/core/sp/sp_write_client.d.ts +53 -0
  53. package/dist/core/sp/sp_write_client.mjs +302 -0
  54. package/dist/core/strings.mjs +0 -2
  55. package/dist/core/types/blobs.d.ts +24 -5
  56. package/dist/core/types/blobs.mjs +24 -1
  57. package/dist/core/types/index.d.ts +2 -2
  58. package/dist/core/types/index.mjs +275 -10
  59. package/dist/core/types/payments.d.ts +6 -6
  60. package/dist/core/types/payments.mjs +230 -5
  61. package/dist/core/types/placement_groups.mjs +0 -1
  62. package/dist/core/types/storage_providers.d.ts +32 -6
  63. package/dist/core/types/storage_providers.mjs +22 -1
  64. package/dist/core/utils.mjs +94 -8
  65. package/dist/gen/rpc_server_pb.d.ts +295 -0
  66. package/dist/gen/rpc_server_pb.mjs +28 -0
  67. package/dist/node/clients/ShelbyNodeClient.d.ts +2 -0
  68. package/dist/node/clients/ShelbyNodeClient.mjs +3237 -24
  69. package/dist/node/clients/index.d.ts +2 -0
  70. package/dist/node/clients/index.mjs +3236 -26
  71. package/dist/node/index.d.ts +9 -9
  72. package/dist/node/index.mjs +4217 -153
  73. package/dist/node/parallel/commitment_worker.d.ts +9 -0
  74. package/dist/node/parallel/commitment_worker.mjs +85 -0
  75. package/dist/node/parallel/commitment_worker_pool.d.ts +35 -0
  76. package/dist/node/parallel/commitment_worker_pool.mjs +339 -0
  77. package/dist/node/parallel/coverage_flush.d.ts +16 -0
  78. package/dist/node/parallel/coverage_flush.mjs +43 -0
  79. package/dist/node/parallel/default_commitment_worker_pool.d.ts +24 -0
  80. package/dist/node/parallel/default_commitment_worker_pool.mjs +355 -0
  81. package/dist/node/parallel/index.d.ts +12 -0
  82. package/dist/node/parallel/index.mjs +631 -0
  83. package/dist/node/parallel/parallel_commitments.d.ts +32 -0
  84. package/dist/node/parallel/parallel_commitments.mjs +614 -0
  85. package/dist/node/parallel/worker_pool.d.ts +74 -0
  86. package/dist/node/parallel/worker_pool.mjs +301 -0
  87. package/dist/node/testUtil.mjs +8 -4
  88. package/package.json +16 -5
  89. package/dist/chunk-3NRBHSMQ.mjs +0 -12
  90. package/dist/chunk-5BVSWXQJ.mjs +0 -801
  91. package/dist/chunk-6FJNAUU5.mjs +0 -278
  92. package/dist/chunk-6XSZRDLJ.mjs +0 -375
  93. package/dist/chunk-7P6ASYW6.mjs +0 -9
  94. package/dist/chunk-A4IG6GSE.mjs +0 -21
  95. package/dist/chunk-AD2G3QYD.mjs +0 -0
  96. package/dist/chunk-AUQDI5BS.mjs +0 -43
  97. package/dist/chunk-AY3HBWXA.mjs +0 -51
  98. package/dist/chunk-BDSW5PHM.mjs +0 -37
  99. package/dist/chunk-C6RQ3AEU.mjs +0 -51
  100. package/dist/chunk-CQ6QPIZK.mjs +0 -37
  101. package/dist/chunk-D6GQHO6G.mjs +0 -15
  102. package/dist/chunk-EM67QTMR.mjs +0 -0
  103. package/dist/chunk-I6NG5GNL.mjs +0 -8
  104. package/dist/chunk-JTXYKO3U.mjs +0 -38
  105. package/dist/chunk-KG2TMLEV.mjs +0 -207
  106. package/dist/chunk-M3CP5TFP.mjs +0 -39
  107. package/dist/chunk-M7W43K2Q.mjs +0 -505
  108. package/dist/chunk-MB7C7VQF.mjs +0 -0
  109. package/dist/chunk-MNCQBEMS.mjs +0 -55
  110. package/dist/chunk-MQUVYMNQ.mjs +0 -0
  111. package/dist/chunk-NEO7Z3ZQ.mjs +0 -49
  112. package/dist/chunk-NHWWORCH.mjs +0 -72
  113. package/dist/chunk-OEK24ON7.mjs +0 -135
  114. package/dist/chunk-QQ57OGQ2.mjs +0 -0
  115. package/dist/chunk-RNNJXTX2.mjs +0 -154
  116. package/dist/chunk-S6Q4OG7H.mjs +0 -83
  117. package/dist/chunk-TET3DJEO.mjs +0 -199
  118. package/dist/chunk-UEZNZBJO.mjs +0 -104
  119. package/dist/chunk-V46D5NBW.mjs +0 -11
  120. package/dist/chunk-V4B3GAMQ.mjs +0 -42
  121. package/dist/chunk-WFWRBNTW.mjs +0 -412
  122. package/dist/chunk-WTICJPDB.mjs +0 -0
  123. package/dist/chunk-XNEIWM4O.mjs +0 -0
  124. package/dist/chunk-Z4FZ7W6L.mjs +0 -39
  125. package/dist/chunk-Z7RFCADT.mjs +0 -0
  126. package/dist/chunk-ZHXCVRZX.mjs +0 -0
@@ -1,22 +1,1291 @@
1
+ // src/core/clients/ShelbyBlobClient.ts
1
2
  import {
2
- MissingTransactionSubmitterError,
3
- ShelbyBlobClient
4
- } from "../../chunk-5BVSWXQJ.mjs";
5
- import "../../chunk-XNEIWM4O.mjs";
6
- import "../../chunk-NHWWORCH.mjs";
7
- import "../../chunk-AY3HBWXA.mjs";
8
- import "../../chunk-OEK24ON7.mjs";
9
- import "../../chunk-NEO7Z3ZQ.mjs";
10
- import "../../chunk-TET3DJEO.mjs";
11
- import "../../chunk-V4B3GAMQ.mjs";
12
- import "../../chunk-3NRBHSMQ.mjs";
13
- import "../../chunk-RNNJXTX2.mjs";
14
- import "../../chunk-UEZNZBJO.mjs";
15
- import "../../chunk-JTXYKO3U.mjs";
16
- import "../../chunk-AUQDI5BS.mjs";
17
- import "../../chunk-MNCQBEMS.mjs";
18
- import "../../chunk-7P6ASYW6.mjs";
3
+ AccountAddress as AccountAddress2,
4
+ Aptos,
5
+ Hex as Hex3,
6
+ U32
7
+ } from "@aptos-labs/ts-sdk";
8
+
9
+ // src/core/utils.ts
10
+ import {
11
+ AccountAddress,
12
+ Hex
13
+ } from "@aptos-labs/ts-sdk";
14
+ function getBlobNameSuffix(blobName) {
15
+ const parts = blobName.split("/");
16
+ return parts.slice(1).join("/") || "";
17
+ }
18
+ function normalizeAddress(address) {
19
+ return AccountAddress.from(address, { maxMissingChars: 63 });
20
+ }
21
+
22
+ // src/core/blobs.ts
23
+ var createBlobKey = (params) => {
24
+ return `@${normalizeAddress(params.account).toStringLongWithoutPrefix()}/${params.blobName}`;
25
+ };
26
+
27
+ // src/core/erasure/constants.ts
28
+ var ERASURE_CODE_PARAMS = {
29
+ ["ClayCode_16Total_10Data_13Helper" /* ClayCode_16Total_10Data_13Helper */]: {
30
+ // total chunks (data + parity)
31
+ erasure_n: 16,
32
+ // data chunks
33
+ erasure_k: 10,
34
+ // helper nodes
35
+ erasure_d: 13,
36
+ // enum index
37
+ enumIndex: 0
38
+ },
39
+ ["ClayCode_4Total_2Data_3Helper" /* ClayCode_4Total_2Data_3Helper */]: {
40
+ // total chunks (data + parity)
41
+ erasure_n: 4,
42
+ // data chunks
43
+ erasure_k: 2,
44
+ // helper nodes
45
+ erasure_d: 3,
46
+ // enum index
47
+ enumIndex: 1
48
+ }
49
+ };
50
+ var DEFAULT_ERASURE_N = ERASURE_CODE_PARAMS["ClayCode_16Total_10Data_13Helper" /* ClayCode_16Total_10Data_13Helper */].erasure_n;
51
+ var DEFAULT_ERASURE_K = ERASURE_CODE_PARAMS["ClayCode_16Total_10Data_13Helper" /* ClayCode_16Total_10Data_13Helper */].erasure_k;
52
+ var DEFAULT_ERASURE_D = ERASURE_CODE_PARAMS["ClayCode_16Total_10Data_13Helper" /* ClayCode_16Total_10Data_13Helper */].erasure_d;
53
+ var DEFAULT_ERASURE_M = DEFAULT_ERASURE_N - DEFAULT_ERASURE_K;
54
+
55
+ // src/core/chunk.ts
56
+ var CHUNK_SIZE_PARAMS = {
57
+ ["ChunkSet10MiB_Chunk1MiB" /* ChunkSet10MiB_Chunk1MiB */]: {
58
+ // 1MiB
59
+ chunkSizeBytes: 1 * 1024 * 1024,
60
+ // 10MiB
61
+ chunksetSizeBytes: 10 * 1024 * 1024
62
+ },
63
+ ["ChunkSet2MiB_Chunk1MiB" /* ChunkSet2MiB_Chunk1MiB */]: {
64
+ // 1MiB
65
+ chunkSizeBytes: 1 * 1024 * 1024,
66
+ // 2MiB
67
+ chunksetSizeBytes: 2 * 1024 * 1024
68
+ }
69
+ };
70
+ var DEFAULT_CHUNK_SIZE_BYTES = CHUNK_SIZE_PARAMS["ChunkSet10MiB_Chunk1MiB" /* ChunkSet10MiB_Chunk1MiB */].chunkSizeBytes;
71
+ var DEFAULT_CHUNKSET_SIZE_BYTES = CHUNK_SIZE_PARAMS["ChunkSet10MiB_Chunk1MiB" /* ChunkSet10MiB_Chunk1MiB */].chunksetSizeBytes;
72
+ var ERASURE_CODE_AND_CHUNK_MAPPING = {
73
+ ["ClayCode_16Total_10Data_13Helper" /* ClayCode_16Total_10Data_13Helper */]: {
74
+ ...CHUNK_SIZE_PARAMS.ChunkSet10MiB_Chunk1MiB
75
+ },
76
+ ["ClayCode_4Total_2Data_3Helper" /* ClayCode_4Total_2Data_3Helper */]: {
77
+ ...CHUNK_SIZE_PARAMS.ChunkSet2MiB_Chunk1MiB
78
+ }
79
+ };
80
+
81
+ // src/core/commitments.ts
82
+ import { Hex as Hex2 } from "@aptos-labs/ts-sdk";
83
+ import { z } from "zod";
84
+ var ChunksetCommitmentSchema = z.object({
85
+ // Chunkset root (vector commitment of child chunks)
86
+ chunkset_root: z.string(),
87
+ // the size is known statically from the current configuration
88
+ chunk_commitments: z.array(z.string())
89
+ }).refine(
90
+ (data) => {
91
+ return data.chunk_commitments.length === DEFAULT_ERASURE_K + DEFAULT_ERASURE_M;
92
+ },
93
+ {
94
+ message: `Chunkset must have exactly ${DEFAULT_ERASURE_K + DEFAULT_ERASURE_M} chunks (ERASURE_K + ERASURE_M = ${DEFAULT_ERASURE_K} + ${DEFAULT_ERASURE_M})`,
95
+ path: ["chunk_commitments"]
96
+ }
97
+ );
98
+ function expectedTotalChunksets(rawSize, chunksetSize = DEFAULT_CHUNKSET_SIZE_BYTES) {
99
+ if (chunksetSize <= 0) {
100
+ throw new Error("chunksetSize must be positive");
101
+ }
102
+ if (rawSize === 0) return 1;
103
+ return Math.ceil(rawSize / chunksetSize);
104
+ }
105
+ var BlobCommitmentsSchema = z.object({
106
+ schema_version: z.string(),
107
+ raw_data_size: z.number(),
108
+ // FIXME I am not sure about this being here, or if it should be somewhere else
109
+ blob_merkle_root: z.string(),
110
+ chunkset_commitments: z.array(ChunksetCommitmentSchema)
111
+ }).refine(
112
+ (data) => {
113
+ return expectedTotalChunksets(data.raw_data_size) === data.chunkset_commitments.length;
114
+ },
115
+ {
116
+ message: "Total chunkset count mismatches with raw data size",
117
+ // FIXME put more details in here
118
+ path: ["chunkset_commitments"]
119
+ }
120
+ );
121
+
122
+ // src/core/constants.ts
123
+ import { Network } from "@aptos-labs/ts-sdk";
124
+ var NetworkToShelbyRPCBaseUrl = {
125
+ [Network.SHELBYNET]: "https://shelby.shelbynet.shelby.xyz/shelby",
126
+ [Network.NETNA]: void 0,
127
+ [Network.DEVNET]: void 0,
128
+ [Network.TESTNET]: "https://api.testnet.shelby.xyz/shelby",
129
+ [Network.MAINNET]: void 0,
130
+ [Network.LOCAL]: "http://localhost:9090",
131
+ [Network.CUSTOM]: void 0
132
+ };
133
+ var NetworkToShelbyBlobIndexerBaseUrl = {
134
+ [Network.SHELBYNET]: "https://api.shelbynet.aptoslabs.com/nocode/v1/public/alias/shelby/shelbynet/v1/graphql",
135
+ [Network.NETNA]: void 0,
136
+ [Network.DEVNET]: void 0,
137
+ [Network.TESTNET]: "https://api.testnet.aptoslabs.com/nocode/v1/public/alias/shelby/testnet/v1/graphql",
138
+ [Network.MAINNET]: void 0,
139
+ [Network.LOCAL]: "http://localhost:8091/v1/graphql",
140
+ [Network.CUSTOM]: void 0
141
+ };
142
+ var NetworkToGasStationBaseUrl = {
143
+ [Network.SHELBYNET]: "https://api.shelbynet.shelby.xyz/gs/v1",
144
+ [Network.NETNA]: void 0,
145
+ [Network.DEVNET]: void 0,
146
+ [Network.TESTNET]: "https://api.testnet.shelby.xyz/gs/v1",
147
+ [Network.MAINNET]: void 0,
148
+ [Network.LOCAL]: void 0,
149
+ [Network.CUSTOM]: void 0
150
+ };
151
+ var SHELBY_DEPLOYER = "0x85fdb9a176ab8ef1d9d9c1b60d60b3924f0800ac1de1cc2085fb0b8bb4988e6a";
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
+
174
+ // src/core/erasure/clay-codes.ts
175
+ import {
176
+ createDecoder,
177
+ createEncoder
178
+ } from "@shelby-protocol/clay-codes";
179
+
180
+ // src/core/erasure/default.ts
181
+ function defaultErasureCodingConfig() {
182
+ const encoding = Number(process.env.SHELBY_ENCODING) || 0;
183
+ if (encoding === 0) {
184
+ return erasureCodingConfig16Total10Data13Helper();
185
+ }
186
+ return erasureCodingConfig4Total2Data3Helper();
187
+ }
188
+ function erasureCodingConfig16Total10Data13Helper() {
189
+ return erasureCodingConfig(
190
+ "ClayCode_16Total_10Data_13Helper" /* ClayCode_16Total_10Data_13Helper */
191
+ );
192
+ }
193
+ function erasureCodingConfig4Total2Data3Helper() {
194
+ return erasureCodingConfig("ClayCode_4Total_2Data_3Helper" /* ClayCode_4Total_2Data_3Helper */);
195
+ }
196
+ function erasureCodingConfig(encodingScheme) {
197
+ return {
198
+ erasure_n: ERASURE_CODE_PARAMS[encodingScheme].erasure_n,
199
+ erasure_k: ERASURE_CODE_PARAMS[encodingScheme].erasure_k,
200
+ erasure_d: ERASURE_CODE_PARAMS[encodingScheme].erasure_d,
201
+ chunkSizeBytes: DEFAULT_CHUNK_SIZE_BYTES,
202
+ enumIndex: ERASURE_CODE_PARAMS[encodingScheme].enumIndex
203
+ };
204
+ }
205
+
206
+ // src/core/erasure/reed-solomon.ts
207
+ import { createWasmReedSolomonBinding } from "@shelby-protocol/reed-solomon";
208
+ var DEFAULT_CHUNK_SIZE_BYTES2 = 2 * 1024 * 1024;
209
+
210
+ // src/core/operations/index.ts
211
+ import { Network as Network2 } from "@aptos-labs/ts-sdk";
212
+ import { GraphQLClient } from "graphql-request";
213
+
214
+ // src/core/clients/utils.ts
215
+ import { AptosConfig } from "@aptos-labs/ts-sdk";
216
+ var getAptosConfig = (config) => {
217
+ const baseFaucetConfig = config.faucet?.authToken ? { AUTH_TOKEN: config.faucet.authToken } : void 0;
218
+ if (config.aptos) {
219
+ return new AptosConfig({
220
+ // Spread user's aptos config first
221
+ ...config.aptos,
222
+ // Network from top-level is authoritative - cannot be overridden
223
+ network: config.network,
224
+ // Merge clientConfig with API_KEY default
225
+ clientConfig: {
226
+ API_KEY: config.apiKey,
227
+ ...config.aptos.clientConfig
228
+ },
229
+ // Merge faucetConfig: aptos config first, then base authToken (authoritative)
230
+ faucetConfig: {
231
+ ...config.aptos.faucetConfig,
232
+ ...baseFaucetConfig
233
+ }
234
+ });
235
+ }
236
+ return new AptosConfig({
237
+ network: config.network,
238
+ clientConfig: {
239
+ API_KEY: config.apiKey
240
+ },
241
+ faucetConfig: baseFaucetConfig
242
+ });
243
+ };
244
+
245
+ // src/core/operations/generated/sdk.ts
246
+ import gql from "graphql-tag";
247
+ var GetBlobsDocument = gql`
248
+ query getBlobs($where: blobs_bool_exp, $orderBy: [blobs_order_by!], $limit: Int, $offset: Int) {
249
+ blobs(where: $where, order_by: $orderBy, limit: $limit, offset: $offset) {
250
+ uid
251
+ object_name
252
+ owner
253
+ blob_commitment
254
+ created_at
255
+ expires_at
256
+ updated_at
257
+ num_chunksets
258
+ size
259
+ slice_address
260
+ placement_group
261
+ is_persisted
262
+ is_committed
263
+ is_deleted
264
+ }
265
+ }
266
+ `;
267
+ var GetBlobActivitiesDocument = gql`
268
+ query getBlobActivities($where: blob_activities_bool_exp, $orderBy: [blob_activities_order_by!], $limit: Int, $offset: Int) {
269
+ blob_activities(
270
+ where: $where
271
+ order_by: $orderBy
272
+ limit: $limit
273
+ offset: $offset
274
+ ) {
275
+ uid
276
+ object_name
277
+ event_index
278
+ event_type
279
+ transaction_hash
280
+ transaction_version
281
+ timestamp
282
+ owner
283
+ }
284
+ }
285
+ `;
286
+ var GetBlobsCountDocument = gql`
287
+ query getBlobsCount($where: blobs_bool_exp) {
288
+ blobs_aggregate(where: $where) {
289
+ aggregate {
290
+ count
291
+ }
292
+ }
293
+ }
294
+ `;
295
+ var GetBlobActivitiesCountDocument = gql`
296
+ query getBlobActivitiesCount($where: blob_activities_bool_exp) {
297
+ blob_activities_aggregate(where: $where) {
298
+ aggregate {
299
+ count
300
+ }
301
+ }
302
+ }
303
+ `;
304
+ var GetTotalBlobsSizeDocument = gql`
305
+ query getTotalBlobsSize($where: blobs_bool_exp) {
306
+ blobs_aggregate(where: $where) {
307
+ aggregate {
308
+ sum {
309
+ size
310
+ }
311
+ }
312
+ }
313
+ }
314
+ `;
315
+ var GetPlacementGroupSlotsDocument = gql`
316
+ query getPlacementGroupSlots($where: placement_group_slots_bool_exp, $orderBy: [placement_group_slots_order_by!], $limit: Int, $offset: Int) {
317
+ placement_group_slots(
318
+ where: $where
319
+ order_by: $orderBy
320
+ limit: $limit
321
+ offset: $offset
322
+ ) {
323
+ placement_group
324
+ slot_index
325
+ storage_provider
326
+ status
327
+ updated_at
328
+ }
329
+ }
330
+ `;
331
+ var GetPlacementGroupSlotsCountDocument = gql`
332
+ query getPlacementGroupSlotsCount($where: placement_group_slots_bool_exp) {
333
+ placement_group_slots_aggregate(where: $where) {
334
+ aggregate {
335
+ count
336
+ }
337
+ }
338
+ }
339
+ `;
340
+ var GetProcessorStatusDocument = gql`
341
+ query getProcessorStatus {
342
+ processor_status {
343
+ last_success_version
344
+ last_transaction_timestamp
345
+ last_updated
346
+ }
347
+ }
348
+ `;
349
+ var defaultWrapper = (action, _operationName, _operationType, _variables) => action();
350
+ function getSdk(client, withWrapper = defaultWrapper) {
351
+ return {
352
+ getBlobs(variables, requestHeaders, signal) {
353
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: GetBlobsDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getBlobs", "query", variables);
354
+ },
355
+ getBlobActivities(variables, requestHeaders, signal) {
356
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: GetBlobActivitiesDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getBlobActivities", "query", variables);
357
+ },
358
+ getBlobsCount(variables, requestHeaders, signal) {
359
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: GetBlobsCountDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getBlobsCount", "query", variables);
360
+ },
361
+ getBlobActivitiesCount(variables, requestHeaders, signal) {
362
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: GetBlobActivitiesCountDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getBlobActivitiesCount", "query", variables);
363
+ },
364
+ getTotalBlobsSize(variables, requestHeaders, signal) {
365
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: GetTotalBlobsSizeDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getTotalBlobsSize", "query", variables);
366
+ },
367
+ getPlacementGroupSlots(variables, requestHeaders, signal) {
368
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: GetPlacementGroupSlotsDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getPlacementGroupSlots", "query", variables);
369
+ },
370
+ getPlacementGroupSlotsCount(variables, requestHeaders, signal) {
371
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: GetPlacementGroupSlotsCountDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getPlacementGroupSlotsCount", "query", variables);
372
+ },
373
+ getProcessorStatus(variables, requestHeaders, signal) {
374
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: GetProcessorStatusDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getProcessorStatus", "query", variables);
375
+ }
376
+ };
377
+ }
378
+
379
+ // src/core/operations/index.ts
380
+ function createShelbyIndexerClient(baseUrl, options) {
381
+ const graphqlClient = new GraphQLClient(baseUrl, options);
382
+ return getSdk(graphqlClient);
383
+ }
384
+ function getShelbyIndexerClient(config) {
385
+ const aptosConfig = getAptosConfig(config);
386
+ let { apiKey: indexerApiKey, baseUrl } = config.indexer ?? {};
387
+ if (!baseUrl) {
388
+ switch (aptosConfig?.network) {
389
+ // TODO: Add endpoints for core networks
390
+ case Network2.MAINNET:
391
+ case Network2.TESTNET:
392
+ case Network2.DEVNET:
393
+ case Network2.SHELBYNET:
394
+ case Network2.LOCAL:
395
+ baseUrl = NetworkToShelbyBlobIndexerBaseUrl[aptosConfig.network];
396
+ break;
397
+ }
398
+ }
399
+ if (baseUrl === void 0) {
400
+ throw new Error(
401
+ "The ShelbyClientConfig does not support the Shelby indexer. Please configure the endpoint in the ShelbyClientConfig.indexer.endpoint or provide a supported Aptos network."
402
+ );
403
+ }
404
+ const apiKey = indexerApiKey ?? config.apiKey;
405
+ return createShelbyIndexerClient(baseUrl, {
406
+ headers: {
407
+ ...apiKey ? { Authorization: `Bearer ${apiKey}` } : {},
408
+ "x-aptos-client": "shelby-ts-sdk"
409
+ }
410
+ });
411
+ }
412
+
413
+ // src/core/clients/ShelbyBlobClient.ts
414
+ var MissingTransactionSubmitterError = class extends Error {
415
+ constructor() {
416
+ super(
417
+ "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."
418
+ );
419
+ this.name = "MissingTransactionSubmitterError";
420
+ }
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
+ }
449
+ var ShelbyBlobClient = class _ShelbyBlobClient {
450
+ aptos;
451
+ deployer;
452
+ indexer;
453
+ defaultOptions;
454
+ orderless;
455
+ /**
456
+ * The ShelbyBlobClient is used to interact with the Shelby contract on the Aptos blockchain. This
457
+ * includes functions for registering blob commitments and retrieving blob metadata.
458
+ *
459
+ * @param config - The client configuration object.
460
+ * @param config.network - The Shelby network to use.
461
+ * @param defaultOptions - Optional default options for blob operations.
462
+ *
463
+ * @example
464
+ * ```typescript
465
+ * const blobClient = new ShelbyBlobClient({
466
+ * aptos: {
467
+ * network: Network.SHELBYNET,
468
+ * clientConfig: {
469
+ * API_KEY: "AG-***",
470
+ * },
471
+ * },
472
+ * });
473
+ * ```
474
+ *
475
+ * @example
476
+ * ```typescript
477
+ * // With default options for USD sponsorship
478
+ * const blobClient = new ShelbyBlobClient(
479
+ * {
480
+ * network: Network.SHELBYNET,
481
+ * aptos: {
482
+ * pluginSettings: {
483
+ * TRANSACTION_SUBMITTER: myGasStationSubmitter,
484
+ * },
485
+ * },
486
+ * },
487
+ * {
488
+ * usdSponsor: { feePayerAddress: sponsorAddress },
489
+ * }
490
+ * );
491
+ * ```
492
+ */
493
+ constructor(config, defaultOptions) {
494
+ this.aptos = new Aptos(getAptosConfig(config));
495
+ this.deployer = config.deployer ?? AccountAddress2.fromString(SHELBY_DEPLOYER);
496
+ this.indexer = getShelbyIndexerClient(config);
497
+ this.defaultOptions = {
498
+ locationHint: config.locationHint,
499
+ ...defaultOptions
500
+ };
501
+ this.orderless = config.orderless ?? false;
502
+ }
503
+ /**
504
+ * Merges method-level options with default options, giving precedence to method-level values.
505
+ */
506
+ mergeOptions(options) {
507
+ return {
508
+ build: options?.build ?? this.defaultOptions.build,
509
+ submit: options?.submit ?? this.defaultOptions.submit,
510
+ usdSponsor: options?.usdSponsor ?? this.defaultOptions.usdSponsor,
511
+ chunksetSizeBytes: options?.chunksetSizeBytes ?? this.defaultOptions.chunksetSizeBytes,
512
+ selectedLocation: options?.selectedLocation ?? this.defaultOptions.selectedLocation,
513
+ locationHint: options?.locationHint ?? this.defaultOptions.locationHint
514
+ };
515
+ }
516
+ /**
517
+ * Validates that if USD sponsorship is requested, a transaction submitter is
518
+ * configured as well. Checks both the client-level and method-level transaction
519
+ * submitter configurations. Throws MissingTransactionSubmitterError if usdSponsor is
520
+ * provided without a transaction submitter.
521
+ */
522
+ validateUsdSponsorConfig(usdSponsor, submit) {
523
+ if (!usdSponsor) {
524
+ return;
525
+ }
526
+ const hasClientSubmitter = this.aptos.config.getTransactionSubmitter();
527
+ const hasMethodSubmitter = submit?.transactionSubmitter !== void 0 && submit?.transactionSubmitter !== null;
528
+ if (!hasClientSubmitter && !hasMethodSubmitter) {
529
+ throw new MissingTransactionSubmitterError();
530
+ }
531
+ }
532
+ /**
533
+ * Merges orderless replay protection into transaction options when
534
+ * `config.orderless` is enabled. If the caller already supplies options
535
+ * (e.g. custom gas limits), those are preserved and the nonce is injected
536
+ * alongside them. When orderless mode is off, user options are returned as-is.
537
+ */
538
+ orderlessTxOptions(userOptions) {
539
+ if (!this.orderless) return userOptions;
540
+ return {
541
+ replayProtectionNonce: crypto.getRandomValues(new Uint32Array(1))[0],
542
+ ...userOptions
543
+ };
544
+ }
545
+ /**
546
+ * Retrieves the blob metadata from the blockchain. If it does not exist,
547
+ * returns `undefined`.
548
+ *
549
+ * @param params.account - The account namespace the blob is stored in (e.g. "0x1")
550
+ * @param params.name - The name of the blob (e.g. "foo/bar")
551
+ * @returns The blob metadata.
552
+ *
553
+ * @example
554
+ * ```typescript
555
+ * const metadata = await client.getFullObjectMetadata({
556
+ * account: AccountAddress.fromString("0x1"),
557
+ * name: "foo/bar.txt",
558
+ * });
559
+ * ```
560
+ */
561
+ async getFullObjectMetadata(params) {
562
+ try {
563
+ const rawMetadata = await this.aptos.view({
564
+ payload: {
565
+ function: `${this.deployer.toString()}::blob_metadata::get_full_object_metadata`,
566
+ functionArguments: [
567
+ createBlobKey({
568
+ account: params.account,
569
+ blobName: params.name
570
+ })
571
+ ]
572
+ }
573
+ });
574
+ if (!rawMetadata?.[0]?.vec?.[0]) {
575
+ return void 0;
576
+ }
577
+ const view = rawMetadata[0].vec[0];
578
+ return this.parseBlobMetadata(view.blob_metadata, {
579
+ uid: BigInt(view.object_metadata.current_blob_uid),
580
+ name: params.name,
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
+ });
585
+ } catch (error) {
586
+ if (error instanceof Error && // Depending on the network, the error message may show up differently.
587
+ (error.message?.includes("sub_status: Some(404)") || error.message?.includes("EBLOB_NOT_FOUND") || error.message?.includes("EOBJECT_NOT_FOUND"))) {
588
+ return void 0;
589
+ }
590
+ throw error;
591
+ }
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
+ }
665
+ /**
666
+ * Retrieves all the blobs and their metadata for an account from the
667
+ * blockchain.
668
+ *
669
+ * @param params.account - The account namespace the blobs are stored in (e.g. "0x1")
670
+ * @param params.pagination (optional) - The pagination options.
671
+ * @param params.orderBy (optional) - The order by clause to sort the blobs by.
672
+ * @returns The blob metadata for all the blobs for the account.
673
+ *
674
+ * @example
675
+ * ```typescript
676
+ * // FullObjectMetadata[]
677
+ * const blobs = await client.getAccountBlobs({
678
+ * account: AccountAddress.fromString("0x1"),
679
+ * });
680
+ * ```
681
+ */
682
+ getAccountBlobs(params) {
683
+ const { where, ...rest } = params;
684
+ return this.getBlobs({
685
+ where: {
686
+ ...where,
687
+ owner: { _eq: normalizeAddress(params.account).toString() }
688
+ },
689
+ pagination: rest.pagination,
690
+ orderBy: rest.orderBy
691
+ });
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
+ }
712
+ /**
713
+ * Retrieves blobs and their metadata from the blockchain.
714
+ *
715
+ * @param params.where (optional) - The where clause to filter the blobs by.
716
+ * @param params.pagination (optional) - The pagination options.
717
+ * @param params.orderBy (optional) - The order by clause to sort the blobs by.
718
+ * @returns The blob metadata for all the blobs that match the where clause.
719
+ *
720
+ * @example
721
+ * ```typescript
722
+ * // FullObjectMetadata[]
723
+ * const blobs = await client.getBlobs({
724
+ * where: { owner: { _eq: AccountAddress.fromString("0x1").toString() } },
725
+ * });
726
+ * ```
727
+ */
728
+ async getBlobs(params = {}) {
729
+ const { limit, offset } = params.pagination ?? {};
730
+ const { orderBy, where } = params;
731
+ const finalWhere = this.activeBlobsWhere(where);
732
+ const { blobs } = await this.indexer.getBlobs({
733
+ where: finalWhere,
734
+ limit,
735
+ offset,
736
+ orderBy
737
+ });
738
+ return blobs.map(
739
+ (blob) => ({
740
+ uid: BigInt(blob.uid),
741
+ owner: normalizeAddress(blob.owner),
742
+ name: blob.object_name,
743
+ blobNameSuffix: getBlobNameSuffix(blob.object_name),
744
+ blobMerkleRoot: Hex3.fromHexInput(blob.blob_commitment).toUint8Array(),
745
+ size: Number(blob.size),
746
+ // TODO: Add encoding when supported in NCI
747
+ encoding: {
748
+ variant: "clay",
749
+ ...ERASURE_CODE_PARAMS.ClayCode_16Total_10Data_13Helper,
750
+ ...ERASURE_CODE_AND_CHUNK_MAPPING.ClayCode_16Total_10Data_13Helper
751
+ },
752
+ expirationMicros: Number(blob.expires_at),
753
+ creationMicros: Number(blob.created_at),
754
+ sliceAddress: normalizeAddress(blob.slice_address),
755
+ isWritten: Boolean(Number(blob.is_persisted)),
756
+ isDeleted: Boolean(Number(blob.is_deleted))
757
+ })
758
+ );
759
+ }
760
+ async getBlobActivities(params) {
761
+ const { limit, offset } = params.pagination ?? {};
762
+ const { orderBy, where } = params;
763
+ const { blob_activities } = await this.indexer.getBlobActivities({
764
+ where,
765
+ limit,
766
+ offset,
767
+ orderBy
768
+ });
769
+ const activityTypeMapping = {
770
+ [`${this.deployer.toStringLong()}::blob_metadata::BlobRegisteredEvent`]: "register_blob",
771
+ [`${this.deployer.toStringLong()}::blob_metadata::BlobDeletedEvent`]: "delete_blob",
772
+ [`${this.deployer.toStringLong()}::blob_metadata::BlobExpirationExtendedEvent`]: "extend_blob_expiration",
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"
777
+ };
778
+ return blob_activities.map(
779
+ (activity) => ({
780
+ blobName: activity.object_name,
781
+ accountAddress: normalizeAddress(activity.object_name.substring(1, 65)),
782
+ type: activityTypeMapping[activity.event_type] ?? "unknown",
783
+ eventType: activity.event_type,
784
+ eventIndex: Number(activity.event_index),
785
+ transactionHash: activity.transaction_hash,
786
+ // Using Number here in JS is technically not okay because txn version can be
787
+ // as large as u64::MAX, but it should be fine for a long while.
788
+ transactionVersion: Number(activity.transaction_version),
789
+ timestamp: `${activity.timestamp}Z`
790
+ })
791
+ );
792
+ }
793
+ /**
794
+ * Retrieves the total number of blobs from the blockchain.
795
+ *
796
+ * @param params.where (optional) - The where clause to filter the blobs by.
797
+ * @returns The total number of blobs.
798
+ *
799
+ * @example
800
+ * ```typescript
801
+ * const count = await client.getBlobsCount();
802
+ * ```
803
+ */
804
+ async getBlobsCount(params = {}) {
805
+ const { blobs_aggregate } = await this.indexer.getBlobsCount({
806
+ where: this.activeBlobsWhere(params.where)
807
+ });
808
+ return blobs_aggregate?.aggregate?.count ?? 0;
809
+ }
810
+ /**
811
+ * Retrieves the total size of blobs from the blockchain.
812
+ *
813
+ * @param params.where (optional) - The where clause to filter the blobs by.
814
+ * @returns The total size of blobs in bytes.
815
+ *
816
+ * @example
817
+ * ```typescript
818
+ * const size = await client.getTotalBlobsSize();
819
+ * ```
820
+ */
821
+ async getTotalBlobsSize(params = {}) {
822
+ const { blobs_aggregate } = await this.indexer.getTotalBlobsSize({
823
+ where: this.activeBlobsWhere(params.where)
824
+ });
825
+ return Number(blobs_aggregate?.aggregate?.sum?.size ?? 0);
826
+ }
827
+ /**
828
+ * Retrieves the total number of blob activities from the blockchain.
829
+ *
830
+ * @param params.where (optional) - The where clause to filter the blob activities by.
831
+ * @returns The total number of blob activities.
832
+ *
833
+ * @example
834
+ * ```typescript
835
+ * const count = await client.getBlobActivitiesCount();
836
+ * ```
837
+ */
838
+ async getBlobActivitiesCount(params) {
839
+ const { where } = params;
840
+ const { blob_activities_aggregate } = await this.indexer.getBlobActivitiesCount({ where });
841
+ return blob_activities_aggregate?.aggregate?.count ?? 0;
842
+ }
843
+ /**
844
+ * Registers a blob on the blockchain by writing its merkle root and metadata.
845
+ *
846
+ * @param params.account - The account that is signing and paying for the transaction.
847
+ * @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
848
+ * @param params.blobMerkleRoot - The merkle root of the blob commitments.
849
+ * @param params.size - The size of the blob in bytes.
850
+ * @param params.expirationMicros - The expiration time of the blob in microseconds.
851
+ * @param params.options - Optional transaction building options.
852
+ * @param params.options.chunksetSizeBytes - Custom chunkset size (defaults to DEFAULT_CHUNKSET_SIZE_BYTES).
853
+ * @param params.options.build - Additional Aptos transaction building options.
854
+ *
855
+ * @returns An object containing the pending transaction.
856
+ *
857
+ * @example
858
+ * ```typescript
859
+ * const provider = await ClayErasureCodingProvider.create();
860
+ * const blobCommitments = await generateCommitments(provider, data);
861
+ *
862
+ * const { transaction } = await client.registerBlob({
863
+ * account: signer,
864
+ * blobName: "foo/bar.txt",
865
+ * blobMerkleRoot: blobCommitments.blob_merkle_root,
866
+ * size: data.length,
867
+ * expirationMicros: Date.now() * 1000 + 3600_000_000, // 1 hour from now in microseconds
868
+ * });
869
+ * ```
870
+ */
871
+ async registerBlob(params) {
872
+ const options = this.mergeOptions(params.options);
873
+ this.validateUsdSponsorConfig(options.usdSponsor, options.submit);
874
+ const config = params.config ?? defaultErasureCodingConfig();
875
+ const chunksetSize = config.chunkSizeBytes * config.erasure_k;
876
+ const buildArgs = {
877
+ ...options.build,
878
+ options: this.orderlessTxOptions(options.build?.options),
879
+ data: _ShelbyBlobClient.createRegisterBlobPayload({
880
+ deployer: this.deployer,
881
+ account: params.account.accountAddress,
882
+ blobName: params.blobName,
883
+ selectedLocation: options.selectedLocation,
884
+ locationHint: options.locationHint,
885
+ blobSize: params.size,
886
+ blobMerkleRoot: params.blobMerkleRoot,
887
+ numChunksets: expectedTotalChunksets(params.size, chunksetSize),
888
+ expirationMicros: params.expirationMicros,
889
+ useSponsoredUsdVariant: options.usdSponsor !== void 0,
890
+ encoding: config.enumIndex,
891
+ encryption: params.encryption
892
+ }),
893
+ sender: params.account.accountAddress
894
+ };
895
+ const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
896
+ ...buildArgs,
897
+ secondarySignerAddresses: [options.usdSponsor.feePayerAddress]
898
+ }) : await this.aptos.transaction.build.simple(buildArgs);
899
+ return {
900
+ transaction: await this.aptos.signAndSubmitTransaction({
901
+ signer: params.account,
902
+ transaction,
903
+ ...options.submit
904
+ })
905
+ };
906
+ }
907
+ /**
908
+ * Deletes a blob on the blockchain.
909
+ *
910
+ * @param params.account - The account that is signing and paying for the transaction.
911
+ * @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
912
+ * @param params.options - Optional transaction building options.
913
+ *
914
+ * @returns An object containing the pending transaction.
915
+ *
916
+ * @example
917
+ * ```typescript
918
+ *
919
+ * const { transaction } = await client.deleteObject({
920
+ * account: signer,
921
+ * blobName: "foo/bar.txt",
922
+ * });
923
+ * ```
924
+ */
925
+ async deleteObject(params) {
926
+ const transaction = await this.aptos.transaction.build.simple({
927
+ options: this.orderlessTxOptions(params.options),
928
+ data: _ShelbyBlobClient.createDeleteObjectPayload({
929
+ deployer: this.deployer,
930
+ blobName: params.blobName
931
+ }),
932
+ sender: params.account.accountAddress
933
+ });
934
+ return {
935
+ transaction: await this.aptos.signAndSubmitTransaction({
936
+ signer: params.account,
937
+ transaction
938
+ })
939
+ };
940
+ }
941
+ /**
942
+ * Deletes multiple blobs on the blockchain in a single atomic transaction.
943
+ *
944
+ * This operation is atomic: if any blob deletion fails (e.g., blob not found),
945
+ * the entire transaction fails and no blobs are deleted.
946
+ *
947
+ * @param params.account - The account that is signing and paying for the transaction.
948
+ * @param params.blobNames - Array of blob name suffixes without the account address prefix
949
+ * (e.g. ["foo/bar.txt", "baz.txt"], NOT ["0x1/foo/bar.txt"]). The account address
950
+ * prefix is automatically derived from the signer.
951
+ * @param params.options - Optional transaction building options.
952
+ *
953
+ * @returns An object containing the pending transaction.
954
+ *
955
+ * @example
956
+ * ```typescript
957
+ *
958
+ * const { transaction } = await client.deleteMultipleObjects({
959
+ * account: signer,
960
+ * blobNames: ["foo/bar.txt", "baz.txt"],
961
+ * });
962
+ * ```
963
+ */
964
+ async deleteMultipleObjects(params) {
965
+ const transaction = await this.aptos.transaction.build.simple({
966
+ options: this.orderlessTxOptions(params.options),
967
+ data: _ShelbyBlobClient.createDeleteMultipleObjectsPayload({
968
+ deployer: this.deployer,
969
+ blobNames: params.blobNames
970
+ }),
971
+ sender: params.account.accountAddress
972
+ });
973
+ return {
974
+ transaction: await this.aptos.signAndSubmitTransaction({
975
+ signer: params.account,
976
+ transaction
977
+ })
978
+ };
979
+ }
980
+ /**
981
+ * Registers multiple blobs on the blockchain by writing their merkle roots and metadata.
982
+ *
983
+ * @param params.account - The account that is signing and paying for the transaction.
984
+ * @param params.expirationMicros - The expiration time of the blobs in microseconds.
985
+ * @param params.blobs - The blobs to register.
986
+ * @param params.blobs.blobName - The name/path of the blob (e.g. "foo/bar.txt").
987
+ * @param params.blobs.blobSize - The size of the blob in bytes.
988
+ * @param params.blobs.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
989
+ * @param params.options - Optional transaction building options.
990
+ * @param params.options.chunksetSizeBytes - Custom chunkset size (defaults to DEFAULT_CHUNKSET_SIZE_BYTES).
991
+ * @param params.options.build - Additional Aptos transaction building options.
992
+ *
993
+ * @returns An object containing the pending transaction.
994
+ *
995
+ * @example
996
+ * ```typescript
997
+ * const provider = await ClayErasureCodingProvider.create();
998
+ * const blobCommitments = await generateCommitments(provider, data);
999
+ *
1000
+ * const { transaction } = await client.batchRegisterBlobs({
1001
+ * account: signer,
1002
+ * expirationMicros: Date.now() * 1000 + 3600_000_000, // 1 hour from now in microseconds
1003
+ * blobs: [
1004
+ * {
1005
+ * blobName: "foo/bar.txt",
1006
+ * blobSize: data.length,
1007
+ * blobMerkleRoot: blobCommitments.blob_merkle_root,
1008
+ * },
1009
+ * ],
1010
+ * });
1011
+ * ```
1012
+ */
1013
+ async batchRegisterBlobs(params) {
1014
+ const options = this.mergeOptions(params.options);
1015
+ this.validateUsdSponsorConfig(options.usdSponsor, options.submit);
1016
+ const config = params.config ?? defaultErasureCodingConfig();
1017
+ const chunksetSize = config.chunkSizeBytes * config.erasure_k;
1018
+ const buildArgs = {
1019
+ ...options.build,
1020
+ options: this.orderlessTxOptions(options.build?.options),
1021
+ sender: params.account.accountAddress,
1022
+ data: _ShelbyBlobClient.createBatchRegisterBlobsPayload({
1023
+ deployer: this.deployer,
1024
+ account: params.account.accountAddress,
1025
+ selectedLocation: options.selectedLocation,
1026
+ locationHint: options.locationHint,
1027
+ expirationMicros: params.expirationMicros,
1028
+ blobs: params.blobs.map((blob) => ({
1029
+ blobName: blob.blobName,
1030
+ blobSize: blob.blobSize,
1031
+ blobMerkleRoot: blob.blobMerkleRoot,
1032
+ numChunksets: expectedTotalChunksets(blob.blobSize, chunksetSize)
1033
+ })),
1034
+ useSponsoredUsdVariant: options.usdSponsor !== void 0,
1035
+ encoding: config.enumIndex,
1036
+ encryption: params.encryption
1037
+ })
1038
+ };
1039
+ const transaction = options.usdSponsor ? await this.aptos.transaction.build.multiAgent({
1040
+ ...buildArgs,
1041
+ secondarySignerAddresses: [options.usdSponsor.feePayerAddress]
1042
+ }) : await this.aptos.transaction.build.simple(buildArgs);
1043
+ return {
1044
+ transaction: await this.aptos.signAndSubmitTransaction({
1045
+ signer: params.account,
1046
+ transaction,
1047
+ ...options.submit
1048
+ })
1049
+ };
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
+ }
1100
+ /**
1101
+ * Creates a transaction payload to register a blob on the blockchain.
1102
+ * This is a static helper method for constructing the Move function call payload.
1103
+ *
1104
+ * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
1105
+ * @param params.account - The account that will own the blob.
1106
+ * @param params.blobName - The name/path of the blob (e.g. "foo/bar.txt").
1107
+ * @param params.blobSize - The size of the blob in bytes.
1108
+ * @param params.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
1109
+ * @param params.expirationMicros - The expiration time of the blob in microseconds.
1110
+ * @param params.numChunksets - The total number of chunksets in the blob.
1111
+ *
1112
+ * @returns An Aptos transaction payload data object for the register_blob Move function.
1113
+ */
1114
+ static createRegisterBlobPayload(params) {
1115
+ const functionName = params.useSponsoredUsdVariant ? "register_blob_with_sponsor" : "register_blob";
1116
+ return {
1117
+ function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
1118
+ functionArguments: [
1119
+ params.blobName,
1120
+ params.selectedLocation ?? null,
1121
+ params.locationHint ?? null,
1122
+ params.expirationMicros,
1123
+ Hex3.fromHexString(params.blobMerkleRoot).toUint8Array(),
1124
+ params.numChunksets,
1125
+ params.blobSize,
1126
+ // TODO
1127
+ 0,
1128
+ // payment tier
1129
+ params.encoding,
1130
+ ...encryptionFunctionArgs(params)
1131
+ ]
1132
+ };
1133
+ }
1134
+ /**
1135
+ * Creates a transaction payload to register multiple blobs on the blockchain.
1136
+ * This is a static helper method for constructing the Move function call payload.
1137
+ *
1138
+ * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
1139
+ * @param params.account - The account that will own the blobs.
1140
+ * @param params.expirationMicros - The expiration time of the blobs in microseconds.
1141
+ * @param params.blobs - The blobs to register.
1142
+ * @param params.blobs.blobName - The name/path of the blob (e.g. "foo/bar.txt").
1143
+ * @param params.blobs.blobSize - The size of the blob in bytes.
1144
+ * @param params.blobs.blobMerkleRoot - The merkle root of the blob commitments as a hex string.
1145
+ * @param params.blobs.numChunksets - The total number of chunksets in the blob.
1146
+ *
1147
+ * @returns An Aptos transaction payload data object for the register_multiple_blobs Move function.
1148
+ */
1149
+ static createBatchRegisterBlobsPayload(params) {
1150
+ const functionName = params.useSponsoredUsdVariant ? "register_multiple_blobs_with_sponsor" : "register_multiple_blobs";
1151
+ const blobNames = [];
1152
+ const blobMerkleRoots = [];
1153
+ const blobNumChunksets = [];
1154
+ const blobSizes = [];
1155
+ params.blobs.forEach((blob) => {
1156
+ blobNames.push(blob.blobName);
1157
+ blobMerkleRoots.push(
1158
+ Hex3.fromHexString(blob.blobMerkleRoot).toUint8Array()
1159
+ );
1160
+ blobNumChunksets.push(blob.numChunksets);
1161
+ blobSizes.push(blob.blobSize);
1162
+ });
1163
+ return {
1164
+ function: `${(params.deployer ?? SHELBY_DEPLOYER).toString()}::blob_metadata::${functionName}`,
1165
+ functionArguments: [
1166
+ blobNames,
1167
+ params.selectedLocation ?? null,
1168
+ params.locationHint ?? null,
1169
+ params.expirationMicros,
1170
+ blobMerkleRoots,
1171
+ blobNumChunksets,
1172
+ blobSizes,
1173
+ // TODO
1174
+ 0,
1175
+ // payment tier
1176
+ params.encoding,
1177
+ ...encryptionFunctionArgs(params)
1178
+ ]
1179
+ };
1180
+ }
1181
+ /**
1182
+ * Creates a transaction payload to delete a blob on the blockchain.
1183
+ * This is a static helper method for constructing the Move function call payload.
1184
+ *
1185
+ * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
1186
+ * @param params.blobName - The blob name (e.g. "bar.txt", without the account address prefix).
1187
+ *
1188
+ * @returns An Aptos transaction payload data object for the delete_object Move function.
1189
+ */
1190
+ static createDeleteObjectPayload(params) {
1191
+ return {
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]
1196
+ };
1197
+ }
1198
+ /**
1199
+ * Creates a transaction payload to delete multiple blobs on the blockchain.
1200
+ * This is a static helper method for constructing the Move function call payload.
1201
+ *
1202
+ * This operation is atomic: if any blob deletion fails (e.g., blob not found),
1203
+ * the entire transaction fails and no blobs are deleted.
1204
+ *
1205
+ * @param params.deployer - Optional deployer account address. Defaults to SHELBY_DEPLOYER.
1206
+ * @param params.blobNames - Array of blob name suffixes without the account address prefix
1207
+ * (e.g. ["foo/bar.txt", "baz.txt"], NOT ["0x1/foo/bar.txt"]). The account address
1208
+ * prefix is automatically derived from the transaction sender.
1209
+ *
1210
+ * @returns An Aptos transaction payload data object for the delete_multiple_objects Move function.
1211
+ */
1212
+ static createDeleteMultipleObjectsPayload(params) {
1213
+ return {
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, []]
1218
+ };
1219
+ }
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(
1228
+ (acc, ack) => acc | 1 << ack.slot,
1229
+ 0
1230
+ );
1231
+ return {
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`,
1254
+ functionArguments: [
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
1263
+ ]
1264
+ };
1265
+ }
1266
+ async commitObject(params) {
1267
+ const transaction = await this.aptos.transaction.build.simple({
1268
+ ...params.options?.build,
1269
+ options: this.orderlessTxOptions(params.options?.build?.options),
1270
+ data: _ShelbyBlobClient.createCommitObjectPayload({
1271
+ deployer: this.deployer,
1272
+ uid: params.uid,
1273
+ blobName: params.blobName,
1274
+ overwrite: params.overwrite,
1275
+ storageProviderAcks: params.storageProviderAcks
1276
+ }),
1277
+ sender: params.account.accountAddress
1278
+ });
1279
+ return {
1280
+ transaction: await this.aptos.signAndSubmitTransaction({
1281
+ signer: params.account,
1282
+ transaction
1283
+ })
1284
+ };
1285
+ }
1286
+ };
19
1287
  export {
20
1288
  MissingTransactionSubmitterError,
1289
+ ObjectCommitRejectedError,
21
1290
  ShelbyBlobClient
22
1291
  };