@0xsequence/marketplace-sdk 0.8.7 → 0.8.8

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 (130) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/chunk-2PSNAIAT.js +1 -0
  3. package/dist/chunk-2PSNAIAT.js.map +1 -0
  4. package/dist/{chunk-7FVZD2LL.js → chunk-4XLXOEXQ.js} +2 -2
  5. package/dist/{chunk-Y6AOCO3Q.js → chunk-7IYKUVC3.js} +312 -145
  6. package/dist/chunk-7IYKUVC3.js.map +1 -0
  7. package/dist/{chunk-5HEZNTSU.js → chunk-D7RVSZAQ.js} +131 -83
  8. package/dist/chunk-D7RVSZAQ.js.map +1 -0
  9. package/dist/chunk-DWTLVJAW.js +42 -0
  10. package/dist/chunk-DWTLVJAW.js.map +1 -0
  11. package/dist/{chunk-YAUZLETY.js → chunk-G3447GIP.js} +37 -18
  12. package/dist/chunk-G3447GIP.js.map +1 -0
  13. package/dist/{chunk-O6GWM7C3.js → chunk-HHYNOPPI.js} +2 -2
  14. package/dist/{chunk-KTT27YUN.js → chunk-KGM2WLSP.js} +12 -156
  15. package/dist/chunk-KGM2WLSP.js.map +1 -0
  16. package/dist/chunk-MAD64DLJ.js +81 -0
  17. package/dist/chunk-MAD64DLJ.js.map +1 -0
  18. package/dist/chunk-N7BPFK46.js +1 -0
  19. package/dist/chunk-N7BPFK46.js.map +1 -0
  20. package/dist/chunk-NX52D7NX.js +135 -0
  21. package/dist/chunk-NX52D7NX.js.map +1 -0
  22. package/dist/chunk-O34GCB47.js +32 -0
  23. package/dist/chunk-O34GCB47.js.map +1 -0
  24. package/dist/{chunk-Q2DA477S.js → chunk-YALXP2PW.js} +3 -3
  25. package/dist/{chunk-A6V7XDY4.js → chunk-YBOFRP65.js} +2 -2
  26. package/dist/{create-config-CdooE7aU.d.ts → create-config-DwrnzwpM.d.ts} +2 -2
  27. package/dist/{index-ClKHzm0B.d.ts → index-DGsVBflk.d.ts} +3 -12
  28. package/dist/index.css +7 -5
  29. package/dist/index.css.map +1 -1
  30. package/dist/index.d.ts +13 -4
  31. package/dist/index.js +13 -5
  32. package/dist/{lowestListing-kFyrUGha.d.ts → lowestListing-BQHIuvNF.d.ts} +2 -2
  33. package/dist/{marketplace.gen-BU6T6f0m.d.ts → marketplace.gen-DQzWciwC.d.ts} +1 -1
  34. package/dist/marketplaceConfig-B4Fdsmxu.d.ts +17 -0
  35. package/dist/react/_internal/api/index.d.ts +3 -3
  36. package/dist/react/_internal/api/index.js +4 -3
  37. package/dist/react/_internal/databeat/index.d.ts +2 -1
  38. package/dist/react/_internal/databeat/index.js +11 -7
  39. package/dist/react/_internal/index.d.ts +6 -6
  40. package/dist/react/_internal/index.js +13 -10
  41. package/dist/react/_internal/wagmi/index.d.ts +6 -5
  42. package/dist/react/_internal/wagmi/index.js +2 -2
  43. package/dist/react/hooks/index.d.ts +9 -8
  44. package/dist/react/hooks/index.js +10 -6
  45. package/dist/react/hooks/options/index.d.ts +4 -4
  46. package/dist/react/hooks/options/index.js +7 -4
  47. package/dist/react/index.css +2650 -0
  48. package/dist/react/index.css.map +1 -1
  49. package/dist/react/index.d.ts +8 -8
  50. package/dist/react/index.js +16 -11
  51. package/dist/react/queries/index.d.ts +3 -3
  52. package/dist/react/queries/index.js +6 -3
  53. package/dist/react/ssr/index.d.ts +3 -3
  54. package/dist/react/ssr/index.js +6 -3
  55. package/dist/react/ssr/index.js.map +1 -1
  56. package/dist/react/ui/components/collectible-card/index.css +2650 -0
  57. package/dist/react/ui/components/collectible-card/index.css.map +1 -1
  58. package/dist/react/ui/components/collectible-card/index.d.ts +1 -1
  59. package/dist/react/ui/components/collectible-card/index.js +14 -9
  60. package/dist/react/ui/icons/index.js +5 -2
  61. package/dist/react/ui/index.css +2650 -0
  62. package/dist/react/ui/index.css.map +1 -1
  63. package/dist/react/ui/index.d.ts +2 -1
  64. package/dist/react/ui/index.js +14 -9
  65. package/dist/react/ui/modals/_internal/components/actionModal/index.js +11 -7
  66. package/dist/sdk-config-txlivEKe.d.ts +133 -0
  67. package/dist/{services-9ApY0U-o.d.ts → services-BI_w8Eq4.d.ts} +4 -4
  68. package/dist/types/index.d.ts +5 -4
  69. package/dist/types/index.js +9 -6
  70. package/dist/{types-DsTwmKG-.d.ts → types-isjvwapz.d.ts} +3 -3
  71. package/dist/utils/index.d.ts +1 -1
  72. package/dist/utils/index.js +5 -2
  73. package/package.json +3 -3
  74. package/src/index.ts +1 -0
  75. package/src/react/{hooks/options/__mocks__/marketplaceConfig.msw.ts → _internal/api/__mocks__/builder.msw.ts} +70 -63
  76. package/src/react/_internal/api/__mocks__/metadata.msw.ts +30 -10
  77. package/src/react/_internal/api/builder-api.ts +32 -0
  78. package/src/react/_internal/api/builder.gen.ts +215 -0
  79. package/src/react/_internal/api/services.ts +9 -2
  80. package/src/react/_internal/databeat/types.ts +1 -0
  81. package/src/react/_internal/wagmi/__tests__/create-config.test.ts +16 -41
  82. package/src/react/_internal/wagmi/create-config.ts +3 -16
  83. package/src/react/_internal/wagmi/get-connectors.ts +31 -21
  84. package/src/react/_internal/wallet/__tests__/wallet.test.ts +30 -0
  85. package/src/react/_internal/wallet/wallet.ts +25 -2
  86. package/src/react/hooks/__tests__/__snapshots__/useMarketplaceConfig.test.tsx.snap +96 -0
  87. package/src/react/hooks/__tests__/useCollection.test.tsx +4 -5
  88. package/src/react/hooks/__tests__/useCurrencies.test.tsx +1 -1
  89. package/src/react/hooks/__tests__/useInventory.test.tsx +15 -16
  90. package/src/react/hooks/__tests__/useListCollections.test.tsx +18 -163
  91. package/src/react/hooks/__tests__/useMarketplaceConfig.test.tsx +10 -11
  92. package/src/react/hooks/options/index.ts +1 -1
  93. package/src/react/hooks/useAutoSelectFeeOption.tsx +1 -0
  94. package/src/react/hooks/useMarketplaceConfig.tsx +2 -2
  95. package/src/react/queries/marketplaceConfig.ts +101 -0
  96. package/src/react/ssr/__tests__/__snapshots__/create-ssr-client.test.ts.snap +1 -0
  97. package/src/react/ssr/create-ssr-client.ts +1 -1
  98. package/src/react/ui/components/collectible-card/CollectibleCard.tsx +2 -2
  99. package/src/react/ui/components/collectible-card/__tests__/CollectibleAsset.test.tsx +72 -42
  100. package/src/react/ui/components/collectible-card/{CollectibleAsset.tsx → collectible-asset/CollectibleAsset.tsx} +44 -44
  101. package/src/react/ui/components/collectible-card/collectible-asset/CollectibleAssetSkeleton.tsx +14 -0
  102. package/src/react/ui/components/collectible-card/collectible-asset/utils.ts +36 -0
  103. package/src/react/ui/modals/BuyModal/hooks/usePaymentModalParams.ts +6 -1
  104. package/src/react/ui/modals/BuyModal/store.ts +1 -0
  105. package/src/react/ui/modals/CreateListingModal/hooks/useTransactionSteps.tsx +20 -2
  106. package/src/react/ui/modals/MakeOfferModal/hooks/useTransactionSteps.tsx +17 -1
  107. package/src/react/ui/modals/SellModal/hooks/useTransactionSteps.tsx +4 -0
  108. package/src/react/ui/modals/_internal/components/actionModal/ActionModal.test.tsx +7 -1
  109. package/src/types/index.ts +7 -1
  110. package/src/types/sdk-config.ts +4 -9
  111. package/src/utils/fetchContentType.ts +101 -0
  112. package/src/utils/getSequenceMarketRequestId.ts +32 -0
  113. package/test/mocks/wallet.ts +3 -1
  114. package/test/test-utils.tsx +1 -1
  115. package/tsconfig.tsbuildinfo +1 -1
  116. package/dist/builder-types-D5HgAUWR.d.ts +0 -82
  117. package/dist/chunk-5HEZNTSU.js.map +0 -1
  118. package/dist/chunk-KTT27YUN.js.map +0 -1
  119. package/dist/chunk-N7E37ENQ.js +0 -58
  120. package/dist/chunk-N7E37ENQ.js.map +0 -1
  121. package/dist/chunk-Y6AOCO3Q.js.map +0 -1
  122. package/dist/chunk-YAUZLETY.js.map +0 -1
  123. package/dist/sdk-config-DIzJk_tI.d.ts +0 -26
  124. package/src/react/hooks/options/__tests__/marketplaceConfigOptions.test.tsx +0 -134
  125. package/src/react/hooks/options/marketplaceConfigOptions.ts +0 -71
  126. package/src/types/builder-types.ts +0 -88
  127. /package/dist/{chunk-7FVZD2LL.js.map → chunk-4XLXOEXQ.js.map} +0 -0
  128. /package/dist/{chunk-O6GWM7C3.js.map → chunk-HHYNOPPI.js.map} +0 -0
  129. /package/dist/{chunk-Q2DA477S.js.map → chunk-YALXP2PW.js.map} +0 -0
  130. /package/dist/{chunk-A6V7XDY4.js.map → chunk-YBOFRP65.js.map} +0 -0
@@ -17,13 +17,10 @@ import {
17
17
  } from '@0xsequence/connect';
18
18
  import React, { type FunctionComponent } from 'react';
19
19
  import type { CreateConnectorFn } from 'wagmi';
20
- import {
21
- type Env,
22
- type MarketplaceConfig,
23
- MarketplaceWallet,
24
- type SdkConfig,
25
- } from '../../../types';
20
+ import type { Env, SdkConfig } from '../../../types';
26
21
  import { MissingConfigError } from '../../../utils/_internal/error/transaction';
22
+ import type { MarketplaceConfig } from '../../queries/marketplaceConfig';
23
+ import { MarketplaceWallet } from '../api/builder.gen';
27
24
  import { DEFAULT_NETWORK } from '../consts';
28
25
 
29
26
  export function getConnectors({
@@ -40,7 +37,7 @@ export function getConnectors({
40
37
  if (walletType === MarketplaceWallet.UNIVERSAL) {
41
38
  connectors.push(...getUniversalWalletConfigs(sdkConfig, marketplaceConfig));
42
39
  } else if (walletType === MarketplaceWallet.EMBEDDED) {
43
- connectors.push(...getWaasConnectors(sdkConfig));
40
+ connectors.push(...getWaasConnectors(sdkConfig, marketplaceConfig));
44
41
  } else if (walletType === MarketplaceWallet.ECOSYSTEM) {
45
42
  connectors.push(getEcosystemConnector(marketplaceConfig, sdkConfig));
46
43
  } else {
@@ -57,7 +54,7 @@ function commonConnectors(
57
54
  const wallets = [];
58
55
  const { title: appName } = marketplaceConfig;
59
56
  const walletOptions = marketplaceConfig.walletOptions;
60
- const walletConnectProjectId = sdkConfig.wallet?.walletConnectProjectId;
57
+ const walletConnectProjectId = sdkConfig.walletConnectProjectId;
61
58
 
62
59
  if (walletOptions.connectors.includes('coinbase')) {
63
60
  wallets.push(
@@ -110,23 +107,36 @@ function getUniversalWalletConfigs(
110
107
  ] as const;
111
108
  }
112
109
 
113
- export function getWaasConnectors(sdkConfig: SdkConfig): Wallet[] {
114
- const { projectAccessKey } = sdkConfig;
110
+ export function getWaasConnectors(
111
+ config: SdkConfig,
112
+ marketplaceConfig: MarketplaceConfig,
113
+ ): Wallet[] {
114
+ const { projectAccessKey } = config;
115
115
 
116
- const waasConfigKey = sdkConfig.wallet?.embedded?.waasConfigKey;
116
+ const waasConfigKey = marketplaceConfig.walletOptions.waas?.tenantKey;
117
117
 
118
- if (!waasConfigKey) throw new MissingConfigError('waasConfigKey');
118
+ if (!waasConfigKey)
119
+ throw new MissingConfigError(
120
+ 'Embedded wallet config is missing, please check your access key',
121
+ );
119
122
 
120
- const { googleClientId, appleClientId, appleRedirectURI } =
121
- sdkConfig.wallet?.embedded || {};
123
+ const waasOptions = marketplaceConfig.walletOptions.oidcIssuers;
124
+ const googleClientId = waasOptions.google;
125
+ const appleClientId = waasOptions.apple;
126
+ const appleRedirectURI = globalThis.window
127
+ ? `https://${globalThis.window?.location?.origin}${globalThis.window?.location?.pathname}`
128
+ : undefined;
122
129
 
123
- const wallets: Wallet[] = [
124
- emailWaas({
125
- projectAccessKey,
126
- waasConfigKey,
127
- network: DEFAULT_NETWORK,
128
- }),
129
- ];
130
+ const wallets: Wallet[] = [];
131
+
132
+ if (marketplaceConfig.walletOptions.waas?.emailEnabled) {
133
+ wallets.push(
134
+ emailWaas({
135
+ projectAccessKey,
136
+ waasConfigKey,
137
+ }),
138
+ );
139
+ }
130
140
 
131
141
  if (googleClientId) {
132
142
  wallets.push(
@@ -3,8 +3,10 @@ import { server } from '@test';
3
3
  import {
4
4
  type Account,
5
5
  type Address,
6
+ BaseError,
6
7
  type Chain,
7
8
  type PublicClient,
9
+ UserRejectedRequestError as ViemUserRejectedRequestError,
8
10
  type WalletClient,
9
11
  hexToBigInt,
10
12
  } from 'viem';
@@ -264,6 +266,21 @@ describe('wallet', () => {
264
266
  walletInstance.handleSignMessageStep(mockSignatureStep),
265
267
  ).rejects.toThrow(TransactionSignatureError);
266
268
  });
269
+
270
+ it('should throw UserRejectedRequestError when user rejects signature', async () => {
271
+ const error = new TransactionSignatureError(
272
+ StepType.signEIP191,
273
+ new ViemUserRejectedRequestError(
274
+ new BaseError('User rejected request', {
275
+ cause: new Error('User rejected request'),
276
+ }),
277
+ ),
278
+ );
279
+ vi.mocked(mockWalletClient.signMessage).mockRejectedValueOnce(error);
280
+ await expect(
281
+ walletInstance.handleSignMessageStep(mockSignatureStep),
282
+ ).rejects.toThrow(UserRejectedRequestError);
283
+ });
267
284
  });
268
285
 
269
286
  describe('handleSendTransactionStep', () => {
@@ -315,6 +332,19 @@ describe('wallet', () => {
315
332
  ).rejects.toThrow(TransactionExecutionError);
316
333
  });
317
334
 
335
+ it('should throw UserRejectedRequestError when user rejects transaction', async () => {
336
+ const error = new TransactionExecutionError(
337
+ StepType.buy,
338
+ new ViemUserRejectedRequestError(
339
+ new BaseError('User rejected request'),
340
+ ),
341
+ );
342
+ vi.mocked(mockWalletClient.sendTransaction).mockRejectedValueOnce(error);
343
+ await expect(
344
+ walletInstance.handleSendTransactionStep(1, mockTxStep),
345
+ ).rejects.toThrow(UserRejectedRequestError);
346
+ });
347
+
318
348
  it('should handle transaction with contract interaction', async () => {
319
349
  const mockContractTxStep: TransactionStep = {
320
350
  id: StepType.buy,
@@ -2,11 +2,13 @@ import type { TransactionReceipt } from '@0xsequence/indexer';
2
2
  import {
3
3
  type Account,
4
4
  type Address,
5
+ BaseError,
5
6
  type Chain,
6
7
  type Hex,
7
8
  type PublicClient,
8
9
  TransactionReceiptNotFoundError,
9
10
  type TypedDataDomain,
11
+ UserRejectedRequestError as ViemUserRejectedRequestError,
10
12
  type WalletClient as ViemWalletClient,
11
13
  WaitForTransactionReceiptTimeoutError,
12
14
  custom,
@@ -59,6 +61,7 @@ export interface WalletInstance {
59
61
  contractAddress: Address;
60
62
  spender: Address | 'sequenceMarketV1' | 'sequenceMarketV2';
61
63
  }) => Promise<bigint | boolean>;
64
+ publicClient: PublicClient;
62
65
  }
63
66
 
64
67
  const isSequenceWallet = (connector: Connector) =>
@@ -147,8 +150,17 @@ export const wallet = ({
147
150
  message: stepItem.signature!.value,
148
151
  });
149
152
  }
150
- } catch (error) {
153
+ } catch (e) {
154
+ const error = e as TransactionSignatureError;
151
155
  logger.error('Signature failed', error);
156
+
157
+ if (error.cause instanceof BaseError) {
158
+ const viemError = error.cause as BaseError;
159
+ if (viemError instanceof ViemUserRejectedRequestError) {
160
+ throw new UserRejectedRequestError();
161
+ }
162
+ }
163
+
152
164
  throw new TransactionSignatureError(stepItem.id, error as Error);
153
165
  }
154
166
  },
@@ -180,8 +192,17 @@ export const wallet = ({
180
192
  gas: hexToBigInt(stepItem.gas),
181
193
  }),
182
194
  });
183
- } catch (error) {
195
+ } catch (e) {
196
+ const error = e as TransactionExecutionError;
184
197
  logger.error('Transaction failed', error);
198
+
199
+ if (error.cause instanceof BaseError) {
200
+ const viemError = error.cause as BaseError;
201
+ if (viemError instanceof ViemUserRejectedRequestError) {
202
+ throw new UserRejectedRequestError();
203
+ }
204
+ }
205
+
185
206
  throw new TransactionExecutionError(stepItem.id, error as Error);
186
207
  }
187
208
  },
@@ -197,6 +218,7 @@ export const wallet = ({
197
218
  return receipt;
198
219
  } catch (error) {
199
220
  logger.error('Transaction confirmation failed', error);
221
+
200
222
  throw new TransactionConfirmationError(txHash, error as Error);
201
223
  }
202
224
  },
@@ -243,6 +265,7 @@ export const wallet = ({
243
265
  throw new Error('Unsupported contract type for approval checking');
244
266
  }
245
267
  },
268
+ publicClient,
246
269
  };
247
270
 
248
271
  return walletInstance;
@@ -0,0 +1,96 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`useMarketplaceConfig > should fetch marketplace config and styles successfully 1`] = `
4
+ {
5
+ "bannerUrl": "",
6
+ "collections": [
7
+ {
8
+ "address": "0x0000000000000000000000000000000000000000",
9
+ "bannerUrl": "",
10
+ "chainId": 1,
11
+ "currencyOptions": [
12
+ "0x0000000000000000000000000000000000000000",
13
+ "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
14
+ ],
15
+ "destinationMarketplace": "sequence_marketplace_v2",
16
+ "exchanges": [],
17
+ "feePercentage": 3.5,
18
+ "filterSettings": {
19
+ "exclusions": [
20
+ {
21
+ "condition": "SPECIFIC_VALUE",
22
+ "key": "Type",
23
+ "value": "Sample",
24
+ },
25
+ ],
26
+ "filterOrder": [
27
+ "Type",
28
+ "Rarity",
29
+ ],
30
+ },
31
+ "marketplaceType": "ORDERBOOK",
32
+ },
33
+ {
34
+ "address": "0x1234567890123456789012345678901234567890",
35
+ "bannerUrl": "https://example.com/collection-banner.png",
36
+ "chainId": 137,
37
+ "currencyOptions": [
38
+ "0x0000000000000000000000000000000000000000",
39
+ ],
40
+ "destinationMarketplace": "opensea",
41
+ "exchanges": [],
42
+ "feePercentage": 2.5,
43
+ "filterSettings": {
44
+ "exclusions": [
45
+ {
46
+ "condition": "ENTIRE_KEY",
47
+ "key": "Category",
48
+ },
49
+ {
50
+ "condition": "SPECIFIC_VALUE",
51
+ "key": "Level",
52
+ "value": "Legendary",
53
+ },
54
+ ],
55
+ "filterOrder": [
56
+ "Category",
57
+ "Level",
58
+ "Element",
59
+ ],
60
+ },
61
+ "marketplaceType": "ORDERBOOK",
62
+ },
63
+ ],
64
+ "cssString": "
65
+ .marketplace-theme {
66
+ --primary-color: #000000;
67
+ }
68
+ ",
69
+ "faviconUrl": "https://example.com/favicon.png",
70
+ "landingBannerUrl": "https://example.com/banner.png",
71
+ "landingPageLayout": "default",
72
+ "logoUrl": "https://example.com/logo.png",
73
+ "manifestUrl": "https://api.sequence.build/marketplace//manifest.json",
74
+ "projectId": 1,
75
+ "publisherId": "test-publisher",
76
+ "shortDescription": "A test marketplace",
77
+ "socials": {
78
+ "discord": "https://discord.com/test",
79
+ "instagram": "https://instagram.com/test",
80
+ "tiktok": "",
81
+ "twitter": "https://twitter.com/test",
82
+ "website": "",
83
+ "youtube": "",
84
+ },
85
+ "title": "Test Marketplace",
86
+ "walletOptions": {
87
+ "connectors": [
88
+ "coinbase",
89
+ "walletconnect",
90
+ ],
91
+ "includeEIP6963Wallets": true,
92
+ "oidcIssuers": {},
93
+ "walletType": "UNIVERSAL",
94
+ },
95
+ }
96
+ `;
@@ -3,7 +3,7 @@ import { http, HttpResponse } from 'msw';
3
3
  import { zeroAddress } from 'viem';
4
4
  import { describe, expect, it } from 'vitest';
5
5
  import {
6
- mockContractInfo,
6
+ mockEthCollection,
7
7
  mockMetadataEndpoint,
8
8
  } from '../../_internal/api/__mocks__/metadata.msw';
9
9
  import type { UseCollectionArgs } from '../useCollection';
@@ -11,9 +11,8 @@ import { useCollection } from '../useCollection';
11
11
 
12
12
  describe('useCollection', () => {
13
13
  const defaultArgs: UseCollectionArgs = {
14
- chainId: 1,
15
- collectionAddress: zeroAddress,
16
- query: {},
14
+ chainId: mockEthCollection.chainId,
15
+ collectionAddress: mockEthCollection.address,
17
16
  };
18
17
 
19
18
  it('should fetch collection data successfully', async () => {
@@ -29,7 +28,7 @@ describe('useCollection', () => {
29
28
  });
30
29
 
31
30
  // Verify the data matches our mock
32
- expect(result.current.data).toEqual(mockContractInfo);
31
+ expect(result.current.data).toEqual(mockEthCollection);
33
32
  expect(result.current.error).toBeNull();
34
33
  });
35
34
 
@@ -2,11 +2,11 @@ import { renderHook, server, waitFor } from '@test';
2
2
  import { USDC_ADDRESS } from '@test/const';
3
3
  import { http, HttpResponse } from 'msw';
4
4
  import { describe, expect, it } from 'vitest';
5
+ import { mockConfig } from '../../_internal/api/__mocks__/builder.msw';
5
6
  import {
6
7
  mockCurrencies,
7
8
  mockMarketplaceEndpoint,
8
9
  } from '../../_internal/api/__mocks__/marketplace.msw';
9
- import { mockConfig } from '../options/__mocks__/marketplaceConfig.msw';
10
10
  import { useCurrencies } from '../useCurrencies';
11
11
 
12
12
  describe('useCurrencies', () => {
@@ -2,6 +2,10 @@ import { renderHook, server, waitFor } from '@test';
2
2
  import { http, HttpResponse } from 'msw';
3
3
  import { zeroAddress } from 'viem';
4
4
  import { beforeEach, describe, expect, it } from 'vitest';
5
+ import {
6
+ createLookupMarketplaceConfigHandler,
7
+ mockConfig,
8
+ } from '../../_internal/api/__mocks__/builder.msw';
5
9
  import {
6
10
  mockIndexerEndpoint,
7
11
  mockTokenBalance,
@@ -11,7 +15,6 @@ import {
11
15
  mockMarketplaceEndpoint,
12
16
  } from '../../_internal/api/__mocks__/marketplace.msw';
13
17
  import type { UseInventoryArgs } from '../../queries/inventory';
14
- import { mockConfig } from '../options/__mocks__/marketplaceConfig.msw';
15
18
  import { useInventory } from '../useInventory';
16
19
 
17
20
  // Make sure mockCollectibleOrder has a tokenId of "1" for tests
@@ -128,21 +131,17 @@ describe('useInventory', () => {
128
131
  it('should use isLaos721 flag from marketplaceConfig', async () => {
129
132
  // Setup config with LAOS collection
130
133
  const laosCollectionAddress = '0x1234567890123456789012345678901234567890';
131
- server.use(
132
- http.get('*/marketplace/*/settings.json', () => {
133
- const configWithLaos = {
134
- ...mockConfig,
135
- collections: [
136
- {
137
- ...mockConfig.collections[0],
138
- address: laosCollectionAddress,
139
- isLAOSERC721: true,
140
- },
141
- ],
142
- };
143
- return HttpResponse.json(configWithLaos);
144
- }),
145
- );
134
+ const configWithLaos = {
135
+ ...mockConfig,
136
+ collections: [
137
+ {
138
+ ...mockConfig.collections[0],
139
+ address: laosCollectionAddress,
140
+ isLAOSERC721: true,
141
+ },
142
+ ],
143
+ };
144
+ server.use(createLookupMarketplaceConfigHandler(configWithLaos));
146
145
 
147
146
  const laosArgs: UseInventoryArgs = {
148
147
  ...defaultArgs,
@@ -1,51 +1,20 @@
1
- import { ResourceStatus } from '@0xsequence/metadata';
2
1
  import { renderHook, server, waitFor } from '@test';
3
2
  import { http, HttpResponse } from 'msw';
4
3
  import { describe, expect, it } from 'vitest';
5
4
  import { MarketplaceType, OrderbookKind } from '../../../types';
6
- import { mockContractInfo } from '../../_internal/api/__mocks__/metadata.msw';
7
5
  import {
8
- createConfigHandler,
6
+ createLookupMarketplaceConfigHandler,
9
7
  mockConfig,
10
- } from '../options/__mocks__/marketplaceConfig.msw';
8
+ } from '../../_internal/api/__mocks__/builder.msw';
9
+ import {
10
+ mockEthCollection,
11
+ mockPolCollection,
12
+ } from '../../_internal/api/__mocks__/metadata.msw';
11
13
  import { useListCollections } from '../useListCollections';
12
14
 
13
15
  describe('useListCollections', () => {
14
- const defaultArgs = {
15
- query: {
16
- enabled: true,
17
- },
18
- };
19
-
20
16
  it('should fetch collections successfully', async () => {
21
- // Mock marketplace config with collection
22
- server.use(
23
- createConfigHandler({
24
- ...mockConfig,
25
- collections: [
26
- {
27
- chainId: 1,
28
- address:
29
- '0x1234567890123456789012345678901234567890' as `0x${string}`,
30
- feePercentage: 2.5,
31
- marketplaceType: MarketplaceType.ORDERBOOK,
32
- currencyOptions: [],
33
- exchanges: [],
34
- bannerUrl: '',
35
- destinationMarketplace: OrderbookKind.sequence_marketplace_v2,
36
- },
37
- ],
38
- }),
39
- http.post('*/rpc/Metadata/GetContractInfoBatch', () => {
40
- return HttpResponse.json({
41
- contractInfoMap: {
42
- '0x1234567890123456789012345678901234567890': mockContractInfo,
43
- },
44
- });
45
- }),
46
- );
47
-
48
- const { result } = renderHook(() => useListCollections(defaultArgs));
17
+ const { result } = renderHook(() => useListCollections());
49
18
 
50
19
  // Wait for data to be loaded
51
20
  await waitFor(() => {
@@ -53,20 +22,20 @@ describe('useListCollections', () => {
53
22
  });
54
23
 
55
24
  // Verify the data matches our mock
56
- expect(result.current.data).toEqual([mockContractInfo]);
25
+ expect(result.current.data).toEqual([mockEthCollection, mockPolCollection]);
57
26
  expect(result.current.error).toBeNull();
58
27
  });
59
28
 
60
29
  it('should handle empty collections', async () => {
61
30
  // Mock marketplace config with empty collections
62
31
  server.use(
63
- createConfigHandler({
32
+ createLookupMarketplaceConfigHandler({
64
33
  ...mockConfig,
65
34
  collections: [],
66
35
  }),
67
36
  );
68
37
 
69
- const { result } = renderHook(() => useListCollections(defaultArgs));
38
+ const { result } = renderHook(() => useListCollections());
70
39
 
71
40
  await waitFor(() => {
72
41
  expect(result.current.data).toBeDefined();
@@ -79,7 +48,7 @@ describe('useListCollections', () => {
79
48
  it('should handle error states', async () => {
80
49
  // Mock marketplace config with collection
81
50
  server.use(
82
- createConfigHandler({
51
+ createLookupMarketplaceConfigHandler({
83
52
  ...mockConfig,
84
53
  collections: [
85
54
  {
@@ -103,7 +72,7 @@ describe('useListCollections', () => {
103
72
  }),
104
73
  );
105
74
 
106
- const { result } = renderHook(() => useListCollections(defaultArgs));
75
+ const { result } = renderHook(() => useListCollections());
107
76
 
108
77
  await waitFor(() => {
109
78
  expect(result.current.isError).toBe(true);
@@ -118,7 +87,7 @@ describe('useListCollections', () => {
118
87
 
119
88
  // Mock marketplace config with collection
120
89
  server.use(
121
- createConfigHandler({
90
+ createLookupMarketplaceConfigHandler({
122
91
  ...mockConfig,
123
92
  collections: [
124
93
  {
@@ -138,7 +107,7 @@ describe('useListCollections', () => {
138
107
  requestMade = true;
139
108
  return HttpResponse.json({
140
109
  contractInfoMap: {
141
- '0x1234567890123456789012345678901234567890': mockContractInfo,
110
+ '0x1234567890123456789012345678901234567890': mockEthCollection,
142
111
  },
143
112
  });
144
113
  }),
@@ -160,128 +129,14 @@ describe('useListCollections', () => {
160
129
  });
161
130
 
162
131
  it('should handle multiple collections from different chains', async () => {
163
- const mockContractInfo2 = {
164
- ...mockContractInfo,
165
- address: '0x1234567890123456789012345678901234567890' as `0x${string}`,
166
- chainId: 137, // Different chain (Polygon)
167
- };
168
-
169
- // Mock marketplace config with multiple collections
170
- server.use(
171
- createConfigHandler({
172
- ...mockConfig,
173
- collections: [
174
- {
175
- chainId: 1,
176
- address:
177
- '0x1234567890123456789012345678901234567890' as `0x${string}`,
178
- feePercentage: 2.5,
179
- marketplaceType: MarketplaceType.ORDERBOOK,
180
- currencyOptions: [],
181
- exchanges: [],
182
- bannerUrl: '',
183
- destinationMarketplace: OrderbookKind.sequence_marketplace_v2,
184
- },
185
- {
186
- chainId: 137,
187
- address: mockContractInfo2.address,
188
- feePercentage: 2.5,
189
- marketplaceType: MarketplaceType.ORDERBOOK,
190
- currencyOptions: [],
191
- exchanges: [],
192
- bannerUrl: '',
193
- destinationMarketplace: OrderbookKind.sequence_marketplace_v2,
194
- },
195
- ],
196
- }),
197
- http.post('*/rpc/Metadata/GetContractInfoBatch', async ({ request }) => {
198
- const body = (await request.json()) as { chainID: string };
199
- if (body.chainID === '1') {
200
- return HttpResponse.json({
201
- contractInfoMap: {
202
- '0x1234567890123456789012345678901234567890': mockContractInfo,
203
- },
204
- });
205
- }
206
- return HttpResponse.json({
207
- contractInfoMap: {
208
- [mockContractInfo2.address]: mockContractInfo2,
209
- },
210
- });
211
- }),
212
- );
213
-
214
- const { result } = renderHook(() => useListCollections(defaultArgs));
132
+ // TODO: This test should be more robust, make sure we validate that the marketplace config has multiple chains
133
+ // then the to equal should just check that we are fetching the data from those
134
+ const { result } = renderHook(() => useListCollections());
215
135
 
216
136
  await waitFor(() => {
217
137
  expect(result.current.data).toBeDefined();
218
138
  });
219
139
 
220
- expect(result.current.data).toHaveLength(2);
221
- expect(result.current.data).toEqual(
222
- expect.arrayContaining([mockContractInfo, mockContractInfo2]),
223
- );
224
- });
225
-
226
- it('should handle collections with different resource statuses', async () => {
227
- const mockUnavailableContract = {
228
- ...mockContractInfo,
229
- address: '0x9876543210987654321098765432109876543210' as `0x${string}`,
230
- status: ResourceStatus.NOT_AVAILABLE,
231
- };
232
-
233
- // Mock marketplace config with multiple collections
234
- server.use(
235
- createConfigHandler({
236
- ...mockConfig,
237
- collections: [
238
- {
239
- chainId: 1,
240
- address:
241
- '0x1234567890123456789012345678901234567890' as `0x${string}`,
242
- feePercentage: 2.5,
243
- marketplaceType: MarketplaceType.ORDERBOOK,
244
- currencyOptions: [],
245
- exchanges: [],
246
- bannerUrl: '',
247
- destinationMarketplace: OrderbookKind.sequence_marketplace_v2,
248
- },
249
- {
250
- chainId: 1,
251
- address: mockUnavailableContract.address,
252
- feePercentage: 2.5,
253
- marketplaceType: MarketplaceType.ORDERBOOK,
254
- currencyOptions: [],
255
- exchanges: [],
256
- bannerUrl: '',
257
- destinationMarketplace: OrderbookKind.sequence_marketplace_v2,
258
- },
259
- ],
260
- }),
261
- );
262
-
263
- // Mock metadata response for both contracts
264
- server.use(
265
- http.post('*/rpc/Metadata/GetContractInfoBatch', () => {
266
- return HttpResponse.json({
267
- contractInfoMap: {
268
- '0x1234567890123456789012345678901234567890': mockContractInfo,
269
- '0x9876543210987654321098765432109876543210':
270
- mockUnavailableContract,
271
- },
272
- });
273
- }),
274
- );
275
-
276
- const { result } = renderHook(() => useListCollections(defaultArgs));
277
-
278
- await waitFor(() => {
279
- expect(result.current.data).toBeDefined();
280
- });
281
-
282
- expect(result.current.data).toHaveLength(2);
283
- expect(result.current.data).toEqual(
284
- expect.arrayContaining([mockContractInfo, mockUnavailableContract]),
285
- );
140
+ expect(result.current.data).toEqual([mockEthCollection, mockPolCollection]);
286
141
  });
287
142
  });