@0xsequence/marketplace-sdk 0.4.7 → 0.4.9

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 (114) hide show
  1. package/dist/{chunk-6R4G7J6Q.js → chunk-7HWJ4DUX.js} +29 -5
  2. package/dist/chunk-7HWJ4DUX.js.map +1 -0
  3. package/dist/{chunk-5UCKYAMR.js → chunk-BJLOO4NP.js} +647 -376
  4. package/dist/chunk-BJLOO4NP.js.map +1 -0
  5. package/dist/{chunk-2OJB35FS.js → chunk-BMWCIHCB.js} +5 -5
  6. package/dist/{chunk-2OJB35FS.js.map → chunk-BMWCIHCB.js.map} +1 -1
  7. package/dist/{chunk-R7GVMKMM.js → chunk-CUA4SGWT.js} +540 -18
  8. package/dist/chunk-CUA4SGWT.js.map +1 -0
  9. package/dist/{chunk-ZEH4JI2U.js → chunk-FCF57DZI.js} +7 -2
  10. package/dist/chunk-FCF57DZI.js.map +1 -0
  11. package/dist/{chunk-JEOUQFT3.js → chunk-TFCSNRD5.js} +4 -3
  12. package/dist/chunk-TFCSNRD5.js.map +1 -0
  13. package/dist/{chunk-AQT3BQ67.js → chunk-Y3KINNAU.js} +12 -5
  14. package/dist/chunk-Y3KINNAU.js.map +1 -0
  15. package/dist/{create-config-D5WqfUft.d.ts → create-config-CgYQDyMD.d.ts} +2 -2
  16. package/dist/index.css +31 -17
  17. package/dist/index.d.ts +3 -3
  18. package/dist/index.js +3 -3
  19. package/dist/{marketplace-config-C_fDWzz0.d.ts → marketplace-config-BP5-XnFG.d.ts} +1 -1
  20. package/dist/{marketplace.gen-B8S8fflj.d.ts → marketplace.gen-BzmWLP9L.d.ts} +14 -4
  21. package/dist/react/_internal/api/index.d.ts +2 -2
  22. package/dist/react/_internal/api/index.js +3 -1
  23. package/dist/react/_internal/index.d.ts +5 -5
  24. package/dist/react/_internal/index.js +4 -2
  25. package/dist/react/_internal/wagmi/index.d.ts +3 -3
  26. package/dist/react/_internal/wagmi/index.js +1 -1
  27. package/dist/react/hooks/index.d.ts +46 -5
  28. package/dist/react/hooks/index.js +12 -5
  29. package/dist/react/index.css +37 -17
  30. package/dist/react/index.css.map +1 -1
  31. package/dist/react/index.d.ts +6 -6
  32. package/dist/react/index.js +15 -8
  33. package/dist/react/ssr/index.js +6 -1
  34. package/dist/react/ssr/index.js.map +1 -1
  35. package/dist/react/ui/components/collectible-card/index.css +37 -17
  36. package/dist/react/ui/components/collectible-card/index.css.map +1 -1
  37. package/dist/react/ui/components/collectible-card/index.d.ts +27 -4
  38. package/dist/react/ui/components/collectible-card/index.js +7 -8
  39. package/dist/react/ui/index.css +37 -17
  40. package/dist/react/ui/index.css.map +1 -1
  41. package/dist/react/ui/index.d.ts +3 -3
  42. package/dist/react/ui/index.js +7 -8
  43. package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +3 -3
  44. package/dist/react/ui/modals/_internal/components/actionModal/index.js +5 -5
  45. package/dist/{sdk-config-BXVH8PS2.d.ts → sdk-config-LbbmA85k.d.ts} +27 -7
  46. package/dist/{services-CdXAIjt1.d.ts → services-DW26ougH.d.ts} +1 -1
  47. package/dist/styles/index.css +31 -17
  48. package/dist/styles/index.css.map +1 -1
  49. package/dist/styles/index.d.ts +2 -2
  50. package/dist/styles/index.js +1 -1
  51. package/dist/types/index.d.ts +3 -3
  52. package/dist/types/index.js +2 -2
  53. package/dist/{types-eX4P9xju.d.ts → types-DhTZWw1U.d.ts} +2 -2
  54. package/dist/utils/index.d.ts +3 -3
  55. package/dist/utils/index.js +3 -3
  56. package/package.json +3 -2
  57. package/src/react/__tests__/provider.test.tsx +75 -0
  58. package/src/react/_internal/api/__mocks__/marketplace.msw.ts +4 -0
  59. package/src/react/_internal/api/marketplace.gen.ts +42 -7
  60. package/src/react/_internal/wagmi/__tests__/create-config.test.ts +196 -0
  61. package/src/react/_internal/wagmi/create-config.ts +9 -1
  62. package/src/react/_internal/wallet/useWallet.ts +30 -46
  63. package/src/react/_internal/wallet/wallet.ts +52 -6
  64. package/src/react/hooks/index.ts +2 -0
  65. package/src/react/hooks/options/__mocks__/marketplaceConfig.msw.ts +10 -1
  66. package/src/react/hooks/useCollectionDetails.tsx +35 -0
  67. package/src/react/hooks/useCollectionDetailsPolling.tsx +60 -0
  68. package/src/react/provider.tsx +5 -0
  69. package/src/react/ui/components/_internals/action-button/ActionButton.tsx +36 -118
  70. package/src/react/ui/components/_internals/action-button/components/ActionButtonBody.tsx +52 -0
  71. package/src/react/ui/components/_internals/action-button/components/NonOwnerActions.tsx +72 -0
  72. package/src/react/ui/components/_internals/action-button/components/OwnerActions.tsx +81 -0
  73. package/src/react/ui/components/_internals/action-button/hooks/useActionButtonLogic.ts +93 -0
  74. package/src/react/ui/components/_internals/action-button/store.ts +47 -0
  75. package/src/react/ui/components/_internals/action-button/styles.css.ts +8 -0
  76. package/src/react/ui/components/collectible-card/CollectibleCard.tsx +34 -14
  77. package/src/react/ui/components/collectible-card/Footer.tsx +9 -9
  78. package/src/react/ui/components/collectible-card/styles.css.ts +44 -31
  79. package/src/react/ui/icons/CartIcon.tsx +46 -0
  80. package/src/react/ui/modals/BuyModal/Modal.tsx +11 -4
  81. package/src/react/ui/modals/BuyModal/__tests__/Modal.test.tsx +253 -0
  82. package/src/react/ui/modals/BuyModal/__tests__/store.test.ts +100 -0
  83. package/src/react/ui/modals/BuyModal/hooks/__tests__/useBuyCollectable.test.tsx +402 -0
  84. package/src/react/ui/modals/BuyModal/hooks/__tests__/useCheckoutOptions.test.tsx +267 -0
  85. package/src/react/ui/modals/BuyModal/hooks/__tests__/useFees.test.tsx +166 -0
  86. package/src/react/ui/modals/BuyModal/hooks/__tests__/useLoadData.test.tsx +209 -0
  87. package/src/react/ui/modals/BuyModal/hooks/useCheckoutOptions.ts +19 -17
  88. package/src/react/ui/modals/BuyModal/hooks/useLoadData.ts +9 -7
  89. package/src/react/ui/modals/BuyModal/modals/CheckoutModal.tsx +7 -0
  90. package/src/react/ui/modals/BuyModal/modals/Modal1155.tsx +36 -18
  91. package/src/react/ui/modals/BuyModal/modals/__tests__/CheckoutModal.test.tsx +162 -0
  92. package/src/react/ui/modals/BuyModal/modals/__tests__/Modal1155.test.tsx +243 -0
  93. package/src/react/ui/modals/BuyModal/store.ts +11 -10
  94. package/src/react/ui/modals/CreateListingModal/Modal.tsx +26 -3
  95. package/src/react/ui/modals/CreateListingModal/__tests__/Modal.test.tsx +141 -29
  96. package/src/react/ui/modals/SuccessfulPurchaseModal/__tests__/Modal.test.tsx +145 -0
  97. package/src/react/ui/modals/_internal/components/actionModal/ActionModal.tsx +20 -11
  98. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/__tests__/index.test.tsx +13 -58
  99. package/src/react/ui/modals/_internal/components/priceInput/__tests__/index.test.tsx +2 -0
  100. package/src/react/ui/modals/_internal/components/transactionStatusModal/__tests__/TransactionStatusModal.test.tsx +18 -19
  101. package/src/react/ui/modals/_internal/components/transactionStatusModal/__tests__/utils.test.ts +2 -0
  102. package/src/react/ui/modals/_internal/components/transactionStatusModal/hooks/useTransactionStatus.ts +62 -0
  103. package/src/react/ui/modals/_internal/components/transactionStatusModal/index.tsx +53 -100
  104. package/src/react/ui/modals/_internal/components/transactionStatusModal/store.ts +2 -10
  105. package/src/utils/_internal/error/config.ts +16 -0
  106. package/tsconfig.tsbuildinfo +1 -1
  107. package/dist/chunk-5UCKYAMR.js.map +0 -1
  108. package/dist/chunk-6R4G7J6Q.js.map +0 -1
  109. package/dist/chunk-AQT3BQ67.js.map +0 -1
  110. package/dist/chunk-FWN2MCLI.js +0 -425
  111. package/dist/chunk-FWN2MCLI.js.map +0 -1
  112. package/dist/chunk-JEOUQFT3.js.map +0 -1
  113. package/dist/chunk-R7GVMKMM.js.map +0 -1
  114. package/dist/chunk-ZEH4JI2U.js.map +0 -1
@@ -0,0 +1,267 @@
1
+ import { renderHook } from '@testing-library/react';
2
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
3
+ import { useCheckoutOptions } from '../useCheckoutOptions';
4
+ import { useWallet } from '../../../../../_internal/wallet/useWallet';
5
+ import { useConfig } from '../../../../../hooks';
6
+ import { useFees } from '../useFees';
7
+ import {
8
+ MarketplaceKind,
9
+ getMarketplaceClient,
10
+ } from '../../../../../_internal';
11
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
12
+ import type { ReactNode } from 'react';
13
+
14
+ // Mock dependencies
15
+ vi.mock('../../../../../_internal/wallet/useWallet', () => ({
16
+ useWallet: vi.fn(),
17
+ }));
18
+
19
+ vi.mock('../../../../../hooks', () => ({
20
+ useConfig: vi.fn(),
21
+ }));
22
+
23
+ vi.mock('../useFees', () => ({
24
+ useFees: vi.fn(),
25
+ }));
26
+
27
+ vi.mock('../../../../../_internal', async () => {
28
+ const actual = (await vi.importActual('../../../../../_internal')) as Record<
29
+ string,
30
+ unknown
31
+ >;
32
+ return {
33
+ ...actual,
34
+ getMarketplaceClient: vi.fn(),
35
+ };
36
+ });
37
+
38
+ const createWrapper = () => {
39
+ const queryClient = new QueryClient({
40
+ defaultOptions: {
41
+ queries: {
42
+ retry: false,
43
+ },
44
+ },
45
+ });
46
+ return ({ children }: { children: ReactNode }) => (
47
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
48
+ );
49
+ };
50
+
51
+ describe('useCheckoutOptions', () => {
52
+ const defaultProps = {
53
+ chainId: 1,
54
+ collectionAddress: '0x123' as `0x${string}`,
55
+ orderId: '1',
56
+ marketplace: MarketplaceKind.sequence_marketplace_v2,
57
+ };
58
+
59
+ beforeEach(() => {
60
+ vi.clearAllMocks();
61
+
62
+ // Setup default mock implementations
63
+ (useConfig as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
64
+ projectAccessKey: 'test-key',
65
+ projectId: 'test-id',
66
+ });
67
+
68
+ (useFees as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
69
+ amount: '250',
70
+ receiver: '0x123',
71
+ });
72
+ });
73
+
74
+ it('should return undefined when wallet is not available', () => {
75
+ // Mock useWallet to return no wallet
76
+ (useWallet as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
77
+ wallet: undefined,
78
+ });
79
+
80
+ const { result } = renderHook(() => useCheckoutOptions(defaultProps), {
81
+ wrapper: createWrapper(),
82
+ });
83
+
84
+ expect(result.current.data).toBeUndefined();
85
+ });
86
+
87
+ it('should fetch checkout options when wallet is available', async () => {
88
+ // Mock useWallet to return a valid wallet
89
+ (useWallet as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
90
+ wallet: {
91
+ address: async () => '0x123',
92
+ },
93
+ });
94
+
95
+ // Mock the marketplace client
96
+ const checkoutOptionsMarketplaceMock = vi.fn().mockResolvedValue({
97
+ options: {
98
+ swap: [],
99
+ nftCheckout: [],
100
+ onRamp: [],
101
+ crypto: ['ETH', 'USDC'],
102
+ },
103
+ });
104
+
105
+ const marketplaceClientMock = {
106
+ checkoutOptionsMarketplace: checkoutOptionsMarketplaceMock,
107
+ };
108
+
109
+ (
110
+ getMarketplaceClient as unknown as ReturnType<typeof vi.fn>
111
+ ).mockReturnValue(marketplaceClientMock);
112
+
113
+ const { result } = renderHook(() => useCheckoutOptions(defaultProps), {
114
+ wrapper: createWrapper(),
115
+ });
116
+
117
+ // Wait for the query to complete
118
+ await vi.waitFor(() => {
119
+ expect(result.current.isSuccess).toBe(true);
120
+ });
121
+
122
+ // Verify the marketplace client was called with correct parameters
123
+ expect(checkoutOptionsMarketplaceMock).toHaveBeenCalledWith({
124
+ wallet: '0x123',
125
+ orders: [
126
+ {
127
+ contractAddress: defaultProps.collectionAddress,
128
+ orderId: defaultProps.orderId,
129
+ marketplace: defaultProps.marketplace,
130
+ },
131
+ ],
132
+ additionalFee: 250,
133
+ });
134
+
135
+ // Verify the returned data
136
+ expect(result.current.data).toEqual({
137
+ swap: [],
138
+ nftCheckout: [],
139
+ onRamp: [],
140
+ crypto: ['ETH', 'USDC'],
141
+ });
142
+ });
143
+
144
+ it('should call marketplaceClient.checkoutOptionsMarketplace with correct params', async () => {
145
+ // Mock useWallet to return a valid wallet
146
+ (useWallet as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
147
+ wallet: {
148
+ address: async () => '0x456',
149
+ },
150
+ });
151
+
152
+ // Mock the marketplace client
153
+ const checkoutOptionsMarketplaceMock = vi.fn().mockResolvedValue({
154
+ options: {
155
+ swap: ['uniswap'],
156
+ nftCheckout: ['moonpay'],
157
+ onRamp: ['ramp'],
158
+ crypto: ['ETH'],
159
+ },
160
+ });
161
+
162
+ const marketplaceClientMock = {
163
+ checkoutOptionsMarketplace: checkoutOptionsMarketplaceMock,
164
+ };
165
+
166
+ (
167
+ getMarketplaceClient as unknown as ReturnType<typeof vi.fn>
168
+ ).mockReturnValue(marketplaceClientMock);
169
+
170
+ const customProps = {
171
+ chainId: 137,
172
+ collectionAddress: '0x789' as `0x${string}`,
173
+ orderId: '42',
174
+ marketplace: MarketplaceKind.sequence_marketplace_v2,
175
+ };
176
+
177
+ // Mock fees with different values to ensure they're passed correctly
178
+ (useFees as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
179
+ amount: '500',
180
+ receiver: '0xabc',
181
+ });
182
+
183
+ renderHook(() => useCheckoutOptions(customProps), {
184
+ wrapper: createWrapper(),
185
+ });
186
+
187
+ // Wait for the query to be called
188
+ await vi.waitFor(() => {
189
+ expect(checkoutOptionsMarketplaceMock).toHaveBeenCalledTimes(1);
190
+ });
191
+
192
+ // Verify exact parameters passed to the marketplace client
193
+ expect(checkoutOptionsMarketplaceMock).toHaveBeenCalledWith({
194
+ wallet: '0x456',
195
+ orders: [
196
+ {
197
+ contractAddress: customProps.collectionAddress,
198
+ orderId: customProps.orderId,
199
+ marketplace: customProps.marketplace,
200
+ },
201
+ ],
202
+ additionalFee: 500, // Using the mocked fee amount
203
+ });
204
+
205
+ // Verify the marketplace client was initialized with correct chain ID
206
+ expect(getMarketplaceClient).toHaveBeenCalledWith(
207
+ customProps.chainId,
208
+ expect.objectContaining({
209
+ projectAccessKey: 'test-key',
210
+ projectId: 'test-id',
211
+ }),
212
+ );
213
+ });
214
+
215
+ it('should handle API errors', async () => {
216
+ // Mock useWallet to return a valid wallet
217
+ (useWallet as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
218
+ wallet: {
219
+ address: async () => '0x123',
220
+ },
221
+ });
222
+
223
+ // Mock the marketplace client to throw an error
224
+ const errorMessage = 'Failed to fetch checkout options';
225
+ const checkoutOptionsMarketplaceMock = vi
226
+ .fn()
227
+ .mockRejectedValue(new Error(errorMessage));
228
+
229
+ const marketplaceClientMock = {
230
+ checkoutOptionsMarketplace: checkoutOptionsMarketplaceMock,
231
+ };
232
+
233
+ (
234
+ getMarketplaceClient as unknown as ReturnType<typeof vi.fn>
235
+ ).mockReturnValue(marketplaceClientMock);
236
+
237
+ const { result } = renderHook(() => useCheckoutOptions(defaultProps), {
238
+ wrapper: createWrapper(),
239
+ });
240
+
241
+ // Wait for the query to fail
242
+ await vi.waitFor(() => {
243
+ expect(result.current.isError).toBe(true);
244
+ });
245
+
246
+ // Verify error state
247
+ expect(result.current.error).toBeDefined();
248
+ expect(result.current.error).toBeInstanceOf(Error);
249
+ expect((result.current.error as Error).message).toBe(errorMessage);
250
+
251
+ // Verify data is undefined when there's an error
252
+ expect(result.current.data).toBeUndefined();
253
+
254
+ // Verify the API was called with correct parameters despite the error
255
+ expect(checkoutOptionsMarketplaceMock).toHaveBeenCalledWith({
256
+ wallet: '0x123',
257
+ orders: [
258
+ {
259
+ contractAddress: defaultProps.collectionAddress,
260
+ orderId: defaultProps.orderId,
261
+ marketplace: defaultProps.marketplace,
262
+ },
263
+ ],
264
+ additionalFee: 250,
265
+ });
266
+ });
267
+ });
@@ -0,0 +1,166 @@
1
+ import { renderHook } from '@testing-library/react';
2
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
3
+ import { useFees } from '../useFees';
4
+ import { useMarketplaceConfig } from '../../../../../hooks';
5
+ import { avalanche, optimism } from 'viem/chains';
6
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
7
+ import type { ReactNode } from 'react';
8
+
9
+ // Mock dependencies
10
+ vi.mock('../../../../../hooks', () => ({
11
+ useMarketplaceConfig: vi.fn(),
12
+ }));
13
+
14
+ const createWrapper = () => {
15
+ const queryClient = new QueryClient({
16
+ defaultOptions: {
17
+ queries: {
18
+ retry: false,
19
+ },
20
+ },
21
+ });
22
+ return ({ children }: { children: ReactNode }) => (
23
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
24
+ );
25
+ };
26
+
27
+ describe('useFees', () => {
28
+ const defaultProps = {
29
+ chainId: 1,
30
+ collectionAddress: '0x123',
31
+ };
32
+
33
+ const defaultPlatformFeeRecipient =
34
+ '0x858dB1cbF6D09D447C96A11603189b49B2D1C219';
35
+ const avalancheAndOptimismPlatformFeeRecipient =
36
+ '0x400cdab4676c17aec07e8ec748a5fc3b674bca41';
37
+
38
+ beforeEach(() => {
39
+ vi.clearAllMocks();
40
+ });
41
+
42
+ it('should return default fee when collection not found', () => {
43
+ // Mock marketplace config with no matching collection
44
+ (
45
+ useMarketplaceConfig as unknown as ReturnType<typeof vi.fn>
46
+ ).mockReturnValue({
47
+ data: {
48
+ collections: [
49
+ {
50
+ collectionAddress: '0x456',
51
+ chainId: '1',
52
+ marketplaceFeePercentage: '5.0',
53
+ },
54
+ ],
55
+ },
56
+ });
57
+
58
+ const { result } = renderHook(() => useFees(defaultProps), {
59
+ wrapper: createWrapper(),
60
+ });
61
+
62
+ // Default fee should be 2.5%, which is 250 in BPS (basis points)
63
+ expect(result.current).toEqual({
64
+ amount: '250',
65
+ receiver: defaultPlatformFeeRecipient,
66
+ });
67
+ });
68
+
69
+ it('should return collection-specific fee when found in config', () => {
70
+ const collectionFee = '5.0';
71
+ const collectionAddress = '0x789';
72
+ const chainId = 1;
73
+
74
+ // Mock marketplace config with a matching collection
75
+ (
76
+ useMarketplaceConfig as unknown as ReturnType<typeof vi.fn>
77
+ ).mockReturnValue({
78
+ data: {
79
+ collections: [
80
+ {
81
+ collectionAddress,
82
+ chainId: chainId.toString(),
83
+ marketplaceFeePercentage: collectionFee,
84
+ },
85
+ ],
86
+ },
87
+ });
88
+
89
+ const { result } = renderHook(
90
+ () => useFees({ chainId, collectionAddress }),
91
+ {
92
+ wrapper: createWrapper(),
93
+ },
94
+ );
95
+
96
+ // 5.0% fee should be 500 in BPS (basis points)
97
+ expect(result.current).toEqual({
98
+ amount: '500',
99
+ receiver: defaultPlatformFeeRecipient,
100
+ });
101
+ });
102
+
103
+ it('should use Avalanche/Optimism fee recipient for those chains', () => {
104
+ // Test Avalanche chain
105
+ const { result: avalancheResult } = renderHook(
106
+ () => useFees({ ...defaultProps, chainId: avalanche.id }),
107
+ {
108
+ wrapper: createWrapper(),
109
+ },
110
+ );
111
+
112
+ expect(avalancheResult.current.receiver).toBe(
113
+ avalancheAndOptimismPlatformFeeRecipient,
114
+ );
115
+
116
+ // Test Optimism chain
117
+ const { result: optimismResult } = renderHook(
118
+ () => useFees({ ...defaultProps, chainId: optimism.id }),
119
+ {
120
+ wrapper: createWrapper(),
121
+ },
122
+ );
123
+
124
+ expect(optimismResult.current.receiver).toBe(
125
+ avalancheAndOptimismPlatformFeeRecipient,
126
+ );
127
+ });
128
+
129
+ it('should handle case-insensitive collection address matching', () => {
130
+ const collectionFee = '3.5';
131
+ const collectionAddress = '0xABC123';
132
+ const chainId = 1;
133
+
134
+ // Mock marketplace config with a collection in different case
135
+ (
136
+ useMarketplaceConfig as unknown as ReturnType<typeof vi.fn>
137
+ ).mockReturnValue({
138
+ data: {
139
+ collections: [
140
+ {
141
+ collectionAddress: collectionAddress.toLowerCase(),
142
+ chainId: chainId.toString(),
143
+ marketplaceFeePercentage: collectionFee,
144
+ },
145
+ ],
146
+ },
147
+ });
148
+
149
+ const { result } = renderHook(
150
+ () =>
151
+ useFees({
152
+ chainId,
153
+ collectionAddress: collectionAddress.toUpperCase(),
154
+ }),
155
+ {
156
+ wrapper: createWrapper(),
157
+ },
158
+ );
159
+
160
+ // 3.5% fee should be 350 in BPS (basis points)
161
+ expect(result.current).toEqual({
162
+ amount: '350',
163
+ receiver: defaultPlatformFeeRecipient,
164
+ });
165
+ });
166
+ });
@@ -0,0 +1,209 @@
1
+ import { renderHook } from '@testing-library/react';
2
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
3
+ import { useLoadData } from '../useLoadData';
4
+ import { useCollection, useCollectible } from '../../../../../hooks';
5
+ import { useCheckoutOptions } from '../useCheckoutOptions';
6
+ import { MarketplaceKind } from '../../../../../_internal';
7
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
8
+ import type { ReactNode } from 'react';
9
+
10
+ // Mock dependencies
11
+ vi.mock('../../../../../hooks', () => ({
12
+ useCollection: vi.fn(),
13
+ useCollectible: vi.fn(),
14
+ }));
15
+
16
+ vi.mock('../useCheckoutOptions', () => ({
17
+ useCheckoutOptions: vi.fn(),
18
+ }));
19
+
20
+ const createWrapper = () => {
21
+ const queryClient = new QueryClient({
22
+ defaultOptions: {
23
+ queries: {
24
+ retry: false,
25
+ },
26
+ },
27
+ });
28
+ return ({ children }: { children: ReactNode }) => (
29
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
30
+ );
31
+ };
32
+
33
+ describe('useLoadData', () => {
34
+ const defaultProps = {
35
+ chainId: 1,
36
+ collectionAddress: '0x123' as `0x${string}`,
37
+ collectibleId: '1',
38
+ orderId: '1',
39
+ marketplace: MarketplaceKind.sequence_marketplace_v2,
40
+ };
41
+
42
+ beforeEach(() => {
43
+ vi.clearAllMocks();
44
+ });
45
+
46
+ it('should return loading state when any data is loading', () => {
47
+ // Mock one hook to be loading
48
+ (useCollection as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
49
+ data: null,
50
+ isLoading: true,
51
+ isError: false,
52
+ });
53
+
54
+ (useCollectible as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
55
+ data: null,
56
+ isLoading: false,
57
+ isError: false,
58
+ });
59
+
60
+ (useCheckoutOptions as unknown as ReturnType<typeof vi.fn>).mockReturnValue(
61
+ {
62
+ data: null,
63
+ isLoading: false,
64
+ isError: false,
65
+ },
66
+ );
67
+
68
+ const { result } = renderHook(() => useLoadData(defaultProps), {
69
+ wrapper: createWrapper(),
70
+ });
71
+
72
+ expect(result.current.isLoading).toBe(true);
73
+ expect(result.current.isError).toBe(false);
74
+ expect(result.current.collection).toBeNull();
75
+ expect(result.current.collectable).toBeNull();
76
+ expect(result.current.checkoutOptions).toBeNull();
77
+ });
78
+
79
+ it('should return error state when any request fails', () => {
80
+ // Mock one hook to have an error
81
+ (useCollection as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
82
+ data: null,
83
+ isLoading: false,
84
+ isError: true,
85
+ });
86
+
87
+ (useCollectible as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
88
+ data: null,
89
+ isLoading: false,
90
+ isError: false,
91
+ });
92
+
93
+ (useCheckoutOptions as unknown as ReturnType<typeof vi.fn>).mockReturnValue(
94
+ {
95
+ data: null,
96
+ isLoading: false,
97
+ isError: false,
98
+ },
99
+ );
100
+
101
+ const { result } = renderHook(() => useLoadData(defaultProps), {
102
+ wrapper: createWrapper(),
103
+ });
104
+
105
+ expect(result.current.isError).toBe(true);
106
+ expect(result.current.isLoading).toBe(false);
107
+ });
108
+
109
+ it('should return all data when successfully loaded', () => {
110
+ const mockCollection = { type: 'ERC721', name: 'Test Collection' };
111
+ const mockCollectable = { tokenId: '1', name: 'Test NFT' };
112
+ const mockCheckoutOptions = {
113
+ swap: [],
114
+ nftCheckout: [],
115
+ onRamp: [],
116
+ crypto: ['ETH'],
117
+ };
118
+
119
+ (useCollection as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
120
+ data: mockCollection,
121
+ isLoading: false,
122
+ isError: false,
123
+ });
124
+
125
+ (useCollectible as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
126
+ data: mockCollectable,
127
+ isLoading: false,
128
+ isError: false,
129
+ });
130
+
131
+ (useCheckoutOptions as unknown as ReturnType<typeof vi.fn>).mockReturnValue(
132
+ {
133
+ data: mockCheckoutOptions,
134
+ isLoading: false,
135
+ isError: false,
136
+ },
137
+ );
138
+
139
+ const { result } = renderHook(() => useLoadData(defaultProps), {
140
+ wrapper: createWrapper(),
141
+ });
142
+
143
+ expect(result.current.isLoading).toBe(false);
144
+ expect(result.current.isError).toBe(false);
145
+ expect(result.current.collection).toBe(mockCollection);
146
+ expect(result.current.collectable).toBe(mockCollectable);
147
+ expect(result.current.checkoutOptions).toBe(mockCheckoutOptions);
148
+ });
149
+
150
+ it('should handle partial data loading states', () => {
151
+ // Mock different loading states for each hook
152
+ (useCollection as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
153
+ data: { type: 'ERC721', name: 'Test Collection' },
154
+ isLoading: false,
155
+ isError: false,
156
+ });
157
+
158
+ (useCollectible as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
159
+ data: null,
160
+ isLoading: true,
161
+ isError: false,
162
+ });
163
+
164
+ (useCheckoutOptions as unknown as ReturnType<typeof vi.fn>).mockReturnValue(
165
+ {
166
+ data: {
167
+ swap: [],
168
+ nftCheckout: [],
169
+ onRamp: [],
170
+ crypto: ['ETH'],
171
+ },
172
+ isLoading: false,
173
+ isError: false,
174
+ },
175
+ );
176
+
177
+ const { result } = renderHook(() => useLoadData(defaultProps), {
178
+ wrapper: createWrapper(),
179
+ });
180
+
181
+ // Should be loading if any data is loading
182
+ expect(result.current.isLoading).toBe(true);
183
+ expect(result.current.isError).toBe(false);
184
+
185
+ // Should have partial data available
186
+ expect(result.current.collection).toBeDefined();
187
+ expect(result.current.collectable).toBeNull();
188
+ expect(result.current.checkoutOptions).toBeDefined();
189
+
190
+ // Verify hook calls
191
+ expect(useCollection).toHaveBeenCalledWith({
192
+ chainId: defaultProps.chainId,
193
+ collectionAddress: defaultProps.collectionAddress,
194
+ });
195
+
196
+ expect(useCollectible).toHaveBeenCalledWith({
197
+ chainId: String(defaultProps.chainId),
198
+ collectionAddress: defaultProps.collectionAddress,
199
+ collectibleId: defaultProps.collectibleId,
200
+ });
201
+
202
+ expect(useCheckoutOptions).toHaveBeenCalledWith({
203
+ chainId: defaultProps.chainId,
204
+ collectionAddress: defaultProps.collectionAddress,
205
+ orderId: defaultProps.orderId,
206
+ marketplace: defaultProps.marketplace,
207
+ });
208
+ });
209
+ });
@@ -6,7 +6,7 @@ import {
6
6
  import { useConfig } from '../../../../hooks';
7
7
  import { useWallet } from '../../../../_internal/wallet/useWallet';
8
8
  import { useFees } from './useFees';
9
- import { useQuery } from '@tanstack/react-query';
9
+ import { skipToken, useQuery } from '@tanstack/react-query';
10
10
 
11
11
  export const useCheckoutOptions = (input: {
12
12
  chainId: number;
@@ -29,22 +29,24 @@ export const useCheckoutOptions = (input: {
29
29
  input.orderId,
30
30
  input.marketplace,
31
31
  ],
32
- queryFn: async () => {
33
- const marketplaceClient = getMarketplaceClient(input.chainId, config);
34
- return marketplaceClient
35
- .checkoutOptionsMarketplace({
36
- wallet: await wallet!.address(),
37
- orders: [
38
- {
39
- contractAddress: input.collectionAddress,
40
- orderId: input.orderId,
41
- marketplace: input.marketplace,
42
- },
43
- ],
44
- additionalFee: Number(fees.amount),
45
- })
46
- .then((res) => res.options);
47
- },
32
+ queryFn: wallet
33
+ ? async () => {
34
+ const marketplaceClient = getMarketplaceClient(input.chainId, config);
35
+ return marketplaceClient
36
+ .checkoutOptionsMarketplace({
37
+ wallet: await wallet.address(),
38
+ orders: [
39
+ {
40
+ contractAddress: input.collectionAddress,
41
+ orderId: input.orderId,
42
+ marketplace: input.marketplace,
43
+ },
44
+ ],
45
+ additionalFee: Number(fees.amount),
46
+ })
47
+ .then((res) => res.options);
48
+ }
49
+ : skipToken,
48
50
  enabled: !!wallet,
49
51
  });
50
52
  };