@0xsequence/marketplace-sdk 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/dist/builder-types-wOwfTJpd.d.ts +73 -0
  2. package/dist/{chunk-FCF57DZI.js → chunk-7FN62HOP.js} +5 -9
  3. package/dist/chunk-7FN62HOP.js.map +1 -0
  4. package/dist/{chunk-F4E3WJ2K.js → chunk-BVXIRVEC.js} +261 -249
  5. package/dist/chunk-BVXIRVEC.js.map +1 -0
  6. package/dist/{chunk-XP3WY5AX.js → chunk-BZD2LDJJ.js} +2 -2
  7. package/dist/{chunk-XP3WY5AX.js.map → chunk-BZD2LDJJ.js.map} +1 -1
  8. package/dist/chunk-DZKPDV63.js +27 -0
  9. package/dist/chunk-DZKPDV63.js.map +1 -0
  10. package/dist/{chunk-I37CRQ4S.js → chunk-H5YWG6WN.js} +128 -88
  11. package/dist/chunk-H5YWG6WN.js.map +1 -0
  12. package/dist/{chunk-ZUEQGPLO.js → chunk-J6F5QOW5.js} +2 -2
  13. package/dist/{chunk-ZUEQGPLO.js.map → chunk-J6F5QOW5.js.map} +1 -1
  14. package/dist/{chunk-LJAB3S6U.js → chunk-TFRAOS7F.js} +22 -13
  15. package/dist/chunk-TFRAOS7F.js.map +1 -0
  16. package/dist/{chunk-5NORRVPM.js → chunk-UZIAX32Y.js} +1 -1
  17. package/dist/{chunk-5NORRVPM.js.map → chunk-UZIAX32Y.js.map} +1 -1
  18. package/dist/{chunk-MKGSGTQC.js → chunk-Y7YTLAO2.js} +3 -3
  19. package/dist/{create-config-BXvwUh55.d.ts → create-config-Bltg8Enl.d.ts} +1 -1
  20. package/dist/index.css +1 -1
  21. package/dist/index.d.ts +3 -3
  22. package/dist/index.js +10 -6
  23. package/dist/react/_internal/index.d.ts +3 -3
  24. package/dist/react/_internal/index.js +1 -1
  25. package/dist/react/_internal/wagmi/index.d.ts +2 -3
  26. package/dist/react/_internal/wagmi/index.js +1 -1
  27. package/dist/react/hooks/index.d.ts +72 -20
  28. package/dist/react/hooks/index.js +5 -7
  29. package/dist/react/index.css +1 -1
  30. package/dist/react/index.css.map +1 -1
  31. package/dist/react/index.d.ts +4 -4
  32. package/dist/react/index.js +8 -10
  33. package/dist/react/ssr/index.d.ts +54 -41
  34. package/dist/react/ssr/index.js +5 -9
  35. package/dist/react/ssr/index.js.map +1 -1
  36. package/dist/react/ui/components/collectible-card/index.css +1 -1
  37. package/dist/react/ui/components/collectible-card/index.css.map +1 -1
  38. package/dist/react/ui/components/collectible-card/index.d.ts +2 -2
  39. package/dist/react/ui/components/collectible-card/index.js +8 -8
  40. package/dist/react/ui/index.css +1 -1
  41. package/dist/react/ui/index.css.map +1 -1
  42. package/dist/react/ui/index.d.ts +2 -2
  43. package/dist/react/ui/index.js +8 -8
  44. package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +2 -2
  45. package/dist/react/ui/modals/_internal/components/actionModal/index.js +6 -6
  46. package/dist/styles/index.css +1 -1
  47. package/dist/styles/index.css.map +1 -1
  48. package/dist/styles/index.js +1 -1
  49. package/dist/types/index.d.ts +1 -3
  50. package/dist/types/index.js +9 -5
  51. package/dist/{types-Yto6KrTN.d.ts → types-BY3husBh.d.ts} +1 -1
  52. package/dist/utils/index.d.ts +2 -2
  53. package/dist/utils/index.js +4 -4
  54. package/package.json +11 -10
  55. package/src/react/_internal/api/__mocks__/indexer.msw.ts +197 -0
  56. package/src/react/_internal/api/__mocks__/marketplace.msw.ts +140 -1
  57. package/src/react/_internal/api/__mocks__/metadata.msw.ts +162 -0
  58. package/src/react/_internal/test/mocks/publicClient.ts +39 -0
  59. package/src/react/_internal/test/mocks/wagmi.ts +61 -0
  60. package/src/react/_internal/test/mocks/wallet.ts +61 -0
  61. package/src/react/_internal/test/setup.ts +28 -0
  62. package/src/react/_internal/test-utils.tsx +31 -2
  63. package/src/react/_internal/wagmi/__tests__/create-config.test.ts +53 -20
  64. package/src/react/_internal/wagmi/create-config.ts +3 -4
  65. package/src/react/_internal/wagmi/embedded.ts +1 -4
  66. package/src/react/_internal/wagmi/universal.ts +1 -4
  67. package/src/react/_internal/wallet/wallet.ts +1 -0
  68. package/src/react/hooks/__tests__/useAutoSelectFeeOption.test.tsx +314 -0
  69. package/src/react/hooks/__tests__/useBalanceOfCollectible.test.tsx +148 -0
  70. package/src/react/hooks/__tests__/useCancelOrder.test.tsx +410 -0
  71. package/src/react/hooks/__tests__/useCancelTransactionSteps.test.tsx +269 -0
  72. package/src/react/hooks/__tests__/useCollectible.test.tsx +120 -0
  73. package/src/react/hooks/__tests__/useCollection.test.tsx +101 -0
  74. package/src/react/hooks/__tests__/useCollectionBalanceDetails.test.tsx +175 -0
  75. package/src/react/hooks/__tests__/useCollectionDetails.test.tsx +82 -0
  76. package/src/react/hooks/__tests__/useCollectionDetailsPolling.test.tsx +133 -0
  77. package/src/react/hooks/__tests__/useCountListingsForCollectible.test.tsx +108 -0
  78. package/src/react/hooks/__tests__/useCountOfCollectables.test.tsx +129 -0
  79. package/src/react/hooks/__tests__/useCountOffersForCollectible.test.tsx +108 -0
  80. package/src/react/hooks/__tests__/useCurrencies.test.tsx +176 -0
  81. package/src/react/hooks/__tests__/useCurrency.test.tsx +153 -0
  82. package/src/react/hooks/__tests__/useCurrencyBalance.test.tsx +111 -0
  83. package/src/react/hooks/__tests__/useFilters.test.tsx +127 -0
  84. package/src/react/hooks/__tests__/useFloorOrder.test.tsx +101 -0
  85. package/src/react/hooks/__tests__/useGenerateBuyTransaction.test.tsx +173 -0
  86. package/src/react/hooks/__tests__/useGenerateCancelTransaction.test.tsx +207 -0
  87. package/src/react/hooks/__tests__/useGenerateListingTransaction.test.tsx +207 -0
  88. package/src/react/hooks/__tests__/useGenerateOfferTransaction.test.tsx +205 -0
  89. package/src/react/hooks/__tests__/useGenerateSellTransaction.test.tsx +181 -0
  90. package/src/react/hooks/__tests__/useHighestOffer.test.tsx +118 -0
  91. package/src/react/hooks/__tests__/useListBalances.test.tsx +136 -0
  92. package/src/react/hooks/__tests__/useListCollectibleActivities.test.tsx +200 -0
  93. package/src/react/hooks/__tests__/useListCollectibles.test.tsx +232 -0
  94. package/src/react/hooks/__tests__/useListCollectionActivities.test.tsx +235 -0
  95. package/src/react/hooks/__tests__/useListCollections.test.tsx +296 -0
  96. package/src/react/hooks/__tests__/useListListingsForCollectible.test.tsx +140 -0
  97. package/src/react/hooks/__tests__/useListOffersForCollectible.test.tsx +140 -0
  98. package/src/react/hooks/__tests__/useLowestListing.test.tsx +148 -0
  99. package/src/react/hooks/__tests__/useMarketplaceConfig.test.tsx +106 -0
  100. package/src/react/hooks/__tests__/useRoyaltyPercentage.test.tsx +129 -0
  101. package/src/react/hooks/index.ts +0 -1
  102. package/src/react/hooks/options/__mocks__/marketplaceConfig.msw.ts +66 -10
  103. package/src/react/hooks/options/__tests__/marketplaceConfigOptions.test.tsx +2 -11
  104. package/src/react/hooks/options/marketplaceConfigOptions.ts +8 -3
  105. package/src/react/hooks/useAutoSelectFeeOption.tsx +4 -3
  106. package/src/react/hooks/useCancelTransactionSteps.tsx +17 -9
  107. package/src/react/hooks/useCollectionDetailsPolling.tsx +1 -1
  108. package/src/react/hooks/useCurrencies.tsx +29 -28
  109. package/src/react/hooks/useFilters.tsx +69 -2
  110. package/src/react/hooks/useGenerateBuyTransaction.tsx +13 -5
  111. package/src/react/hooks/useListCollectibleActivities.tsx +1 -0
  112. package/src/react/hooks/useListCollectibles.tsx +1 -0
  113. package/src/react/hooks/useListCollectionActivities.tsx +1 -0
  114. package/src/react/hooks/useListCollections.tsx +2 -2
  115. package/src/react/ui/components/_internals/custom-select/__tests__/CustomSelect.test.tsx +6 -2
  116. package/src/react/ui/components/collectible-card/CollectibleCard.tsx +1 -1
  117. package/src/react/ui/components/collectible-card/Footer.tsx +9 -5
  118. package/src/react/ui/modals/BuyModal/Modal.tsx +9 -4
  119. package/src/react/ui/modals/BuyModal/__tests__/Modal.test.tsx +0 -1
  120. package/src/react/ui/modals/BuyModal/__tests__/store.test.ts +4 -2
  121. package/src/react/ui/modals/BuyModal/hooks/__tests__/useBuyCollectable.test.tsx +1 -24
  122. package/src/react/ui/modals/BuyModal/hooks/__tests__/useCheckoutOptions.test.tsx +152 -210
  123. package/src/react/ui/modals/BuyModal/hooks/__tests__/useFees.test.tsx +19 -49
  124. package/src/react/ui/modals/BuyModal/hooks/useFees.ts +6 -6
  125. package/src/react/ui/modals/BuyModal/modals/Modal1155.tsx +4 -2
  126. package/src/react/ui/modals/BuyModal/modals/__tests__/Modal1155.test.tsx +161 -52
  127. package/src/react/ui/modals/BuyModal/store.ts +7 -0
  128. package/src/react/ui/modals/CreateListingModal/Modal.tsx +1 -3
  129. package/src/react/ui/modals/CreateListingModal/__tests__/Modal.test.tsx +59 -227
  130. package/src/react/ui/modals/CreateListingModal/hooks/useCreateListing.tsx +2 -1
  131. package/src/react/ui/modals/CreateListingModal/hooks/useGetTokenApproval.ts +8 -2
  132. package/src/react/ui/modals/CreateListingModal/hooks/useTransactionSteps.tsx +9 -5
  133. package/src/react/ui/modals/MakeOfferModal/Modal.tsx +1 -8
  134. package/src/react/ui/modals/MakeOfferModal/__tests__/Modal.test.tsx +41 -118
  135. package/src/react/ui/modals/MakeOfferModal/hooks/useMakeOffer.tsx +2 -1
  136. package/src/react/ui/modals/MakeOfferModal/hooks/useTransactionSteps.tsx +9 -5
  137. package/src/react/ui/modals/SellModal/__tests__/Modal.test.tsx +4 -3
  138. package/src/react/ui/modals/SellModal/hooks/useGetTokenApproval.tsx +33 -31
  139. package/src/react/ui/modals/SellModal/hooks/useSell.tsx +1 -0
  140. package/src/react/ui/modals/SellModal/hooks/useTransactionSteps.tsx +9 -5
  141. package/src/react/ui/modals/SuccessfulPurchaseModal/__tests__/Modal.test.tsx +0 -1
  142. package/src/react/ui/modals/_internal/components/actionModal/ErrorModal.tsx +4 -2
  143. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/__tests__/index.test.tsx +129 -57
  144. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/index.tsx +1 -3
  145. package/src/react/ui/modals/_internal/components/priceInput/__tests__/index.test.tsx +1 -3
  146. package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +2 -2
  147. package/src/react/ui/modals/_internal/components/transactionStatusModal/__tests__/TransactionStatusModal.test.tsx +8 -8
  148. package/src/react/ui/modals/_internal/components/transactionStatusModal/hooks/useTransactionStatus.ts +1 -0
  149. package/src/types/builder-types.ts +79 -0
  150. package/src/types/index.ts +1 -1
  151. package/src/utils/__tests__/get-public-rpc-client.test.ts +2 -0
  152. package/src/utils/getMarketplaceDetails.ts +2 -2
  153. package/tsconfig.tsbuildinfo +1 -1
  154. package/vitest.config.js +2 -1
  155. package/dist/chunk-F4E3WJ2K.js.map +0 -1
  156. package/dist/chunk-FCF57DZI.js.map +0 -1
  157. package/dist/chunk-I37CRQ4S.js.map +0 -1
  158. package/dist/chunk-LJAB3S6U.js.map +0 -1
  159. package/dist/chunk-RK6KYMZM.js +0 -18
  160. package/dist/chunk-RK6KYMZM.js.map +0 -1
  161. package/dist/marketplace-config-znEu4L0K.d.ts +0 -60
  162. package/src/react/hooks/useCurrencyOptions.tsx +0 -16
  163. package/src/types/marketplace-config.ts +0 -67
  164. /package/dist/{chunk-MKGSGTQC.js.map → chunk-Y7YTLAO2.js.map} +0 -0
@@ -1,4 +1,3 @@
1
- import '@testing-library/jest-dom/vitest';
2
1
  import {
3
2
  render,
4
3
  screen,
@@ -8,34 +7,96 @@ import {
8
7
  act,
9
8
  cleanup,
10
9
  } from '../../../../../_internal/test-utils';
11
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
10
+ import {
11
+ describe,
12
+ it,
13
+ expect,
14
+ vi,
15
+ beforeEach,
16
+ afterEach,
17
+ type Mock,
18
+ } from 'vitest';
12
19
  import { ERC1155QuantityModal } from '../Modal1155';
13
20
  import { buyModal$ } from '../../store';
14
- import { MarketplaceKind } from '../../../../../_internal';
15
21
  import type { Order, TokenMetadata } from '../../../../../_internal';
22
+ import { createMockWallet } from '../../../../../_internal/test/mocks/wallet';
23
+ import {
24
+ mockCurrencies,
25
+ mockOrder as baseMockOrder,
26
+ mockTokenMetadata,
27
+ } from '../../../../../_internal/api/__mocks__/marketplace.msw';
28
+
29
+ // Mock hooks
30
+ vi.mock('../../../../../hooks', () => ({
31
+ useCurrency: () => ({
32
+ data: mockCurrencies[0],
33
+ isLoading: false,
34
+ }),
35
+ useConfig: () => ({
36
+ chainId: 1,
37
+ isTestnet: false,
38
+ }),
39
+ }));
40
+
41
+ const mockWallet = createMockWallet();
42
+
43
+ const getChainIdMock = mockWallet.getChainId as Mock<
44
+ typeof mockWallet.getChainId
45
+ >;
46
+ const switchChainMock = mockWallet.switchChain as Mock<
47
+ typeof mockWallet.switchChain
48
+ >;
49
+
50
+ vi.mock('../../../../../_internal/wallet/useWallet', () => ({
51
+ useWallet: () => ({
52
+ wallet: mockWallet,
53
+ }),
54
+ }));
55
+
56
+ // Mock switch chain modal hook
57
+ vi.mock('../../_internal/components/switchChainModal', () => ({
58
+ useSwitchChainModal: () => ({
59
+ show: vi.fn(),
60
+ }),
61
+ }));
62
+
63
+ // Mock getProviderEl and MarketplaceKind
64
+ vi.mock('../../../../../_internal', () => {
65
+ const actual = vi.importActual('../../../../../_internal');
66
+ return {
67
+ ...actual,
68
+ getProviderEl: () => document.body,
69
+ MarketplaceKind: {
70
+ unknown: 'unknown',
71
+ sequence_marketplace_v1: 'sequence_marketplace_v1',
72
+ sequence_marketplace_v2: 'sequence_marketplace_v2',
73
+ blur: 'blur',
74
+ zerox: 'zerox',
75
+ opensea: 'opensea',
76
+ looks_rare: 'looks_rare',
77
+ x2y2: 'x2y2',
78
+ alienswap: 'alienswap',
79
+ payment_processor: 'payment_processor',
80
+ mintify: 'mintify',
81
+ },
82
+ };
83
+ });
16
84
 
17
85
  describe('ERC1155QuantityModal', () => {
18
- const mockOrder = {
19
- orderId: '1',
86
+ // Customize the mock order for ERC1155 testing with specific price for predictable calculations
87
+ const mockOrder: Order = {
88
+ ...baseMockOrder,
20
89
  priceAmount: '1000000000000000000', // 1 ETH in wei
21
- priceCurrencyAddress: '0x0',
90
+ priceAmountFormatted: '1',
22
91
  quantityRemaining: '10',
92
+ quantityRemainingFormatted: '10',
93
+ quantityAvailable: '10',
94
+ quantityAvailableFormatted: '10',
23
95
  quantityDecimals: 0,
24
- chainId: 1,
25
- marketplace: MarketplaceKind.sequence_marketplace_v2,
26
- createdAt: new Date().toISOString(),
27
- quantityAvailableFormatted: '1',
28
- } as Order;
29
-
30
- const mockCollectable: TokenMetadata = {
31
- decimals: 0,
32
- tokenId: '1',
33
- name: 'Test Token',
34
- description: 'Test Description',
35
- image: 'https://example.com/image.png',
36
- attributes: [],
37
96
  };
38
97
 
98
+ const mockCollectable: TokenMetadata = mockTokenMetadata;
99
+
39
100
  const mockBuy = vi.fn();
40
101
 
41
102
  beforeEach(() => {
@@ -46,7 +107,11 @@ describe('ERC1155QuantityModal', () => {
46
107
  buyModal$.state.checkoutModalLoaded.set(false);
47
108
  buyModal$.state.checkoutModalIsLoading.set(false);
48
109
  buyModal$.state.invalidQuantity.set(false);
49
- buyModal$.state.quantity.set('1');
110
+ buyModal$.state.quantity.set('10'); // Match the initial quantity with the mock order
111
+
112
+ // Reset mock wallet calls
113
+ getChainIdMock.mockClear();
114
+ switchChainMock.mockClear();
50
115
  });
51
116
 
52
117
  afterEach(() => {
@@ -84,28 +149,29 @@ describe('ERC1155QuantityModal', () => {
84
149
  name: /enter quantity/i,
85
150
  });
86
151
  expect(quantityInput).toBeInTheDocument();
87
- expect(quantityInput).toHaveValue('1');
152
+ expect(quantityInput).toHaveValue('10'); // Match the initial quantity
153
+
154
+ // Wait for price to be displayed
155
+ await waitFor(() => {
156
+ const priceLabels = screen.getAllByText('Total Price');
157
+ const priceContainer = priceLabels[0].parentElement;
158
+ if (!priceContainer) throw new Error('Price container not found');
88
159
 
89
- // Verify total price calculation (1 ETH)
90
- const priceLabels = screen.getAllByText('Total Price');
91
- const priceContainer = priceLabels[0].parentElement;
92
- if (!priceContainer) throw new Error('Price container not found');
93
- expect(within(priceContainer).getByText('1')).toBeInTheDocument();
94
- expect(within(priceContainer).getByText('ETH')).toBeInTheDocument();
160
+ // Check for the price without decimal
161
+ const priceElement = within(priceContainer).getByText('10');
162
+ expect(priceElement).toBeInTheDocument();
163
+ expect(within(priceContainer).getByText('ETH')).toBeInTheDocument();
164
+ });
95
165
 
96
166
  // Verify buy button
97
167
  const buyButton = screen.getByRole('button', { name: /buy now/i });
98
168
  expect(buyButton).toBeInTheDocument();
99
169
  expect(buyButton).not.toBeDisabled();
100
170
 
101
- // Verify token image
102
- const tokenImage = screen.getByRole('img', { name: '' });
103
- expect(tokenImage).toBeInTheDocument();
104
- expect(tokenImage).toHaveAttribute('src', 'https://example.com/eth.png');
105
-
106
- // Ensure loading state is false and button is enabled before clicking
107
- buyModal$.state.checkoutModalIsLoading.set(false);
108
- buyModal$.state.invalidQuantity.set(false);
171
+ // Verify currency image (not NFT image)
172
+ const currencyImage = screen.getByRole('img', { name: '' });
173
+ expect(currencyImage).toBeInTheDocument();
174
+ expect(currencyImage).toHaveAttribute('src', mockCurrencies[0].imageUrl);
109
175
  });
110
176
 
111
177
  it('should update total price when quantity changes', async () => {
@@ -137,13 +203,15 @@ describe('ERC1155QuantityModal', () => {
137
203
  fireEvent.change(quantityInput, { target: { value: '2' } });
138
204
  });
139
205
 
140
- // Verify total price updates to 2 ETH
141
- const priceLabels = screen.getAllByText('Total Price');
142
- const priceContainer = priceLabels[0].parentElement;
143
- if (!priceContainer) throw new Error('Price container not found');
144
-
206
+ // Wait for updated price to be displayed
145
207
  await waitFor(() => {
146
- expect(within(priceContainer).getByText('2')).toBeInTheDocument();
208
+ const priceLabels = screen.getAllByText('Total Price');
209
+ const priceContainer = priceLabels[0].parentElement;
210
+ if (!priceContainer) throw new Error('Price container not found');
211
+
212
+ // Check for the price without decimal
213
+ const priceElement = within(priceContainer).getByText('2');
214
+ expect(priceElement).toBeInTheDocument();
147
215
  });
148
216
  });
149
217
 
@@ -213,13 +281,15 @@ describe('ERC1155QuantityModal', () => {
213
281
  expect(screen.getAllByText('Total Price')[0]).toBeInTheDocument();
214
282
  });
215
283
 
216
- // Verify initial total price (1 ETH)
217
- const priceLabels = screen.getAllByText('Total Price');
218
- const priceContainer = priceLabels[0].parentElement;
219
- if (!priceContainer) throw new Error('Price container not found');
220
-
284
+ // Wait for initial price
221
285
  await waitFor(() => {
222
- expect(within(priceContainer).getByText('1')).toBeInTheDocument();
286
+ const priceLabels = screen.getAllByText('Total Price');
287
+ const priceContainer = priceLabels[0].parentElement;
288
+ if (!priceContainer) throw new Error('Price container not found');
289
+
290
+ // Check for the price without decimal
291
+ const priceElement = within(priceContainer).getByText('10');
292
+ expect(priceElement).toBeInTheDocument();
223
293
  expect(within(priceContainer).getByText('ETH')).toBeInTheDocument();
224
294
  });
225
295
 
@@ -231,13 +301,52 @@ describe('ERC1155QuantityModal', () => {
231
301
  fireEvent.change(quantityInput, { target: { value: '3' } });
232
302
  });
233
303
 
234
- // Verify total price updates to 3 ETH
304
+ // Wait for updated price
235
305
  await waitFor(() => {
236
- expect(within(priceContainer).getByText('3')).toBeInTheDocument();
306
+ const priceLabels = screen.getAllByText('Total Price');
307
+ const priceContainer = priceLabels[0].parentElement;
308
+ if (!priceContainer) throw new Error('Price container not found');
309
+
310
+ // Check for the price without decimal
311
+ const priceElement = within(priceContainer).getByText('3');
312
+ expect(priceElement).toBeInTheDocument();
237
313
  });
314
+ });
315
+
316
+ it('should handle chain mismatch correctly', async () => {
317
+ // Mock wallet to return a different chain ID
318
+ getChainIdMock.mockResolvedValueOnce(2); // Different from order.chainId (1)
238
319
 
239
- // Verify modal is in a valid state
240
- expect(buyModal$.state.checkoutModalIsLoading.get()).toBe(false);
241
- expect(buyModal$.state.invalidQuantity.get()).toBe(false);
320
+ buyModal$.open({
321
+ order: mockOrder,
322
+ callbacks: {},
323
+ chainId: '1',
324
+ collectionAddress: '0x123',
325
+ tokenId: '1',
326
+ });
327
+
328
+ render(
329
+ <ERC1155QuantityModal
330
+ buy={mockBuy}
331
+ collectable={mockCollectable}
332
+ order={mockOrder}
333
+ chainId="1"
334
+ collectionAddress="0x123"
335
+ collectibleId="1"
336
+ />,
337
+ );
338
+
339
+ const buyButton = screen.getByRole('button', { name: /buy now/i });
340
+
341
+ // Click buy button
342
+ fireEvent.click(buyButton);
343
+
344
+ // Verify chain switch was attempted
345
+ await waitFor(() => {
346
+ expect(getChainIdMock).toHaveBeenCalled();
347
+ });
348
+
349
+ // Verify buy function was not called
350
+ expect(mockBuy).not.toHaveBeenCalled();
242
351
  });
243
352
  });
@@ -9,6 +9,7 @@ const buyState = {
9
9
  invalidQuantity: false,
10
10
  checkoutModalIsLoading: false,
11
11
  checkoutModalLoaded: false,
12
+ purchaseProcessing: false,
12
13
  } as const;
13
14
 
14
15
  export interface BuyModalState {
@@ -26,9 +27,11 @@ export interface BuyModalState {
26
27
  invalidQuantity: boolean;
27
28
  checkoutModalIsLoading: boolean;
28
29
  checkoutModalLoaded: boolean;
30
+ purchaseProcessing: boolean;
29
31
  };
30
32
  setCheckoutModalIsLoading: (isLoading: boolean) => void;
31
33
  setCheckoutModalLoaded: (isLoaded: boolean) => void;
34
+ setPurchaseProcessing: (isProcessing: boolean) => void;
32
35
  callbacks?: ModalCallbacks;
33
36
  }
34
37
 
@@ -48,6 +51,7 @@ export const initialState: BuyModalState = {
48
51
  invalidQuantity: false,
49
52
  checkoutModalIsLoading: false,
50
53
  checkoutModalLoaded: false,
54
+ purchaseProcessing: false,
51
55
  });
52
56
  buyModal$.callbacks.set(callbacks || defaultCallbacks);
53
57
  buyModal$.isOpen.set(true);
@@ -64,6 +68,9 @@ export const initialState: BuyModalState = {
64
68
  setCheckoutModalLoaded: (isLoaded: boolean) => {
65
69
  buyModal$.state.checkoutModalLoaded.set(isLoaded);
66
70
  },
71
+ setPurchaseProcessing: (isProcessing: boolean) => {
72
+ buyModal$.state.purchaseProcessing.set(isProcessing);
73
+ },
67
74
  callbacks: undefined,
68
75
  };
69
76
 
@@ -8,7 +8,6 @@ import {
8
8
  useCollectible,
9
9
  useCollection,
10
10
  useCurrencies,
11
- useCurrencyOptions,
12
11
  } from '../../../hooks';
13
12
  import {
14
13
  ActionModal,
@@ -51,14 +50,13 @@ const Modal = observer(() => {
51
50
  collectionAddress,
52
51
  collectibleId,
53
52
  });
54
- const currencyOptions = useCurrencyOptions({ collectionAddress });
55
53
  const {
56
54
  data: currencies,
57
55
  isLoading: currenciesLoading,
58
56
  isError: currenciesIsError,
59
57
  } = useCurrencies({
60
58
  chainId,
61
- currencyOptions,
59
+ collectionAddress,
62
60
  includeNativeCurrency: true,
63
61
  });
64
62
  const {
@@ -1,4 +1,3 @@
1
- import '@testing-library/jest-dom/vitest';
2
1
  import {
3
2
  render,
4
3
  screen,
@@ -9,104 +8,40 @@ import {
9
8
  import { describe, it, expect, vi, beforeEach } from 'vitest';
10
9
  import { CreateListingModal } from '../Modal';
11
10
  import { createListingModal$ } from '../store';
12
- import {
13
- useCollectible,
14
- useCollection,
15
- useBalanceOfCollectible,
16
- useCurrencies,
17
- useCurrencyOptions,
18
- } from '../../../../hooks';
19
- import { useCreateListing } from '../hooks/useCreateListing';
20
- import { useWallet } from '../../../../_internal/wallet/useWallet';
21
-
22
- // Mock the hooks
23
- vi.mock('../../../../hooks', () => ({
24
- useCollectible: vi.fn(),
25
- useCollection: vi.fn(),
26
- useBalanceOfCollectible: vi.fn(),
27
- useCurrencies: vi.fn().mockReturnValue({
28
- data: [],
29
- isLoading: false,
30
- isError: false,
31
- }),
32
- useCurrencyOptions: vi.fn().mockReturnValue({
33
- data: ['0x123'],
34
- isLoading: false,
35
- isError: false,
36
- }),
37
- useMarketplaceConfig: vi.fn().mockReturnValue({
38
- data: {
39
- collections: [
40
- {
41
- collectionAddress: '0x123',
42
- marketplaceFeePercentage: 2.5,
43
- },
44
- ],
45
- },
46
- isLoading: false,
47
- isError: false,
48
- }),
49
- useRoyaltyPercentage: vi.fn().mockReturnValue({
50
- data: 0n,
51
- isLoading: false,
52
- isError: false,
53
- }),
54
- useLowestListing: vi.fn().mockReturnValue({
55
- data: null,
56
- isLoading: false,
57
- isError: false,
58
- }),
59
- }));
60
-
61
- vi.mock('../../../../_internal/wallet/useWallet', () => ({
62
- useWallet: vi.fn(),
63
- }));
64
-
65
- vi.mock('../hooks/useCreateListing', () => ({
66
- useCreateListing: vi.fn(),
67
- }));
11
+ import * as hooks from '../../../../hooks';
12
+ import { zeroAddress } from 'viem';
13
+ import { useWaasFeeOptions } from '@0xsequence/kit';
14
+
15
+ vi.mock(import('../../../../hooks'), async (importOriginal) => {
16
+ const actual = await importOriginal();
17
+ return {
18
+ ...actual,
19
+ useCollectible: vi.fn(actual.useCollectible),
20
+ useCollection: vi.fn(actual.useCollection),
21
+ useCurrencies: vi.fn(actual.useCurrencies),
22
+ useMarketplaceConfig: vi.fn(actual.useMarketplaceConfig),
23
+ useLowestListing: vi.fn(actual.useLowestListing),
24
+ };
25
+ });
68
26
 
69
27
  vi.mock('@0xsequence/kit', () => ({
70
- useWaasFeeOptions: vi.fn().mockReturnValue([false, vi.fn()]),
28
+ useWaasFeeOptions: vi.fn(),
71
29
  }));
72
30
 
31
+ const defaultArgs = {
32
+ collectionAddress: zeroAddress,
33
+ chainId: '1',
34
+ collectibleId: '1',
35
+ };
36
+
73
37
  describe('CreateListingModal', () => {
74
38
  beforeEach(() => {
75
39
  cleanup();
76
40
  // Reset all mocks
77
41
  vi.clearAllMocks();
78
-
79
- // Setup default mock values
80
- (useWallet as any).mockReturnValue({
81
- wallet: {
82
- address: () => Promise.resolve('0x123'),
83
- },
84
- isLoading: false,
85
- isError: false,
86
- });
87
-
88
- (useCollectible as any).mockReturnValue({
89
- data: { decimals: 18, name: 'Test NFT' },
90
- isLoading: false,
91
- isError: false,
92
- });
93
-
94
- (useCollection as any).mockReturnValue({
95
- data: { type: 'ERC721', name: 'Test Collection' },
96
- isLoading: false,
97
- isError: false,
98
- });
99
-
100
- (useBalanceOfCollectible as any).mockReturnValue({
101
- data: { balance: '1' },
102
- });
103
-
104
- (useCreateListing as any).mockReturnValue({
105
- isLoading: false,
106
- executeApproval: vi.fn(),
107
- createListing: vi.fn(),
108
- tokenApprovalIsLoading: false,
109
- });
42
+ vi.resetAllMocks();
43
+ // @ts-expect-error - Mock this differently
44
+ vi.mocked(useWaasFeeOptions).mockReturnValue([]);
110
45
  });
111
46
 
112
47
  it('should not render when modal is closed', () => {
@@ -114,50 +49,42 @@ describe('CreateListingModal', () => {
114
49
  expect(screen.queryByText('List item for sale')).toBeNull();
115
50
  });
116
51
 
117
- it('should render main form when data is loaded', () => {
118
- // Mock successful states for all required hooks
119
- (useCollectible as any).mockReturnValue({
120
- data: { decimals: 18, name: 'Test NFT' },
121
- isLoading: false,
122
- isError: false,
123
- });
124
- (useCollection as any).mockReturnValue({
125
- data: { type: 'ERC721', name: 'Test Collection' },
126
- isLoading: false,
127
- isError: false,
128
- });
129
- (useCurrencyOptions as any).mockReturnValue({
130
- data: ['0x123'],
131
- isLoading: false,
132
- isError: false,
133
- });
134
- (useCurrencies as any).mockReturnValue({
135
- data: [{ address: '0x123', symbol: 'TEST', decimals: 18 }],
52
+ it('should show loading modal when data is being fetched', () => {
53
+ createListingModal$.open(defaultArgs);
54
+
55
+ render(<CreateListingModal />);
56
+
57
+ expect(screen.getByTestId('loading-modal')).toBeInTheDocument();
58
+ });
59
+
60
+ it('should show error modal when there is an error fetching data', async () => {
61
+ // @ts-expect-error - TODO: Add a common mock object with the correct shape
62
+ vi.mocked(hooks.useCollection).mockReturnValue({
63
+ data: undefined,
136
64
  isLoading: false,
137
- isError: false,
65
+ isError: true,
138
66
  });
139
67
 
140
- createListingModal$.open({
141
- collectionAddress: '0x123',
142
- chainId: '1',
143
- collectibleId: '1',
144
- });
68
+ createListingModal$.open(defaultArgs);
69
+
70
+ render(<CreateListingModal />);
71
+
72
+ expect(
73
+ await screen.findByText('Error loading item details'),
74
+ ).toBeInTheDocument();
75
+ });
145
76
 
77
+ it('should render main form when data is loaded', async () => {
78
+ createListingModal$.open(defaultArgs);
146
79
  render(<CreateListingModal />);
147
80
 
148
- // Check for the modal title using a more specific selector
149
- expect(screen.getByRole('dialog')).toBeInTheDocument();
150
81
  // Check for the collection name in the token preview
151
- expect(screen.getByText('Test Collection')).toBeInTheDocument();
82
+ expect(await screen.findByText('Mock Collection')).toBeInTheDocument();
152
83
  });
153
84
 
154
85
  it('should reset store values when modal is closed and reopened', () => {
155
86
  // Open modal first time
156
- createListingModal$.open({
157
- collectionAddress: '0x123',
158
- chainId: '1',
159
- collectibleId: '1',
160
- });
87
+ createListingModal$.open(defaultArgs);
161
88
 
162
89
  // Set some values in the store
163
90
  createListingModal$.listingPrice.amountRaw.set('1000000000000000000');
@@ -183,33 +110,7 @@ describe('CreateListingModal', () => {
183
110
  });
184
111
 
185
112
  it('should update state based on price input', async () => {
186
- // Mock successful states for all required hooks
187
- (useCollectible as any).mockReturnValue({
188
- data: { decimals: 18, name: 'Test NFT' },
189
- isLoading: false,
190
- isError: false,
191
- });
192
- (useCollection as any).mockReturnValue({
193
- data: { type: 'ERC721', name: 'Test Collection' },
194
- isLoading: false,
195
- isError: false,
196
- });
197
- (useCurrencyOptions as any).mockReturnValue({
198
- data: ['0x123'],
199
- isLoading: false,
200
- isError: false,
201
- });
202
- (useCurrencies as any).mockReturnValue({
203
- data: [{ address: '0x123', symbol: 'TEST', decimals: 18 }],
204
- isLoading: false,
205
- isError: false,
206
- });
207
-
208
- createListingModal$.open({
209
- collectionAddress: '0x123',
210
- chainId: '1',
211
- collectibleId: '1',
212
- });
113
+ createListingModal$.open(defaultArgs);
213
114
 
214
115
  render(<CreateListingModal />);
215
116
 
@@ -217,7 +118,9 @@ describe('CreateListingModal', () => {
217
118
  expect(createListingModal$.listingPrice.amountRaw.get()).toBe('0');
218
119
 
219
120
  // Find and interact with price input using id
220
- const priceInput = screen.getByRole('textbox', { name: /enter price/i });
121
+ const priceInput = await screen.findByRole('textbox', {
122
+ name: /enter price/i,
123
+ });
221
124
  expect(priceInput).toBeInTheDocument();
222
125
 
223
126
  fireEvent.change(priceInput, { target: { value: '1.5' } });
@@ -228,91 +131,20 @@ describe('CreateListingModal', () => {
228
131
  });
229
132
  });
230
133
 
231
- it('should show loading modal when data is being fetched', () => {
232
- // Mock loading states for all required hooks
233
- (useCollectible as any).mockReturnValue({
234
- isLoading: true,
235
- isError: false,
236
- });
237
- (useCollection as any).mockReturnValue({
238
- isLoading: true,
239
- isError: false,
240
- });
241
- (useCurrencyOptions as any).mockReturnValue({
242
- isLoading: true,
243
- isError: false,
244
- });
245
-
246
- createListingModal$.open({
247
- collectionAddress: '0x123',
248
- chainId: '1',
249
- collectibleId: '1',
250
- });
251
-
252
- render(<CreateListingModal />);
253
-
254
- expect(screen.getByTestId('loading-modal')).toBeInTheDocument();
255
- });
256
-
257
- it('should show error modal when there is an error fetching data', () => {
258
- // Mock error states for required hooks
259
- (useCollectible as any).mockReturnValue({
260
- isLoading: false,
261
- isError: true,
262
- });
263
- (useCollection as any).mockReturnValue({
264
- isLoading: false,
265
- isError: false,
266
- });
267
- (useCurrencyOptions as any).mockReturnValue({
268
- isLoading: false,
269
- isError: false,
270
- });
271
-
272
- createListingModal$.open({
273
- collectionAddress: '0x123',
274
- chainId: '1',
275
- collectibleId: '1',
276
- });
277
-
278
- render(<CreateListingModal />);
279
-
280
- expect(screen.getByText('Error loading item details')).toBeInTheDocument();
281
- });
282
-
283
- it('should show no ERC20 configured modal when currencies array is empty', () => {
284
- // Reset all hooks to success state
285
- (useCollectible as any).mockReturnValue({
286
- data: { decimals: 18, name: 'Test NFT' },
287
- isLoading: false,
288
- isError: false,
289
- });
290
- (useCollection as any).mockReturnValue({
291
- data: { type: 'ERC721', name: 'Test Collection' },
292
- isLoading: false,
293
- isError: false,
294
- });
295
- (useCurrencyOptions as any).mockReturnValue({
296
- data: [],
297
- isLoading: false,
298
- isError: false,
299
- });
300
- (useCurrencies as any).mockReturnValue({
134
+ it('should show no currencies configured modal when currencies array is empty', async () => {
135
+ // @ts-expect-error - Improve this mock
136
+ vi.mocked(hooks.useCurrencies).mockReturnValue({
301
137
  data: [],
302
138
  isLoading: false,
303
139
  isError: false,
304
140
  });
305
141
 
306
- createListingModal$.open({
307
- collectionAddress: '0x123',
308
- chainId: '1',
309
- collectibleId: '1',
310
- });
142
+ createListingModal$.open(defaultArgs);
311
143
 
312
144
  render(<CreateListingModal />);
313
145
 
314
146
  expect(
315
- screen.getByText(
147
+ await screen.findByText(
316
148
  'No currencies are configured for the marketplace, contact the marketplace owners',
317
149
  ),
318
150
  ).toBeInTheDocument();