@0xsequence/marketplace-sdk 0.5.5 → 0.5.7

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 (132) hide show
  1. package/dist/{builder-types-Jl3Ymws8.d.ts → builder-types-DgncJB3q.d.ts} +1 -1
  2. package/dist/{chunk-TFRAOS7F.js → chunk-3OP3WHPU.js} +1 -1
  3. package/dist/chunk-3OP3WHPU.js.map +1 -0
  4. package/dist/{chunk-J6F5QOW5.js → chunk-3OU7BADC.js} +9 -75
  5. package/dist/chunk-3OU7BADC.js.map +1 -0
  6. package/dist/{chunk-Y75XGZOB.js → chunk-5O3ZAEEX.js} +4 -2
  7. package/dist/chunk-5O3ZAEEX.js.map +1 -0
  8. package/dist/{chunk-P7UNMRZ5.js → chunk-G2T7HCWE.js} +5 -7
  9. package/dist/chunk-G2T7HCWE.js.map +1 -0
  10. package/dist/chunk-GFADBQPX.js +2 -0
  11. package/dist/chunk-GFADBQPX.js.map +1 -0
  12. package/dist/{chunk-CIPPTQDA.js → chunk-L2K4DBH2.js} +162 -108
  13. package/dist/chunk-L2K4DBH2.js.map +1 -0
  14. package/dist/{chunk-SA3U25NU.js → chunk-LNMMWV77.js} +23 -8
  15. package/dist/chunk-LNMMWV77.js.map +1 -0
  16. package/dist/{chunk-7C7ADZ2H.js → chunk-OMCWTRBR.js} +9 -42
  17. package/dist/chunk-OMCWTRBR.js.map +1 -0
  18. package/dist/{chunk-7FN62HOP.js → chunk-UMYRZJVY.js} +11 -3
  19. package/dist/chunk-UMYRZJVY.js.map +1 -0
  20. package/dist/{chunk-UZIAX32Y.js → chunk-Y56IIYDF.js} +6 -4
  21. package/dist/{chunk-UZIAX32Y.js.map → chunk-Y56IIYDF.js.map} +1 -1
  22. package/dist/{chunk-AXTDPTRD.js → chunk-YA3DWLDC.js} +30 -26
  23. package/dist/chunk-YA3DWLDC.js.map +1 -0
  24. package/dist/{chunk-3BLBZYQX.js → chunk-YYBU45PK.js} +10 -4
  25. package/dist/chunk-YYBU45PK.js.map +1 -0
  26. package/dist/{create-config-DOUq8Day.d.ts → create-config-CILyA_Hy.d.ts} +2 -2
  27. package/dist/index.css +12 -6
  28. package/dist/index.d.ts +8 -7
  29. package/dist/index.js +9 -6
  30. package/dist/{marketplace.gen-CCJ-URn2.d.ts → marketplace.gen-BVOc6fUW.d.ts} +4 -0
  31. package/dist/{marketplace.gen-D0ADxbfH.d.ts → marketplace.gen-DLOcW6C4.d.ts} +15 -3
  32. package/dist/react/_internal/api/index.d.ts +3 -3
  33. package/dist/react/_internal/api/index.js +1 -1
  34. package/dist/react/_internal/databeat/index.css.map +1 -1
  35. package/dist/react/_internal/databeat/index.d.ts +1 -1
  36. package/dist/react/_internal/databeat/index.js +7 -7
  37. package/dist/react/_internal/index.d.ts +6 -6
  38. package/dist/react/_internal/index.js +2 -2
  39. package/dist/react/_internal/wagmi/index.d.ts +4 -4
  40. package/dist/react/_internal/wagmi/index.js +1 -1
  41. package/dist/react/hooks/index.css.map +1 -1
  42. package/dist/react/hooks/index.d.ts +10 -17
  43. package/dist/react/hooks/index.js +6 -6
  44. package/dist/react/index.css +12 -6
  45. package/dist/react/index.css.map +1 -1
  46. package/dist/react/index.d.ts +6 -6
  47. package/dist/react/index.js +11 -10
  48. package/dist/react/ssr/index.d.ts +1 -0
  49. package/dist/react/ssr/index.js +10 -2
  50. package/dist/react/ssr/index.js.map +1 -1
  51. package/dist/react/ui/components/collectible-card/index.css +12 -6
  52. package/dist/react/ui/components/collectible-card/index.css.map +1 -1
  53. package/dist/react/ui/components/collectible-card/index.d.ts +4 -4
  54. package/dist/react/ui/components/collectible-card/index.js +11 -10
  55. package/dist/react/ui/icons/index.css.map +1 -1
  56. package/dist/react/ui/index.css +12 -6
  57. package/dist/react/ui/index.css.map +1 -1
  58. package/dist/react/ui/index.d.ts +4 -4
  59. package/dist/react/ui/index.js +11 -10
  60. package/dist/react/ui/modals/_internal/components/actionModal/index.css.map +1 -1
  61. package/dist/react/ui/modals/_internal/components/actionModal/index.d.ts +4 -4
  62. package/dist/react/ui/modals/_internal/components/actionModal/index.js +7 -7
  63. package/dist/react/ui/styles/index.css.map +1 -1
  64. package/dist/{sdk-config-xWkdBdrL.d.ts → sdk-config-Bs3H_le_.d.ts} +1 -0
  65. package/dist/{services-Dd2MoBTM.d.ts → services-C3lzi1sL.d.ts} +2 -2
  66. package/dist/styles/index.css +12 -6
  67. package/dist/styles/index.css.map +1 -1
  68. package/dist/styles/index.d.ts +3 -2
  69. package/dist/styles/index.js +4 -2
  70. package/dist/types/index.d.ts +4 -4
  71. package/dist/types/index.js +2 -2
  72. package/dist/{types-vOfhbBkR.d.ts → types-BVD42zE_.d.ts} +3 -3
  73. package/dist/utils/index.d.ts +7 -8
  74. package/dist/utils/index.js +5 -5
  75. package/package.json +14 -14
  76. package/src/consts.ts +2 -0
  77. package/src/react/_internal/api/__mocks__/marketplace.msw.ts +13 -12
  78. package/src/react/_internal/api/marketplace.gen.ts +38 -13
  79. package/src/react/_internal/databeat/index.ts +11 -3
  80. package/src/react/_internal/utils.ts +3 -0
  81. package/src/react/_internal/wagmi/create-config.ts +11 -2
  82. package/src/react/_internal/wallet/__tests__/wallet.test.ts +343 -0
  83. package/src/react/_internal/wallet/useWallet.ts +22 -15
  84. package/src/react/_internal/wallet/wallet.ts +11 -9
  85. package/src/react/hooks/__tests__/useBalanceOfCollectible.test.tsx +6 -14
  86. package/src/react/hooks/__tests__/useCancelOrder.test.tsx +51 -154
  87. package/src/react/hooks/__tests__/useCancelTransactionSteps.test.tsx +21 -19
  88. package/src/react/hooks/__tests__/useCollectionBalanceDetails.test.tsx +5 -14
  89. package/src/react/hooks/__tests__/useCollectionDetailsPolling.test.tsx +5 -10
  90. package/src/react/hooks/__tests__/useCurrencyBalance.test.tsx +69 -80
  91. package/src/react/hooks/__tests__/useGenerateCancelTransaction.test.tsx +12 -67
  92. package/src/react/hooks/__tests__/useGenerateListingTransaction.test.tsx +7 -17
  93. package/src/react/hooks/__tests__/useGenerateOfferTransaction.test.tsx +7 -16
  94. package/src/react/hooks/__tests__/useGenerateSellTransaction.test.tsx +8 -17
  95. package/src/react/hooks/__tests__/useListBalances.test.tsx +3 -8
  96. package/src/react/hooks/__tests__/useListCollectibleActivities.test.tsx +5 -10
  97. package/src/react/hooks/__tests__/useListCollectionActivities.test.tsx +6 -11
  98. package/src/react/hooks/__tests__/useListCollections.test.tsx +5 -13
  99. package/src/react/hooks/__tests__/useMarketplaceConfig.test.tsx +5 -13
  100. package/src/react/hooks/__tests__/useRoyaltyPercentage.test.tsx +46 -78
  101. package/src/react/hooks/options/__mocks__/marketplaceConfig.msw.ts +9 -4
  102. package/src/react/hooks/useCurrencyBalance.tsx +4 -5
  103. package/src/react/hooks/useRoyaltyPercentage.tsx +16 -8
  104. package/src/react/ssr/__tests__/create-ssr-client.test.ts +118 -0
  105. package/src/react/ui/components/collectible-card/CollectibleCard.tsx +25 -6
  106. package/src/react/ui/components/collectible-card/Footer.tsx +56 -7
  107. package/src/react/ui/components/collectible-card/styles.css.ts +26 -2
  108. package/src/react/ui/modals/BuyModal/hooks/__tests__/useCheckoutOptions.test.tsx +10 -28
  109. package/src/react/ui/modals/BuyModal/hooks/__tests__/useLoadData.test.tsx +9 -36
  110. package/src/react/ui/modals/BuyModal/hooks/useBuyCollectable.ts +2 -24
  111. package/src/react/ui/modals/BuyModal/modals/Modal1155.tsx +16 -5
  112. package/src/react/ui/modals/CreateListingModal/Modal.tsx +3 -2
  113. package/src/react/ui/modals/SellModal/Modal.tsx +1 -0
  114. package/src/react/ui/modals/_internal/components/transactionDetails/index.tsx +8 -7
  115. package/src/types/sdk-config.ts +1 -0
  116. package/src/utils/index.ts +0 -1
  117. package/src/utils/price.ts +11 -0
  118. package/tsconfig.tsbuildinfo +1 -1
  119. package/dist/chunk-3BLBZYQX.js.map +0 -1
  120. package/dist/chunk-7C7ADZ2H.js.map +0 -1
  121. package/dist/chunk-7FN62HOP.js.map +0 -1
  122. package/dist/chunk-AXTDPTRD.js.map +0 -1
  123. package/dist/chunk-CIPPTQDA.js.map +0 -1
  124. package/dist/chunk-J6F5QOW5.js.map +0 -1
  125. package/dist/chunk-P7UNMRZ5.js.map +0 -1
  126. package/dist/chunk-SA3U25NU.js.map +0 -1
  127. package/dist/chunk-TFRAOS7F.js.map +0 -1
  128. package/dist/chunk-Y75XGZOB.js.map +0 -1
  129. package/src/react/_internal/test/mocks/publicClient.ts +0 -39
  130. package/src/react/_internal/test/mocks/wagmi.ts +0 -61
  131. package/src/utils/__tests__/get-public-rpc-client.test.ts +0 -111
  132. package/src/utils/get-public-rpc-client.ts +0 -41
@@ -0,0 +1,118 @@
1
+ import { QueryClient } from '@tanstack/react-query';
2
+ import { setupServer } from 'msw/node';
3
+ import {
4
+ afterAll,
5
+ beforeAll,
6
+ beforeEach,
7
+ describe,
8
+ expect,
9
+ it,
10
+ vi,
11
+ } from 'vitest';
12
+ import type { SdkConfig } from '../../../types';
13
+ import { mockConfig } from '../../hooks/options/__mocks__/marketplaceConfig.msw';
14
+ import { createSSRClient } from '../create-ssr-client';
15
+
16
+ const server = setupServer();
17
+
18
+ vi.mock('wagmi', () => ({
19
+ cookieToInitialState: vi.fn().mockReturnValue({
20
+ data: { account: { address: '0x123' } },
21
+ }),
22
+ }));
23
+
24
+ describe('createSSRClient', () => {
25
+ let queryClient: QueryClient;
26
+ let config: SdkConfig;
27
+
28
+ beforeAll(() => {
29
+ // Start MSW server once before all tests
30
+ server.listen({ onUnhandledRequest: 'error' });
31
+ });
32
+
33
+ afterAll(() => {
34
+ // Clean up after all tests are done
35
+ server.close();
36
+ });
37
+
38
+ beforeEach(() => {
39
+ // Reset QueryClient
40
+ queryClient = new QueryClient({
41
+ defaultOptions: {
42
+ queries: {
43
+ retry: false,
44
+ },
45
+ },
46
+ });
47
+
48
+ // Setup basic config
49
+ config = {
50
+ projectId: 'test-project',
51
+ projectAccessKey: 'test-key',
52
+ _internal: {
53
+ builderEnv: 'production',
54
+ },
55
+ };
56
+ });
57
+
58
+ it('should create SSR client with proper methods', () => {
59
+ const client = createSSRClient({
60
+ cookie: 'test-cookie',
61
+ config,
62
+ queryClient,
63
+ });
64
+
65
+ expect(client).toHaveProperty('getInitialState');
66
+ expect(client).toHaveProperty('getMarketplaceConfig');
67
+ expect(client).toHaveProperty('config');
68
+ expect(typeof client.getInitialState).toBe('function');
69
+ expect(typeof client.getMarketplaceConfig).toBe('function');
70
+ });
71
+
72
+ it('should fetch marketplace config successfully', async () => {
73
+ const client = createSSRClient({
74
+ cookie: 'test-cookie',
75
+ config,
76
+ queryClient,
77
+ });
78
+
79
+ const marketplaceConfig = await client.getMarketplaceConfig();
80
+
81
+ expect(marketplaceConfig).toBeDefined();
82
+ expect(marketplaceConfig).toMatchObject({
83
+ publisherId: mockConfig.publisherId,
84
+ title: mockConfig.title,
85
+ collections: expect.arrayContaining([
86
+ expect.objectContaining({
87
+ address: expect.any(String),
88
+ chainId: expect.any(Number),
89
+ }),
90
+ ]),
91
+ });
92
+ });
93
+
94
+ it('should get initial state with wagmi configuration', async () => {
95
+ const client = createSSRClient({
96
+ cookie: 'test-cookie',
97
+ config,
98
+ queryClient,
99
+ });
100
+
101
+ const state = await client.getInitialState();
102
+
103
+ expect(state).toHaveProperty('wagmi');
104
+ expect(state.wagmi).toEqual({
105
+ data: { account: { address: '0x123' } },
106
+ });
107
+ });
108
+
109
+ it('should preserve provided config in the client', () => {
110
+ const client = createSSRClient({
111
+ cookie: 'test-cookie',
112
+ config,
113
+ queryClient,
114
+ });
115
+
116
+ expect(client.config).toEqual(config);
117
+ });
118
+ });
@@ -97,6 +97,7 @@ export function CollectibleCard({
97
97
  const collectibleMetadata = lowestListing?.metadata;
98
98
  const highestOffer = lowestListing?.offer;
99
99
  const [imageLoadingError, setImageLoadingError] = useState(false);
100
+ const [imageLoading, setImageLoading] = useState(true);
100
101
 
101
102
  const { data: lowestListingCurrency } = useCurrency({
102
103
  chainId,
@@ -169,12 +170,30 @@ export function CollectibleCard({
169
170
  />
170
171
  )}
171
172
 
172
- <img
173
- src={imageLoadingError ? ChessTileImage : image || ChessTileImage}
174
- alt={name}
175
- className={collectibleImage}
176
- onError={() => setImageLoadingError(true)}
177
- />
173
+ <Box position="relative">
174
+ {imageLoading && (
175
+ <Skeleton
176
+ position="absolute"
177
+ top="0"
178
+ left="0"
179
+ width="full"
180
+ height="full"
181
+ zIndex="10"
182
+ style={{ borderRadius: 0 }}
183
+ />
184
+ )}
185
+ <img
186
+ src={imageLoadingError ? ChessTileImage : image || ChessTileImage}
187
+ alt={name}
188
+ className={
189
+ imageLoading
190
+ ? collectibleImage.loading
191
+ : collectibleImage.loaded
192
+ }
193
+ onError={() => setImageLoadingError(true)}
194
+ onLoad={() => setImageLoading(false)}
195
+ />
196
+ </Box>
178
197
 
179
198
  <Footer
180
199
  name={name || ''}
@@ -1,15 +1,57 @@
1
- import { Box, IconButton, Image, Text } from '@0xsequence/design-system';
1
+ import {
2
+ Box,
3
+ ChevronLeftIcon,
4
+ ChevronRightIcon,
5
+ IconButton,
6
+ Image,
7
+ Text,
8
+ } from '@0xsequence/design-system';
2
9
  import { formatUnits } from 'viem';
3
10
  import { ContractType, type Currency, type Order } from '../../../_internal';
4
11
  import SvgBellIcon from '../../icons/Bell';
5
- import { footer, offerBellButton } from './styles.css';
12
+ import { footer, footerPriceChevron, offerBellButton } from './styles.css';
6
13
 
7
- const formatPrice = (amount: string, currency: Currency): string => {
14
+ const OVERFLOW_PRICE = 100000000;
15
+ const UNDERFLOW_PRICE = 0.0001;
16
+
17
+ const formatPrice = (amount: string, currency: Currency): React.ReactNode => {
8
18
  const formattedPrice = formatUnits(BigInt(amount), currency.decimals);
9
19
  const numericPrice = Number.parseFloat(formattedPrice);
10
- return numericPrice < 0.0001
11
- ? `< 0.0001 ${currency.symbol}`
12
- : `${formattedPrice} ${currency.symbol}`;
20
+
21
+ if (numericPrice < UNDERFLOW_PRICE) {
22
+ return (
23
+ <Box display="flex" alignItems="center">
24
+ <ChevronLeftIcon className={footerPriceChevron} />
25
+ <Text>{`${UNDERFLOW_PRICE} ${currency.symbol}`}</Text>
26
+ </Box>
27
+ );
28
+ }
29
+
30
+ if (numericPrice > OVERFLOW_PRICE) {
31
+ return (
32
+ <Box display="flex" alignItems="center">
33
+ <ChevronRightIcon className={footerPriceChevron} />
34
+ <Text>{`${OVERFLOW_PRICE.toLocaleString('en-US', {
35
+ maximumFractionDigits: 2,
36
+ })} ${currency.symbol}`}</Text>
37
+ </Box>
38
+ );
39
+ }
40
+
41
+ const maxDecimals = numericPrice < 0.01 ? 6 : 4;
42
+
43
+ const formattedNumber = numericPrice.toLocaleString('en-US', {
44
+ minimumFractionDigits: 0,
45
+ maximumFractionDigits: maxDecimals,
46
+ });
47
+
48
+ return (
49
+ <Box display="flex" alignItems="center" gap="1">
50
+ <Text>
51
+ {formattedNumber} {currency.symbol}
52
+ </Text>
53
+ </Box>
54
+ );
13
55
  };
14
56
 
15
57
  type FooterProps = {
@@ -90,7 +132,14 @@ export const Footer = ({
90
132
 
91
133
  <Box display="flex" alignItems="center" gap="1">
92
134
  {listed && lowestListingCurrency.imageUrl && (
93
- <Image src={lowestListingCurrency.imageUrl} width="3" height="3" />
135
+ <Image
136
+ src={lowestListingCurrency.imageUrl}
137
+ width="3"
138
+ height="3"
139
+ onError={(e) => {
140
+ e.currentTarget.style.display = 'none';
141
+ }}
142
+ />
94
143
  )}
95
144
 
96
145
  <Text
@@ -1,5 +1,5 @@
1
1
  import { atoms } from '@0xsequence/design-system';
2
- import { style } from '@vanilla-extract/css';
2
+ import { style, styleVariants } from '@vanilla-extract/css';
3
3
 
4
4
  export const collectibleCard = style([
5
5
  {
@@ -37,7 +37,7 @@ export const collectibleTileWrapper = style({
37
37
  },
38
38
  });
39
39
 
40
- export const collectibleImage = style({
40
+ const collectibleImageBase = style({
41
41
  width: '175px',
42
42
  height: '175px',
43
43
  objectFit: 'cover',
@@ -49,6 +49,22 @@ export const collectibleImage = style({
49
49
  },
50
50
  });
51
51
 
52
+ export const collectibleImage = styleVariants({
53
+ default: [collectibleImageBase],
54
+ loading: [
55
+ collectibleImageBase,
56
+ {
57
+ visibility: 'hidden',
58
+ },
59
+ ],
60
+ loaded: [
61
+ collectibleImageBase,
62
+ {
63
+ visibility: 'visible',
64
+ },
65
+ ],
66
+ });
67
+
52
68
  export const offerBellButton = style({
53
69
  width: '22px',
54
70
  height: '22px',
@@ -56,6 +72,14 @@ export const offerBellButton = style({
56
72
 
57
73
  export const footer = style([atoms({ background: 'backgroundPrimary' })]);
58
74
 
75
+ export const footerPriceChevron = style([
76
+ atoms({
77
+ width: '3',
78
+ height: '3',
79
+ color: 'text100',
80
+ }),
81
+ ]);
82
+
59
83
  export const actionWrapper = style([
60
84
  atoms({
61
85
  backdropFilter: 'blur',
@@ -1,19 +1,19 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import { useCheckoutOptions } from '../useCheckoutOptions';
3
- import { useWallet } from '../../../../../_internal/wallet/useWallet';
4
- import { useFees } from '../useFees';
1
+ import { http, HttpResponse } from 'msw';
2
+ import { zeroAddress } from 'viem';
3
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
5
4
  import { MarketplaceKind } from '../../../../../_internal';
5
+ import { mockMarketplaceEndpoint } from '../../../../../_internal/api/__mocks__/marketplace.msw';
6
+ import { TransactionCrypto } from '../../../../../_internal/api/marketplace.gen';
6
7
  import {
8
+ type RenderHookOptions,
7
9
  renderHook,
8
10
  waitFor,
9
- type RenderHookOptions,
10
11
  } from '../../../../../_internal/test-utils';
11
- import { http, HttpResponse } from 'msw';
12
- import { server } from '../../../../../_internal/test/setup';
13
12
  import { createMockWallet } from '../../../../../_internal/test/mocks/wallet';
14
- import { mockMarketplaceEndpoint } from '../../../../../_internal/api/__mocks__/marketplace.msw';
15
- import { zeroAddress } from 'viem';
16
- import { TransactionCrypto } from '../../../../../_internal/api/marketplace.gen';
13
+ import { server } from '../../../../../_internal/test/setup';
14
+ import { useWallet } from '../../../../../_internal/wallet/useWallet';
15
+ import { useCheckoutOptions } from '../useCheckoutOptions';
16
+ import { useFees } from '../useFees';
17
17
 
18
18
  // Mock dependencies
19
19
  vi.mock('../../../../../_internal/wallet/useWallet');
@@ -47,24 +47,6 @@ describe('useCheckoutOptions', () => {
47
47
  amount: '100000000000000000',
48
48
  receiver: zeroAddress,
49
49
  });
50
-
51
- // Set up default API response
52
- server.use(
53
- http.post(mockMarketplaceEndpoint('CheckoutOptionsMarketplace'), () => {
54
- return HttpResponse.json({
55
- options: {
56
- crypto: TransactionCrypto.all,
57
- swap: [],
58
- nftCheckout: [],
59
- onRamp: [],
60
- },
61
- });
62
- }),
63
- );
64
- });
65
-
66
- afterEach(() => {
67
- server.resetHandlers();
68
50
  });
69
51
 
70
52
  it('should fetch checkout options successfully', async () => {
@@ -1,11 +1,9 @@
1
- import { renderHook } from '@testing-library/react';
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import { useLoadData } from '../useLoadData';
4
- import { useCollection, useCollectible } from '../../../../../hooks';
5
- import { useCheckoutOptions } from '../useCheckoutOptions';
1
+ import { describe, expect, it, vi } from 'vitest';
6
2
  import { MarketplaceKind } from '../../../../../_internal';
7
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
8
- import type { ReactNode } from 'react';
3
+ import { renderHook } from '../../../../../_internal/test-utils';
4
+ import { useCollectible, useCollection } from '../../../../../hooks';
5
+ import { useCheckoutOptions } from '../useCheckoutOptions';
6
+ import { useLoadData } from '../useLoadData';
9
7
 
10
8
  // Mock dependencies
11
9
  vi.mock('../../../../../hooks', () => ({
@@ -17,19 +15,6 @@ vi.mock('../useCheckoutOptions', () => ({
17
15
  useCheckoutOptions: vi.fn(),
18
16
  }));
19
17
 
20
- const createWrapper = () => {
21
- const queryClient = new QueryClient({
22
- defaultOptions: {
23
- queries: {
24
- retry: false,
25
- },
26
- },
27
- });
28
- return ({ children }: { children: ReactNode }) => (
29
- <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
30
- );
31
- };
32
-
33
18
  describe('useLoadData', () => {
34
19
  const defaultProps = {
35
20
  chainId: 1,
@@ -39,10 +24,6 @@ describe('useLoadData', () => {
39
24
  marketplace: MarketplaceKind.sequence_marketplace_v2,
40
25
  };
41
26
 
42
- beforeEach(() => {
43
- vi.clearAllMocks();
44
- });
45
-
46
27
  it('should return loading state when any data is loading', () => {
47
28
  // Mock one hook to be loading
48
29
  (useCollection as unknown as ReturnType<typeof vi.fn>).mockReturnValue({
@@ -65,9 +46,7 @@ describe('useLoadData', () => {
65
46
  },
66
47
  );
67
48
 
68
- const { result } = renderHook(() => useLoadData(defaultProps), {
69
- wrapper: createWrapper(),
70
- });
49
+ const { result } = renderHook(() => useLoadData(defaultProps));
71
50
 
72
51
  expect(result.current.isLoading).toBe(true);
73
52
  expect(result.current.isError).toBe(false);
@@ -98,9 +77,7 @@ describe('useLoadData', () => {
98
77
  },
99
78
  );
100
79
 
101
- const { result } = renderHook(() => useLoadData(defaultProps), {
102
- wrapper: createWrapper(),
103
- });
80
+ const { result } = renderHook(() => useLoadData(defaultProps));
104
81
 
105
82
  expect(result.current.isError).toBe(true);
106
83
  expect(result.current.isLoading).toBe(false);
@@ -136,9 +113,7 @@ describe('useLoadData', () => {
136
113
  },
137
114
  );
138
115
 
139
- const { result } = renderHook(() => useLoadData(defaultProps), {
140
- wrapper: createWrapper(),
141
- });
116
+ const { result } = renderHook(() => useLoadData(defaultProps));
142
117
 
143
118
  expect(result.current.isLoading).toBe(false);
144
119
  expect(result.current.isError).toBe(false);
@@ -174,9 +149,7 @@ describe('useLoadData', () => {
174
149
  },
175
150
  );
176
151
 
177
- const { result } = renderHook(() => useLoadData(defaultProps), {
178
- wrapper: createWrapper(),
179
- });
152
+ const { result } = renderHook(() => useLoadData(defaultProps));
180
153
 
181
154
  // Should be loading if any data is loading
182
155
  expect(result.current.isLoading).toBe(true);
@@ -1,6 +1,6 @@
1
1
  import { useSelectPaymentModal } from '@0xsequence/kit-checkout';
2
2
  import type { QueryKey } from '@tanstack/react-query';
3
- import { type Hash, type Hex, zeroAddress } from 'viem';
3
+ import type { Hash, Hex } from 'viem';
4
4
  import {
5
5
  type CheckoutOptions,
6
6
  type MarketplaceKind,
@@ -93,16 +93,6 @@ export const useBuyCollectable = ({
93
93
  walletType: WalletKind.unknown,
94
94
  });
95
95
 
96
- const order = await marketplaceClient.getOrders({
97
- input: [
98
- {
99
- orderId: input.orderId,
100
- contractAddress: collectionAddress,
101
- marketplace: input.marketplace,
102
- },
103
- ],
104
- });
105
-
106
96
  // these states are necessary to manage appearance of the quantity modal
107
97
  setCheckoutModalLoaded(true);
108
98
  setCheckoutModalIsLoading(false);
@@ -113,18 +103,6 @@ export const useBuyCollectable = ({
113
103
  throw new Error('Buy step not found');
114
104
  }
115
105
 
116
- const feesBps = BigInt(fees.amount);
117
- let price = String(
118
- (BigInt(order.orders[0].priceAmount) *
119
- BigInt(input.quantity) *
120
- (10000n + feesBps)) /
121
- 10000n,
122
- );
123
-
124
- if (order.orders[0].priceCurrencyAddress !== zeroAddress) {
125
- price = '0';
126
- }
127
-
128
106
  openSelectPaymentModal({
129
107
  chain: chainId,
130
108
  collectibles: [
@@ -135,7 +113,7 @@ export const useBuyCollectable = ({
135
113
  },
136
114
  ],
137
115
  currencyAddress: priceCurrencyAddress,
138
- price,
116
+ price: step.price,
139
117
  targetContractAddress: step.to,
140
118
  txData: step.data as Hex,
141
119
  collectionAddress,
@@ -1,8 +1,13 @@
1
1
  import { Box, Text, TokenImage } from '@0xsequence/design-system';
2
2
  import { observer } from '@legendapp/state/react';
3
3
  import type { Hex } from 'viem';
4
- import { formatUnits, parseUnits } from 'viem';
5
- import { useCurrency } from '../../../../hooks';
4
+ import { parseUnits } from 'viem';
5
+ import {
6
+ DEFAULT_MARKETPLACE_FEE_PERCENTAGE,
7
+ compareAddress,
8
+ formatPrice,
9
+ } from '../../../../..';
10
+ import { useCurrency, useMarketplaceConfig } from '../../../../hooks';
6
11
  import { ActionModal } from '../../_internal/components/actionModal';
7
12
  import QuantityInput from '../../_internal/components/quantityInput';
8
13
  import { buyModal$ } from '../store';
@@ -16,14 +21,20 @@ interface ERC1155QuantityModalProps extends CheckoutModalProps {
16
21
 
17
22
  export const ERC1155QuantityModal = observer(
18
23
  ({ buy, collectable, order }: ERC1155QuantityModalProps) => {
24
+ const { data: marketplaceConfig } = useMarketplaceConfig();
19
25
  const { data: currency, isLoading: isCurrencyLoading } = useCurrency({
20
26
  chainId: order.chainId,
21
27
  currencyAddress: order.priceCurrencyAddress,
22
28
  });
23
-
24
29
  const quantity = Number(buyModal$.state.quantity.get());
25
30
  const pricePerToken = order.priceAmount;
26
- const totalPrice = (BigInt(quantity) * BigInt(pricePerToken)).toString();
31
+ const marketplaceFeePercentage =
32
+ marketplaceConfig?.collections.find((collection) =>
33
+ compareAddress(collection.address, order.collectionContractAddress),
34
+ )?.feePercentage || DEFAULT_MARKETPLACE_FEE_PERCENTAGE;
35
+ const price = Number(quantity) * Number(pricePerToken);
36
+ const totalPrice =
37
+ price + (price * Number(marketplaceFeePercentage || 0)) / 100;
27
38
 
28
39
  if (
29
40
  buyModal$.state.checkoutModalLoaded.get() &&
@@ -92,7 +103,7 @@ export const ERC1155QuantityModal = observer(
92
103
  fontWeight="bold"
93
104
  fontFamily="body"
94
105
  >
95
- {formatUnits(BigInt(totalPrice), currency.decimals || 0)}
106
+ {formatPrice(totalPrice, currency.decimals)}
96
107
  </Text>
97
108
 
98
109
  <Text color="text80" fontSize="small" fontFamily="body">
@@ -2,6 +2,7 @@ import { Box } from '@0xsequence/design-system';
2
2
  import { Show, observer } from '@legendapp/state/react';
3
3
  import { parseUnits } from 'viem';
4
4
  import { useAccount } from 'wagmi';
5
+ import { dateToUnixTime } from '../../../../utils/date';
5
6
  import type { ContractType } from '../../../_internal';
6
7
  import {
7
8
  useBalanceOfCollectible,
@@ -21,9 +22,8 @@ import PriceInput from '../_internal/components/priceInput';
21
22
  import QuantityInput from '../_internal/components/quantityInput';
22
23
  import TokenPreview from '../_internal/components/tokenPreview';
23
24
  import TransactionDetails from '../_internal/components/transactionDetails';
24
- import { createListingModal$ } from './store';
25
- import { dateToUnixTime } from '../../../../utils/date';
26
25
  import { useCreateListing } from './hooks/useCreateListing';
26
+ import { createListingModal$ } from './store';
27
27
 
28
28
  export const CreateListingModal = () => {
29
29
  return <Show if={createListingModal$.isOpen}>{() => <Modal />}</Show>;
@@ -211,6 +211,7 @@ const Modal = observer(() => {
211
211
  chainId={chainId}
212
212
  price={createListingModal$.listingPrice.get()}
213
213
  currencyImageUrl={listingPrice.currency.imageUrl}
214
+ includeMarketplaceFee={false}
214
215
  />
215
216
  </ActionModal>
216
217
  );
@@ -133,6 +133,7 @@ const Modal = observer(() => {
133
133
  collectibleId={tokenId}
134
134
  collectionAddress={collectionAddress}
135
135
  chainId={chainId}
136
+ includeMarketplaceFee={true}
136
137
  price={
137
138
  currency
138
139
  ? {
@@ -1,5 +1,6 @@
1
1
  import { Box, Image, Skeleton, Text } from '@0xsequence/design-system';
2
2
  import { type Hex, formatUnits } from 'viem';
3
+ import { DEFAULT_MARKETPLACE_FEE_PERCENTAGE } from '../../../../../../consts';
3
4
  import type { Price } from '../../../../../../types';
4
5
  import {
5
6
  useMarketplaceConfig,
@@ -12,27 +13,27 @@ type TransactionDetailsProps = {
12
13
  chainId: string;
13
14
  price?: Price;
14
15
  currencyImageUrl?: string;
16
+ includeMarketplaceFee: boolean;
15
17
  // We use a placeholder price for create listing modal
16
18
  showPlaceholderPrice?: boolean;
17
19
  };
18
20
 
19
- //TODO: Move this
20
- const DEFAULT_MARKETPLACE_FEE_PERCENTAGE = 2.5;
21
-
22
21
  export default function TransactionDetails({
23
22
  collectibleId,
24
23
  collectionAddress,
25
24
  chainId,
25
+ includeMarketplaceFee,
26
26
  price,
27
27
  showPlaceholderPrice,
28
28
  currencyImageUrl,
29
29
  }: TransactionDetailsProps) {
30
30
  const { data, isLoading: marketplaceConfigLoading } = useMarketplaceConfig();
31
31
 
32
- const marketplaceFeePercentage =
33
- data?.collections.find(
34
- (collection) => collection.address === collectionAddress,
35
- )?.feePercentage || DEFAULT_MARKETPLACE_FEE_PERCENTAGE;
32
+ const marketplaceFeePercentage = includeMarketplaceFee
33
+ ? data?.collections.find(
34
+ (collection) => collection.address === collectionAddress,
35
+ )?.feePercentage || DEFAULT_MARKETPLACE_FEE_PERCENTAGE
36
+ : 0;
36
37
  const { data: royaltyPercentage, isLoading: royaltyPercentageLoading } =
37
38
  useRoyaltyPercentage({
38
39
  chainId,
@@ -17,6 +17,7 @@ export type SdkConfig = {
17
17
  nextAccessKey?: string;
18
18
  builderEnv?: Env;
19
19
  marketplaceEnv?: Env;
20
+ nodeGatewayEnv?: Env;
20
21
  metadataEnv?: Env;
21
22
  indexerEnv?: Env;
22
23
  };
@@ -1,6 +1,5 @@
1
1
  export * from './abi';
2
2
  export * from './address';
3
- export * from './get-public-rpc-client';
4
3
  export * from './network';
5
4
  export * from './price';
6
5
  export * from './getMarketplaceDetails';
@@ -18,3 +18,14 @@ export const calculatePriceDifferencePercentage = ({
18
18
 
19
19
  return percentageDifference.toFixed(2);
20
20
  };
21
+
22
+ export const formatPrice = (
23
+ amount: string | number | bigint,
24
+ decimals: number,
25
+ ): string => {
26
+ const formattedUnits = Number(formatUnits(BigInt(amount), decimals));
27
+ return formattedUnits.toLocaleString('en-US', {
28
+ minimumFractionDigits: 0,
29
+ maximumFractionDigits: decimals,
30
+ });
31
+ };