@shelby-protocol/sdk 0.2.4 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.d.ts +13 -4
- package/dist/browser/index.mjs +3719 -140
- package/dist/{clay-codes-DHP-bYcP.d.ts → clay-codes-DdXABBDx.d.ts} +0 -7
- package/dist/core/aptos-explorer.mjs +46 -5
- package/dist/core/blobs.d.ts +1 -1
- package/dist/core/blobs.mjs +12 -4
- package/dist/core/chunk.mjs +58 -9
- package/dist/core/clients/ShelbyBlobClient.d.ts +9 -44
- package/dist/core/clients/ShelbyBlobClient.mjs +1084 -17
- package/dist/core/clients/ShelbyClient.d.ts +12 -2
- package/dist/core/clients/ShelbyClient.mjs +2915 -23
- package/dist/core/clients/ShelbyClientConfig.d.ts +8 -0
- package/dist/core/clients/ShelbyClientConfig.mjs +0 -1
- package/dist/core/clients/ShelbyMetadataClient.d.ts +0 -18
- package/dist/core/clients/ShelbyMetadataClient.mjs +306 -6
- package/dist/core/clients/ShelbyMicropaymentChannelClient.d.ts +7 -49
- package/dist/core/clients/ShelbyMicropaymentChannelClient.mjs +839 -13
- package/dist/core/clients/ShelbyPlacementGroupClient.mjs +307 -8
- package/dist/core/clients/ShelbyRPCClient.d.ts +107 -4
- package/dist/core/clients/ShelbyRPCClient.mjs +1261 -12
- package/dist/core/clients/index.d.ts +3 -2
- package/dist/core/clients/index.mjs +3421 -40
- package/dist/core/clients/utils.mjs +65 -6
- package/dist/core/commitments.d.ts +3 -12
- package/dist/core/commitments.mjs +270 -11
- package/dist/core/constants.d.ts +4 -4
- package/dist/core/constants.mjs +39 -16
- package/dist/core/erasure/clay-codes.d.ts +1 -1
- package/dist/core/erasure/clay-codes.mjs +129 -4
- package/dist/core/erasure/constants.mjs +33 -10
- package/dist/core/erasure/default.d.ts +1 -1
- package/dist/core/erasure/default.mjs +191 -9
- package/dist/core/erasure/index.d.ts +1 -1
- package/dist/core/erasure/index.mjs +266 -23
- package/dist/core/erasure/provider.d.ts +1 -1
- package/dist/core/erasure/reed-solomon.d.ts +1 -1
- package/dist/core/erasure/reed-solomon.mjs +68 -4
- package/dist/core/erasure/utils.d.ts +1 -1
- package/dist/core/erasure/utils.mjs +0 -2
- package/dist/core/errors.mjs +29 -8
- package/dist/core/index.d.ts +4 -4
- package/dist/core/index.mjs +3713 -140
- package/dist/core/layout.d.ts +1 -1
- package/dist/core/layout.mjs +37 -5
- package/dist/core/networks.mjs +10 -5
- package/dist/core/operations/generated/sdk.d.ts +9 -0
- package/dist/core/operations/generated/sdk.mjs +183 -18
- package/dist/core/operations/index.mjs +284 -24
- package/dist/core/promises.mjs +4 -4
- package/dist/core/rpc-responses.d.ts +38 -1
- package/dist/core/rpc-responses.mjs +31 -8
- package/dist/core/shelby-explorer.mjs +31 -6
- package/dist/core/strings.mjs +0 -2
- package/dist/core/types/blobs.d.ts +1 -1
- package/dist/core/types/blobs.mjs +0 -1
- package/dist/core/types/index.d.ts +1 -1
- package/dist/core/types/index.mjs +230 -9
- package/dist/core/types/payments.d.ts +6 -6
- package/dist/core/types/payments.mjs +230 -5
- package/dist/core/types/placement_groups.mjs +0 -1
- package/dist/core/types/storage_providers.mjs +0 -1
- package/dist/core/utils.mjs +94 -8
- package/dist/node/clients/ShelbyNodeClient.d.ts +2 -1
- package/dist/node/clients/ShelbyNodeClient.mjs +2919 -24
- package/dist/node/clients/index.d.ts +2 -1
- package/dist/node/clients/index.mjs +2920 -26
- package/dist/node/index.d.ts +4 -4
- package/dist/node/index.mjs +3736 -147
- package/dist/node/parallel/commitment_worker.d.ts +9 -0
- package/dist/node/parallel/commitment_worker.mjs +298 -0
- package/dist/node/parallel/commitment_worker_pool.d.ts +35 -0
- package/dist/node/parallel/commitment_worker_pool.mjs +286 -0
- package/dist/node/parallel/default_commitment_worker_pool.d.ts +24 -0
- package/dist/node/parallel/default_commitment_worker_pool.mjs +302 -0
- package/dist/node/parallel/index.d.ts +11 -0
- package/dist/node/parallel/index.mjs +563 -0
- package/dist/node/parallel/parallel_commitments.d.ts +32 -0
- package/dist/node/parallel/parallel_commitments.mjs +561 -0
- package/dist/node/parallel/worker_pool.d.ts +74 -0
- package/dist/node/parallel/worker_pool.mjs +248 -0
- package/dist/node/testUtil.mjs +8 -4
- package/package.json +9 -6
- package/dist/chunk-3NRBHSMQ.mjs +0 -12
- package/dist/chunk-3PCG7PNP.mjs +0 -375
- package/dist/chunk-7OV5ZYW6.mjs +0 -55
- package/dist/chunk-7P6ASYW6.mjs +0 -9
- package/dist/chunk-A4IG6GSE.mjs +0 -21
- package/dist/chunk-AD2G3QYD.mjs +0 -0
- package/dist/chunk-AEDVYYGD.mjs +0 -11
- package/dist/chunk-AUQDI5BS.mjs +0 -43
- package/dist/chunk-BDSW5PHM.mjs +0 -37
- package/dist/chunk-BKL7NCUB.mjs +0 -412
- package/dist/chunk-BUWAD67L.mjs +0 -505
- package/dist/chunk-BXEVML7N.mjs +0 -169
- package/dist/chunk-C6RQ3AEU.mjs +0 -51
- package/dist/chunk-CQ6QPIZK.mjs +0 -37
- package/dist/chunk-D6GQHO6G.mjs +0 -15
- package/dist/chunk-EM67QTMR.mjs +0 -0
- package/dist/chunk-I6NG5GNL.mjs +0 -8
- package/dist/chunk-IE6LYVIA.mjs +0 -26
- package/dist/chunk-IKRWBDG5.mjs +0 -42
- package/dist/chunk-JTXYKO3U.mjs +0 -38
- package/dist/chunk-KYQRWJ3U.mjs +0 -49
- package/dist/chunk-MB7C7VQF.mjs +0 -0
- package/dist/chunk-MQUVYMNQ.mjs +0 -0
- package/dist/chunk-NHWWORCH.mjs +0 -72
- package/dist/chunk-NI6XBZLI.mjs +0 -83
- package/dist/chunk-OGKZ575S.mjs +0 -136
- package/dist/chunk-QQ57OGQ2.mjs +0 -0
- package/dist/chunk-SSE4MFNN.mjs +0 -278
- package/dist/chunk-TET3DJEO.mjs +0 -199
- package/dist/chunk-TVLV7C74.mjs +0 -207
- package/dist/chunk-UEZNZBJO.mjs +0 -104
- package/dist/chunk-WJTVYLKW.mjs +0 -782
- package/dist/chunk-WTICJPDB.mjs +0 -0
- package/dist/chunk-XNEIWM4O.mjs +0 -0
- package/dist/chunk-XRLHLAOW.mjs +0 -51
- package/dist/chunk-Z4FZ7W6L.mjs +0 -39
- package/dist/chunk-Z7RFCADT.mjs +0 -0
- package/dist/chunk-ZHXCVRZX.mjs +0 -0
- package/dist/core/operations/generated/types.d.ts +0 -908
- package/dist/core/operations/generated/types.mjs +0 -63
- package/dist/core/types/encodings.d.ts +0 -11
- package/dist/core/types/encodings.mjs +0 -0
package/dist/chunk-7OV5ZYW6.mjs
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
// src/core/constants.ts
|
|
2
|
-
import { Network } from "@aptos-labs/ts-sdk";
|
|
3
|
-
var DEFAULT_PROJECT_NAME = "shelby";
|
|
4
|
-
var DEFAULT_PROJECT_DESCRIPTION = "High performance, decentralized storage";
|
|
5
|
-
var NetworkToShelbyRPCBaseUrl = {
|
|
6
|
-
[Network.SHELBYNET]: "https://api.shelbynet.shelby.xyz/shelby",
|
|
7
|
-
[Network.NETNA]: void 0,
|
|
8
|
-
[Network.DEVNET]: void 0,
|
|
9
|
-
[Network.TESTNET]: "https://api.testnet.shelby.xyz/shelby",
|
|
10
|
-
[Network.MAINNET]: void 0,
|
|
11
|
-
[Network.LOCAL]: void 0,
|
|
12
|
-
[Network.CUSTOM]: void 0
|
|
13
|
-
};
|
|
14
|
-
var NetworkToShelbyBlobIndexerBaseUrl = {
|
|
15
|
-
[Network.SHELBYNET]: "https://api.shelbynet.aptoslabs.com/nocode/v1/public/cmforrguw0042s601fn71f9l2/v1/graphql",
|
|
16
|
-
[Network.NETNA]: void 0,
|
|
17
|
-
[Network.DEVNET]: void 0,
|
|
18
|
-
[Network.TESTNET]: "https://api.testnet.aptoslabs.com/nocode/v1/public/cmlfqs5wt00qrs601zt5s4kfj/v1/graphql",
|
|
19
|
-
[Network.MAINNET]: void 0,
|
|
20
|
-
[Network.LOCAL]: void 0,
|
|
21
|
-
[Network.CUSTOM]: void 0
|
|
22
|
-
};
|
|
23
|
-
var NetworkToGasStationBaseUrl = {
|
|
24
|
-
[Network.SHELBYNET]: "https://api.shelbynet.shelby.xyz/gs/v1",
|
|
25
|
-
[Network.NETNA]: void 0,
|
|
26
|
-
[Network.DEVNET]: void 0,
|
|
27
|
-
[Network.TESTNET]: "https://api.testnet.shelby.xyz/gs/v1",
|
|
28
|
-
[Network.MAINNET]: void 0,
|
|
29
|
-
[Network.LOCAL]: void 0,
|
|
30
|
-
[Network.CUSTOM]: void 0
|
|
31
|
-
};
|
|
32
|
-
var SHELBY_DEPLOYER = "0x85fdb9a176ab8ef1d9d9c1b60d60b3924f0800ac1de1cc2085fb0b8bb4988e6a";
|
|
33
|
-
var MICROPAYMENTS_DEPLOYER = "0x1ae7275148bf6ef742b658fd9cbcc2e094201606f4a7bc707bab0201da8043ee";
|
|
34
|
-
var TOKEN_DEPLOYER = "0x33009e852be7f93762dd0bf303383c2cb2c5cab7a30d8238ca5f9f177ae75124";
|
|
35
|
-
var TOKEN_OBJECT_ADDRESS = "0x249f5c642a63885ff88a5113b3ba0079840af5a1357706f8c7f3bfc5dd12511f";
|
|
36
|
-
var SHELBYUSD_TOKEN_ADDRESS = TOKEN_OBJECT_ADDRESS;
|
|
37
|
-
var SHELBYUSD_TOKEN_MODULE = "shelby_usd";
|
|
38
|
-
var SHELBYUSD_TOKEN_NAME = "ShelbyUSD";
|
|
39
|
-
var SHELBYUSD_FA_METADATA_ADDRESS = "0x1b18363a9f1fe5e6ebf247daba5cc1c18052bb232efdc4c50f556053922d98e1";
|
|
40
|
-
|
|
41
|
-
export {
|
|
42
|
-
DEFAULT_PROJECT_NAME,
|
|
43
|
-
DEFAULT_PROJECT_DESCRIPTION,
|
|
44
|
-
NetworkToShelbyRPCBaseUrl,
|
|
45
|
-
NetworkToShelbyBlobIndexerBaseUrl,
|
|
46
|
-
NetworkToGasStationBaseUrl,
|
|
47
|
-
SHELBY_DEPLOYER,
|
|
48
|
-
MICROPAYMENTS_DEPLOYER,
|
|
49
|
-
TOKEN_DEPLOYER,
|
|
50
|
-
TOKEN_OBJECT_ADDRESS,
|
|
51
|
-
SHELBYUSD_TOKEN_ADDRESS,
|
|
52
|
-
SHELBYUSD_TOKEN_MODULE,
|
|
53
|
-
SHELBYUSD_TOKEN_NAME,
|
|
54
|
-
SHELBYUSD_FA_METADATA_ADDRESS
|
|
55
|
-
};
|
package/dist/chunk-7P6ASYW6.mjs
DELETED
package/dist/chunk-A4IG6GSE.mjs
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
__export
|
|
3
|
-
} from "./chunk-7P6ASYW6.mjs";
|
|
4
|
-
|
|
5
|
-
// src/node/testUtil.ts
|
|
6
|
-
var testUtil_exports = {};
|
|
7
|
-
__export(testUtil_exports, {
|
|
8
|
-
makeChunk: () => makeChunk
|
|
9
|
-
});
|
|
10
|
-
function makeChunk(n) {
|
|
11
|
-
const c = Buffer.alloc(n);
|
|
12
|
-
for (let i = 0; i < n; ++i) {
|
|
13
|
-
c[i] = i % 256;
|
|
14
|
-
}
|
|
15
|
-
return c;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export {
|
|
19
|
-
makeChunk,
|
|
20
|
-
testUtil_exports
|
|
21
|
-
};
|
package/dist/chunk-AD2G3QYD.mjs
DELETED
|
File without changes
|
package/dist/chunk-AEDVYYGD.mjs
DELETED
package/dist/chunk-AUQDI5BS.mjs
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// src/core/erasure/constants.ts
|
|
2
|
-
var ErasureCodingScheme = /* @__PURE__ */ ((ErasureCodingScheme2) => {
|
|
3
|
-
ErasureCodingScheme2["ClayCode_16Total_10Data_13Helper"] = "ClayCode_16Total_10Data_13Helper";
|
|
4
|
-
ErasureCodingScheme2["ClayCode_4Total_2Data_3Helper"] = "ClayCode_4Total_2Data_3Helper";
|
|
5
|
-
return ErasureCodingScheme2;
|
|
6
|
-
})(ErasureCodingScheme || {});
|
|
7
|
-
var ERASURE_CODE_PARAMS = {
|
|
8
|
-
["ClayCode_16Total_10Data_13Helper" /* ClayCode_16Total_10Data_13Helper */]: {
|
|
9
|
-
// total chunks (data + parity)
|
|
10
|
-
erasure_n: 16,
|
|
11
|
-
// data chunks
|
|
12
|
-
erasure_k: 10,
|
|
13
|
-
// helper nodes
|
|
14
|
-
erasure_d: 13,
|
|
15
|
-
// enum index
|
|
16
|
-
enumIndex: 0
|
|
17
|
-
},
|
|
18
|
-
["ClayCode_4Total_2Data_3Helper" /* ClayCode_4Total_2Data_3Helper */]: {
|
|
19
|
-
// total chunks (data + parity)
|
|
20
|
-
erasure_n: 4,
|
|
21
|
-
// data chunks
|
|
22
|
-
erasure_k: 2,
|
|
23
|
-
// helper nodes
|
|
24
|
-
erasure_d: 3,
|
|
25
|
-
// enum index
|
|
26
|
-
enumIndex: 1
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
var DEFAULT_ERASURE_N = ERASURE_CODE_PARAMS["ClayCode_16Total_10Data_13Helper" /* ClayCode_16Total_10Data_13Helper */].erasure_n;
|
|
30
|
-
var DEFAULT_ERASURE_K = ERASURE_CODE_PARAMS["ClayCode_16Total_10Data_13Helper" /* ClayCode_16Total_10Data_13Helper */].erasure_k;
|
|
31
|
-
var DEFAULT_ERASURE_D = ERASURE_CODE_PARAMS["ClayCode_16Total_10Data_13Helper" /* ClayCode_16Total_10Data_13Helper */].erasure_d;
|
|
32
|
-
var DEFAULT_ERASURE_M = DEFAULT_ERASURE_N - DEFAULT_ERASURE_K;
|
|
33
|
-
var DEFAULT_SAMPLE_SIZE = 1024;
|
|
34
|
-
|
|
35
|
-
export {
|
|
36
|
-
ErasureCodingScheme,
|
|
37
|
-
ERASURE_CODE_PARAMS,
|
|
38
|
-
DEFAULT_ERASURE_N,
|
|
39
|
-
DEFAULT_ERASURE_K,
|
|
40
|
-
DEFAULT_ERASURE_D,
|
|
41
|
-
DEFAULT_ERASURE_M,
|
|
42
|
-
DEFAULT_SAMPLE_SIZE
|
|
43
|
-
};
|
package/dist/chunk-BDSW5PHM.mjs
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// src/core/shelby-explorer.ts
|
|
2
|
-
import { Network } from "@aptos-labs/ts-sdk";
|
|
3
|
-
function getShelbyExplorerBaseUrl(network) {
|
|
4
|
-
const normalizedNetwork = network.toLowerCase();
|
|
5
|
-
switch (normalizedNetwork) {
|
|
6
|
-
case Network.MAINNET.toLowerCase():
|
|
7
|
-
return "https://explorer.shelby.xyz/mainnet";
|
|
8
|
-
case Network.TESTNET.toLowerCase():
|
|
9
|
-
return "https://explorer.shelby.xyz/testnet";
|
|
10
|
-
case Network.DEVNET.toLowerCase():
|
|
11
|
-
return "https://explorer.shelby.xyz/devnet";
|
|
12
|
-
case Network.LOCAL.toLowerCase():
|
|
13
|
-
return "https://explorer.shelby.xyz/local";
|
|
14
|
-
case Network.SHELBYNET.toLowerCase():
|
|
15
|
-
return "https://explorer.shelby.xyz/shelbynet";
|
|
16
|
-
default:
|
|
17
|
-
return `https://explorer.shelby.xyz/${normalizedNetwork}`;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
function getShelbyAccountBlobsExplorerUrl(network, accountAddress) {
|
|
21
|
-
const baseUrl = getShelbyExplorerBaseUrl(network);
|
|
22
|
-
return `${baseUrl}/account/${accountAddress}/blobs`;
|
|
23
|
-
}
|
|
24
|
-
function getShelbyBlobExplorerUrl(network, accountAddress, blobName) {
|
|
25
|
-
const baseUrl = getShelbyExplorerBaseUrl(network);
|
|
26
|
-
return `${baseUrl}/account/${accountAddress}/blob/${encodeURIComponent(blobName)}`;
|
|
27
|
-
}
|
|
28
|
-
function getShelbyAccountExplorerUrl(network, accountAddress) {
|
|
29
|
-
const baseUrl = getShelbyExplorerBaseUrl(network);
|
|
30
|
-
return `${baseUrl}/account/${accountAddress}`;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export {
|
|
34
|
-
getShelbyAccountBlobsExplorerUrl,
|
|
35
|
-
getShelbyBlobExplorerUrl,
|
|
36
|
-
getShelbyAccountExplorerUrl
|
|
37
|
-
};
|
package/dist/chunk-BKL7NCUB.mjs
DELETED
|
@@ -1,412 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
StaleChannelStateError
|
|
3
|
-
} from "./chunk-TVLV7C74.mjs";
|
|
4
|
-
import {
|
|
5
|
-
getShelbyIndexerClient
|
|
6
|
-
} from "./chunk-KYQRWJ3U.mjs";
|
|
7
|
-
import {
|
|
8
|
-
getShelbyRPCBaseUrl
|
|
9
|
-
} from "./chunk-IKRWBDG5.mjs";
|
|
10
|
-
import {
|
|
11
|
-
sleep
|
|
12
|
-
} from "./chunk-I6NG5GNL.mjs";
|
|
13
|
-
import {
|
|
14
|
-
StaleMicropaymentErrorResponseSchema,
|
|
15
|
-
StartMultipartUploadResponseSchema
|
|
16
|
-
} from "./chunk-IE6LYVIA.mjs";
|
|
17
|
-
import {
|
|
18
|
-
buildRequestUrl,
|
|
19
|
-
normalizeAddress,
|
|
20
|
-
readInChunks
|
|
21
|
-
} from "./chunk-UEZNZBJO.mjs";
|
|
22
|
-
import {
|
|
23
|
-
BlobNameSchema
|
|
24
|
-
} from "./chunk-Z4FZ7W6L.mjs";
|
|
25
|
-
|
|
26
|
-
// src/core/clients/ShelbyRPCClient.ts
|
|
27
|
-
var MICROPAYMENT_HEADER = "X-Shelby-Micropayment";
|
|
28
|
-
function encodeURIComponentKeepSlashes(str) {
|
|
29
|
-
return encodeURIComponent(str).replace(/%2F/g, "/");
|
|
30
|
-
}
|
|
31
|
-
function validateTotalBytes(totalBytes) {
|
|
32
|
-
if (!Number.isInteger(totalBytes) || totalBytes < 0) {
|
|
33
|
-
throw new Error("totalBytes must be a non-negative integer");
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function getErrorCode(error) {
|
|
37
|
-
if (typeof error === "object" && error !== null && "code" in error && typeof error.code === "string") {
|
|
38
|
-
return error.code;
|
|
39
|
-
}
|
|
40
|
-
if (error instanceof Error) {
|
|
41
|
-
const match = error.message.match(/\bE[A-Z0-9_]+\b/);
|
|
42
|
-
return match?.[0];
|
|
43
|
-
}
|
|
44
|
-
return void 0;
|
|
45
|
-
}
|
|
46
|
-
var ShelbyRPCClient = class {
|
|
47
|
-
baseUrl;
|
|
48
|
-
apiKey;
|
|
49
|
-
rpcConfig;
|
|
50
|
-
indexer;
|
|
51
|
-
/**
|
|
52
|
-
* Creates a new ShelbyRPCClient for interacting with Shelby RPC nodes.
|
|
53
|
-
* This client handles blob storage operations including upload and download.
|
|
54
|
-
*
|
|
55
|
-
* @param config - The client configuration object.
|
|
56
|
-
* @param config.network - The Shelby network to use.
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* ```typescript
|
|
60
|
-
* const client = new ShelbyRPCClient({
|
|
61
|
-
* network: Network.SHELBYNET,
|
|
62
|
-
* apiKey: "AG-***",
|
|
63
|
-
* });
|
|
64
|
-
* ```
|
|
65
|
-
*/
|
|
66
|
-
constructor(config) {
|
|
67
|
-
this.baseUrl = getShelbyRPCBaseUrl(config);
|
|
68
|
-
this.apiKey = config.apiKey ?? config.rpc?.apiKey;
|
|
69
|
-
this.rpcConfig = config.rpc ?? {};
|
|
70
|
-
this.indexer = getShelbyIndexerClient(config);
|
|
71
|
-
}
|
|
72
|
-
async #uploadPart(uploadId, partIdx, partData) {
|
|
73
|
-
const nRetries = 5;
|
|
74
|
-
let lastResponse;
|
|
75
|
-
let lastError;
|
|
76
|
-
const partUrl = buildRequestUrl(
|
|
77
|
-
`/v1/multipart-uploads/${uploadId}/parts/${partIdx}`,
|
|
78
|
-
this.baseUrl
|
|
79
|
-
);
|
|
80
|
-
for (let i = 0; i < nRetries; ++i) {
|
|
81
|
-
try {
|
|
82
|
-
lastResponse = await fetch(partUrl, {
|
|
83
|
-
method: "PUT",
|
|
84
|
-
headers: {
|
|
85
|
-
"Content-Type": "application/octet-stream",
|
|
86
|
-
...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
|
|
87
|
-
},
|
|
88
|
-
body: partData
|
|
89
|
-
});
|
|
90
|
-
lastError = void 0;
|
|
91
|
-
} catch (error) {
|
|
92
|
-
lastError = error;
|
|
93
|
-
if (i < nRetries - 1) {
|
|
94
|
-
const delay = 2 ** i * 100;
|
|
95
|
-
await sleep(delay);
|
|
96
|
-
continue;
|
|
97
|
-
}
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
if (lastResponse.ok) return;
|
|
101
|
-
if (i < nRetries - 1) {
|
|
102
|
-
const delay = 2 ** i * 100;
|
|
103
|
-
await sleep(delay);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
if (lastError !== void 0) {
|
|
107
|
-
const errorCode = getErrorCode(lastError);
|
|
108
|
-
const errorMessage = lastError instanceof Error ? lastError.message : String(lastError);
|
|
109
|
-
throw new Error(
|
|
110
|
-
`Failed to upload part ${partIdx} for multipart upload ${uploadId} after ${nRetries} attempts. The connection to the Shelby RPC endpoint was interrupted while sending data${errorCode ? ` (${errorCode})` : ""}. Endpoint: ${partUrl.toString()}, partBytes: ${partData.length}. Last error: ${errorMessage}`,
|
|
111
|
-
{ cause: lastError }
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
const errorBody = await lastResponse?.text().catch(() => "");
|
|
115
|
-
throw new Error(
|
|
116
|
-
`Failed to upload part ${partIdx} for multipart upload ${uploadId} after ${nRetries} attempts. status: ${lastResponse?.status}, body: ${errorBody}`
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
async #putBlobMultipart(account, blobName, blobData, totalBytes, partSize = 5 * 1024 * 1024, onProgress) {
|
|
120
|
-
validateTotalBytes(totalBytes);
|
|
121
|
-
const startResponse = await fetch(
|
|
122
|
-
buildRequestUrl("/v1/multipart-uploads", this.baseUrl),
|
|
123
|
-
{
|
|
124
|
-
method: "POST",
|
|
125
|
-
headers: {
|
|
126
|
-
"Content-Type": "application/json",
|
|
127
|
-
...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
|
|
128
|
-
},
|
|
129
|
-
body: JSON.stringify({
|
|
130
|
-
rawAccount: account.toString(),
|
|
131
|
-
rawBlobName: blobName,
|
|
132
|
-
rawPartSize: partSize
|
|
133
|
-
})
|
|
134
|
-
}
|
|
135
|
-
);
|
|
136
|
-
if (!startResponse.ok) {
|
|
137
|
-
let errorBodyText = "Could not read error body";
|
|
138
|
-
try {
|
|
139
|
-
errorBodyText = await startResponse.text();
|
|
140
|
-
} catch (_e) {
|
|
141
|
-
}
|
|
142
|
-
throw new Error(
|
|
143
|
-
`Failed to start multipart upload! status: ${startResponse.status}, body: ${errorBodyText}`
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
const { uploadId } = StartMultipartUploadResponseSchema.parse(
|
|
147
|
-
await startResponse.json()
|
|
148
|
-
);
|
|
149
|
-
const totalParts = Math.ceil(totalBytes / partSize);
|
|
150
|
-
let uploadedBytes = 0;
|
|
151
|
-
for await (const [partIdx, partData] of readInChunks(blobData, partSize)) {
|
|
152
|
-
await this.#uploadPart(uploadId, partIdx, partData);
|
|
153
|
-
uploadedBytes += partData.length;
|
|
154
|
-
onProgress?.({
|
|
155
|
-
phase: "uploading",
|
|
156
|
-
partIdx,
|
|
157
|
-
totalParts,
|
|
158
|
-
partBytes: partData.length,
|
|
159
|
-
uploadedBytes,
|
|
160
|
-
totalBytes
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
if (uploadedBytes !== totalBytes) {
|
|
164
|
-
throw new Error(
|
|
165
|
-
`Uploaded bytes (${uploadedBytes}) did not match declared totalBytes (${totalBytes})`
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
const finalPartIdx = totalParts > 0 ? totalParts - 1 : 0;
|
|
169
|
-
onProgress?.({
|
|
170
|
-
phase: "finalizing",
|
|
171
|
-
partIdx: finalPartIdx,
|
|
172
|
-
totalParts,
|
|
173
|
-
// no part uploaded in this phase
|
|
174
|
-
partBytes: 0,
|
|
175
|
-
uploadedBytes: totalBytes,
|
|
176
|
-
totalBytes
|
|
177
|
-
});
|
|
178
|
-
const completeResponse = await fetch(
|
|
179
|
-
buildRequestUrl(
|
|
180
|
-
`/v1/multipart-uploads/${uploadId}/complete`,
|
|
181
|
-
this.baseUrl
|
|
182
|
-
),
|
|
183
|
-
{
|
|
184
|
-
method: "POST",
|
|
185
|
-
headers: {
|
|
186
|
-
"Content-Type": "application/json",
|
|
187
|
-
...this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
);
|
|
191
|
-
if (!completeResponse.ok) {
|
|
192
|
-
let errorBodyText = "Could not read error body";
|
|
193
|
-
try {
|
|
194
|
-
errorBodyText = await completeResponse.text();
|
|
195
|
-
} catch (_e) {
|
|
196
|
-
}
|
|
197
|
-
throw new Error(
|
|
198
|
-
`Failed to complete multipart upload! status: ${completeResponse.status}, body: ${errorBodyText}`
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Uploads blob data to the Shelby RPC node for storage by storage providers.
|
|
204
|
-
* This method should be called after blob commitments have been registered on the blockchain.
|
|
205
|
-
* Uses multipart upload for efficient handling of large files.
|
|
206
|
-
*
|
|
207
|
-
* @param params.account - The account that owns the blob.
|
|
208
|
-
* @param params.blobName - The name/path of the blob (e.g. "folder/file.txt").
|
|
209
|
-
* @param params.blobData - The raw blob data as a Uint8Array or ReadableStream.
|
|
210
|
-
* @param params.totalBytes - Total byte length. Required for streams; optional for Uint8Array.
|
|
211
|
-
*
|
|
212
|
-
* @example
|
|
213
|
-
* ```typescript
|
|
214
|
-
* const blobData = new TextEncoder().encode("Hello, world!");
|
|
215
|
-
*
|
|
216
|
-
* await client.putBlob({
|
|
217
|
-
* account: AccountAddress.from("0x1"),
|
|
218
|
-
* blobName: "greetings/hello.txt",
|
|
219
|
-
* blobData,
|
|
220
|
-
* });
|
|
221
|
-
* ```
|
|
222
|
-
*/
|
|
223
|
-
async putBlob(params) {
|
|
224
|
-
BlobNameSchema.parse(params.blobName);
|
|
225
|
-
let totalBytes;
|
|
226
|
-
if (params.blobData instanceof Uint8Array) {
|
|
227
|
-
totalBytes = params.totalBytes ?? params.blobData.length;
|
|
228
|
-
if (totalBytes !== params.blobData.length) {
|
|
229
|
-
throw new Error(
|
|
230
|
-
"totalBytes must match blobData.length when blobData is a Uint8Array"
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
} else {
|
|
234
|
-
if (params.totalBytes === void 0) {
|
|
235
|
-
throw new Error(
|
|
236
|
-
"totalBytes is required when blobData is a ReadableStream"
|
|
237
|
-
);
|
|
238
|
-
}
|
|
239
|
-
totalBytes = params.totalBytes;
|
|
240
|
-
}
|
|
241
|
-
validateTotalBytes(totalBytes);
|
|
242
|
-
await this.#putBlobMultipart(
|
|
243
|
-
params.account,
|
|
244
|
-
params.blobName,
|
|
245
|
-
params.blobData,
|
|
246
|
-
totalBytes,
|
|
247
|
-
void 0,
|
|
248
|
-
params.onProgress
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Downloads a blob from the Shelby RPC node.
|
|
253
|
-
* Returns a streaming response with validation to ensure data integrity.
|
|
254
|
-
*
|
|
255
|
-
* @param params.account - The account that owns the blob.
|
|
256
|
-
* @param params.blobName - The name/path of the blob (e.g. "folder/file.txt").
|
|
257
|
-
* @param params.range - Optional byte range for partial downloads.
|
|
258
|
-
* @param params.range.start - Starting byte position (inclusive).
|
|
259
|
-
* @param params.range.end - Ending byte position (inclusive, optional).
|
|
260
|
-
* @param params.micropayment - Optional micropayment to attach to the request.
|
|
261
|
-
*
|
|
262
|
-
* @returns A ShelbyBlob object containing the account, name, readable stream, and content length.
|
|
263
|
-
*
|
|
264
|
-
* @throws Error if the download fails or content length doesn't match.
|
|
265
|
-
* @throws StaleChannelStateError if the micropayment is stale (server has newer state).
|
|
266
|
-
*
|
|
267
|
-
* @example
|
|
268
|
-
* ```typescript
|
|
269
|
-
* // Download entire blob
|
|
270
|
-
* const blob = await client.getBlob({
|
|
271
|
-
* account: AccountAddress.from("0x1"),
|
|
272
|
-
* blobName: "documents/report.pdf"
|
|
273
|
-
* });
|
|
274
|
-
*
|
|
275
|
-
* // Download partial content (bytes 100-199)
|
|
276
|
-
* const partial = await client.getBlob({
|
|
277
|
-
* account: AccountAddress.from("0x1"),
|
|
278
|
-
* blobName: "large-file.bin",
|
|
279
|
-
* range: { start: 100, end: 199 }
|
|
280
|
-
* });
|
|
281
|
-
*
|
|
282
|
-
* // Download with micropayment
|
|
283
|
-
* const blob = await client.getBlob({
|
|
284
|
-
* account: AccountAddress.from("0x1"),
|
|
285
|
-
* blobName: "documents/report.pdf",
|
|
286
|
-
* micropayment: senderBuiltMicropayment
|
|
287
|
-
* });
|
|
288
|
-
* ```
|
|
289
|
-
*/
|
|
290
|
-
async getBlob(params) {
|
|
291
|
-
BlobNameSchema.parse(params.blobName);
|
|
292
|
-
const url = buildRequestUrl(
|
|
293
|
-
`/v1/blobs/${params.account.toString()}/${encodeURIComponentKeepSlashes(
|
|
294
|
-
params.blobName
|
|
295
|
-
)}`,
|
|
296
|
-
this.baseUrl
|
|
297
|
-
);
|
|
298
|
-
const headers = new Headers();
|
|
299
|
-
if (params.range !== void 0) {
|
|
300
|
-
const { start, end } = params.range;
|
|
301
|
-
if (end === void 0) {
|
|
302
|
-
headers.set("Range", `bytes=${start}-`);
|
|
303
|
-
} else {
|
|
304
|
-
if (end < start) {
|
|
305
|
-
throw new Error("Range end cannot be less than start.");
|
|
306
|
-
}
|
|
307
|
-
headers.set("Range", `bytes=${start}-${end}`);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
if (this.apiKey) {
|
|
311
|
-
headers.set("Authorization", `Bearer ${this.apiKey}`);
|
|
312
|
-
}
|
|
313
|
-
if (params.micropayment) {
|
|
314
|
-
const bytes = params.micropayment.bcsToBytes();
|
|
315
|
-
const binaryString = Array.from(
|
|
316
|
-
bytes,
|
|
317
|
-
(byte) => String.fromCharCode(byte)
|
|
318
|
-
).join("");
|
|
319
|
-
headers.set(MICROPAYMENT_HEADER, btoa(binaryString));
|
|
320
|
-
}
|
|
321
|
-
const response = await fetch(url, { headers });
|
|
322
|
-
if (response.status === 409) {
|
|
323
|
-
let json;
|
|
324
|
-
try {
|
|
325
|
-
json = await response.json();
|
|
326
|
-
} catch {
|
|
327
|
-
throw new Error(
|
|
328
|
-
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
329
|
-
);
|
|
330
|
-
}
|
|
331
|
-
const parseResult = StaleMicropaymentErrorResponseSchema.safeParse(json);
|
|
332
|
-
if (!parseResult.success) {
|
|
333
|
-
throw new Error(
|
|
334
|
-
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
335
|
-
);
|
|
336
|
-
}
|
|
337
|
-
const errorBody = parseResult.data;
|
|
338
|
-
if (errorBody.storedMicropayment) {
|
|
339
|
-
throw StaleChannelStateError.fromBase64(
|
|
340
|
-
errorBody.storedMicropayment,
|
|
341
|
-
errorBody.error
|
|
342
|
-
);
|
|
343
|
-
}
|
|
344
|
-
throw new Error(
|
|
345
|
-
errorBody.error ?? `Failed to download blob: ${response.status} ${response.statusText}`
|
|
346
|
-
);
|
|
347
|
-
}
|
|
348
|
-
if (!response.ok) {
|
|
349
|
-
throw new Error(
|
|
350
|
-
`Failed to download blob: ${response.status} ${response.statusText}`
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
if (!response.body) {
|
|
354
|
-
throw new Error("Response body is null");
|
|
355
|
-
}
|
|
356
|
-
const contentLengthHeader = response.headers.get("content-length");
|
|
357
|
-
if (contentLengthHeader === null) {
|
|
358
|
-
throw new Error(
|
|
359
|
-
"Response did not have content-length header, which is required"
|
|
360
|
-
);
|
|
361
|
-
}
|
|
362
|
-
const expectedContentLength = Number.parseInt(contentLengthHeader, 10);
|
|
363
|
-
if (Number.isNaN(expectedContentLength)) {
|
|
364
|
-
throw new Error(
|
|
365
|
-
`Invalid content-length header received: ${contentLengthHeader}`
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
|
-
const validatingStream = new ReadableStream({
|
|
369
|
-
start(controller) {
|
|
370
|
-
const maybeReader = response.body?.getReader();
|
|
371
|
-
if (!maybeReader) {
|
|
372
|
-
controller.error(new Error("Response body reader is unavailable"));
|
|
373
|
-
return;
|
|
374
|
-
}
|
|
375
|
-
const reader = maybeReader;
|
|
376
|
-
let bytesReceived = 0;
|
|
377
|
-
function pump() {
|
|
378
|
-
return reader.read().then(({ done, value }) => {
|
|
379
|
-
if (done) {
|
|
380
|
-
if (bytesReceived !== expectedContentLength) {
|
|
381
|
-
controller.error(
|
|
382
|
-
new Error(
|
|
383
|
-
`Downloaded data size (${bytesReceived} bytes) does not match content-length header (${expectedContentLength} bytes). This might indicate a partial or corrupted download.`
|
|
384
|
-
)
|
|
385
|
-
);
|
|
386
|
-
return;
|
|
387
|
-
}
|
|
388
|
-
controller.close();
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
bytesReceived += value.byteLength;
|
|
392
|
-
controller.enqueue(value);
|
|
393
|
-
return pump();
|
|
394
|
-
}).catch((error) => {
|
|
395
|
-
controller.error(error);
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
return pump();
|
|
399
|
-
}
|
|
400
|
-
});
|
|
401
|
-
return {
|
|
402
|
-
account: normalizeAddress(params.account),
|
|
403
|
-
name: params.blobName,
|
|
404
|
-
readable: validatingStream,
|
|
405
|
-
contentLength: expectedContentLength
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
export {
|
|
411
|
-
ShelbyRPCClient
|
|
412
|
-
};
|