@0xsequence/marketplace-sdk 0.5.2 → 0.5.4

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 (184) hide show
  1. package/dist/builder-types-Jl3Ymws8.d.ts +73 -0
  2. package/dist/{chunk-XP3WY5AX.js → chunk-7C7ADZ2H.js} +3 -3
  3. package/dist/{chunk-XP3WY5AX.js.map → chunk-7C7ADZ2H.js.map} +1 -1
  4. package/dist/{chunk-FCF57DZI.js → chunk-7FN62HOP.js} +5 -9
  5. package/dist/chunk-7FN62HOP.js.map +1 -0
  6. package/dist/chunk-DZKPDV63.js +27 -0
  7. package/dist/chunk-DZKPDV63.js.map +1 -0
  8. package/dist/{chunk-ZUEQGPLO.js → chunk-J6F5QOW5.js} +2 -2
  9. package/dist/{chunk-ZUEQGPLO.js.map → chunk-J6F5QOW5.js.map} +1 -1
  10. package/dist/{chunk-I37CRQ4S.js → chunk-JWNONWD6.js} +259 -173
  11. package/dist/chunk-JWNONWD6.js.map +1 -0
  12. package/dist/{chunk-LJAB3S6U.js → chunk-TFRAOS7F.js} +22 -13
  13. package/dist/chunk-TFRAOS7F.js.map +1 -0
  14. package/dist/{chunk-MKGSGTQC.js → chunk-TLNRD4BQ.js} +3 -3
  15. package/dist/{chunk-5NORRVPM.js → chunk-UZIAX32Y.js} +1 -1
  16. package/dist/{chunk-5NORRVPM.js.map → chunk-UZIAX32Y.js.map} +1 -1
  17. package/dist/chunk-WGGZEQHL.js +56 -0
  18. package/dist/chunk-WGGZEQHL.js.map +1 -0
  19. package/dist/{chunk-MWDG7UTB.js → chunk-ZBLU3Q22.js} +1 -1
  20. package/dist/{chunk-MSTTVFVQ.js → chunk-ZGVCOQ4I.js} +383 -283
  21. package/dist/chunk-ZGVCOQ4I.js.map +1 -0
  22. package/dist/{create-config-BXvwUh55.d.ts → create-config-DOUq8Day.d.ts} +2 -2
  23. package/dist/index.css +1 -1
  24. package/dist/index.d.ts +5 -4
  25. package/dist/index.js +10 -6
  26. package/dist/{sdk-config-B32_2bG3.d.ts → marketplace.gen-D0ADxbfH.d.ts} +1 -24
  27. package/dist/react/_internal/api/index.d.ts +3 -2
  28. package/dist/react/_internal/databeat/index.css +82 -0
  29. package/dist/react/_internal/databeat/index.css.map +1 -0
  30. package/dist/react/_internal/databeat/index.d.ts +68 -0
  31. package/dist/react/_internal/databeat/index.js +26 -0
  32. package/dist/react/_internal/databeat/index.js.map +1 -0
  33. package/dist/react/_internal/index.d.ts +6 -5
  34. package/dist/react/_internal/index.js +6 -6
  35. package/dist/react/_internal/wagmi/index.d.ts +4 -4
  36. package/dist/react/_internal/wagmi/index.js +1 -1
  37. package/dist/react/hooks/index.d.ts +367 -22
  38. package/dist/react/hooks/index.js +9 -7
  39. package/dist/react/index.css +1 -1
  40. package/dist/react/index.css.map +1 -1
  41. package/dist/react/index.d.ts +7 -6
  42. package/dist/react/index.js +15 -12
  43. package/dist/react/ssr/index.d.ts +54 -41
  44. package/dist/react/ssr/index.js +5 -9
  45. package/dist/react/ssr/index.js.map +1 -1
  46. package/dist/react/ui/components/collectible-card/index.css +1 -1
  47. package/dist/react/ui/components/collectible-card/index.css.map +1 -1
  48. package/dist/react/ui/components/collectible-card/index.d.ts +4 -3
  49. package/dist/react/ui/components/collectible-card/index.js +9 -8
  50. package/dist/react/ui/components/marketplace-logos/index.js +1 -1
  51. package/dist/react/ui/index.css +1 -1
  52. package/dist/react/ui/index.css.map +1 -1
  53. package/dist/react/ui/index.d.ts +4 -3
  54. package/dist/react/ui/index.js +9 -8
  55. package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +4 -3
  56. package/dist/react/ui/modals/_internal/components/actionModal/index.js +6 -6
  57. package/dist/react/ui/styles/index.d.ts +1 -1
  58. package/dist/sdk-config-xWkdBdrL.d.ts +24 -0
  59. package/dist/{services-BRBVE0mm.d.ts → services-Dd2MoBTM.d.ts} +2 -1
  60. package/dist/styles/index.css +1 -1
  61. package/dist/styles/index.css.map +1 -1
  62. package/dist/styles/index.d.ts +1 -1
  63. package/dist/styles/index.js +1 -1
  64. package/dist/types/index.d.ts +4 -5
  65. package/dist/types/index.js +9 -5
  66. package/dist/{types-Yto6KrTN.d.ts → types-vOfhbBkR.d.ts} +3 -2
  67. package/dist/utils/index.d.ts +4 -3
  68. package/dist/utils/index.js +4 -4
  69. package/package.json +12 -10
  70. package/src/react/_internal/api/__mocks__/indexer.msw.ts +197 -0
  71. package/src/react/_internal/api/__mocks__/marketplace.msw.ts +140 -1
  72. package/src/react/_internal/api/__mocks__/metadata.msw.ts +162 -0
  73. package/src/react/_internal/databeat/index.ts +63 -0
  74. package/src/react/_internal/databeat/types.ts +70 -0
  75. package/src/react/_internal/test/mocks/publicClient.ts +39 -0
  76. package/src/react/_internal/test/mocks/wagmi.ts +61 -0
  77. package/src/react/_internal/test/mocks/wallet.ts +61 -0
  78. package/src/react/_internal/test/setup.ts +28 -0
  79. package/src/react/_internal/test-utils.tsx +31 -2
  80. package/src/react/_internal/wagmi/__tests__/create-config.test.ts +53 -20
  81. package/src/react/_internal/wagmi/create-config.ts +3 -4
  82. package/src/react/_internal/wagmi/embedded.ts +1 -4
  83. package/src/react/_internal/wagmi/universal.ts +1 -4
  84. package/src/react/_internal/wallet/wallet.ts +1 -0
  85. package/src/react/hooks/__tests__/useAutoSelectFeeOption.test.tsx +314 -0
  86. package/src/react/hooks/__tests__/useBalanceOfCollectible.test.tsx +148 -0
  87. package/src/react/hooks/__tests__/useCancelOrder.test.tsx +410 -0
  88. package/src/react/hooks/__tests__/useCancelTransactionSteps.test.tsx +269 -0
  89. package/src/react/hooks/__tests__/useCollectible.test.tsx +120 -0
  90. package/src/react/hooks/__tests__/useCollection.test.tsx +101 -0
  91. package/src/react/hooks/__tests__/useCollectionBalanceDetails.test.tsx +175 -0
  92. package/src/react/hooks/__tests__/useCollectionDetails.test.tsx +82 -0
  93. package/src/react/hooks/__tests__/useCollectionDetailsPolling.test.tsx +133 -0
  94. package/src/react/hooks/__tests__/useCountListingsForCollectible.test.tsx +108 -0
  95. package/src/react/hooks/__tests__/useCountOfCollectables.test.tsx +129 -0
  96. package/src/react/hooks/__tests__/useCountOffersForCollectible.test.tsx +108 -0
  97. package/src/react/hooks/__tests__/useCurrencies.test.tsx +176 -0
  98. package/src/react/hooks/__tests__/useCurrency.test.tsx +153 -0
  99. package/src/react/hooks/__tests__/useCurrencyBalance.test.tsx +111 -0
  100. package/src/react/hooks/__tests__/useFilters.test.tsx +127 -0
  101. package/src/react/hooks/__tests__/useFloorOrder.test.tsx +101 -0
  102. package/src/react/hooks/__tests__/useGenerateBuyTransaction.test.tsx +173 -0
  103. package/src/react/hooks/__tests__/useGenerateCancelTransaction.test.tsx +207 -0
  104. package/src/react/hooks/__tests__/useGenerateListingTransaction.test.tsx +207 -0
  105. package/src/react/hooks/__tests__/useGenerateOfferTransaction.test.tsx +205 -0
  106. package/src/react/hooks/__tests__/useGenerateSellTransaction.test.tsx +181 -0
  107. package/src/react/hooks/__tests__/useHighestOffer.test.tsx +118 -0
  108. package/src/react/hooks/__tests__/useListBalances.test.tsx +136 -0
  109. package/src/react/hooks/__tests__/useListCollectibleActivities.test.tsx +200 -0
  110. package/src/react/hooks/__tests__/useListCollectibles.test.tsx +232 -0
  111. package/src/react/hooks/__tests__/useListCollectiblesPaginated.test.tsx +217 -0
  112. package/src/react/hooks/__tests__/useListCollectionActivities.test.tsx +235 -0
  113. package/src/react/hooks/__tests__/useListCollections.test.tsx +296 -0
  114. package/src/react/hooks/__tests__/useListListingsForCollectible.test.tsx +140 -0
  115. package/src/react/hooks/__tests__/useListOffersForCollectible.test.tsx +140 -0
  116. package/src/react/hooks/__tests__/useLowestListing.test.tsx +148 -0
  117. package/src/react/hooks/__tests__/useMarketplaceConfig.test.tsx +106 -0
  118. package/src/react/hooks/__tests__/useRoyaltyPercentage.test.tsx +129 -0
  119. package/src/react/hooks/index.ts +1 -1
  120. package/src/react/hooks/options/__mocks__/marketplaceConfig.msw.ts +66 -10
  121. package/src/react/hooks/options/__tests__/marketplaceConfigOptions.test.tsx +2 -11
  122. package/src/react/hooks/options/marketplaceConfigOptions.ts +8 -3
  123. package/src/react/hooks/useAutoSelectFeeOption.tsx +4 -3
  124. package/src/react/hooks/useCancelTransactionSteps.tsx +17 -9
  125. package/src/react/hooks/useCollectionDetailsPolling.tsx +1 -1
  126. package/src/react/hooks/useCurrencies.tsx +29 -28
  127. package/src/react/hooks/useFilters.tsx +75 -2
  128. package/src/react/hooks/useGenerateBuyTransaction.tsx +13 -5
  129. package/src/react/hooks/useListCollectibleActivities.tsx +1 -0
  130. package/src/react/hooks/useListCollectibles.tsx +1 -0
  131. package/src/react/hooks/useListCollectiblesPaginated.tsx +78 -0
  132. package/src/react/hooks/useListCollectionActivities.tsx +1 -0
  133. package/src/react/hooks/useListCollections.tsx +2 -2
  134. package/src/react/ui/components/_internals/custom-select/__tests__/CustomSelect.test.tsx +6 -2
  135. package/src/react/ui/components/collectible-card/CollectibleCard.tsx +1 -1
  136. package/src/react/ui/components/collectible-card/Footer.tsx +9 -5
  137. package/src/react/ui/modals/BuyModal/Modal.tsx +9 -4
  138. package/src/react/ui/modals/BuyModal/__tests__/Modal.test.tsx +0 -1
  139. package/src/react/ui/modals/BuyModal/__tests__/store.test.ts +4 -2
  140. package/src/react/ui/modals/BuyModal/hooks/__tests__/useBuyCollectable.test.tsx +1 -24
  141. package/src/react/ui/modals/BuyModal/hooks/__tests__/useCheckoutOptions.test.tsx +152 -210
  142. package/src/react/ui/modals/BuyModal/hooks/__tests__/useFees.test.tsx +19 -49
  143. package/src/react/ui/modals/BuyModal/hooks/useFees.ts +6 -6
  144. package/src/react/ui/modals/BuyModal/modals/Modal1155.tsx +4 -2
  145. package/src/react/ui/modals/BuyModal/modals/__tests__/Modal1155.test.tsx +161 -52
  146. package/src/react/ui/modals/BuyModal/store.ts +7 -0
  147. package/src/react/ui/modals/CreateListingModal/Modal.tsx +1 -3
  148. package/src/react/ui/modals/CreateListingModal/__tests__/Modal.test.tsx +59 -227
  149. package/src/react/ui/modals/CreateListingModal/hooks/useCreateListing.tsx +2 -1
  150. package/src/react/ui/modals/CreateListingModal/hooks/useTransactionSteps.tsx +47 -7
  151. package/src/react/ui/modals/MakeOfferModal/Modal.tsx +1 -8
  152. package/src/react/ui/modals/MakeOfferModal/__tests__/Modal.test.tsx +41 -118
  153. package/src/react/ui/modals/MakeOfferModal/hooks/useMakeOffer.tsx +2 -1
  154. package/src/react/ui/modals/MakeOfferModal/hooks/useTransactionSteps.tsx +34 -6
  155. package/src/react/ui/modals/SellModal/Modal.tsx +3 -1
  156. package/src/react/ui/modals/SellModal/__tests__/Modal.test.tsx +4 -3
  157. package/src/react/ui/modals/SellModal/hooks/useGetTokenApproval.tsx +33 -31
  158. package/src/react/ui/modals/SellModal/hooks/useSell.tsx +11 -7
  159. package/src/react/ui/modals/SellModal/hooks/useTransactionSteps.tsx +58 -16
  160. package/src/react/ui/modals/SuccessfulPurchaseModal/__tests__/Modal.test.tsx +0 -1
  161. package/src/react/ui/modals/_internal/components/actionModal/ErrorModal.tsx +4 -2
  162. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/__tests__/index.test.tsx +129 -57
  163. package/src/react/ui/modals/_internal/components/currencyOptionsSelect/index.tsx +1 -3
  164. package/src/react/ui/modals/_internal/components/priceInput/__tests__/index.test.tsx +1 -3
  165. package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +2 -2
  166. package/src/react/ui/modals/_internal/components/transactionStatusModal/__tests__/TransactionStatusModal.test.tsx +8 -8
  167. package/src/react/ui/modals/_internal/components/transactionStatusModal/hooks/useTransactionStatus.ts +1 -0
  168. package/src/types/builder-types.ts +79 -0
  169. package/src/types/index.ts +1 -1
  170. package/src/utils/__tests__/get-public-rpc-client.test.ts +2 -0
  171. package/src/utils/getMarketplaceDetails.ts +2 -2
  172. package/tsconfig.tsbuildinfo +1 -1
  173. package/vitest.config.js +2 -1
  174. package/dist/chunk-FCF57DZI.js.map +0 -1
  175. package/dist/chunk-I37CRQ4S.js.map +0 -1
  176. package/dist/chunk-LJAB3S6U.js.map +0 -1
  177. package/dist/chunk-MSTTVFVQ.js.map +0 -1
  178. package/dist/chunk-RK6KYMZM.js +0 -18
  179. package/dist/chunk-RK6KYMZM.js.map +0 -1
  180. package/dist/marketplace-config-znEu4L0K.d.ts +0 -60
  181. package/src/react/hooks/useCurrencyOptions.tsx +0 -16
  182. package/src/types/marketplace-config.ts +0 -67
  183. /package/dist/{chunk-MKGSGTQC.js.map → chunk-TLNRD4BQ.js.map} +0 -0
  184. /package/dist/{chunk-MWDG7UTB.js.map → chunk-ZBLU3Q22.js.map} +0 -0
@@ -0,0 +1,148 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { useLowestListing } from '../useLowestListing';
3
+ import { renderHook, waitFor } from '../../_internal/test-utils';
4
+ import { zeroAddress } from 'viem';
5
+ import { MarketplaceKind } from '../../_internal/api/marketplace.gen';
6
+ import { http, HttpResponse } from 'msw';
7
+ import {
8
+ mockOrder,
9
+ mockMarketplaceEndpoint,
10
+ } from '../../_internal/api/__mocks__/marketplace.msw';
11
+ import { server } from '../../_internal/test/setup';
12
+
13
+ describe('useLowestListing', () => {
14
+ const defaultArgs = {
15
+ chainId: '1',
16
+ collectionAddress: zeroAddress as `0x${string}`,
17
+ tokenId: '1',
18
+ query: {},
19
+ };
20
+
21
+ it('should fetch lowest listing data successfully', async () => {
22
+ const { result } = renderHook(() => useLowestListing(defaultArgs));
23
+
24
+ // Initially loading
25
+ expect(result.current.isLoading).toBe(true);
26
+ expect(result.current.data).toBeUndefined();
27
+
28
+ // Wait for data to be loaded
29
+ await waitFor(() => {
30
+ expect(result.current.isLoading).toBe(false);
31
+ });
32
+
33
+ // Verify the data matches our mock
34
+ expect(result.current.data).toBeDefined();
35
+ expect(result.current.data?.order).toEqual(mockOrder);
36
+ expect(result.current.error).toBeNull();
37
+ });
38
+
39
+ it('should handle error states', async () => {
40
+ // Override the handler for this test to return an error
41
+ server.use(
42
+ http.post(mockMarketplaceEndpoint('GetCollectibleLowestListing'), () => {
43
+ return HttpResponse.json(
44
+ { error: { message: 'Failed to fetch lowest listing' } },
45
+ { status: 500 },
46
+ );
47
+ }),
48
+ );
49
+
50
+ const { result } = renderHook(() => useLowestListing(defaultArgs));
51
+
52
+ await waitFor(() => {
53
+ expect(result.current.isError).toBe(true);
54
+ });
55
+
56
+ expect(result.current.error).toBeDefined();
57
+ expect(result.current.data).toBeUndefined();
58
+ });
59
+
60
+ it('should refetch when args change', async () => {
61
+ const { result, rerender } = renderHook(() =>
62
+ useLowestListing(defaultArgs),
63
+ );
64
+
65
+ // Wait for initial data
66
+ await waitFor(() => {
67
+ expect(result.current.isLoading).toBe(false);
68
+ });
69
+
70
+ // Change args and rerender
71
+ const newArgs = {
72
+ ...defaultArgs,
73
+ collectionAddress:
74
+ '0x1234567890123456789012345678901234567890' as `0x${string}`,
75
+ tokenId: '2',
76
+ };
77
+
78
+ rerender(() => useLowestListing(newArgs));
79
+
80
+ // Wait for new data
81
+ await waitFor(() => {
82
+ expect(result.current.data).toBeDefined();
83
+ });
84
+
85
+ // Verify that the query was refetched with new args
86
+ expect(result.current.data?.order).toEqual(mockOrder);
87
+ expect(result.current.isSuccess).toBe(true);
88
+ });
89
+
90
+ it('should handle optional filter parameter', async () => {
91
+ const argsWithFilter = {
92
+ ...defaultArgs,
93
+ filters: {
94
+ marketplace: [
95
+ MarketplaceKind.sequence_marketplace_v2,
96
+ ] as MarketplaceKind[],
97
+ currencies: [zeroAddress] as string[],
98
+ },
99
+ };
100
+
101
+ const { result } = renderHook(() => useLowestListing(argsWithFilter));
102
+
103
+ await waitFor(() => {
104
+ expect(result.current.isLoading).toBe(false);
105
+ });
106
+
107
+ expect(result.current.data?.order).toEqual(mockOrder);
108
+ expect(result.current.isSuccess).toBe(true);
109
+ });
110
+
111
+ it('should handle query options', async () => {
112
+ const argsWithQuery = {
113
+ ...defaultArgs,
114
+ query: {
115
+ enabled: true,
116
+ staleTime: 5000,
117
+ cacheTime: 10000,
118
+ },
119
+ };
120
+
121
+ const { result } = renderHook(() => useLowestListing(argsWithQuery));
122
+
123
+ await waitFor(() => {
124
+ expect(result.current.isLoading).toBe(false);
125
+ });
126
+
127
+ expect(result.current.data?.order).toEqual(mockOrder);
128
+ expect(result.current.isSuccess).toBe(true);
129
+ });
130
+
131
+ it('should handle disabled query', async () => {
132
+ const argsWithDisabledQuery = {
133
+ ...defaultArgs,
134
+ query: {
135
+ enabled: false,
136
+ },
137
+ };
138
+
139
+ const { result } = renderHook(() =>
140
+ useLowestListing(argsWithDisabledQuery),
141
+ );
142
+
143
+ // Should not be loading since query is disabled
144
+ expect(result.current.isLoading).toBe(false);
145
+ expect(result.current.data).toBeUndefined();
146
+ expect(result.current.isSuccess).toBe(false);
147
+ });
148
+ });
@@ -0,0 +1,106 @@
1
+ import { describe, expect, it, beforeEach } from 'vitest';
2
+ import { useMarketplaceConfig } from '../useMarketplaceConfig';
3
+ import { renderHook, waitFor } from '../../_internal/test-utils';
4
+ import {
5
+ mockConfig,
6
+ mockStyles,
7
+ createConfigHandler,
8
+ createStylesHandler,
9
+ createErrorHandler,
10
+ createStylesErrorHandler,
11
+ } from '../options/__mocks__/marketplaceConfig.msw';
12
+ import { server } from '../../_internal/test/setup';
13
+
14
+ describe('useMarketplaceConfig', () => {
15
+ beforeEach(() => {
16
+ // Reset handlers before each test
17
+ server.resetHandlers();
18
+ // Set up default handlers
19
+ server.use(createConfigHandler(), createStylesHandler());
20
+ });
21
+
22
+ it('should fetch marketplace config and styles successfully', async () => {
23
+ const { result } = renderHook(() => useMarketplaceConfig());
24
+
25
+ // Initially loading
26
+ expect(result.current.isLoading).toBe(true);
27
+ expect(result.current.data).toBeUndefined();
28
+
29
+ // Wait for data to be loaded
30
+ await waitFor(() => {
31
+ expect(result.current.isLoading).toBe(false);
32
+ });
33
+
34
+ // Verify the data matches our mock
35
+ expect(result.current.data).toBeDefined();
36
+ expect(result.current.data).toEqual({
37
+ ...mockConfig,
38
+ cssString: mockStyles.replaceAll(/['"]/g, ''),
39
+ manifestUrl: expect.stringContaining('/manifest.json'),
40
+ });
41
+ expect(result.current.error).toBeNull();
42
+ });
43
+
44
+ it('should handle config fetch error', async () => {
45
+ // Override the handler for this test to return an error
46
+ server.use(createErrorHandler());
47
+
48
+ const { result } = renderHook(() => useMarketplaceConfig());
49
+
50
+ await waitFor(() => {
51
+ expect(result.current.isError).toBe(true);
52
+ });
53
+
54
+ expect(result.current.error).toBeDefined();
55
+ expect(result.current.data).toBeUndefined();
56
+ });
57
+
58
+ it('should handle styles fetch error', async () => {
59
+ // Override the handler for this test to return an error
60
+ server.use(createStylesErrorHandler(), createConfigHandler());
61
+
62
+ const { result } = renderHook(() => useMarketplaceConfig());
63
+
64
+ await waitFor(() => {
65
+ expect(result.current.data).toBeDefined();
66
+ });
67
+
68
+ // They just result in an empty cssString
69
+ expect(result.current.isError).toBe(false);
70
+ expect(result.current.data?.cssString).toBe('');
71
+ });
72
+
73
+ it('should handle both config and styles fetch errors', async () => {
74
+ // Override both handlers to return errors
75
+ server.use(createErrorHandler(), createStylesErrorHandler());
76
+
77
+ const { result } = renderHook(() => useMarketplaceConfig());
78
+
79
+ await waitFor(() => {
80
+ expect(result.current.isError).toBe(true);
81
+ });
82
+
83
+ expect(result.current.error).toBeDefined();
84
+ expect(result.current.data).toBeUndefined();
85
+ });
86
+
87
+ it('should cache the config data', async () => {
88
+ // First render to populate cache
89
+ const { result, rerender } = renderHook(() => useMarketplaceConfig());
90
+
91
+ await waitFor(() => {
92
+ expect(result.current.isLoading).toBe(false);
93
+ });
94
+
95
+ // Trigger a rerender
96
+ rerender();
97
+
98
+ // Should have data immediately from cache
99
+ expect(result.current.isLoading).toBe(false);
100
+ expect(result.current.data).toEqual({
101
+ ...mockConfig,
102
+ cssString: mockStyles.replaceAll(/['"]/g, ''),
103
+ manifestUrl: expect.stringContaining('/manifest.json'),
104
+ });
105
+ });
106
+ });
@@ -0,0 +1,129 @@
1
+ import { describe, expect, it, vi, beforeEach } from 'vitest';
2
+ import type { Mock } from 'vitest';
3
+ import { useRoyaltyPercentage } from '../useRoyaltyPercentage';
4
+ import { renderHook, waitFor } from '../../_internal/test-utils';
5
+ import {
6
+ createMockPublicClient,
7
+ type MockPublicClient,
8
+ } from '../../_internal/test/mocks/publicClient';
9
+ import { getPublicRpcClient } from '../../../utils/get-public-rpc-client';
10
+
11
+ // Mock the getPublicRpcClient
12
+ vi.mock('../../../utils/get-public-rpc-client');
13
+
14
+ describe('useRoyaltyPercentage', () => {
15
+ const mockAddress = '0x1234567890123456789012345678901234567890' as const;
16
+ const mockArgs = {
17
+ chainId: '1',
18
+ collectionAddress: mockAddress,
19
+ collectibleId: '1',
20
+ query: {},
21
+ };
22
+
23
+ const mockRoyaltyAmount = 500n; // 5% royalty
24
+
25
+ beforeEach(() => {
26
+ // Reset all mocks before each test
27
+ vi.resetAllMocks();
28
+
29
+ // Create a mock public client with custom royaltyInfo implementation
30
+ const mockPublicClient = createMockPublicClient({
31
+ readContract: vi.fn().mockImplementation(async ({ functionName }) => {
32
+ if (functionName === 'royaltyInfo') {
33
+ return [
34
+ mockAddress, // receiver address
35
+ mockRoyaltyAmount, // royalty amount
36
+ ];
37
+ }
38
+ return [0n, 0n];
39
+ }),
40
+ });
41
+
42
+ // Mock the getPublicRpcClient to return our mock client
43
+ (getPublicRpcClient as Mock).mockReturnValue(mockPublicClient);
44
+ });
45
+
46
+ it('should fetch royalty percentage successfully', async () => {
47
+ const { result } = renderHook(() => useRoyaltyPercentage(mockArgs));
48
+
49
+ // Initially loading
50
+ expect(result.current.isLoading).toBe(true);
51
+ expect(result.current.data).toBeUndefined();
52
+
53
+ // Wait for data to be loaded
54
+ await waitFor(() => {
55
+ expect(result.current.isLoading).toBe(false);
56
+ });
57
+
58
+ // Verify the data matches our mock
59
+ expect(result.current.data).toBeDefined();
60
+ expect(result.current.data).toBe(mockRoyaltyAmount);
61
+ expect(result.current.error).toBeNull();
62
+ });
63
+
64
+ it('should handle contract read error gracefully', async () => {
65
+ // Override the mock to simulate a contract read error
66
+ const mockPublicClient = createMockPublicClient({
67
+ readContract: vi
68
+ .fn()
69
+ .mockRejectedValue(new Error('Contract read failed')),
70
+ });
71
+ (getPublicRpcClient as Mock).mockReturnValue(mockPublicClient);
72
+
73
+ const { result } = renderHook(() => useRoyaltyPercentage(mockArgs));
74
+
75
+ await waitFor(() => {
76
+ expect(result.current.isLoading).toBe(false);
77
+ });
78
+
79
+ // Should return 0 as specified in the hook implementation
80
+ expect(result.current.data).toBe(0n);
81
+ expect(result.current.isError).toBe(false);
82
+ });
83
+
84
+ it('should validate input parameters', async () => {
85
+ // Using undefined as an invalid chain ID - this will fail Zod's string coercion
86
+ const invalidArgs = {
87
+ ...mockArgs,
88
+ chainId: undefined,
89
+ };
90
+
91
+ // @ts-expect-error - invalid args
92
+ const { result } = renderHook(() => useRoyaltyPercentage(invalidArgs));
93
+
94
+ // Wait for the query to complete
95
+ await waitFor(() => {
96
+ expect(result.current.isLoading).toBe(false);
97
+ });
98
+
99
+ // The query should fail with a validation error
100
+ expect(result.current.isError).toBe(true);
101
+ expect(result.current.error).toBeDefined();
102
+ });
103
+
104
+ it('should cache the royalty data', async () => {
105
+ const { result, rerender } = renderHook(() =>
106
+ useRoyaltyPercentage(mockArgs),
107
+ );
108
+
109
+ await waitFor(() => {
110
+ expect(result.current.isLoading).toBe(false);
111
+ });
112
+
113
+ const mockClient = getPublicRpcClient('1') as MockPublicClient;
114
+ const mockReadContract = mockClient.readContract as Mock;
115
+ // Record the number of calls to readContract
116
+ const initialCalls = mockReadContract.mock.calls.length;
117
+
118
+ // Trigger a rerender
119
+ rerender();
120
+
121
+ // Should have data immediately from cache
122
+ expect(result.current.isLoading).toBe(false);
123
+ expect(result.current.data).toBe(mockRoyaltyAmount);
124
+
125
+ // Verify no additional contract calls were made
126
+ const finalCalls = mockReadContract.mock.calls.length;
127
+ expect(finalCalls).toBe(initialCalls);
128
+ });
129
+ });
@@ -6,7 +6,6 @@ export * from './useCollection';
6
6
  export * from './useCollectionBalanceDetails';
7
7
  export * from './useConfig';
8
8
  export * from './useCurrencies';
9
- export * from './useCurrencyOptions';
10
9
  export * from './useCurrency';
11
10
  export * from './useFilters';
12
11
  export * from './useFloorOrder';
@@ -14,6 +13,7 @@ export * from './useHighestOffer';
14
13
  export * from './useListBalances';
15
14
  export * from './useListCollectibleActivities';
16
15
  export * from './useListCollectibles';
16
+ export * from './useListCollectiblesPaginated';
17
17
  export * from './useListCollectionActivities';
18
18
  export * from './useListOffersForCollectible';
19
19
  export * from './useCountOffersForCollectible';
@@ -1,30 +1,86 @@
1
1
  import { http, HttpResponse } from 'msw';
2
- import { WalletOptions, type MarketplaceConfig } from '../../../../types';
2
+ import {
3
+ MarketplaceType,
4
+ MarketplaceWallet,
5
+ OrderbookKind,
6
+ type MarketplaceConfig,
7
+ FilterCondition,
8
+ } from '../../../../types';
3
9
  import { mockCurrencies } from '../../../_internal/api/__mocks__/marketplace.msw';
10
+ import { zeroAddress } from 'viem';
4
11
 
5
12
  // Mock data
6
13
  export const mockConfig: MarketplaceConfig = {
7
- projectId: 123,
8
14
  publisherId: 'test-publisher',
9
15
  title: 'Test Marketplace',
10
16
  shortDescription: 'A test marketplace',
17
+ socials: {
18
+ twitter: 'https://twitter.com/test',
19
+ discord: 'https://discord.com/test',
20
+ instagram: 'https://instagram.com/test',
21
+ website: '',
22
+ tiktok: '',
23
+ youtube: '',
24
+ },
11
25
  faviconUrl: 'https://example.com/favicon.png',
12
26
  landingBannerUrl: 'https://example.com/banner.png',
13
27
  logoUrl: 'https://example.com/logo.png',
14
- titleTemplate: '%s | Test Marketplace',
15
- walletOptions: [WalletOptions.Sequence],
28
+ walletOptions: {
29
+ walletType: MarketplaceWallet.UNIVERSAL,
30
+ oidcIssuers: {},
31
+ connectors: ['coinbase', 'walletconnect'],
32
+ includeEIP6963Wallets: true,
33
+ },
16
34
  collections: [
17
35
  {
18
- collectionAddress: '0x1234567890123456789012345678901234567890',
36
+ address: zeroAddress,
19
37
  chainId: 1,
20
- marketplaceFeePercentage: 2.5,
21
- marketplaceType: 'orderbook',
38
+ marketplaceType: MarketplaceType.ORDERBOOK,
22
39
  currencyOptions: mockCurrencies.map((c) => c.contractAddress),
40
+ exchanges: [],
41
+ bannerUrl: '',
42
+ feePercentage: 3.5,
43
+ destinationMarketplace: OrderbookKind.sequence_marketplace_v2,
44
+ filterSettings: {
45
+ filterOrder: ['Type', 'Rarity'],
46
+ exclusions: [
47
+ {
48
+ key: 'Type',
49
+ condition: FilterCondition.SPECIFIC_VALUE,
50
+ value: 'Sample',
51
+ },
52
+ ],
53
+ },
54
+ },
55
+ {
56
+ address: '0x1234567890123456789012345678901234567890',
57
+ chainId: 137,
58
+ marketplaceType: MarketplaceType.ORDERBOOK,
59
+ currencyOptions: [mockCurrencies[0].contractAddress],
60
+ exchanges: [],
61
+ bannerUrl: 'https://example.com/collection-banner.png',
62
+ feePercentage: 2.5,
63
+ destinationMarketplace: OrderbookKind.opensea,
64
+ filterSettings: {
65
+ filterOrder: ['Category', 'Level', 'Element'],
66
+ exclusions: [
67
+ {
68
+ key: 'Category',
69
+ condition: FilterCondition.ENTIRE_KEY,
70
+ },
71
+ {
72
+ key: 'Level',
73
+ condition: FilterCondition.SPECIFIC_VALUE,
74
+ value: 'Legendary',
75
+ },
76
+ ],
77
+ },
23
78
  },
24
79
  ],
25
80
  landingPageLayout: 'default',
26
81
  cssString: '',
27
82
  manifestUrl: '',
83
+ bannerUrl: '',
28
84
  };
29
85
 
30
86
  export const mockStyles = `
@@ -54,9 +110,9 @@ const debugLog = (endpoint: string, request: Request, response: Response) => {
54
110
 
55
111
  // MSW handlers
56
112
  export const createConfigHandler = (config = mockConfig) =>
57
- http.get('*/marketplace/*/config.json', ({ request }) => {
113
+ http.get('*/marketplace/*/settings.json', ({ request }) => {
58
114
  const response = HttpResponse.json(config);
59
- debugLog('config.json', request, response);
115
+ debugLog('settings.json', request, response);
60
116
  return response;
61
117
  });
62
118
 
@@ -70,7 +126,7 @@ export const createStylesHandler = (styles = mockStyles) =>
70
126
  });
71
127
 
72
128
  export const createErrorHandler = () =>
73
- http.get('*/marketplace/*/config.json', () => {
129
+ http.get('*/marketplace/*/settings.json', () => {
74
130
  return HttpResponse.json(
75
131
  { code: 3000, msg: 'Project not found' },
76
132
  { status: 404 },
@@ -1,27 +1,18 @@
1
- import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest';
2
- import { setupServer } from 'msw/node';
1
+ import { describe, it, expect } from 'vitest';
3
2
  import { marketplaceConfigOptions } from '../marketplaceConfigOptions';
4
3
  import { renderHook, waitFor } from '../../../_internal/test-utils';
5
4
  import type { QueryFunctionContext } from '@tanstack/react-query';
6
5
  import {
7
- handlers,
8
6
  createErrorHandler,
9
7
  createStylesErrorHandler,
10
8
  mockConfig,
11
9
  mockStyles,
12
10
  } from '../__mocks__/marketplaceConfig.msw';
11
+ import { server } from '../../../_internal/test/setup';
13
12
 
14
13
  type MarketplaceConfigQueryKey = ['configs', 'marketplace', string, string];
15
14
  type MarketplaceConfigContext = QueryFunctionContext<MarketplaceConfigQueryKey>;
16
15
 
17
- // Create MSW server with default handlers
18
- const server = setupServer(...handlers);
19
-
20
- // Setup test environment
21
- beforeAll(() => server.listen());
22
- afterEach(() => server.resetHandlers());
23
- afterAll(() => server.close());
24
-
25
16
  describe('marketplaceConfigOptions', () => {
26
17
  it('should fetch marketplace config and styles successfully', async () => {
27
18
  const { result } = renderHook(() =>
@@ -1,5 +1,10 @@
1
1
  import { queryOptions } from '@tanstack/react-query';
2
- import type { Env, MarketplaceConfig, SdkConfig } from '../../../types';
2
+ import type {
3
+ Env,
4
+ MarketplaceConfig,
5
+ MarketplaceSettings,
6
+ SdkConfig,
7
+ } from '../../../types';
3
8
  import {
4
9
  MarketplaceConfigFetchError,
5
10
  ProjectNotFoundError,
@@ -8,7 +13,7 @@ import { builderMarketplaceApi, configKeys } from '../../_internal';
8
13
 
9
14
  const fetchBuilderConfig = async (projectId: string, env: Env) => {
10
15
  const url = `${builderMarketplaceApi(projectId, env)}`;
11
- const response = await fetch(`${url}/config.json`);
16
+ const response = await fetch(`${url}/settings.json`);
12
17
 
13
18
  const json = await response.json();
14
19
  if (!response.ok) {
@@ -22,7 +27,7 @@ const fetchBuilderConfig = async (projectId: string, env: Env) => {
22
27
  throw new MarketplaceConfigFetchError(json.msg);
23
28
  }
24
29
  }
25
- return json as MarketplaceConfig;
30
+ return json as MarketplaceSettings;
26
31
  };
27
32
 
28
33
  const fetchStyles = async (projectId: string, env: Env) => {
@@ -1,8 +1,9 @@
1
- import { zeroAddress, type Address } from 'viem';
1
+ import { type Address, zeroAddress } from 'viem';
2
+
3
+ import { useChain } from '@0xsequence/kit';
4
+ import { useCallback } from 'react';
2
5
  import { useAccount } from 'wagmi';
3
6
  import type { FeeOption } from '../ui/modals/_internal/components/waasFeeOptionsSelect/WaasFeeOptionsSelect';
4
- import { useCallback } from 'react';
5
- import { useChain } from '@0xsequence/kit';
6
7
  import { useCollectionBalanceDetails } from './useCollectionBalanceDetails';
7
8
 
8
9
  enum AutoSelectFeeOptionError {
@@ -10,14 +10,17 @@ import { useWallet } from '../_internal/wallet/useWallet';
10
10
  import type { ModalCallbacks } from '../ui/modals/_internal/types';
11
11
  import { useConfig } from './useConfig';
12
12
  import { useGenerateCancelTransaction } from './useGenerateCancelTransaction';
13
- import type { TransactionStep } from './useCancelOrder';
14
- import type { SignatureStep } from '../_internal/utils';
13
+ import type {
14
+ SignatureStep,
15
+ TransactionStep as walletTransactionStep,
16
+ } from '../_internal/utils';
15
17
  import type { Hex } from 'viem';
16
18
  import { useSwitchChainModal } from '../ui/modals/_internal/components/switchChainModal';
17
19
  import {
18
20
  ChainSwitchUserRejectedError,
19
21
  WalletInstanceNotFoundError,
20
22
  } from '../../utils/_internal/error/transaction';
23
+ import type { TransactionStep } from './useCancelOrder';
21
24
 
22
25
  interface UseCancelTransactionStepsArgs {
23
26
  collectionAddress: string;
@@ -46,10 +49,10 @@ export const useCancelTransactionSteps = ({
46
49
  });
47
50
 
48
51
  const getWalletChainId = async () => {
49
- return await wallet!.getChainId();
52
+ return await wallet?.getChainId();
50
53
  };
51
54
  const switchChain = async () => {
52
- await wallet!.switchChain(Number(chainId));
55
+ await wallet?.switchChain(Number(chainId));
53
56
  };
54
57
  const checkAndSwitchChain = async () => {
55
58
  const walletChainId = await getWalletChainId();
@@ -82,7 +85,11 @@ export const useCancelTransactionSteps = ({
82
85
  marketplace: MarketplaceKind;
83
86
  }) => {
84
87
  try {
85
- const address = await wallet!.address();
88
+ const address = await wallet?.address();
89
+
90
+ if (!address) {
91
+ throw new Error('Wallet address not found');
92
+ }
86
93
 
87
94
  const steps = await generateCancelTransactionAsync({
88
95
  collectionAddress,
@@ -139,7 +146,8 @@ export const useCancelTransactionSteps = ({
139
146
  throw new Error('No transaction or signature step found');
140
147
  }
141
148
 
142
- let hash: Hex | undefined, reservoirOrderId: string | undefined;
149
+ let hash: Hex | undefined;
150
+ let reservoirOrderId: string | undefined;
143
151
 
144
152
  if (transactionStep && wallet) {
145
153
  hash = await executeTransaction({ transactionStep });
@@ -191,9 +199,9 @@ export const useCancelTransactionSteps = ({
191
199
  }: {
192
200
  transactionStep: Step;
193
201
  }): Promise<Hex | undefined> => {
194
- const hash = await wallet!.handleSendTransactionStep(
202
+ const hash = await wallet?.handleSendTransactionStep(
195
203
  Number(chainId),
196
- transactionStep as any,
204
+ transactionStep as walletTransactionStep,
197
205
  );
198
206
 
199
207
  return hash;
@@ -204,7 +212,7 @@ export const useCancelTransactionSteps = ({
204
212
  }: {
205
213
  signatureStep: Step;
206
214
  }) => {
207
- const signature = await wallet!.handleSignMessageStep(
215
+ const signature = await wallet?.handleSignMessageStep(
208
216
  signatureStep as SignatureStep,
209
217
  );
210
218
 
@@ -41,7 +41,7 @@ export const collectionDetailsPollingOptions = (
41
41
  }
42
42
 
43
43
  const interval = Math.min(
44
- INITIAL_POLLING_INTERVAL * Math.pow(1.5, currentAttempt),
44
+ INITIAL_POLLING_INTERVAL * 1.5 ** currentAttempt,
45
45
  MAX_POLLING_INTERVAL,
46
46
  );
47
47