@shelby-protocol/react 0.0.2
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/CHANGELOG.md +9 -0
- package/README.md +104 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/mutations/index.d.ts +5 -0
- package/dist/mutations/index.d.ts.map +1 -0
- package/dist/mutations/useCommitBlobs.d.ts +50 -0
- package/dist/mutations/useCommitBlobs.d.ts.map +1 -0
- package/dist/mutations/useEncodeBlobs.d.ts +78 -0
- package/dist/mutations/useEncodeBlobs.d.ts.map +1 -0
- package/dist/mutations/useRegisterCommitments.d.ts +69 -0
- package/dist/mutations/useRegisterCommitments.d.ts.map +1 -0
- package/dist/mutations/useUploadBlobs.d.ts +79 -0
- package/dist/mutations/useUploadBlobs.d.ts.map +1 -0
- package/dist/queries/index.d.ts +3 -0
- package/dist/queries/index.d.ts.map +1 -0
- package/dist/queries/useAccountBlobs.d.ts +30 -0
- package/dist/queries/useAccountBlobs.d.ts.map +1 -0
- package/dist/queries/useBlobMetadata.d.ts +29 -0
- package/dist/queries/useBlobMetadata.d.ts.map +1 -0
- package/dist/types/mutations.d.ts +6 -0
- package/dist/types/mutations.d.ts.map +1 -0
- package/dist/types/queries.d.ts +6 -0
- package/dist/types/queries.d.ts.map +1 -0
- package/dist/types/signers.d.ts +9 -0
- package/dist/types/signers.d.ts.map +1 -0
- package/dist/types/walletAdapter.d.ts +3 -0
- package/dist/types/walletAdapter.d.ts.map +1 -0
- package/package.json +80 -0
- package/src/index.ts +2 -0
- package/src/mutations/index.ts +4 -0
- package/src/mutations/useCommitBlobs.tsx +83 -0
- package/src/mutations/useEncodeBlobs.tsx +122 -0
- package/src/mutations/useRegisterCommitments.tsx +129 -0
- package/src/mutations/useUploadBlobs.tsx +194 -0
- package/src/queries/index.ts +2 -0
- package/src/queries/useAccountBlobs.tsx +72 -0
- package/src/queries/useBlobMetadata.tsx +56 -0
- package/src/types/mutations.ts +16 -0
- package/src/types/queries.ts +16 -0
- package/src/types/signers.ts +11 -0
- package/src/types/walletAdapter.ts +4 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { AccountAddress } from "@aptos-labs/ts-sdk";
|
|
2
|
+
import {
|
|
3
|
+
createBlobKey,
|
|
4
|
+
createDefaultErasureCodingProvider,
|
|
5
|
+
DEFAULT_CHUNKSET_SIZE_BYTES,
|
|
6
|
+
expectedTotalChunksets,
|
|
7
|
+
generateCommitments,
|
|
8
|
+
ShelbyBlobClient,
|
|
9
|
+
type UploadOptions,
|
|
10
|
+
} from "@shelby-protocol/sdk/browser";
|
|
11
|
+
import { useMutation } from "@tanstack/react-query";
|
|
12
|
+
import pLimit from "p-limit";
|
|
13
|
+
import type { UseMutationOptionsWithClient } from "../types/mutations";
|
|
14
|
+
import type { AccountSigner, Signer } from "../types/signers";
|
|
15
|
+
|
|
16
|
+
export type UseUploadBlobsVariables = {
|
|
17
|
+
/**
|
|
18
|
+
* The signer to use for the transaction.
|
|
19
|
+
*
|
|
20
|
+
* @see {@link Signer}
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* const signer = new Account.generate();
|
|
25
|
+
* uploadBlobs.mutate({
|
|
26
|
+
* signer,
|
|
27
|
+
* blobs: [
|
|
28
|
+
* { blobName: 'file1.txt', blobData: new Uint8Array([...]) },
|
|
29
|
+
* ],
|
|
30
|
+
* expirationMicros: Date.now() * 1000 + 86400000000,
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
signer: Signer;
|
|
35
|
+
/**
|
|
36
|
+
* The blobs to upload.
|
|
37
|
+
*/
|
|
38
|
+
blobs: {
|
|
39
|
+
blobName: string;
|
|
40
|
+
blobData: Uint8Array;
|
|
41
|
+
}[];
|
|
42
|
+
/**
|
|
43
|
+
* The expiration time of the blobs in microseconds.
|
|
44
|
+
*/
|
|
45
|
+
expirationMicros: number;
|
|
46
|
+
/**
|
|
47
|
+
* Optional transaction building options.
|
|
48
|
+
*/
|
|
49
|
+
options?: UploadOptions;
|
|
50
|
+
/**
|
|
51
|
+
* The maximum number of concurrent uploads.
|
|
52
|
+
* @default 3
|
|
53
|
+
*/
|
|
54
|
+
maxConcurrentUploads?: number;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export type UseUploadBlobsOptions = UseMutationOptionsWithClient<
|
|
58
|
+
void,
|
|
59
|
+
Error,
|
|
60
|
+
UseUploadBlobsVariables
|
|
61
|
+
>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Uploads blobs to the Shelby network.
|
|
65
|
+
*
|
|
66
|
+
* This mutation handles the complete blob upload process including:
|
|
67
|
+
* - Encoding blobs with erasure coding
|
|
68
|
+
* - Registering commitments on-chain (if not already registered)
|
|
69
|
+
* - Uploading blob data to the RPC endpoint
|
|
70
|
+
*
|
|
71
|
+
* It supports both account signers and wallet adapter signers, and includes
|
|
72
|
+
* logic to skip registration for blobs that already exist.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```tsx
|
|
76
|
+
* import { ShelbyClient } from "@shelby-protocol/sdk/browser";
|
|
77
|
+
* import { Network } from "@aptos-labs/ts-sdk";
|
|
78
|
+
* import { useUploadBlobs } from "@shelby-protocol/react";
|
|
79
|
+
*
|
|
80
|
+
* const shelbyClient = new ShelbyClient({ network: Network.SHELBYNET });
|
|
81
|
+
* const uploadBlobs = useUploadBlobs({
|
|
82
|
+
* client: shelbyClient,
|
|
83
|
+
* onSuccess: () => console.log('Upload complete'),
|
|
84
|
+
* });
|
|
85
|
+
*
|
|
86
|
+
* const signer = new Account.generate();
|
|
87
|
+
* uploadBlobs.mutate({
|
|
88
|
+
* signer,
|
|
89
|
+
* blobs: [
|
|
90
|
+
* { blobName: 'file1.txt', blobData: new Uint8Array([...]) },
|
|
91
|
+
* ],
|
|
92
|
+
* expirationMicros: Date.now() * 1000 + 86400000000,
|
|
93
|
+
* });
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export function useUploadBlobs({
|
|
97
|
+
client: shelbyClient,
|
|
98
|
+
...options
|
|
99
|
+
}: UseUploadBlobsOptions) {
|
|
100
|
+
return useMutation({
|
|
101
|
+
mutationFn: async ({
|
|
102
|
+
blobs,
|
|
103
|
+
expirationMicros,
|
|
104
|
+
options,
|
|
105
|
+
signer: signerOrFn,
|
|
106
|
+
maxConcurrentUploads = 3,
|
|
107
|
+
}: UseUploadBlobsVariables) => {
|
|
108
|
+
if (!("account" in signerOrFn)) {
|
|
109
|
+
const accountSigner: AccountSigner = signerOrFn;
|
|
110
|
+
|
|
111
|
+
await shelbyClient.batchUpload({
|
|
112
|
+
blobs: blobs.map(({ blobData, blobName }) => ({
|
|
113
|
+
blobData,
|
|
114
|
+
blobName,
|
|
115
|
+
})),
|
|
116
|
+
expirationMicros,
|
|
117
|
+
signer: accountSigner,
|
|
118
|
+
options,
|
|
119
|
+
});
|
|
120
|
+
} else {
|
|
121
|
+
const { account, signAndSubmitTransaction } = signerOrFn;
|
|
122
|
+
|
|
123
|
+
const chunksetSize =
|
|
124
|
+
options?.chunksetSizeBytes ?? DEFAULT_CHUNKSET_SIZE_BYTES;
|
|
125
|
+
|
|
126
|
+
const existingBlobs = await shelbyClient.coordination.getBlobs({
|
|
127
|
+
where: {
|
|
128
|
+
blob_name: {
|
|
129
|
+
_in: blobs.map((blob) =>
|
|
130
|
+
createBlobKey({ account, blobName: blob.blobName }),
|
|
131
|
+
),
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const blobsToRegister = blobs.filter(
|
|
137
|
+
(blob) =>
|
|
138
|
+
!existingBlobs.some(
|
|
139
|
+
(existingBlob) =>
|
|
140
|
+
existingBlob.name ===
|
|
141
|
+
createBlobKey({ account, blobName: blob.blobName }),
|
|
142
|
+
),
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
if (blobsToRegister.length > 0) {
|
|
146
|
+
const provider = await createDefaultErasureCodingProvider();
|
|
147
|
+
|
|
148
|
+
const blobCommitments = await Promise.all(
|
|
149
|
+
blobsToRegister.map(async (blob) =>
|
|
150
|
+
generateCommitments(provider, blob.blobData),
|
|
151
|
+
),
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
const pendingRegisterBlobTransaction = await signAndSubmitTransaction(
|
|
155
|
+
{
|
|
156
|
+
data: ShelbyBlobClient.createBatchRegisterBlobsPayload({
|
|
157
|
+
account: AccountAddress.from(account),
|
|
158
|
+
expirationMicros,
|
|
159
|
+
blobs: blobsToRegister.map((blob, index) => ({
|
|
160
|
+
blobName: blob.blobName,
|
|
161
|
+
blobSize: blob.blobData.length,
|
|
162
|
+
blobMerkleRoot: blobCommitments[index].blob_merkle_root,
|
|
163
|
+
numChunksets: expectedTotalChunksets(
|
|
164
|
+
blob.blobData.length,
|
|
165
|
+
chunksetSize,
|
|
166
|
+
),
|
|
167
|
+
})),
|
|
168
|
+
}),
|
|
169
|
+
options: options?.build?.options,
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
await shelbyClient.coordination.aptos.waitForTransaction({
|
|
174
|
+
transactionHash: pendingRegisterBlobTransaction.hash,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const limit = pLimit(maxConcurrentUploads);
|
|
179
|
+
const uploadPromises = blobs.map((blob) =>
|
|
180
|
+
limit(() =>
|
|
181
|
+
shelbyClient.rpc.putBlob({
|
|
182
|
+
account,
|
|
183
|
+
blobName: blob.blobName,
|
|
184
|
+
blobData: blob.blobData,
|
|
185
|
+
}),
|
|
186
|
+
),
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
await Promise.all(uploadPromises);
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
...options,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { Network } from "@aptos-labs/ts-sdk";
|
|
2
|
+
import type {
|
|
3
|
+
BlobMetadata,
|
|
4
|
+
ShelbyBlobClient,
|
|
5
|
+
} from "@shelby-protocol/sdk/browser";
|
|
6
|
+
import { useQuery } from "@tanstack/react-query";
|
|
7
|
+
import type { UseQueryOptionsWithClient } from "../types/queries";
|
|
8
|
+
|
|
9
|
+
export const getUseAccountBlobsQueryKey = (
|
|
10
|
+
params: Parameters<ShelbyBlobClient["getAccountBlobs"]>[0] & {
|
|
11
|
+
network: Network;
|
|
12
|
+
},
|
|
13
|
+
) => [
|
|
14
|
+
"account-blobs",
|
|
15
|
+
params.network,
|
|
16
|
+
params.account.toString(),
|
|
17
|
+
params.pagination?.limit,
|
|
18
|
+
params.pagination?.offset,
|
|
19
|
+
params.orderBy,
|
|
20
|
+
params.where,
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
export type UseAccountBlobsOptions = UseQueryOptionsWithClient<BlobMetadata[]> &
|
|
24
|
+
Parameters<ShelbyBlobClient["getAccountBlobs"]>[0];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Queries blobs associated with an account.
|
|
28
|
+
*
|
|
29
|
+
* This query fetches blob metadata for a specific account with support for
|
|
30
|
+
* pagination, filtering, and ordering.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* import { ShelbyClient, Order_By} from "@shelby-protocol/sdk/browser";
|
|
35
|
+
* import { Network } from "@aptos-labs/ts-sdk";
|
|
36
|
+
* import { useAccountBlobs } from "@shelby-protocol/react";
|
|
37
|
+
*
|
|
38
|
+
* const shelbyClient = new ShelbyClient({ network: Network.SHELBYNET });
|
|
39
|
+
* const { data: blobs, isLoading } = useAccountBlobs({
|
|
40
|
+
* client: shelbyClient,
|
|
41
|
+
* account: '0x123...',
|
|
42
|
+
* pagination: { limit: 10, offset: 0 },
|
|
43
|
+
* orderBy: { updated_at: Order_By.Desc },
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export function useAccountBlobs({
|
|
48
|
+
account,
|
|
49
|
+
pagination,
|
|
50
|
+
orderBy,
|
|
51
|
+
where,
|
|
52
|
+
client: shelbyClient,
|
|
53
|
+
...options
|
|
54
|
+
}: UseAccountBlobsOptions) {
|
|
55
|
+
return useQuery<BlobMetadata[]>({
|
|
56
|
+
queryKey: getUseAccountBlobsQueryKey({
|
|
57
|
+
network: shelbyClient.config.network,
|
|
58
|
+
account,
|
|
59
|
+
pagination,
|
|
60
|
+
orderBy,
|
|
61
|
+
where,
|
|
62
|
+
}),
|
|
63
|
+
queryFn: async () =>
|
|
64
|
+
await shelbyClient.coordination.getAccountBlobs({
|
|
65
|
+
account,
|
|
66
|
+
pagination,
|
|
67
|
+
orderBy,
|
|
68
|
+
where,
|
|
69
|
+
}),
|
|
70
|
+
...options,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Network } from "@aptos-labs/ts-sdk";
|
|
2
|
+
import type {
|
|
3
|
+
BlobMetadata,
|
|
4
|
+
ShelbyBlobClient,
|
|
5
|
+
} from "@shelby-protocol/sdk/browser";
|
|
6
|
+
import { useQuery } from "@tanstack/react-query";
|
|
7
|
+
import type { UseQueryOptionsWithClient } from "../types/queries";
|
|
8
|
+
|
|
9
|
+
export const getUseBlobMetadataQueryKey = (
|
|
10
|
+
params: Parameters<ShelbyBlobClient["getBlobMetadata"]>[0] & {
|
|
11
|
+
network: Network;
|
|
12
|
+
},
|
|
13
|
+
) => ["blob-metadata", params.network, params.account.toString(), params.name];
|
|
14
|
+
|
|
15
|
+
export type UseBlobMetadataOptions =
|
|
16
|
+
UseQueryOptionsWithClient<BlobMetadata | null> &
|
|
17
|
+
Parameters<ShelbyBlobClient["getBlobMetadata"]>[0];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Queries the metadata for a specific blob.
|
|
21
|
+
*
|
|
22
|
+
* This query fetches the metadata for a single blob identified by account and blob name.
|
|
23
|
+
* Returns `null` if the blob is not found.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* import { ShelbyClient } from "@shelby-protocol/sdk/browser";
|
|
28
|
+
* import { Network } from "@aptos-labs/ts-sdk";
|
|
29
|
+
* import { useBlobMetadata } from "@shelby-protocol/react";
|
|
30
|
+
*
|
|
31
|
+
* const shelbyClient = new ShelbyClient({ network: Network.SHELBYNET });
|
|
32
|
+
* const { data: metadata } = useBlobMetadata({
|
|
33
|
+
* client: shelbyClient,
|
|
34
|
+
* account: '0x123...',
|
|
35
|
+
* name: 'file1.txt',
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function useBlobMetadata({
|
|
40
|
+
account,
|
|
41
|
+
name,
|
|
42
|
+
client: shelbyClient,
|
|
43
|
+
...options
|
|
44
|
+
}: UseBlobMetadataOptions) {
|
|
45
|
+
return useQuery<BlobMetadata | null>({
|
|
46
|
+
queryKey: getUseBlobMetadataQueryKey({
|
|
47
|
+
network: shelbyClient.config.network,
|
|
48
|
+
account,
|
|
49
|
+
name,
|
|
50
|
+
}),
|
|
51
|
+
queryFn: async () =>
|
|
52
|
+
(await shelbyClient.coordination.getBlobMetadata({ account, name })) ??
|
|
53
|
+
null,
|
|
54
|
+
...options,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ShelbyClient } from "@shelby-protocol/sdk/browser";
|
|
2
|
+
import type {
|
|
3
|
+
DefaultError,
|
|
4
|
+
MutationKey,
|
|
5
|
+
UseMutationOptions,
|
|
6
|
+
} from "@tanstack/react-query";
|
|
7
|
+
|
|
8
|
+
export type UseMutationOptionsWithClient<
|
|
9
|
+
TMutationFnData = unknown,
|
|
10
|
+
TError = DefaultError,
|
|
11
|
+
TData = TMutationFnData,
|
|
12
|
+
TMutationKey extends MutationKey = MutationKey,
|
|
13
|
+
> = Omit<
|
|
14
|
+
UseMutationOptions<TMutationFnData, TError, TData, TMutationKey>,
|
|
15
|
+
"mutationFn"
|
|
16
|
+
> & { client: ShelbyClient };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ShelbyClient } from "@shelby-protocol/sdk/browser";
|
|
2
|
+
import type {
|
|
3
|
+
DefaultError,
|
|
4
|
+
QueryKey,
|
|
5
|
+
UseQueryOptions,
|
|
6
|
+
} from "@tanstack/react-query";
|
|
7
|
+
|
|
8
|
+
export type UseQueryOptionsWithClient<
|
|
9
|
+
TQueryFnData = unknown,
|
|
10
|
+
TError = DefaultError,
|
|
11
|
+
TData = TQueryFnData,
|
|
12
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
13
|
+
> = Omit<
|
|
14
|
+
UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>,
|
|
15
|
+
"queryFn" | "queryKey"
|
|
16
|
+
> & { client: ShelbyClient };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Account, AccountAddressInput } from "@aptos-labs/ts-sdk";
|
|
2
|
+
import type { SignAndSubmitTransactionFn } from "./walletAdapter";
|
|
3
|
+
|
|
4
|
+
export type AccountSigner = Account;
|
|
5
|
+
|
|
6
|
+
export type WalletAdapterSigner = {
|
|
7
|
+
account: AccountAddressInput;
|
|
8
|
+
signAndSubmitTransaction: SignAndSubmitTransactionFn;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type Signer = AccountSigner | WalletAdapterSigner;
|