@shelby-protocol/sdk 0.0.1-experimental.1 → 0.0.1-experimental.3

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 (54) hide show
  1. package/README.md +0 -12
  2. package/dist/browser/index.d.ts +10 -6
  3. package/dist/browser/index.mjs +29 -5
  4. package/dist/chunk-5Z3RVWU3.mjs +67 -0
  5. package/dist/{chunk-EFE5Y7IE.mjs → chunk-B3CB2YEO.mjs} +4 -17
  6. package/dist/chunk-G263DBCY.mjs +105 -0
  7. package/dist/chunk-HMKVGTZV.mjs +11 -0
  8. package/dist/{chunk-DBTBUKCW.mjs → chunk-IAHEBEM6.mjs} +55 -61
  9. package/dist/chunk-P7BVGLTV.mjs +32 -0
  10. package/dist/chunk-QKT5R735.mjs +0 -0
  11. package/dist/{chunk-77TSD6TQ.mjs → chunk-RYJCDQEK.mjs} +40 -21
  12. package/dist/core/blobs.d.ts +0 -5
  13. package/dist/{node → core}/clients/ShelbyBlobClient.d.ts +10 -18
  14. package/dist/core/clients/ShelbyBlobClient.mjs +9 -0
  15. package/dist/core/clients/ShelbyClient.d.ts +99 -0
  16. package/dist/core/clients/ShelbyClient.mjs +16 -0
  17. package/dist/core/clients/ShelbyClientConfig.d.ts +13 -0
  18. package/dist/core/clients/ShelbyClientConfig.mjs +0 -0
  19. package/dist/{node → core}/clients/ShelbyRPCClient.d.ts +8 -8
  20. package/dist/core/clients/ShelbyRPCClient.mjs +10 -0
  21. package/dist/core/clients/index.d.ts +11 -0
  22. package/dist/core/clients/index.mjs +23 -0
  23. package/dist/core/commitments.d.ts +30 -1
  24. package/dist/core/commitments.mjs +7 -3
  25. package/dist/core/constants.d.ts +0 -1
  26. package/dist/core/erasure.d.ts +6 -0
  27. package/dist/{node → core}/erasure.mjs +1 -1
  28. package/dist/core/index.d.ts +10 -6
  29. package/dist/core/index.mjs +29 -5
  30. package/dist/core/utils.d.ts +30 -0
  31. package/dist/{node/readableUtil.mjs → core/utils.mjs} +3 -1
  32. package/dist/node/clients/ShelbyNodeClient.d.ts +8 -87
  33. package/dist/node/clients/ShelbyNodeClient.mjs +7 -12
  34. package/dist/node/clients/index.d.ts +5 -5
  35. package/dist/node/clients/index.mjs +9 -20
  36. package/dist/node/index.d.ts +10 -12
  37. package/dist/node/index.mjs +28 -25
  38. package/package.json +4 -17
  39. package/dist/chunk-E3QOKRQ4.mjs +0 -50
  40. package/dist/chunk-NPM7WXK3.mjs +0 -49
  41. package/dist/chunk-OWIIKLFI.mjs +0 -43
  42. package/dist/chunk-VLLCOFH7.mjs +0 -73
  43. package/dist/chunk-YV67F5NY.mjs +0 -38
  44. package/dist/core/ShelbyClient.d.ts +0 -34
  45. package/dist/core/ShelbyClient.mjs +0 -8
  46. package/dist/node/clients/ShelbyBlobClient.mjs +0 -19
  47. package/dist/node/clients/ShelbyRPCClient.mjs +0 -17
  48. package/dist/node/commitments.d.ts +0 -35
  49. package/dist/node/commitments.mjs +0 -18
  50. package/dist/node/erasure.d.ts +0 -12
  51. package/dist/node/readableUtil.d.ts +0 -2
  52. package/dist/readableUtil-BW_7enT-.d.ts +0 -12
  53. /package/dist/{chunk-PZPMURE4.mjs → chunk-7S6RVKYB.mjs} +0 -0
  54. /package/dist/{chunk-WVWL2OPB.mjs → chunk-PLUDE5C3.mjs} +0 -0
package/README.md CHANGED
@@ -7,9 +7,6 @@ A TypeScript SDK providing core encoding and decoding utilities for both Node.js
7
7
  ```bash
8
8
  # Installing the shelby sdk
9
9
  pnpm install @shelby-protocol/sdk @aptos-labs/ts-sdk
10
-
11
- # If you plan to use the Node.js entrypoint, also install its peer dependencies:
12
- pnpm install fs-extra glob node-fetch yaml
13
10
  ```
14
11
 
15
12
  ## Usage
@@ -36,15 +33,6 @@ import { ShelbyBlob } from '@shelby-protocol/sdk/browser';
36
33
 
37
34
  - `@aptos-labs/ts-sdk`
38
35
 
39
- When using the **Node.js** entrypoint (`@shelby-protocol/sdk/node`), make sure you have the following installed in your project:
40
-
41
- - `fs-extra`
42
- - `glob`
43
- - `node-fetch`
44
- - `yaml`
45
-
46
- These are marked as **peerDependencies** and are **optional** for browser usage.
47
-
48
36
  ## Scripts
49
37
 
50
38
  ```bash
@@ -1,10 +1,14 @@
1
- export { BlobCommitments, BlobCommitmentsSchema, ChunksetCommitment, ChunksetCommitmentSchema } from '../core/commitments.js';
2
- export { BlobName, BlobNameSchema, ChunkKey, allChunksForBlob, roundSize } from '../core/layout.js';
1
+ export { ShelbyBlob, createBlobKey } from '../core/blobs.js';
2
+ export { ShelbyBlobClient } from '../core/clients/ShelbyBlobClient.js';
3
+ export { ShelbyClient } from '../core/clients/ShelbyClient.js';
4
+ export { ShelbyClientConfig } from '../core/clients/ShelbyClientConfig.js';
5
+ export { ShelbyRPCClient } from '../core/clients/ShelbyRPCClient.js';
6
+ export { BlobCommitments, BlobCommitmentsSchema, ChunksetCommitment, ChunksetCommitmentSchema, generateCommitments } from '../core/commitments.js';
3
7
  export { CHUNKSET_SIZE_BYTES, DEFAULT_PROJECT_DESCRIPTION, DEFAULT_PROJECT_NAME, DEFAULT_SHELBY_BASE_URL, ERASURE_K, ERASURE_M, SHELBY_DEPLOYER, TOKEN_DEPLOYER, TOKEN_OBJECT_ADDRESS, getChunkSizeBytes, getChunksetSizeBytes } from '../core/constants.js';
8
+ export { erasureEncode } from '../core/erasure.js';
9
+ export { BlobName, BlobNameSchema, ChunkKey, allChunksForBlob, roundSize } from '../core/layout.js';
4
10
  export { BlobChunk, BlobEncoding, BlobMetadata, ChunkLocation, ClayEncoding, PendingChunkLocation, SignedChunkCommitment, StoredChunkLocation } from '../core/types/blobs.js';
5
11
  export { EncodingOptions } from '../core/types/encodings.js';
6
- export { ShelbyBlob, createBlobKey } from '../core/blobs.js';
7
- export { ShelbyClient, ShelbyClientConfig } from '../core/ShelbyClient.js';
8
- import 'zod';
12
+ export { concatHashes, readInChunks, zeroPadBuffer } from '../core/utils.js';
9
13
  import '@aptos-labs/ts-sdk';
10
- import 'node:stream';
14
+ import 'zod';
@@ -1,17 +1,33 @@
1
- import "../chunk-PZPMURE4.mjs";
1
+ import "../chunk-PLUDE5C3.mjs";
2
2
  import "../chunk-MWDW4ROU.mjs";
3
3
  import "../chunk-ZHXCVRZX.mjs";
4
4
  import "../chunk-IHTPXUYI.mjs";
5
+ import "../chunk-QKT5R735.mjs";
5
6
  import {
6
7
  ShelbyClient
7
- } from "../chunk-YV67F5NY.mjs";
8
+ } from "../chunk-RYJCDQEK.mjs";
9
+ import {
10
+ ShelbyBlobClient
11
+ } from "../chunk-B3CB2YEO.mjs";
12
+ import {
13
+ ShelbyRPCClient
14
+ } from "../chunk-IAHEBEM6.mjs";
8
15
  import {
9
16
  createBlobKey
10
17
  } from "../chunk-QEMIORTL.mjs";
11
18
  import {
12
19
  BlobCommitmentsSchema,
13
- ChunksetCommitmentSchema
14
- } from "../chunk-NPM7WXK3.mjs";
20
+ ChunksetCommitmentSchema,
21
+ generateCommitments
22
+ } from "../chunk-G263DBCY.mjs";
23
+ import {
24
+ concatHashes,
25
+ readInChunks,
26
+ zeroPadBuffer
27
+ } from "../chunk-5Z3RVWU3.mjs";
28
+ import {
29
+ erasureEncode
30
+ } from "../chunk-P7BVGLTV.mjs";
15
31
  import {
16
32
  BlobNameSchema,
17
33
  ChunkKey,
@@ -31,6 +47,7 @@ import {
31
47
  getChunkSizeBytes,
32
48
  getChunksetSizeBytes
33
49
  } from "../chunk-D2FERD4A.mjs";
50
+ import "../chunk-I6NG5GNL.mjs";
34
51
  import "../chunk-7P6ASYW6.mjs";
35
52
  export {
36
53
  BlobCommitmentsSchema,
@@ -44,12 +61,19 @@ export {
44
61
  ERASURE_K,
45
62
  ERASURE_M,
46
63
  SHELBY_DEPLOYER,
64
+ ShelbyBlobClient,
47
65
  ShelbyClient,
66
+ ShelbyRPCClient,
48
67
  TOKEN_DEPLOYER,
49
68
  TOKEN_OBJECT_ADDRESS,
50
69
  allChunksForBlob,
70
+ concatHashes,
51
71
  createBlobKey,
72
+ erasureEncode,
73
+ generateCommitments,
52
74
  getChunkSizeBytes,
53
75
  getChunksetSizeBytes,
54
- roundSize
76
+ readInChunks,
77
+ roundSize,
78
+ zeroPadBuffer
55
79
  };
@@ -0,0 +1,67 @@
1
+ // src/core/utils.ts
2
+ import { Hex } from "@aptos-labs/ts-sdk";
3
+ async function* readInChunks(input, chunkSize) {
4
+ let idx = 0;
5
+ if (Buffer.isBuffer(input)) {
6
+ for (let offset = 0; offset < input.length; offset += chunkSize) {
7
+ yield [idx++, Buffer.from(input.subarray(offset, offset + chunkSize))];
8
+ }
9
+ return;
10
+ }
11
+ const reader = input.getReader();
12
+ let buffer = new Uint8Array(chunkSize);
13
+ let bufferWriteOffset = 0;
14
+ try {
15
+ while (true) {
16
+ const { value, done } = await reader.read();
17
+ if (done) break;
18
+ if (value === void 0) continue;
19
+ let srcOffset = 0;
20
+ while (srcOffset < value.length) {
21
+ const remainingCapacity = chunkSize - bufferWriteOffset;
22
+ const bytesToCopy = Math.min(
23
+ remainingCapacity,
24
+ value.length - srcOffset
25
+ );
26
+ buffer.set(
27
+ value.subarray(srcOffset, srcOffset + bytesToCopy),
28
+ bufferWriteOffset
29
+ );
30
+ bufferWriteOffset += bytesToCopy;
31
+ srcOffset += bytesToCopy;
32
+ if (bufferWriteOffset >= chunkSize) {
33
+ yield [idx++, Buffer.from(buffer)];
34
+ buffer = new Uint8Array(chunkSize);
35
+ bufferWriteOffset = 0;
36
+ }
37
+ }
38
+ }
39
+ } finally {
40
+ reader.releaseLock();
41
+ }
42
+ if (bufferWriteOffset > 0) {
43
+ yield [idx++, Buffer.from(buffer.subarray(0, bufferWriteOffset))];
44
+ }
45
+ }
46
+ function zeroPadBuffer(buffer, desiredLength) {
47
+ if (buffer.length >= desiredLength) {
48
+ return buffer;
49
+ }
50
+ const paddedBuffer = Buffer.alloc(desiredLength);
51
+ buffer.copy(paddedBuffer);
52
+ return paddedBuffer;
53
+ }
54
+ async function concatHashes(parts) {
55
+ const combined = Buffer.concat(
56
+ parts.map((part) => Hex.fromHexInput(part).toUint8Array())
57
+ );
58
+ return Hex.fromHexInput(
59
+ new Uint8Array(await crypto.subtle.digest("SHA-256", combined))
60
+ );
61
+ }
62
+
63
+ export {
64
+ readInChunks,
65
+ zeroPadBuffer,
66
+ concatHashes
67
+ };
@@ -1,6 +1,3 @@
1
- import {
2
- generateCommitments
3
- } from "./chunk-VLLCOFH7.mjs";
4
1
  import {
5
2
  createBlobKey
6
3
  } from "./chunk-QEMIORTL.mjs";
@@ -8,8 +5,7 @@ import {
8
5
  SHELBY_DEPLOYER
9
6
  } from "./chunk-D2FERD4A.mjs";
10
7
 
11
- // src/node/clients/ShelbyBlobClient.ts
12
- import { Readable } from "stream";
8
+ // src/core/clients/ShelbyBlobClient.ts
13
9
  import {
14
10
  AccountAddress,
15
11
  Aptos,
@@ -34,7 +30,7 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
34
30
  */
35
31
  constructor(config) {
36
32
  this.aptos = new Aptos(config.aptos.config);
37
- this.deployer = config.shelbyDeployer ?? AccountAddress.fromString(SHELBY_DEPLOYER);
33
+ this.deployer = config.shelby?.deployer ?? AccountAddress.fromString(SHELBY_DEPLOYER);
38
34
  }
39
35
  /**
40
36
  * Retrieves the blob metadata from the blockchain. If it does not exist,
@@ -181,7 +177,7 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
181
177
  *
182
178
  * @example
183
179
  * ```typescript
184
- * const blobCommitments = await generateCommitments(Readable.from(data));
180
+ * const blobCommitments = await generateCommitments(data);
185
181
  *
186
182
  * const { blobCommitments, transaction } = await client.writeBlobCommitments({
187
183
  * signer,
@@ -192,16 +188,7 @@ var ShelbyBlobClient = class _ShelbyBlobClient {
192
188
  * ```
193
189
  */
194
190
  async writeBlobCommitments(params) {
195
- let blobCommitments;
196
- if ("blobCommitments" in params) {
197
- blobCommitments = params.blobCommitments;
198
- } else {
199
- blobCommitments = await generateCommitments(
200
- Readable.from(params.blobData),
201
- void 0,
202
- params.options?.encoding
203
- );
204
- }
191
+ const blobCommitments = params.blobCommitments;
205
192
  const transaction = await this.aptos.transaction.build.simple({
206
193
  ...params.options?.build,
207
194
  data: _ShelbyBlobClient.createWriteBlobCommitmentsPayload({
@@ -0,0 +1,105 @@
1
+ import {
2
+ concatHashes,
3
+ readInChunks,
4
+ zeroPadBuffer
5
+ } from "./chunk-5Z3RVWU3.mjs";
6
+ import {
7
+ erasureEncode
8
+ } from "./chunk-P7BVGLTV.mjs";
9
+ import {
10
+ roundSize
11
+ } from "./chunk-GGYTHP5F.mjs";
12
+ import {
13
+ ERASURE_K,
14
+ ERASURE_M,
15
+ getChunksetSizeBytes
16
+ } from "./chunk-D2FERD4A.mjs";
17
+
18
+ // src/core/commitments.ts
19
+ import { z } from "zod";
20
+ var ChunksetCommitmentSchema = z.object({
21
+ // Chunkset root (vector commitment of child chunks)
22
+ chunkset_root: z.string().nullable(),
23
+ // the size is known statically from the current configuration
24
+ chunk_commitments: z.array(z.string())
25
+ }).refine(
26
+ (data) => {
27
+ return data.chunk_commitments.length === ERASURE_K + ERASURE_M;
28
+ },
29
+ {
30
+ message: `Chunkset must have exactly ${ERASURE_K + ERASURE_M} chunks (ERASURE_K + ERASURE_M = ${ERASURE_K} + ${ERASURE_M})`,
31
+ path: ["chunk_commitments"]
32
+ }
33
+ );
34
+ function expectedTotalChunksets(rawSize) {
35
+ return roundSize(rawSize) / getChunksetSizeBytes();
36
+ }
37
+ var BlobCommitmentsSchema = z.object({
38
+ schema_version: z.string(),
39
+ raw_data_size: z.number(),
40
+ // FIXME I am not sure about this being here, or if it should be somewhere else
41
+ blob_merkle_root: z.string(),
42
+ chunkset_commitments: z.array(ChunksetCommitmentSchema)
43
+ }).refine(
44
+ (data) => {
45
+ return expectedTotalChunksets(data.raw_data_size) === data.chunkset_commitments.length;
46
+ },
47
+ {
48
+ message: "Total chunkset count mismatches with raw data size",
49
+ // FIXME put more details in here
50
+ path: ["chunkset_commitments"]
51
+ }
52
+ );
53
+ async function generateCommitments(fullData, onChunk, options) {
54
+ const chunksetCommitments = [];
55
+ const chunksetCommitmentHashes = [];
56
+ let rawDataSize = 0;
57
+ const chunksetGen = readInChunks(
58
+ fullData,
59
+ options?.chunksetSize ?? getChunksetSizeBytes()
60
+ );
61
+ for await (const [chunksetIdx, chunksetData] of chunksetGen) {
62
+ const chunkCommitments = [];
63
+ rawDataSize += chunksetData.length;
64
+ const paddedChunksetData = zeroPadBuffer(
65
+ chunksetData,
66
+ options?.chunksetSize ?? getChunksetSizeBytes()
67
+ );
68
+ const chunks = await erasureEncode(
69
+ paddedChunksetData,
70
+ options?.erasureK ?? ERASURE_K,
71
+ options?.erasureM ?? ERASURE_M
72
+ );
73
+ let chunkIdx = 0;
74
+ for (const chunkData of chunks) {
75
+ if (onChunk !== void 0) {
76
+ await onChunk(chunksetIdx, chunkIdx, chunkData);
77
+ }
78
+ const chunkHash = await concatHashes([chunkData]);
79
+ chunkCommitments.push(chunkHash);
80
+ chunkIdx += 1;
81
+ }
82
+ const h = await concatHashes(
83
+ chunkCommitments.map((chunk) => chunk.toUint8Array())
84
+ );
85
+ chunksetCommitments.push({
86
+ chunkset_root: h.toString(),
87
+ chunk_commitments: chunkCommitments.map((chunk) => chunk.toString())
88
+ });
89
+ chunksetCommitmentHashes.push(h);
90
+ }
91
+ return {
92
+ schema_version: "1.3",
93
+ raw_data_size: rawDataSize,
94
+ blob_merkle_root: (await concatHashes(
95
+ chunksetCommitmentHashes.map((chunk) => chunk.toUint8Array())
96
+ )).toString(),
97
+ chunkset_commitments: chunksetCommitments
98
+ };
99
+ }
100
+
101
+ export {
102
+ ChunksetCommitmentSchema,
103
+ BlobCommitmentsSchema,
104
+ generateCommitments
105
+ };
@@ -0,0 +1,11 @@
1
+ import {
2
+ ShelbyClient
3
+ } from "./chunk-RYJCDQEK.mjs";
4
+
5
+ // src/node/clients/ShelbyNodeClient.ts
6
+ var ShelbyNodeClient = class extends ShelbyClient {
7
+ };
8
+
9
+ export {
10
+ ShelbyNodeClient
11
+ };
@@ -1,20 +1,20 @@
1
- import {
2
- ShelbyClient
3
- } from "./chunk-YV67F5NY.mjs";
4
1
  import {
5
2
  BlobNameSchema
6
3
  } from "./chunk-GGYTHP5F.mjs";
4
+ import {
5
+ DEFAULT_SHELBY_BASE_URL
6
+ } from "./chunk-D2FERD4A.mjs";
7
7
  import {
8
8
  sleep
9
9
  } from "./chunk-I6NG5GNL.mjs";
10
10
 
11
- // src/node/clients/ShelbyRPCClient.ts
12
- import { Readable, Transform } from "stream";
11
+ // src/core/clients/ShelbyRPCClient.ts
13
12
  import { AccountAddress } from "@aptos-labs/ts-sdk";
14
13
  function encodeURIComponentKeepSlashes(str) {
15
14
  return encodeURIComponent(str).replace(/%2F/g, "/");
16
15
  }
17
- var ShelbyRPCClient = class extends ShelbyClient {
16
+ var ShelbyRPCClient = class {
17
+ baseUrl;
18
18
  /**
19
19
  * The ShelbyRPCClient is used to interact with the Shelby RPC node. This
20
20
  * includes functions like uploading blobs after they have been committed to the
@@ -25,19 +25,18 @@ var ShelbyRPCClient = class extends ShelbyClient {
25
25
  *
26
26
  * @example
27
27
  * ```typescript
28
- * const aptos = new Aptos(new AptosConfig({ network: Network.DEVNET }));
28
+ * const aptos = new Aptos(new AptosConfig({ network: Network.TESTNET }));
29
29
  * const client = new ShelbyRPCClient({ aptos, shelby: { baseUrl: "https://api.shelby.dev" } });
30
30
  * ```
31
31
  */
32
- // biome-ignore lint/complexity/noUselessConstructor: Add JSDoc
33
32
  constructor(config) {
34
- super(config);
33
+ this.baseUrl = config.shelby?.baseUrl ?? DEFAULT_SHELBY_BASE_URL;
35
34
  }
36
35
  async #uploadPart(uploadId, partIdx, partData) {
37
36
  const nRetries = 5;
38
37
  for (let i = 0; i < nRetries; ++i) {
39
38
  const partResponse = await fetch(
40
- `${this.baseUrl}/api/v1/multipartUpload/uploadPart/${uploadId}/${partIdx}`,
39
+ `${this.baseUrl}/v1/multipart-uploads/${uploadId}/parts/${partIdx}`,
41
40
  {
42
41
  method: "PUT",
43
42
  headers: {
@@ -55,25 +54,22 @@ var ShelbyRPCClient = class extends ShelbyClient {
55
54
  throw new Error(`Failed to upload part ${partIdx}.`);
56
55
  }
57
56
  async #putBlobMultipart(account, blobName, blobData, partSize = 5 * 1024 * 1024) {
58
- const startResponse = await fetch(
59
- `${this.baseUrl}/api/v1/multipartUpload/start`,
60
- {
61
- method: "POST",
62
- headers: {
63
- "Content-Type": "application/json"
64
- },
65
- body: JSON.stringify({
66
- rawAccount: account.toString(),
67
- rawBlobName: blobName,
68
- rawPartSize: partSize
69
- })
70
- }
71
- );
57
+ const startResponse = await fetch(`${this.baseUrl}/v1/multipart-uploads`, {
58
+ method: "POST",
59
+ headers: {
60
+ "Content-Type": "application/json"
61
+ },
62
+ body: JSON.stringify({
63
+ rawAccount: account.toString(),
64
+ rawBlobName: blobName,
65
+ rawPartSize: partSize
66
+ })
67
+ });
72
68
  if (!startResponse.ok) {
73
69
  let errorBodyText = "Could not read error body";
74
70
  try {
75
71
  errorBodyText = await startResponse.text();
76
- } catch (e) {
72
+ } catch (_e) {
77
73
  }
78
74
  throw new Error(
79
75
  `Failed to start multipart upload! status: ${startResponse.status}, body: ${errorBodyText}`
@@ -84,11 +80,11 @@ var ShelbyRPCClient = class extends ShelbyClient {
84
80
  for (let partIdx = 0; partIdx < totalParts; partIdx++) {
85
81
  const start = partIdx * partSize;
86
82
  const end = Math.min(start + partSize, blobData.length);
87
- const partData = blobData.subarray(start, end);
83
+ const partData = blobData.slice(start, end);
88
84
  await this.#uploadPart(uploadId, partIdx, partData);
89
85
  }
90
86
  const completeResponse = await fetch(
91
- `${this.baseUrl}/api/v1/multipartUpload/complete/${uploadId}`,
87
+ `${this.baseUrl}/v1/multipart-uploads/${uploadId}/complete`,
92
88
  {
93
89
  method: "POST",
94
90
  headers: {
@@ -100,7 +96,7 @@ var ShelbyRPCClient = class extends ShelbyClient {
100
96
  let errorBodyText = "Could not read error body";
101
97
  try {
102
98
  errorBodyText = await completeResponse.text();
103
- } catch (e) {
99
+ } catch (_e) {
104
100
  }
105
101
  throw new Error(
106
102
  `Failed to complete multipart upload! status: ${completeResponse.status}, body: ${errorBodyText}`
@@ -117,7 +113,7 @@ var ShelbyRPCClient = class extends ShelbyClient {
117
113
  *
118
114
  * @example
119
115
  * ```typescript
120
- * const blobData = Buffer.from("Hello, world!");
116
+ * const blobData = new TextEncoder().encode("Hello, world!");
121
117
  *
122
118
  * await client.putBlob({ account, blobName: "foo/bar.txt", blobData });
123
119
  * ```
@@ -186,45 +182,43 @@ var ShelbyRPCClient = class extends ShelbyClient {
186
182
  `Invalid content-length header received: ${contentLengthHeader}`
187
183
  );
188
184
  }
189
- let bytesReceived = 0;
190
- const reader = response.body.getReader();
191
- const sourceStream = new Readable({
192
- async read() {
193
- try {
194
- const { done, value } = await reader.read();
195
- if (done) {
196
- this.push(null);
197
- } else {
198
- this.push(Buffer.from(value));
199
- }
200
- } catch (error) {
201
- this.destroy(error);
185
+ const validatingStream = new ReadableStream({
186
+ start(controller) {
187
+ const maybeReader = response.body?.getReader();
188
+ if (!maybeReader) {
189
+ controller.error(new Error("Response body reader is unavailable"));
190
+ return;
202
191
  }
203
- }
204
- });
205
- const validationTransform = new Transform({
206
- transform(chunk, encoding, callback) {
207
- bytesReceived += chunk.length;
208
- callback(null, chunk);
209
- },
210
- flush(callback) {
211
- if (bytesReceived !== expectedContentLength) {
212
- callback(
213
- new Error(
214
- `Downloaded data size (${bytesReceived} bytes) does not match content-length header (${expectedContentLength} bytes). This might indicate a partial or corrupted download.`
215
- )
216
- );
217
- } else {
218
- callback();
192
+ const reader = maybeReader;
193
+ let bytesReceived = 0;
194
+ function pump() {
195
+ return reader.read().then(({ done, value }) => {
196
+ if (done) {
197
+ if (bytesReceived !== expectedContentLength) {
198
+ controller.error(
199
+ new Error(
200
+ `Downloaded data size (${bytesReceived} bytes) does not match content-length header (${expectedContentLength} bytes). This might indicate a partial or corrupted download.`
201
+ )
202
+ );
203
+ return;
204
+ }
205
+ controller.close();
206
+ return;
207
+ }
208
+ bytesReceived += value.byteLength;
209
+ controller.enqueue(value);
210
+ return pump();
211
+ }).catch((error) => {
212
+ controller.error(error);
213
+ });
219
214
  }
215
+ return pump();
220
216
  }
221
217
  });
222
- sourceStream.pipe(validationTransform);
223
218
  return {
224
219
  account: AccountAddress.from(params.account),
225
220
  name: params.blobName,
226
- readable: response.body,
227
- stream: validationTransform,
221
+ readable: validatingStream,
228
222
  contentLength: expectedContentLength
229
223
  };
230
224
  }
@@ -0,0 +1,32 @@
1
+ // src/core/erasure.ts
2
+ import { createWasmReedSolomonBinding } from "@shelby-protocol/reed-solomon";
3
+ function erasureEncode(data, k, m) {
4
+ const rawShardSize = Math.ceil(data.length / k);
5
+ const shardSize = Math.ceil(rawShardSize / 8) * 8;
6
+ const dataSize = shardSize * k;
7
+ const paritySize = shardSize * m;
8
+ const reedSolomon = createWasmReedSolomonBinding();
9
+ const dataBuf = Buffer.alloc(dataSize);
10
+ data.copy(dataBuf, 0);
11
+ const shards = new Uint8Array(dataSize + paritySize);
12
+ shards.set(new Uint8Array(dataBuf), 0);
13
+ reedSolomon.encode(shards, k, m);
14
+ const res = [];
15
+ for (let i = 0; i < k; i++) {
16
+ res.push(
17
+ Buffer.from(shards.slice(i * shardSize, i * shardSize + shardSize))
18
+ );
19
+ }
20
+ for (let j = 0; j < m; j++) {
21
+ res.push(
22
+ Buffer.from(
23
+ shards.slice((k + j) * shardSize, (k + j) * shardSize + shardSize)
24
+ )
25
+ );
26
+ }
27
+ return new Promise((resolve) => resolve(res));
28
+ }
29
+
30
+ export {
31
+ erasureEncode
32
+ };
File without changes
@@ -1,15 +1,21 @@
1
1
  import {
2
2
  ShelbyBlobClient
3
- } from "./chunk-EFE5Y7IE.mjs";
3
+ } from "./chunk-B3CB2YEO.mjs";
4
4
  import {
5
5
  ShelbyRPCClient
6
- } from "./chunk-DBTBUKCW.mjs";
6
+ } from "./chunk-IAHEBEM6.mjs";
7
7
  import {
8
- ShelbyClient
9
- } from "./chunk-YV67F5NY.mjs";
8
+ generateCommitments
9
+ } from "./chunk-G263DBCY.mjs";
10
+ import {
11
+ DEFAULT_SHELBY_BASE_URL
12
+ } from "./chunk-D2FERD4A.mjs";
10
13
 
11
- // src/node/clients/ShelbyNodeClient.ts
12
- var ShelbyNodeClient = class extends ShelbyClient {
14
+ // src/core/clients/ShelbyClient.ts
15
+ import {
16
+ Aptos
17
+ } from "@aptos-labs/ts-sdk";
18
+ var ShelbyClient = class {
13
19
  /**
14
20
  * The coordination client is used to interact with the Aptos blockchain which handles the commitments
15
21
  * and metadata for blobs.
@@ -21,26 +27,31 @@ var ShelbyNodeClient = class extends ShelbyClient {
21
27
  */
22
28
  rpc;
23
29
  /**
24
- * The ShelbyNodeClient is used to interact with the Shelby network.
30
+ * The configuration for the Shelby client.
31
+ */
32
+ config;
33
+ /**
34
+ * The Aptos client.
35
+ */
36
+ aptos;
37
+ /**
38
+ * The base class for Shelby clients
25
39
  *
26
40
  * @param config.aptos.config - The Aptos config.
27
41
  * @param config.shelby.baseUrl - The base URL of the Shelby RPC node. If not provided, the default base URL will be used.
28
- * @param config.shelby.deployer - The deployer account address of the Shelby contract. If not provided, the default deployer address will be used.
29
- *
30
- * @example
31
- * ```typescript
32
- * const aptos = new Aptos(new AptosConfig({ network: Network.DEVNET }));
33
- * const client = new ShelbyNodeClient({ aptos, shelby: { baseUrl: "https://api.shelby.dev" } });
34
- * ```
35
42
  */
36
43
  constructor(config) {
37
- super(config);
38
- this.coordination = new ShelbyBlobClient({
39
- aptos: this.aptos,
40
- shelbyDeployer: config.shelby?.deployer
41
- });
44
+ this.config = config;
45
+ this.aptos = new Aptos(this.config.aptos.config);
46
+ this.coordination = new ShelbyBlobClient(config);
42
47
  this.rpc = new ShelbyRPCClient(config);
43
48
  }
49
+ /**
50
+ * The base URL for the Shelby RPC node.
51
+ */
52
+ get baseUrl() {
53
+ return this.config.shelby?.baseUrl ?? DEFAULT_SHELBY_BASE_URL;
54
+ }
44
55
  /**
45
56
  * Uploads a blob to the Shelby network.
46
57
  *
@@ -53,7 +64,15 @@ var ShelbyNodeClient = class extends ShelbyClient {
53
64
  * @returns The transaction and generated blob commitments.
54
65
  */
55
66
  async upload(params) {
56
- const { transaction, blobCommitments } = await this.coordination.writeBlobCommitments(params);
67
+ const generatedBlobCommitments = await generateCommitments(
68
+ params.blobData,
69
+ void 0,
70
+ params.options?.encoding
71
+ );
72
+ const { transaction, blobCommitments } = await this.coordination.writeBlobCommitments({
73
+ ...params,
74
+ blobCommitments: generatedBlobCommitments
75
+ });
57
76
  const confirmedTransaction = await this.aptos.waitForTransaction({
58
77
  transactionHash: transaction.hash
59
78
  });
@@ -86,5 +105,5 @@ var ShelbyNodeClient = class extends ShelbyClient {
86
105
  };
87
106
 
88
107
  export {
89
- ShelbyNodeClient
108
+ ShelbyClient
90
109
  };