@0xsequence/marketplace-sdk 0.4.8 → 0.5.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.
- package/dist/{chunk-2OJB35FS.js → chunk-5NORRVPM.js} +5 -5
- package/dist/{chunk-2OJB35FS.js.map → chunk-5NORRVPM.js.map} +1 -1
- package/dist/{chunk-ATDCYXXV.js → chunk-6YHHCGGY.js} +2 -2
- package/dist/{chunk-WRMJ5FZM.js → chunk-HV2X2VZN.js} +874 -194
- package/dist/chunk-HV2X2VZN.js.map +1 -0
- package/dist/{chunk-AQT3BQ67.js → chunk-J2XJZ6SJ.js} +12 -5
- package/dist/chunk-J2XJZ6SJ.js.map +1 -0
- package/dist/{chunk-JEOUQFT3.js → chunk-LJAB3S6U.js} +4 -3
- package/dist/chunk-LJAB3S6U.js.map +1 -0
- package/dist/{chunk-7WCZP6FN.js → chunk-OUVFTA63.js} +649 -386
- package/dist/chunk-OUVFTA63.js.map +1 -0
- package/dist/{chunk-XXML5K3X.js → chunk-QTJF5GDQ.js} +2 -2
- package/dist/{chunk-LF44FCG5.js → chunk-TQWM4ER6.js} +2 -2
- package/dist/{chunk-LF44FCG5.js.map → chunk-TQWM4ER6.js.map} +1 -1
- package/dist/{chunk-6R4G7J6Q.js → chunk-WSCUPAGR.js} +33 -5
- package/dist/chunk-WSCUPAGR.js.map +1 -0
- package/dist/{create-config-D5WqfUft.d.ts → create-config-BXvwUh55.d.ts} +2 -2
- package/dist/index.css +31 -17
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/{marketplace-config-C_fDWzz0.d.ts → marketplace-config-znEu4L0K.d.ts} +1 -1
- package/dist/{marketplace.gen-B8S8fflj.d.ts → marketplace.gen-CCJ-URn2.d.ts} +16 -4
- package/dist/react/_internal/api/index.d.ts +3 -2
- package/dist/react/_internal/api/index.js +3 -1
- package/dist/react/_internal/index.d.ts +5 -5
- package/dist/react/_internal/index.js +3 -1
- package/dist/react/_internal/wagmi/index.d.ts +3 -3
- package/dist/react/hooks/index.d.ts +249 -74
- package/dist/react/hooks/index.js +18 -5
- package/dist/react/index.css +37 -17
- package/dist/react/index.css.map +1 -1
- package/dist/react/index.d.ts +6 -6
- package/dist/react/index.js +22 -9
- package/dist/react/ssr/index.js +4 -0
- package/dist/react/ssr/index.js.map +1 -1
- package/dist/react/ui/components/collectible-card/index.css +37 -17
- package/dist/react/ui/components/collectible-card/index.css.map +1 -1
- package/dist/react/ui/components/collectible-card/index.d.ts +27 -4
- package/dist/react/ui/components/collectible-card/index.js +8 -9
- package/dist/react/ui/icons/index.js +3 -3
- package/dist/react/ui/index.css +37 -17
- package/dist/react/ui/index.css.map +1 -1
- package/dist/react/ui/index.d.ts +3 -3
- package/dist/react/ui/index.js +8 -9
- package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +3 -3
- package/dist/react/ui/modals/_internal/components/actionModal/index.js +5 -5
- package/dist/{sdk-config-BXVH8PS2.d.ts → sdk-config-B32_2bG3.d.ts} +29 -7
- package/dist/{services-CdXAIjt1.d.ts → services-BRBVE0mm.d.ts} +1 -1
- package/dist/styles/index.css +31 -17
- package/dist/styles/index.css.map +1 -1
- package/dist/styles/index.d.ts +2 -2
- package/dist/styles/index.js +2 -2
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.js +1 -1
- package/dist/{types-eX4P9xju.d.ts → types-Yto6KrTN.d.ts} +2 -2
- package/dist/utils/index.d.ts +3 -3
- package/dist/utils/index.js +1 -1
- package/package.json +16 -16
- package/src/react/_internal/api/__mocks__/marketplace.msw.ts +4 -0
- package/src/react/_internal/api/marketplace.gen.ts +45 -7
- package/src/react/_internal/api/query-keys.ts +4 -0
- package/src/react/_internal/wallet/useWallet.ts +30 -46
- package/src/react/_internal/wallet/wallet.ts +52 -6
- package/src/react/hooks/index.ts +4 -0
- package/src/react/hooks/options/__mocks__/marketplaceConfig.msw.ts +10 -1
- package/src/react/hooks/useAutoSelectFeeOption.tsx +104 -0
- package/src/react/hooks/useCancelOrder.tsx +57 -1
- package/src/react/hooks/useCollectionBalanceDetails.tsx +87 -0
- package/src/react/hooks/useCollectionDetails.tsx +35 -0
- package/src/react/hooks/useCollectionDetailsPolling.tsx +60 -0
- package/src/react/ui/components/_internals/action-button/ActionButton.tsx +36 -118
- package/src/react/ui/components/_internals/action-button/components/ActionButtonBody.tsx +52 -0
- package/src/react/ui/components/_internals/action-button/components/NonOwnerActions.tsx +72 -0
- package/src/react/ui/components/_internals/action-button/components/OwnerActions.tsx +81 -0
- package/src/react/ui/components/_internals/action-button/hooks/useActionButtonLogic.ts +93 -0
- package/src/react/ui/components/_internals/action-button/store.ts +47 -0
- package/src/react/ui/components/_internals/action-button/styles.css.ts +8 -0
- package/src/react/ui/components/collectible-card/CollectibleCard.tsx +35 -18
- package/src/react/ui/components/collectible-card/Footer.tsx +5 -8
- package/src/react/ui/components/collectible-card/styles.css.ts +44 -31
- package/src/react/ui/icons/CartIcon.tsx +46 -0
- package/src/react/ui/modals/BuyModal/Modal.tsx +0 -2
- package/src/react/ui/modals/BuyModal/__tests__/Modal.test.tsx +253 -0
- package/src/react/ui/modals/BuyModal/__tests__/store.test.ts +100 -0
- package/src/react/ui/modals/BuyModal/hooks/__tests__/useBuyCollectable.test.tsx +402 -0
- package/src/react/ui/modals/BuyModal/hooks/__tests__/useCheckoutOptions.test.tsx +267 -0
- package/src/react/ui/modals/BuyModal/hooks/__tests__/useFees.test.tsx +166 -0
- package/src/react/ui/modals/BuyModal/hooks/__tests__/useLoadData.test.tsx +209 -0
- package/src/react/ui/modals/BuyModal/hooks/useBuyCollectable.ts +7 -4
- package/src/react/ui/modals/BuyModal/hooks/useCheckoutOptions.ts +19 -17
- package/src/react/ui/modals/BuyModal/hooks/useLoadData.ts +9 -7
- package/src/react/ui/modals/BuyModal/modals/Modal1155.tsx +36 -18
- package/src/react/ui/modals/BuyModal/modals/__tests__/CheckoutModal.test.tsx +162 -0
- package/src/react/ui/modals/BuyModal/modals/__tests__/Modal1155.test.tsx +243 -0
- package/src/react/ui/modals/BuyModal/store.ts +11 -10
- package/src/react/ui/modals/CreateListingModal/Modal.tsx +26 -3
- package/src/react/ui/modals/CreateListingModal/__tests__/Modal.test.tsx +141 -29
- package/src/react/ui/modals/TransferModal/_views/enterWalletAddress/useHandleTransfer.tsx +5 -1
- package/src/react/ui/modals/_internal/components/actionModal/ActionModal.tsx +20 -11
- package/src/react/ui/modals/_internal/components/currencyOptionsSelect/__tests__/index.test.tsx +13 -58
- package/src/react/ui/modals/_internal/components/priceInput/__tests__/index.test.tsx +2 -0
- package/src/react/ui/modals/_internal/components/transactionStatusModal/__tests__/TransactionStatusModal.test.tsx +18 -19
- package/src/react/ui/modals/_internal/components/transactionStatusModal/__tests__/utils.test.ts +2 -0
- package/src/react/ui/modals/_internal/components/transactionStatusModal/hooks/useTransactionStatus.ts +62 -0
- package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +53 -100
- package/src/react/ui/modals/_internal/components/transactionStatusModal/store.ts +2 -10
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/chunk-6R4G7J6Q.js.map +0 -1
- package/dist/chunk-7WCZP6FN.js.map +0 -1
- package/dist/chunk-AQT3BQ67.js.map +0 -1
- package/dist/chunk-FWN2MCLI.js +0 -425
- package/dist/chunk-FWN2MCLI.js.map +0 -1
- package/dist/chunk-JEOUQFT3.js.map +0 -1
- package/dist/chunk-WRMJ5FZM.js.map +0 -1
- /package/dist/{chunk-ATDCYXXV.js.map → chunk-6YHHCGGY.js.map} +0 -0
- /package/dist/{chunk-XXML5K3X.js.map → chunk-QTJF5GDQ.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
|
-
// marketplace-api
|
|
2
|
+
// marketplace-api 8d0cafb3a02c5db5bdd5d6b139a752349e301f0c
|
|
3
3
|
// --
|
|
4
4
|
// Code generated by webrpc-gen@v0.22.1 with typescript generator. DO NOT EDIT.
|
|
5
5
|
//
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
export const WebrpcHeader = "Webrpc"
|
|
9
9
|
|
|
10
|
-
export const WebrpcHeaderValue = "webrpc@v0.22.1;gen-typescript@v0.16.2;marketplace-api@v0.0.0-
|
|
10
|
+
export const WebrpcHeaderValue = "webrpc@v0.22.1;gen-typescript@v0.16.2;marketplace-api@v0.0.0-8d0cafb3a02c5db5bdd5d6b139a752349e301f0c"
|
|
11
11
|
|
|
12
12
|
// WebRPC description and code-gen version
|
|
13
13
|
export const WebRPCVersion = "v1"
|
|
@@ -16,7 +16,7 @@ export const WebRPCVersion = "v1"
|
|
|
16
16
|
export const WebRPCSchemaVersion = ""
|
|
17
17
|
|
|
18
18
|
// Schema hash generated from your RIDL schema
|
|
19
|
-
export const WebRPCSchemaHash = "
|
|
19
|
+
export const WebRPCSchemaHash = "8d0cafb3a02c5db5bdd5d6b139a752349e301f0c"
|
|
20
20
|
|
|
21
21
|
type WebrpcGenVersions = {
|
|
22
22
|
webrpcGenVersion: string;
|
|
@@ -126,9 +126,7 @@ export enum MarketplaceKind {
|
|
|
126
126
|
x2y2 = 'x2y2',
|
|
127
127
|
alienswap = 'alienswap',
|
|
128
128
|
payment_processor = 'payment_processor',
|
|
129
|
-
mintify = 'mintify'
|
|
130
|
-
element_erc721 = 'element_erc721',
|
|
131
|
-
element_erc1155 = 'element_erc1155'
|
|
129
|
+
mintify = 'mintify'
|
|
132
130
|
}
|
|
133
131
|
|
|
134
132
|
export enum OrderbookKind {
|
|
@@ -181,6 +179,8 @@ export enum CollectionPriority {
|
|
|
181
179
|
export enum CollectionStatus {
|
|
182
180
|
unknown = 'unknown',
|
|
183
181
|
created = 'created',
|
|
182
|
+
syncing_contract_metadata = 'syncing_contract_metadata',
|
|
183
|
+
synced_contract_metadata = 'synced_contract_metadata',
|
|
184
184
|
syncing_metadata = 'syncing_metadata',
|
|
185
185
|
synced_metadata = 'synced_metadata',
|
|
186
186
|
syncing_tokens = 'syncing_tokens',
|
|
@@ -188,7 +188,8 @@ export enum CollectionStatus {
|
|
|
188
188
|
syncing_orders = 'syncing_orders',
|
|
189
189
|
active = 'active',
|
|
190
190
|
failed = 'failed',
|
|
191
|
-
inactive = 'inactive'
|
|
191
|
+
inactive = 'inactive',
|
|
192
|
+
incompatible_type = 'incompatible_type'
|
|
192
193
|
}
|
|
193
194
|
|
|
194
195
|
export enum ProjectStatus {
|
|
@@ -203,6 +204,14 @@ export enum CollectibleStatus {
|
|
|
203
204
|
inactive = 'inactive'
|
|
204
205
|
}
|
|
205
206
|
|
|
207
|
+
export enum CurrencyStatus {
|
|
208
|
+
unknown = 'unknown',
|
|
209
|
+
created = 'created',
|
|
210
|
+
syncing_metadata = 'syncing_metadata',
|
|
211
|
+
active = 'active',
|
|
212
|
+
failed = 'failed'
|
|
213
|
+
}
|
|
214
|
+
|
|
206
215
|
export enum WalletKind {
|
|
207
216
|
unknown = 'unknown',
|
|
208
217
|
sequence = 'sequence'
|
|
@@ -312,6 +321,7 @@ export interface Order {
|
|
|
312
321
|
priceCurrencyAddress: string
|
|
313
322
|
priceDecimals: number
|
|
314
323
|
priceUSD: number
|
|
324
|
+
priceUSDFormatted: string
|
|
315
325
|
quantityInitial: string
|
|
316
326
|
quantityInitialFormatted: string
|
|
317
327
|
quantityRemaining: string
|
|
@@ -340,6 +350,8 @@ export interface FeeBreakdown {
|
|
|
340
350
|
export interface CollectibleOrder {
|
|
341
351
|
metadata: TokenMetadata
|
|
342
352
|
order?: Order
|
|
353
|
+
listing?: Order
|
|
354
|
+
offer?: Order
|
|
343
355
|
}
|
|
344
356
|
|
|
345
357
|
export interface OrderFilter {
|
|
@@ -397,6 +409,7 @@ export interface Collectible {
|
|
|
397
409
|
export interface Currency {
|
|
398
410
|
chainId: number
|
|
399
411
|
contractAddress: string
|
|
412
|
+
status: CurrencyStatus
|
|
400
413
|
name: string
|
|
401
414
|
symbol: string
|
|
402
415
|
decimals: number
|
|
@@ -594,6 +607,7 @@ export interface DeleteCurrencyReturn {
|
|
|
594
607
|
|
|
595
608
|
export interface Marketplace {
|
|
596
609
|
listCurrencies(headers?: object, signal?: AbortSignal): Promise<ListCurrenciesReturn>
|
|
610
|
+
getCollectionDetail(args: GetCollectionDetailArgs, headers?: object, signal?: AbortSignal): Promise<GetCollectionDetailReturn>
|
|
597
611
|
getCollectible(args: GetCollectibleArgs, headers?: object, signal?: AbortSignal): Promise<GetCollectibleReturn>
|
|
598
612
|
getLowestPriceOfferForCollectible(args: GetLowestPriceOfferForCollectibleArgs, headers?: object, signal?: AbortSignal): Promise<GetLowestPriceOfferForCollectibleReturn>
|
|
599
613
|
getHighestPriceOfferForCollectible(args: GetHighestPriceOfferForCollectibleArgs, headers?: object, signal?: AbortSignal): Promise<GetHighestPriceOfferForCollectibleReturn>
|
|
@@ -636,6 +650,13 @@ export interface ListCurrenciesArgs {
|
|
|
636
650
|
export interface ListCurrenciesReturn {
|
|
637
651
|
currencies: Array<Currency>
|
|
638
652
|
}
|
|
653
|
+
export interface GetCollectionDetailArgs {
|
|
654
|
+
contractAddress: string
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
export interface GetCollectionDetailReturn {
|
|
658
|
+
collection: Collection
|
|
659
|
+
}
|
|
639
660
|
export interface GetCollectibleArgs {
|
|
640
661
|
contractAddress: string
|
|
641
662
|
tokenId: string
|
|
@@ -684,6 +705,7 @@ export interface ListListingsForCollectibleArgs {
|
|
|
684
705
|
contractAddress: string
|
|
685
706
|
tokenId: string
|
|
686
707
|
filter?: OrderFilter
|
|
708
|
+
skipRealtimeSync?: boolean
|
|
687
709
|
page?: Page
|
|
688
710
|
}
|
|
689
711
|
|
|
@@ -695,6 +717,7 @@ export interface ListOffersForCollectibleArgs {
|
|
|
695
717
|
contractAddress: string
|
|
696
718
|
tokenId: string
|
|
697
719
|
filter?: OrderFilter
|
|
720
|
+
skipRealtimeSync?: boolean
|
|
698
721
|
page?: Page
|
|
699
722
|
}
|
|
700
723
|
|
|
@@ -1151,6 +1174,20 @@ export class Marketplace implements Marketplace {
|
|
|
1151
1174
|
})
|
|
1152
1175
|
}
|
|
1153
1176
|
|
|
1177
|
+
getCollectionDetail = (args: GetCollectionDetailArgs, headers?: object, signal?: AbortSignal): Promise<GetCollectionDetailReturn> => {
|
|
1178
|
+
return this.fetch(
|
|
1179
|
+
this.url('GetCollectionDetail'),
|
|
1180
|
+
createHTTPRequest(args, headers, signal)).then((res) => {
|
|
1181
|
+
return buildResponse(res).then(_data => {
|
|
1182
|
+
return {
|
|
1183
|
+
collection: <Collection>(_data.collection),
|
|
1184
|
+
}
|
|
1185
|
+
})
|
|
1186
|
+
}, (error) => {
|
|
1187
|
+
throw WebrpcRequestFailedError.new({ cause: `fetch(): ${error.message || ''}` })
|
|
1188
|
+
})
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1154
1191
|
getCollectible = (args: GetCollectibleArgs, headers?: object, signal?: AbortSignal): Promise<GetCollectibleReturn> => {
|
|
1155
1192
|
return this.fetch(
|
|
1156
1193
|
this.url('GetCollectible'),
|
|
@@ -2084,3 +2121,4 @@ export const webrpcErrorByCode: { [code: number]: any } = {
|
|
|
2084
2121
|
}
|
|
2085
2122
|
|
|
2086
2123
|
export type Fetch = (input: RequestInfo, init?: RequestInit) => Promise<Response>
|
|
2124
|
+
|
|
@@ -50,6 +50,10 @@ class CollectionKeys {
|
|
|
50
50
|
class BalanceQueries {
|
|
51
51
|
static all = ['balances'] as const;
|
|
52
52
|
static lists = [...BalanceQueries.all, 'tokenBalances'] as const;
|
|
53
|
+
static collectionBalanceDetails = [
|
|
54
|
+
...BalanceQueries.all,
|
|
55
|
+
'collectionBalanceDetails',
|
|
56
|
+
] as const;
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
// biome-ignore lint/complexity/noStaticOnlyClass:
|
|
@@ -1,58 +1,42 @@
|
|
|
1
|
-
import { useAccount, useSwitchChain, useWalletClient } from 'wagmi';
|
|
1
|
+
import { useAccount, useChainId, useSwitchChain, useWalletClient } from 'wagmi';
|
|
2
|
+
import { useQuery } from '@tanstack/react-query';
|
|
2
3
|
import { wallet, type WalletInstance } from './wallet';
|
|
4
|
+
import { useConfig } from '../../hooks';
|
|
3
5
|
|
|
4
|
-
type UseWalletReturn =
|
|
5
|
-
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
isError: false;
|
|
10
|
-
}
|
|
11
|
-
| {
|
|
12
|
-
status: 'error';
|
|
13
|
-
wallet: null;
|
|
14
|
-
isLoading: false;
|
|
15
|
-
isError: true;
|
|
16
|
-
}
|
|
17
|
-
| {
|
|
18
|
-
status: 'success';
|
|
19
|
-
wallet: WalletInstance;
|
|
20
|
-
isLoading: false;
|
|
21
|
-
isError: false;
|
|
22
|
-
};
|
|
6
|
+
type UseWalletReturn = {
|
|
7
|
+
wallet: WalletInstance | null | undefined;
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
isError: boolean;
|
|
10
|
+
};
|
|
23
11
|
|
|
24
12
|
export const useWallet = (): UseWalletReturn => {
|
|
25
13
|
const { chains } = useSwitchChain();
|
|
26
|
-
const { data: walletClient, isLoading:
|
|
14
|
+
const { data: walletClient, isLoading: wagmiWalletIsLoading } =
|
|
27
15
|
useWalletClient();
|
|
28
16
|
const { connector, isConnected, isConnecting } = useAccount();
|
|
17
|
+
const sdkConfig = useConfig();
|
|
18
|
+
const chainId = useChainId();
|
|
29
19
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
20
|
+
const { data, isLoading, isError } = useQuery({
|
|
21
|
+
queryKey: ['wallet', chainId, connector?.uid],
|
|
22
|
+
queryFn: () => {
|
|
23
|
+
if (!walletClient || !connector || !isConnected) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return wallet({
|
|
27
|
+
wallet: walletClient,
|
|
28
|
+
chains,
|
|
29
|
+
connector,
|
|
30
|
+
sdkConfig,
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
staleTime: Number.POSITIVE_INFINITY,
|
|
34
|
+
enabled: Boolean(walletClient && connector && isConnected),
|
|
35
|
+
});
|
|
47
36
|
|
|
48
37
|
return {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
chains,
|
|
53
|
-
connector,
|
|
54
|
-
}),
|
|
55
|
-
isLoading: false,
|
|
56
|
-
isError: false,
|
|
38
|
+
wallet: data,
|
|
39
|
+
isLoading: isLoading || isConnecting || wagmiWalletIsLoading,
|
|
40
|
+
isError,
|
|
57
41
|
};
|
|
58
42
|
};
|
|
@@ -3,9 +3,10 @@ import {
|
|
|
3
3
|
type Address,
|
|
4
4
|
type Chain,
|
|
5
5
|
type Hex,
|
|
6
|
-
|
|
6
|
+
TransactionReceiptNotFoundError,
|
|
7
7
|
type TypedDataDomain,
|
|
8
8
|
type WalletClient as ViemWalletClient,
|
|
9
|
+
WaitForTransactionReceiptTimeoutError,
|
|
9
10
|
custom,
|
|
10
11
|
erc20Abi,
|
|
11
12
|
erc721Abi,
|
|
@@ -22,13 +23,15 @@ import {
|
|
|
22
23
|
TransactionSignatureError,
|
|
23
24
|
UserRejectedRequestError,
|
|
24
25
|
} from '../../../utils/_internal/error/transaction';
|
|
25
|
-
import { StepType, WalletKind } from '../api';
|
|
26
|
+
import { getIndexerClient, StepType, WalletKind } from '../api';
|
|
26
27
|
import { createLogger } from '../logger';
|
|
27
28
|
import type { SignatureStep, TransactionStep } from '../utils';
|
|
28
29
|
import {
|
|
29
30
|
SEQUENCE_MARKET_V1_ADDRESS,
|
|
30
31
|
SEQUENCE_MARKET_V2_ADDRESS,
|
|
31
32
|
} from '../../../consts';
|
|
33
|
+
import type { SdkConfig } from '../../../types';
|
|
34
|
+
import type { TransactionReceipt } from '@0xsequence/indexer';
|
|
32
35
|
|
|
33
36
|
interface WalletClient extends Omit<ViemWalletClient, 'account'> {
|
|
34
37
|
account: Account;
|
|
@@ -61,10 +64,12 @@ export const wallet = ({
|
|
|
61
64
|
wallet,
|
|
62
65
|
chains,
|
|
63
66
|
connector,
|
|
67
|
+
sdkConfig,
|
|
64
68
|
}: {
|
|
65
69
|
wallet: WalletClient;
|
|
66
70
|
chains: readonly [Chain, ...Chain[]];
|
|
67
71
|
connector: Connector;
|
|
72
|
+
sdkConfig: SdkConfig;
|
|
68
73
|
}): WalletInstance => {
|
|
69
74
|
const logger = createLogger('Wallet');
|
|
70
75
|
|
|
@@ -174,11 +179,11 @@ export const wallet = ({
|
|
|
174
179
|
},
|
|
175
180
|
handleConfirmTransactionStep: async (txHash: Hex, chainId: number) => {
|
|
176
181
|
logger.debug('Confirming transaction', { txHash, chainId });
|
|
177
|
-
|
|
178
182
|
try {
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
183
|
+
const receipt = await awaitTransactionReceipt({
|
|
184
|
+
txHash,
|
|
185
|
+
chainId,
|
|
186
|
+
sdkConfig,
|
|
182
187
|
});
|
|
183
188
|
logger.info('Transaction confirmed', { txHash, receipt });
|
|
184
189
|
return receipt;
|
|
@@ -235,3 +240,44 @@ export const wallet = ({
|
|
|
235
240
|
|
|
236
241
|
return walletInstance;
|
|
237
242
|
};
|
|
243
|
+
|
|
244
|
+
const ONE_MIN = 60 * 1000;
|
|
245
|
+
const THREE_MIN = 3 * ONE_MIN;
|
|
246
|
+
|
|
247
|
+
const awaitTransactionReceipt = async ({
|
|
248
|
+
txHash,
|
|
249
|
+
chainId,
|
|
250
|
+
sdkConfig,
|
|
251
|
+
timeout = THREE_MIN,
|
|
252
|
+
}: {
|
|
253
|
+
txHash: Hex;
|
|
254
|
+
chainId: number;
|
|
255
|
+
sdkConfig: SdkConfig;
|
|
256
|
+
timeout?: number;
|
|
257
|
+
}) => {
|
|
258
|
+
const indexer = getIndexerClient(chainId, sdkConfig);
|
|
259
|
+
return Promise.race([
|
|
260
|
+
new Promise<TransactionReceipt>((resolve, reject) => {
|
|
261
|
+
indexer.subscribeReceipts(
|
|
262
|
+
{
|
|
263
|
+
filter: {
|
|
264
|
+
txnHash: txHash,
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
onMessage: ({ receipt }) => {
|
|
269
|
+
resolve(receipt);
|
|
270
|
+
},
|
|
271
|
+
onError: () => {
|
|
272
|
+
reject(TransactionReceiptNotFoundError);
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
);
|
|
276
|
+
}),
|
|
277
|
+
new Promise<TransactionReceipt>((_, reject) => {
|
|
278
|
+
setTimeout(() => {
|
|
279
|
+
reject(WaitForTransactionReceiptTimeoutError);
|
|
280
|
+
}, timeout);
|
|
281
|
+
}),
|
|
282
|
+
]);
|
|
283
|
+
};
|
package/src/react/hooks/index.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
export * from './useAutoSelectFeeOption';
|
|
1
2
|
export * from './useBalanceOfCollectible';
|
|
2
3
|
export * from './useCountOfCollectables';
|
|
3
4
|
export * from './useCollectible';
|
|
4
5
|
export * from './useCollection';
|
|
6
|
+
export * from './useCollectionBalanceDetails';
|
|
5
7
|
export * from './useConfig';
|
|
6
8
|
export * from './useCurrencies';
|
|
7
9
|
export * from './useCurrencyOptions';
|
|
@@ -29,3 +31,5 @@ export * from './useCheckoutOptions';
|
|
|
29
31
|
export * from './useListCollections';
|
|
30
32
|
export * from './useGenerateBuyTransaction';
|
|
31
33
|
export * from './useCancelOrder';
|
|
34
|
+
export * from './useCollectionDetails';
|
|
35
|
+
export * from './useCollectionDetailsPolling';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { http, HttpResponse } from 'msw';
|
|
2
2
|
import { WalletOptions, type MarketplaceConfig } from '../../../../types';
|
|
3
|
+
import { mockCurrencies } from '../../../_internal/api/__mocks__/marketplace.msw';
|
|
3
4
|
|
|
4
5
|
// Mock data
|
|
5
6
|
export const mockConfig: MarketplaceConfig = {
|
|
@@ -12,7 +13,15 @@ export const mockConfig: MarketplaceConfig = {
|
|
|
12
13
|
logoUrl: 'https://example.com/logo.png',
|
|
13
14
|
titleTemplate: '%s | Test Marketplace',
|
|
14
15
|
walletOptions: [WalletOptions.Sequence],
|
|
15
|
-
collections: [
|
|
16
|
+
collections: [
|
|
17
|
+
{
|
|
18
|
+
collectionAddress: '0x1234567890123456789012345678901234567890',
|
|
19
|
+
chainId: 1,
|
|
20
|
+
marketplaceFeePercentage: 2.5,
|
|
21
|
+
marketplaceType: 'orderbook',
|
|
22
|
+
currencyOptions: mockCurrencies.map((c) => c.contractAddress),
|
|
23
|
+
},
|
|
24
|
+
],
|
|
16
25
|
landingPageLayout: 'default',
|
|
17
26
|
cssString: '',
|
|
18
27
|
manifestUrl: '',
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { Address } from 'viem';
|
|
2
|
+
import { useAccount, useConfig } from 'wagmi';
|
|
3
|
+
import type { FeeOption } from '../ui/modals/_internal/components/waasFeeOptionsSelect/WaasFeeOptionsSelect';
|
|
4
|
+
import { getBalance } from 'wagmi/actions';
|
|
5
|
+
import { useCallback } from 'react';
|
|
6
|
+
|
|
7
|
+
type Error =
|
|
8
|
+
| 'User not connected'
|
|
9
|
+
| 'No options provided'
|
|
10
|
+
| 'Insufficient balance for any fee option'
|
|
11
|
+
| 'Failed to check balances';
|
|
12
|
+
|
|
13
|
+
type UseAutoSelectFeeOptionArgs = {
|
|
14
|
+
pendingFeeOptionConfirmation: {
|
|
15
|
+
id: string;
|
|
16
|
+
options: FeeOption[] | undefined;
|
|
17
|
+
chainId: number;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
type AutoSelectFeeOptionResult = Promise<{
|
|
22
|
+
selectedOption: FeeOption | null;
|
|
23
|
+
error: Error | null;
|
|
24
|
+
isLoading: boolean;
|
|
25
|
+
}>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Automatically selects the first fee option that user has enough balance for
|
|
29
|
+
* @param pendingFeeOptionConfirmation
|
|
30
|
+
* @returns The selected fee option, an error message if any, and a loading flag
|
|
31
|
+
*/
|
|
32
|
+
export function useAutoSelectFeeOption({
|
|
33
|
+
pendingFeeOptionConfirmation,
|
|
34
|
+
}: UseAutoSelectFeeOptionArgs): AutoSelectFeeOptionResult {
|
|
35
|
+
const { address: userAddress } = useAccount();
|
|
36
|
+
const config = useConfig();
|
|
37
|
+
|
|
38
|
+
const findAffordableOption = useCallback(async () => {
|
|
39
|
+
if (!userAddress) {
|
|
40
|
+
return {
|
|
41
|
+
selectedOption: null,
|
|
42
|
+
error: 'User not connected' as Error,
|
|
43
|
+
isLoading: false,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!pendingFeeOptionConfirmation.options) {
|
|
48
|
+
return {
|
|
49
|
+
selectedOption: null,
|
|
50
|
+
error: 'No options provided' as Error,
|
|
51
|
+
isLoading: false,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
// Try each option until we find an affordable one
|
|
57
|
+
for (const option of pendingFeeOptionConfirmation.options) {
|
|
58
|
+
if (!option.token.contractAddress) continue;
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
const balance = await getBalance(config, {
|
|
62
|
+
address: userAddress as Address,
|
|
63
|
+
token: option.token.contractAddress as Address,
|
|
64
|
+
chainId: pendingFeeOptionConfirmation.chainId,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const optionValue = BigInt(option.value);
|
|
68
|
+
if (balance.value >= optionValue) {
|
|
69
|
+
return {
|
|
70
|
+
selectedOption: option,
|
|
71
|
+
error: null,
|
|
72
|
+
isLoading: false,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error(
|
|
77
|
+
'Error fetching balance for currency:',
|
|
78
|
+
option.token.contractAddress,
|
|
79
|
+
error,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
selectedOption: null,
|
|
86
|
+
error: 'Insufficient balance for any fee option' as Error,
|
|
87
|
+
isLoading: false,
|
|
88
|
+
};
|
|
89
|
+
} catch (error) {
|
|
90
|
+
return {
|
|
91
|
+
selectedOption: null,
|
|
92
|
+
error: 'Failed to check balances' as Error,
|
|
93
|
+
isLoading: false,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}, [
|
|
97
|
+
pendingFeeOptionConfirmation.options,
|
|
98
|
+
pendingFeeOptionConfirmation.chainId,
|
|
99
|
+
userAddress,
|
|
100
|
+
config,
|
|
101
|
+
]);
|
|
102
|
+
|
|
103
|
+
return findAffordableOption();
|
|
104
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
2
|
import { useCancelTransactionSteps } from './useCancelTransactionSteps';
|
|
3
3
|
import type { MarketplaceKind } from '../../types';
|
|
4
|
+
import { useWaasFeeOptions } from '@0xsequence/kit';
|
|
5
|
+
import { useAutoSelectFeeOption } from './useAutoSelectFeeOption';
|
|
4
6
|
|
|
5
7
|
interface UseCancelOrderArgs {
|
|
6
8
|
collectionAddress: string;
|
|
@@ -29,6 +31,60 @@ export const useCancelOrder = ({
|
|
|
29
31
|
const [cancellingOrderId, setCancellingOrderId] = useState<string | null>(
|
|
30
32
|
null,
|
|
31
33
|
);
|
|
34
|
+
const [pendingFeeOptionConfirmation, confirmPendingFeeOption] =
|
|
35
|
+
useWaasFeeOptions();
|
|
36
|
+
const autoSelectFeeOptionResult = useAutoSelectFeeOption({
|
|
37
|
+
pendingFeeOptionConfirmation: pendingFeeOptionConfirmation
|
|
38
|
+
? {
|
|
39
|
+
id: pendingFeeOptionConfirmation.id,
|
|
40
|
+
options: pendingFeeOptionConfirmation.options?.map((opt) => ({
|
|
41
|
+
...opt,
|
|
42
|
+
token: {
|
|
43
|
+
...opt.token,
|
|
44
|
+
contractAddress: opt.token.contractAddress || null,
|
|
45
|
+
decimals: opt.token.decimals || 0,
|
|
46
|
+
tokenID: opt.token.tokenID || null,
|
|
47
|
+
},
|
|
48
|
+
})),
|
|
49
|
+
chainId: Number(chainId),
|
|
50
|
+
}
|
|
51
|
+
: {
|
|
52
|
+
id: '',
|
|
53
|
+
options: undefined,
|
|
54
|
+
chainId: Number(chainId),
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
const handleFeeOptionSelection = async () => {
|
|
60
|
+
if (!pendingFeeOptionConfirmation) return;
|
|
61
|
+
|
|
62
|
+
const { selectedOption, error } = await autoSelectFeeOptionResult;
|
|
63
|
+
|
|
64
|
+
if (error) {
|
|
65
|
+
console.error('Error selecting fee option:', error);
|
|
66
|
+
onError?.(new Error(`Failed to select fee option: ${error}`));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (
|
|
71
|
+
selectedOption?.token.contractAddress &&
|
|
72
|
+
pendingFeeOptionConfirmation.id
|
|
73
|
+
) {
|
|
74
|
+
confirmPendingFeeOption(
|
|
75
|
+
pendingFeeOptionConfirmation.id,
|
|
76
|
+
selectedOption.token.contractAddress,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
handleFeeOptionSelection();
|
|
82
|
+
}, [
|
|
83
|
+
pendingFeeOptionConfirmation,
|
|
84
|
+
autoSelectFeeOptionResult,
|
|
85
|
+
confirmPendingFeeOption,
|
|
86
|
+
onError,
|
|
87
|
+
]);
|
|
32
88
|
|
|
33
89
|
const { cancelOrder: cancelOrderBase } = useCancelTransactionSteps({
|
|
34
90
|
collectionAddress,
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import {
|
|
3
|
+
AddressSchema,
|
|
4
|
+
ChainIdSchema,
|
|
5
|
+
QueryArgSchema,
|
|
6
|
+
balanceQueries,
|
|
7
|
+
getIndexerClient,
|
|
8
|
+
} from '../_internal';
|
|
9
|
+
import { queryOptions, useQuery } from '@tanstack/react-query';
|
|
10
|
+
import { useConfig } from './useConfig';
|
|
11
|
+
import type { GetTokenBalancesDetailsReturn } from '@0xsequence/indexer';
|
|
12
|
+
import type { SdkConfig } from '../../types';
|
|
13
|
+
|
|
14
|
+
const filterSchema = z.object({
|
|
15
|
+
accountAddresses: z.array(AddressSchema),
|
|
16
|
+
contractWhitelist: z.array(AddressSchema).optional(),
|
|
17
|
+
omitNativeBalances: z.boolean(),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const useCollectionBalanceDetailsArgsSchema = z.object({
|
|
21
|
+
chainId: ChainIdSchema.pipe(z.coerce.number()),
|
|
22
|
+
filter: filterSchema,
|
|
23
|
+
query: QueryArgSchema.optional(),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export type CollectionBalanceFilter = z.infer<typeof filterSchema>;
|
|
27
|
+
export type UseCollectionBalanceDetailsArgs = z.input<
|
|
28
|
+
typeof useCollectionBalanceDetailsArgsSchema
|
|
29
|
+
>;
|
|
30
|
+
|
|
31
|
+
const fetchCollectionBalanceDetails = async (
|
|
32
|
+
args: UseCollectionBalanceDetailsArgs,
|
|
33
|
+
indexerClient: Awaited<ReturnType<typeof getIndexerClient>>,
|
|
34
|
+
) => {
|
|
35
|
+
const promises = args.filter.accountAddresses.map((accountAddress) =>
|
|
36
|
+
indexerClient.getTokenBalancesDetails({
|
|
37
|
+
filter: {
|
|
38
|
+
accountAddresses: [accountAddress],
|
|
39
|
+
contractWhitelist: args.filter.contractWhitelist,
|
|
40
|
+
omitNativeBalances: args.filter.omitNativeBalances,
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const responses = await Promise.all(promises);
|
|
46
|
+
const mergedResponse = responses.reduce<GetTokenBalancesDetailsReturn>(
|
|
47
|
+
(acc, curr) => {
|
|
48
|
+
if (!curr) return acc;
|
|
49
|
+
return {
|
|
50
|
+
page: curr.page,
|
|
51
|
+
nativeBalances: [
|
|
52
|
+
...(acc.nativeBalances || []),
|
|
53
|
+
...(curr.nativeBalances || []),
|
|
54
|
+
],
|
|
55
|
+
balances: [...(acc.balances || []), ...(curr.balances || [])],
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
{ page: {}, nativeBalances: [], balances: [] },
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
if (!mergedResponse) {
|
|
62
|
+
throw new Error('Failed to fetch collection balance details');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return mergedResponse;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const collectionBalanceDetailsOptions = (
|
|
69
|
+
args: UseCollectionBalanceDetailsArgs,
|
|
70
|
+
config: SdkConfig,
|
|
71
|
+
) => {
|
|
72
|
+
const parsedArgs = useCollectionBalanceDetailsArgsSchema.parse(args);
|
|
73
|
+
const indexerClient = getIndexerClient(parsedArgs.chainId, config);
|
|
74
|
+
|
|
75
|
+
return queryOptions({
|
|
76
|
+
queryKey: [...balanceQueries.collectionBalanceDetails, args, config],
|
|
77
|
+
queryFn: () => fetchCollectionBalanceDetails(parsedArgs, indexerClient),
|
|
78
|
+
...args.query,
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export const useCollectionBalanceDetails = (
|
|
83
|
+
args: UseCollectionBalanceDetailsArgs,
|
|
84
|
+
) => {
|
|
85
|
+
const config = useConfig();
|
|
86
|
+
return useQuery(collectionBalanceDetailsOptions(args, config));
|
|
87
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { queryOptions, useQuery } from '@tanstack/react-query';
|
|
2
|
+
import type { SdkConfig } from '../../types';
|
|
3
|
+
import { getMarketplaceClient } from '../_internal';
|
|
4
|
+
import { useConfig } from './useConfig';
|
|
5
|
+
|
|
6
|
+
type UseCollectionDetails = {
|
|
7
|
+
collectionAddress: string;
|
|
8
|
+
chainId: number;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const fetchCollectionDetails = async (
|
|
12
|
+
args: { collectionAddress: string },
|
|
13
|
+
marketplaceClient: Awaited<ReturnType<typeof getMarketplaceClient>>,
|
|
14
|
+
) => {
|
|
15
|
+
const { collection } = await marketplaceClient.getCollectionDetail({
|
|
16
|
+
contractAddress: args.collectionAddress,
|
|
17
|
+
});
|
|
18
|
+
return collection;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const collectionDetailsOptions = (
|
|
22
|
+
args: UseCollectionDetails,
|
|
23
|
+
config: SdkConfig,
|
|
24
|
+
) => {
|
|
25
|
+
const marketplaceClient = getMarketplaceClient(args.chainId, config);
|
|
26
|
+
return queryOptions({
|
|
27
|
+
queryKey: ['collectionDetails', args],
|
|
28
|
+
queryFn: () => fetchCollectionDetails(args, marketplaceClient),
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const useCollectionDetails = (args: UseCollectionDetails) => {
|
|
33
|
+
const config = useConfig();
|
|
34
|
+
return useQuery(collectionDetailsOptions(args, config));
|
|
35
|
+
};
|