@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
@@ -0,0 +1,207 @@
1
+ import { describe, expect, it, vi, beforeEach } from 'vitest';
2
+ import {
3
+ commonWagmiMocks,
4
+ mockChains,
5
+ mockConnectors,
6
+ } from '../../_internal/test/mocks/wagmi';
7
+
8
+ // Mock wagmi
9
+ vi.mock('wagmi', () => ({
10
+ useAccount: commonWagmiMocks.useAccount,
11
+ createConfig: commonWagmiMocks.createConfig,
12
+ http: commonWagmiMocks.http,
13
+ WagmiProvider: commonWagmiMocks.WagmiProvider,
14
+ }));
15
+
16
+ // Mock wagmi/chains
17
+ vi.mock('wagmi/chains', () => mockChains);
18
+
19
+ // Mock wagmi/connectors
20
+ vi.mock('wagmi/connectors', () => mockConnectors);
21
+
22
+ // Mock useConfig hook
23
+ vi.mock('../useConfig', () => ({
24
+ useConfig: vi.fn(),
25
+ }));
26
+
27
+ import { useGenerateCancelTransaction } from '../useGenerateCancelTransaction';
28
+ import { renderHook, waitFor } from '../../_internal/test-utils';
29
+ import { zeroAddress } from 'viem';
30
+ import { http, HttpResponse } from 'msw';
31
+ import {
32
+ mockSteps,
33
+ mockMarketplaceEndpoint,
34
+ } from '../../_internal/api/__mocks__/marketplace.msw';
35
+ import { server } from '../../_internal/test/setup';
36
+ import { MarketplaceKind } from '../../_internal/api/marketplace.gen';
37
+ import { useConfig } from '../useConfig';
38
+ import { act } from '@testing-library/react';
39
+
40
+ describe('useGenerateCancelTransaction', () => {
41
+ const defaultArgs = {
42
+ chainId: '1',
43
+ orderId: '0x9876543210987654321098765432109876543210',
44
+ marketplace: MarketplaceKind.sequence_marketplace_v2,
45
+ collectionAddress: zeroAddress,
46
+ maker: '0x1234567890123456789012345678901234567890',
47
+ };
48
+
49
+ const mockConfig = {
50
+ projectAccessKey: 'test-key',
51
+ projectId: 'test-id',
52
+ };
53
+
54
+ beforeEach(() => {
55
+ // Reset handlers
56
+ server.resetHandlers();
57
+
58
+ // Mock useAccount to return an address
59
+ commonWagmiMocks.useAccount.mockReturnValue({
60
+ address: '0x1234567890123456789012345678901234567890',
61
+ isConnecting: false,
62
+ isDisconnected: false,
63
+ isReconnecting: false,
64
+ status: 'connected',
65
+ });
66
+
67
+ // Mock useConfig to return config
68
+ (useConfig as unknown as ReturnType<typeof vi.fn>).mockReturnValue(
69
+ mockConfig,
70
+ );
71
+
72
+ // Set up default success handler
73
+ server.use(
74
+ http.post(mockMarketplaceEndpoint('GenerateCancelTransaction'), () => {
75
+ return HttpResponse.json({ steps: mockSteps });
76
+ }),
77
+ );
78
+ });
79
+
80
+ it('should generate cancel transaction successfully', async () => {
81
+ const { result } = renderHook(() =>
82
+ useGenerateCancelTransaction(defaultArgs),
83
+ );
84
+
85
+ await act(async () => {
86
+ await result.current.generateCancelTransactionAsync(defaultArgs);
87
+ });
88
+
89
+ await waitFor(() => {
90
+ expect(result.current.data).toEqual(mockSteps);
91
+ });
92
+ expect(result.current.error).toBeNull();
93
+ });
94
+
95
+ it('should handle error states', async () => {
96
+ server.use(
97
+ http.post(mockMarketplaceEndpoint('GenerateCancelTransaction'), () => {
98
+ return HttpResponse.json(
99
+ { error: { message: 'Failed to generate cancel transaction' } },
100
+ { status: 500 },
101
+ );
102
+ }),
103
+ );
104
+
105
+ const { result } = renderHook(() =>
106
+ useGenerateCancelTransaction(defaultArgs),
107
+ );
108
+
109
+ await act(async () => {
110
+ try {
111
+ await result.current.generateCancelTransactionAsync(defaultArgs);
112
+ } catch (error) {
113
+ // Expected error
114
+ }
115
+ });
116
+
117
+ await waitFor(() => {
118
+ expect(result.current.isError).toBe(true);
119
+ });
120
+ expect(result.current.error).toBeDefined();
121
+ });
122
+
123
+ it('should not make request when wallet is not connected', async () => {
124
+ commonWagmiMocks.useAccount.mockReturnValue({
125
+ address: undefined,
126
+ isConnecting: false,
127
+ isDisconnected: true,
128
+ isReconnecting: false,
129
+ status: 'disconnected',
130
+ });
131
+
132
+ const { result } = renderHook(() =>
133
+ useGenerateCancelTransaction(defaultArgs),
134
+ );
135
+
136
+ expect(result.current.isPending).toBe(false);
137
+ expect(result.current.data).toBeUndefined();
138
+ expect(result.current.error).toBeNull();
139
+ });
140
+
141
+ it('should handle invalid order data', async () => {
142
+ const invalidArgs = {
143
+ ...defaultArgs,
144
+ orderId: '', // Invalid order ID
145
+ };
146
+
147
+ server.use(
148
+ http.post(mockMarketplaceEndpoint('GenerateCancelTransaction'), () => {
149
+ return HttpResponse.json({ error: 'endpoint error' }, { status: 400 });
150
+ }),
151
+ );
152
+
153
+ const { result } = renderHook(() =>
154
+ useGenerateCancelTransaction(invalidArgs),
155
+ );
156
+
157
+ await act(async () => {
158
+ try {
159
+ await result.current.generateCancelTransactionAsync(invalidArgs);
160
+ } catch (error) {
161
+ // Expected error
162
+ }
163
+ });
164
+
165
+ await waitFor(() => {
166
+ expect(result.current.isError).toBe(true);
167
+ });
168
+ expect(result.current.error?.message).toBe('endpoint error');
169
+ });
170
+
171
+ it('should not make request when wallet is connecting', async () => {
172
+ commonWagmiMocks.useAccount.mockReturnValue({
173
+ address: undefined,
174
+ isConnecting: true,
175
+ isDisconnected: false,
176
+ isReconnecting: false,
177
+ status: 'connecting',
178
+ });
179
+
180
+ const { result } = renderHook(() =>
181
+ useGenerateCancelTransaction(defaultArgs),
182
+ );
183
+
184
+ expect(result.current.isPending).toBe(false);
185
+ expect(result.current.data).toBeUndefined();
186
+ expect(result.current.error).toBeNull();
187
+ });
188
+
189
+ it('should call onSuccess callback when provided', async () => {
190
+ const onSuccess = vi.fn();
191
+ const { result } = renderHook(() =>
192
+ useGenerateCancelTransaction({ ...defaultArgs, onSuccess }),
193
+ );
194
+
195
+ await act(async () => {
196
+ await result.current.generateCancelTransactionAsync(defaultArgs);
197
+ });
198
+
199
+ await waitFor(() => {
200
+ expect(onSuccess).toHaveBeenCalledWith(
201
+ [mockSteps[0]],
202
+ defaultArgs,
203
+ undefined,
204
+ );
205
+ });
206
+ });
207
+ });
@@ -0,0 +1,207 @@
1
+ import { describe, expect, it, vi, beforeEach } from 'vitest';
2
+ import { useGenerateListingTransaction } from '../useGenerateListingTransaction';
3
+ import { renderHook, waitFor } from '../../_internal/test-utils';
4
+ import { zeroAddress } from 'viem';
5
+ import { http, HttpResponse } from 'msw';
6
+ import {
7
+ mockSteps,
8
+ mockMarketplaceEndpoint,
9
+ } from '../../_internal/api/__mocks__/marketplace.msw';
10
+ import { server } from '../../_internal/test/setup';
11
+ import {
12
+ ContractType,
13
+ OrderbookKind,
14
+ } from '../../_internal/api/marketplace.gen';
15
+ import { useConfig } from '../useConfig';
16
+ import type { SdkConfig } from '../../../types';
17
+ import type { CreateReqWithDateExpiry } from '../useGenerateListingTransaction';
18
+
19
+ // Mock useConfig hook
20
+ vi.mock('../useConfig');
21
+
22
+ describe('useGenerateListingTransaction', () => {
23
+ const mockOnSuccess = vi.fn();
24
+
25
+ const mockConfig: SdkConfig = {
26
+ projectId: 'test-project',
27
+ projectAccessKey: 'test-access-key',
28
+ };
29
+
30
+ const mockListing: CreateReqWithDateExpiry = {
31
+ tokenId: '1',
32
+ quantity: '1',
33
+ expiry: new Date('2024-12-31'),
34
+ currencyAddress: zeroAddress,
35
+ pricePerToken: '1000000000000000000',
36
+ };
37
+
38
+ const mockTransactionProps = {
39
+ collectionAddress: zeroAddress,
40
+ owner: zeroAddress,
41
+ contractType: ContractType.ERC721,
42
+ orderbook: OrderbookKind.sequence_marketplace_v2,
43
+ listing: mockListing,
44
+ };
45
+
46
+ const defaultArgs = {
47
+ chainId: '1' as const,
48
+ onSuccess: mockOnSuccess,
49
+ };
50
+
51
+ beforeEach(() => {
52
+ vi.clearAllMocks();
53
+
54
+ // Set up the mock implementation for useConfig
55
+ vi.mocked(useConfig).mockReturnValue(mockConfig);
56
+
57
+ // Mock default steps response
58
+ server.use(
59
+ http.post(mockMarketplaceEndpoint('GenerateListingTransaction'), () => {
60
+ return HttpResponse.json({
61
+ steps: mockSteps,
62
+ });
63
+ }),
64
+ );
65
+ });
66
+
67
+ it('should generate listing transaction successfully', async () => {
68
+ const { result } = renderHook(() =>
69
+ useGenerateListingTransaction(defaultArgs),
70
+ );
71
+
72
+ await result.current.generateListingTransactionAsync(mockTransactionProps);
73
+
74
+ expect(mockOnSuccess).toHaveBeenCalledWith(
75
+ mockSteps,
76
+ mockTransactionProps,
77
+ undefined,
78
+ );
79
+ });
80
+
81
+ it('should handle async generation with await', async () => {
82
+ const { result } = renderHook(() =>
83
+ useGenerateListingTransaction(defaultArgs),
84
+ );
85
+
86
+ const steps =
87
+ await result.current.generateListingTransactionAsync(
88
+ mockTransactionProps,
89
+ );
90
+
91
+ expect(steps).toEqual(mockSteps);
92
+ });
93
+
94
+ it('should handle non-async generation with callback', async () => {
95
+ const { result } = renderHook(() =>
96
+ useGenerateListingTransaction(defaultArgs),
97
+ );
98
+
99
+ result.current.generateListingTransaction(mockTransactionProps);
100
+
101
+ await waitFor(() => {
102
+ expect(mockOnSuccess).toHaveBeenCalledWith(
103
+ mockSteps,
104
+ mockTransactionProps,
105
+ undefined,
106
+ );
107
+ });
108
+ });
109
+
110
+ it('should handle API errors', async () => {
111
+ // Mock error response
112
+ server.use(
113
+ http.post(mockMarketplaceEndpoint('GenerateListingTransaction'), () => {
114
+ return new HttpResponse(null, { status: 500 });
115
+ }),
116
+ );
117
+
118
+ const { result } = renderHook(() =>
119
+ useGenerateListingTransaction(defaultArgs),
120
+ );
121
+
122
+ await expect(
123
+ result.current.generateListingTransactionAsync(mockTransactionProps),
124
+ ).rejects.toThrow();
125
+
126
+ expect(mockOnSuccess).not.toHaveBeenCalled();
127
+ });
128
+
129
+ it('should convert Date expiry to Unix timestamp', async () => {
130
+ const expectedUnixTime = Math.floor(mockListing.expiry.getTime() / 1000);
131
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
132
+ let requestBody: any;
133
+
134
+ server.use(
135
+ http.post(
136
+ mockMarketplaceEndpoint('GenerateListingTransaction'),
137
+ async ({ request }) => {
138
+ requestBody = await request.json();
139
+ return HttpResponse.json({ steps: mockSteps });
140
+ },
141
+ ),
142
+ );
143
+
144
+ const { result } = renderHook(() =>
145
+ useGenerateListingTransaction(defaultArgs),
146
+ );
147
+ await result.current.generateListingTransactionAsync(mockTransactionProps);
148
+
149
+ expect(Number(requestBody.listing.expiry)).toBe(expectedUnixTime);
150
+ });
151
+
152
+ it('should use provided config from useConfig hook', async () => {
153
+ const customConfig: SdkConfig = {
154
+ projectId: 'custom-project',
155
+ projectAccessKey: 'custom-access-key',
156
+ };
157
+
158
+ let requestHeaders: Headers | undefined;
159
+
160
+ server.use(
161
+ http.post(
162
+ mockMarketplaceEndpoint('GenerateListingTransaction'),
163
+ async ({ request }) => {
164
+ requestHeaders = request.headers;
165
+ return HttpResponse.json({ steps: mockSteps });
166
+ },
167
+ ),
168
+ );
169
+
170
+ vi.mocked(useConfig).mockReturnValue(customConfig);
171
+
172
+ const { result } = renderHook(() =>
173
+ useGenerateListingTransaction(defaultArgs),
174
+ );
175
+ await result.current.generateListingTransactionAsync(mockTransactionProps);
176
+
177
+ expect(requestHeaders?.get('x-access-key')).toBe(
178
+ customConfig.projectAccessKey,
179
+ );
180
+ });
181
+
182
+ it('should handle invalid listing data', async () => {
183
+ const invalidListing = {
184
+ ...mockListing,
185
+ pricePerToken: 'invalid-price',
186
+ };
187
+
188
+ server.use(
189
+ http.post(mockMarketplaceEndpoint('GenerateListingTransaction'), () => {
190
+ return new HttpResponse(null, { status: 400 });
191
+ }),
192
+ );
193
+
194
+ const { result } = renderHook(() =>
195
+ useGenerateListingTransaction(defaultArgs),
196
+ );
197
+
198
+ await expect(
199
+ result.current.generateListingTransactionAsync({
200
+ ...mockTransactionProps,
201
+ listing: invalidListing,
202
+ }),
203
+ ).rejects.toThrow();
204
+
205
+ expect(mockOnSuccess).not.toHaveBeenCalled();
206
+ });
207
+ });
@@ -0,0 +1,205 @@
1
+ import { describe, expect, it, vi, beforeEach } from 'vitest';
2
+ import { useGenerateOfferTransaction } from '../useGenerateOfferTransaction';
3
+ import { renderHook, waitFor } from '../../_internal/test-utils';
4
+ import { zeroAddress } from 'viem';
5
+ import { http, HttpResponse } from 'msw';
6
+ import {
7
+ mockSteps,
8
+ mockMarketplaceEndpoint,
9
+ } from '../../_internal/api/__mocks__/marketplace.msw';
10
+ import { server } from '../../_internal/test/setup';
11
+ import {
12
+ ContractType,
13
+ OrderbookKind,
14
+ } from '../../_internal/api/marketplace.gen';
15
+ import { useConfig } from '../useConfig';
16
+ import type { SdkConfig } from '../../../types';
17
+
18
+ // Mock useConfig hook
19
+ vi.mock('../useConfig');
20
+
21
+ describe('useGenerateOfferTransaction', () => {
22
+ const mockOnSuccess = vi.fn();
23
+
24
+ const mockConfig: SdkConfig = {
25
+ projectId: 'test-project',
26
+ projectAccessKey: 'test-access-key',
27
+ };
28
+
29
+ const mockOffer = {
30
+ tokenId: '1',
31
+ quantity: '1',
32
+ expiry: new Date('2024-12-31'),
33
+ currencyAddress: zeroAddress,
34
+ pricePerToken: '1000000000000000000',
35
+ };
36
+
37
+ const mockTransactionProps = {
38
+ collectionAddress: zeroAddress,
39
+ maker: zeroAddress,
40
+ contractType: ContractType.ERC721,
41
+ orderbook: OrderbookKind.sequence_marketplace_v2,
42
+ offer: mockOffer,
43
+ };
44
+
45
+ const defaultArgs = {
46
+ chainId: '1' as const,
47
+ onSuccess: mockOnSuccess,
48
+ };
49
+
50
+ beforeEach(() => {
51
+ vi.clearAllMocks();
52
+
53
+ // Set up the mock implementation for useConfig
54
+ vi.mocked(useConfig).mockReturnValue(mockConfig);
55
+
56
+ // Mock default steps response
57
+ server.use(
58
+ http.post(mockMarketplaceEndpoint('GenerateOfferTransaction'), () => {
59
+ return HttpResponse.json({
60
+ steps: mockSteps,
61
+ });
62
+ }),
63
+ );
64
+ });
65
+
66
+ it('should generate offer transaction successfully', async () => {
67
+ const { result } = renderHook(() =>
68
+ useGenerateOfferTransaction(defaultArgs),
69
+ );
70
+
71
+ await result.current.generateOfferTransactionAsync(mockTransactionProps);
72
+
73
+ expect(mockOnSuccess).toHaveBeenCalledWith(
74
+ mockSteps,
75
+ mockTransactionProps,
76
+ undefined,
77
+ );
78
+ });
79
+
80
+ it('should handle async generation with await', async () => {
81
+ const { result } = renderHook(() =>
82
+ useGenerateOfferTransaction(defaultArgs),
83
+ );
84
+
85
+ const steps =
86
+ await result.current.generateOfferTransactionAsync(mockTransactionProps);
87
+
88
+ expect(steps).toEqual(mockSteps);
89
+ });
90
+
91
+ it('should handle non-async generation with callback', async () => {
92
+ const { result } = renderHook(() =>
93
+ useGenerateOfferTransaction(defaultArgs),
94
+ );
95
+
96
+ result.current.generateOfferTransaction(mockTransactionProps);
97
+
98
+ await waitFor(() => {
99
+ expect(mockOnSuccess).toHaveBeenCalledWith(
100
+ mockSteps,
101
+ mockTransactionProps,
102
+ undefined,
103
+ );
104
+ });
105
+ });
106
+
107
+ it('should handle API errors', async () => {
108
+ // Mock error response
109
+ server.use(
110
+ http.post(mockMarketplaceEndpoint('GenerateOfferTransaction'), () => {
111
+ return new HttpResponse(null, { status: 500 });
112
+ }),
113
+ );
114
+
115
+ const { result } = renderHook(() =>
116
+ useGenerateOfferTransaction(defaultArgs),
117
+ );
118
+
119
+ await expect(
120
+ result.current.generateOfferTransactionAsync(mockTransactionProps),
121
+ ).rejects.toThrow();
122
+
123
+ expect(mockOnSuccess).not.toHaveBeenCalled();
124
+ });
125
+
126
+ it('should convert Date expiry to Unix timestamp', async () => {
127
+ const expectedUnixTime = Math.floor(mockOffer.expiry.getTime() / 1000);
128
+
129
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
130
+ let requestBody: any;
131
+
132
+ server.use(
133
+ http.post(
134
+ mockMarketplaceEndpoint('GenerateOfferTransaction'),
135
+ async ({ request }) => {
136
+ requestBody = await request.json();
137
+ return HttpResponse.json({ steps: mockSteps });
138
+ },
139
+ ),
140
+ );
141
+
142
+ const { result } = renderHook(() =>
143
+ useGenerateOfferTransaction(defaultArgs),
144
+ );
145
+ await result.current.generateOfferTransactionAsync(mockTransactionProps);
146
+
147
+ expect(Number(requestBody.offer.expiry)).toBe(expectedUnixTime);
148
+ });
149
+
150
+ it('should use provided config from useConfig hook', async () => {
151
+ const customConfig: SdkConfig = {
152
+ projectId: 'custom-project',
153
+ projectAccessKey: 'custom-access-key',
154
+ };
155
+
156
+ let requestHeaders: Headers | undefined;
157
+
158
+ server.use(
159
+ http.post(
160
+ mockMarketplaceEndpoint('GenerateOfferTransaction'),
161
+ async ({ request }) => {
162
+ requestHeaders = request.headers;
163
+ return HttpResponse.json({ steps: mockSteps });
164
+ },
165
+ ),
166
+ );
167
+
168
+ vi.mocked(useConfig).mockReturnValue(customConfig);
169
+
170
+ const { result } = renderHook(() =>
171
+ useGenerateOfferTransaction(defaultArgs),
172
+ );
173
+ await result.current.generateOfferTransactionAsync(mockTransactionProps);
174
+
175
+ expect(requestHeaders?.get('x-access-key')).toBe(
176
+ customConfig.projectAccessKey,
177
+ );
178
+ });
179
+
180
+ it('should handle invalid offer data', async () => {
181
+ const invalidOffer = {
182
+ ...mockOffer,
183
+ pricePerToken: 'invalid-price',
184
+ };
185
+
186
+ server.use(
187
+ http.post(mockMarketplaceEndpoint('GenerateOfferTransaction'), () => {
188
+ return new HttpResponse(null, { status: 400 });
189
+ }),
190
+ );
191
+
192
+ const { result } = renderHook(() =>
193
+ useGenerateOfferTransaction(defaultArgs),
194
+ );
195
+
196
+ await expect(
197
+ result.current.generateOfferTransactionAsync({
198
+ ...mockTransactionProps,
199
+ offer: invalidOffer,
200
+ }),
201
+ ).rejects.toThrow();
202
+
203
+ expect(mockOnSuccess).not.toHaveBeenCalled();
204
+ });
205
+ });